pgbus 0.2.1 → 0.2.2

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/pgbus/api/insights_controller.rb +5 -4
  3. data/app/controllers/pgbus/application_controller.rb +40 -0
  4. data/app/controllers/pgbus/insights_controller.rb +3 -2
  5. data/app/controllers/pgbus/locale_controller.rb +15 -0
  6. data/app/helpers/pgbus/application_helper.rb +67 -7
  7. data/app/views/layouts/pgbus/application.html.erb +50 -14
  8. data/app/views/pgbus/dashboard/_processes_table.html.erb +6 -6
  9. data/app/views/pgbus/dashboard/_queues_table.html.erb +8 -8
  10. data/app/views/pgbus/dashboard/_recent_failures.html.erb +6 -6
  11. data/app/views/pgbus/dashboard/_stats_cards.html.erb +9 -9
  12. data/app/views/pgbus/dashboard/show.html.erb +1 -1
  13. data/app/views/pgbus/dead_letter/_messages_table.html.erb +19 -19
  14. data/app/views/pgbus/dead_letter/index.html.erb +5 -5
  15. data/app/views/pgbus/dead_letter/show.html.erb +12 -12
  16. data/app/views/pgbus/events/index.html.erb +11 -11
  17. data/app/views/pgbus/events/show.html.erb +6 -6
  18. data/app/views/pgbus/insights/show.html.erb +41 -21
  19. data/app/views/pgbus/jobs/_enqueued_table.html.erb +19 -19
  20. data/app/views/pgbus/jobs/_failed_table.html.erb +11 -11
  21. data/app/views/pgbus/jobs/index.html.erb +5 -5
  22. data/app/views/pgbus/jobs/show.html.erb +13 -13
  23. data/app/views/pgbus/locks/index.html.erb +11 -11
  24. data/app/views/pgbus/outbox/index.html.erb +15 -15
  25. data/app/views/pgbus/processes/_processes_table.html.erb +7 -7
  26. data/app/views/pgbus/processes/index.html.erb +1 -1
  27. data/app/views/pgbus/queues/_queues_list.html.erb +14 -14
  28. data/app/views/pgbus/queues/index.html.erb +1 -1
  29. data/app/views/pgbus/queues/show.html.erb +11 -11
  30. data/app/views/pgbus/recurring_tasks/_tasks_table.html.erb +14 -14
  31. data/app/views/pgbus/recurring_tasks/index.html.erb +2 -2
  32. data/app/views/pgbus/recurring_tasks/show.html.erb +21 -21
  33. data/config/i18n-tasks.yml +41 -0
  34. data/config/locales/da.yml +348 -0
  35. data/config/locales/de.yml +348 -0
  36. data/config/locales/en.yml +348 -0
  37. data/config/locales/es.yml +348 -0
  38. data/config/locales/fi.yml +348 -0
  39. data/config/locales/fr.yml +348 -0
  40. data/config/locales/it.yml +348 -0
  41. data/config/locales/ja.yml +348 -0
  42. data/config/locales/nb.yml +348 -0
  43. data/config/locales/nl.yml +348 -0
  44. data/config/locales/pt.yml +348 -0
  45. data/config/locales/sv.yml +348 -0
  46. data/config/routes.rb +2 -0
  47. data/lib/pgbus/configuration.rb +8 -2
  48. data/lib/pgbus/engine.rb +4 -0
  49. data/lib/pgbus/version.rb +1 -1
  50. metadata +15 -1
@@ -1,20 +1,20 @@
1
1
  <div class="mb-6">
2
- <h1 class="text-2xl font-bold text-gray-900 dark:text-white">Outbox</h1>
3
- <p class="mt-1 text-sm text-gray-500">Transactional outbox entries pending publication to PGMQ</p>
2
+ <h1 class="text-2xl font-bold text-gray-900 dark:text-white"><%= t("pgbus.outbox.index.title") %></h1>
3
+ <p class="mt-1 text-sm text-gray-500"><%= t("pgbus.outbox.index.description") %></p>
4
4
  </div>
5
5
 
6
6
  <div class="mb-6 grid grid-cols-3 gap-4">
7
7
  <div class="rounded-lg bg-white dark:bg-gray-800 p-4 shadow ring-1 ring-gray-200 dark:ring-gray-700">
8
- <dt class="text-xs font-medium uppercase text-gray-500">Unpublished</dt>
8
+ <dt class="text-xs font-medium uppercase text-gray-500"><%= t("pgbus.outbox.index.stats.unpublished") %></dt>
9
9
  <dd class="mt-1 text-2xl font-semibold text-gray-900 dark:text-white"><%= pgbus_number(@stats[:unpublished]) %></dd>
10
10
  </div>
11
11
  <div class="rounded-lg bg-white dark:bg-gray-800 p-4 shadow ring-1 ring-gray-200 dark:ring-gray-700">
12
- <dt class="text-xs font-medium uppercase text-gray-500">Total</dt>
12
+ <dt class="text-xs font-medium uppercase text-gray-500"><%= t("pgbus.outbox.index.stats.total") %></dt>
13
13
  <dd class="mt-1 text-2xl font-semibold text-gray-900 dark:text-white"><%= pgbus_number(@stats[:total]) %></dd>
14
14
  </div>
15
15
  <div class="rounded-lg bg-white dark:bg-gray-800 p-4 shadow ring-1 ring-gray-200 dark:ring-gray-700">
16
- <dt class="text-xs font-medium uppercase text-gray-500">Oldest Unpublished</dt>
17
- <dd class="mt-1 text-2xl font-semibold text-gray-900 dark:text-white"><%= @stats[:oldest_unpublished_age] ? "#{@stats[:oldest_unpublished_age]}s" : "" %></dd>
16
+ <dt class="text-xs font-medium uppercase text-gray-500"><%= t("pgbus.outbox.index.stats.oldest_unpublished") %></dt>
17
+ <dd class="mt-1 text-2xl font-semibold text-gray-900 dark:text-white"><%= @stats[:oldest_unpublished_age] ? t("pgbus.outbox.index.stats.oldest_age", seconds: @stats[:oldest_unpublished_age]) : t("pgbus.outbox.index.stats.no_age") %></dd>
18
18
  </div>
19
19
  </div>
20
20
 
@@ -22,12 +22,12 @@
22
22
  <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
23
23
  <thead class="bg-gray-50 dark:bg-gray-900">
24
24
  <tr>
25
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">ID</th>
26
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">Queue / Topic</th>
27
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">Payload</th>
28
- <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500">Priority</th>
29
- <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500">Status</th>
30
- <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500">Created</th>
25
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.outbox.index.headers.id") %></th>
26
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.outbox.index.headers.queue_topic") %></th>
27
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.outbox.index.headers.payload") %></th>
28
+ <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.outbox.index.headers.priority") %></th>
29
+ <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.outbox.index.headers.status") %></th>
30
+ <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.outbox.index.headers.created") %></th>
31
31
  </tr>
32
32
  </thead>
33
33
  <tbody class="divide-y divide-gray-100 dark:divide-gray-700">
@@ -39,16 +39,16 @@
39
39
  <td class="px-4 py-3 text-sm text-right text-gray-500"><%= entry.priority %></td>
40
40
  <td class="px-4 py-3 text-sm text-right">
41
41
  <% if entry.published_at %>
42
- <span class="inline-flex items-center rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-800">Published</span>
42
+ <span class="inline-flex items-center rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-800"><%= t("pgbus.outbox.index.published") %></span>
43
43
  <% else %>
44
- <span class="inline-flex items-center rounded-full bg-yellow-100 px-2 py-0.5 text-xs font-medium text-yellow-800">Pending</span>
44
+ <span class="inline-flex items-center rounded-full bg-yellow-100 px-2 py-0.5 text-xs font-medium text-yellow-800"><%= t("pgbus.outbox.index.pending") %></span>
45
45
  <% end %>
46
46
  </td>
47
47
  <td class="px-4 py-3 text-sm text-right text-gray-500"><%= pgbus_time_ago(entry.created_at) %></td>
48
48
  </tr>
49
49
  <% end %>
50
50
  <% if @entries.empty? %>
51
- <tr><td colspan="6" class="px-4 py-8 text-center text-sm text-gray-400">No outbox entries</td></tr>
51
+ <tr><td colspan="6" class="px-4 py-8 text-center text-sm text-gray-400"><%= t("pgbus.outbox.index.empty") %></td></tr>
52
52
  <% end %>
53
53
  </tbody>
54
54
  </table>
@@ -3,12 +3,12 @@
3
3
  <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
4
4
  <thead class="bg-gray-50 dark:bg-gray-900">
5
5
  <tr>
6
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">Kind</th>
7
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">Hostname</th>
8
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">PID</th>
9
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">Status</th>
10
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">Last Heartbeat</th>
11
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">Metadata</th>
6
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.processes.processes_table.headers.kind") %></th>
7
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.processes.processes_table.headers.hostname") %></th>
8
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.processes.processes_table.headers.pid") %></th>
9
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.processes.processes_table.headers.status") %></th>
10
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.processes.processes_table.headers.last_heartbeat") %></th>
11
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.processes.processes_table.headers.metadata") %></th>
12
12
  </tr>
13
13
  </thead>
14
14
  <tbody class="divide-y divide-gray-100 dark:divide-gray-700">
@@ -29,7 +29,7 @@
29
29
  </tr>
30
30
  <% end %>
31
31
  <% if @processes.empty? %>
32
- <tr><td colspan="6" class="px-4 py-8 text-center text-sm text-gray-400">No processes running</td></tr>
32
+ <tr><td colspan="6" class="px-4 py-8 text-center text-sm text-gray-400"><%= t("pgbus.processes.processes_table.empty") %></td></tr>
33
33
  <% end %>
34
34
  </tbody>
35
35
  </table>
@@ -1,3 +1,3 @@
1
- <h1 class="text-2xl font-bold text-gray-900 dark:text-white mb-6">Processes</h1>
1
+ <h1 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%= t("pgbus.processes.index.title") %></h1>
2
2
 
3
3
  <%= render "pgbus/processes/processes_table" %>
@@ -3,13 +3,13 @@
3
3
  <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
4
4
  <thead class="bg-gray-50 dark:bg-gray-900">
5
5
  <tr>
6
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">Queue</th>
7
- <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500">Depth</th>
8
- <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500">Visible</th>
9
- <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500">Oldest (s)</th>
10
- <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500">Newest (s)</th>
11
- <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500">Total Ever</th>
12
- <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500">Actions</th>
6
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.queues_list.headers.queue") %></th>
7
+ <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.queues_list.headers.depth") %></th>
8
+ <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.queues_list.headers.visible") %></th>
9
+ <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.queues_list.headers.oldest") %></th>
10
+ <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.queues_list.headers.newest") %></th>
11
+ <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.queues_list.headers.total_ever") %></th>
12
+ <th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.queues_list.headers.actions") %></th>
13
13
  </tr>
14
14
  </thead>
15
15
  <tbody class="divide-y divide-gray-100 dark:divide-gray-700">
@@ -19,7 +19,7 @@
19
19
  <%= link_to q[:name], pgbus.queue_path(name: q[:name]), class: "font-medium text-indigo-600 hover:text-indigo-500", data: { turbo_frame: "_top" } %>
20
20
  <%= pgbus_queue_badge(q[:name]) %>
21
21
  <% if q[:paused] %>
22
- <span class="inline-flex items-center rounded-full bg-yellow-100 px-2 py-0.5 text-xs font-medium text-yellow-800">Paused</span>
22
+ <span class="inline-flex items-center rounded-full bg-yellow-100 px-2 py-0.5 text-xs font-medium text-yellow-800"><%= t("pgbus.queues.queues_list.paused") %></span>
23
23
  <% end %>
24
24
  </td>
25
25
  <td class="px-4 py-3 text-sm text-right font-mono text-gray-700"><%= pgbus_number(q[:queue_length]) %></td>
@@ -29,25 +29,25 @@
29
29
  <td class="px-4 py-3 text-sm text-right text-gray-500"><%= pgbus_number(q[:total_messages]) %></td>
30
30
  <td class="px-4 py-3 text-sm text-right space-x-2">
31
31
  <% if q[:paused] %>
32
- <%= button_to "Resume", pgbus.resume_queue_path(name: q[:name]),
32
+ <%= button_to t("pgbus.queues.queues_list.resume"), pgbus.resume_queue_path(name: q[:name]),
33
33
  method: :post,
34
34
  class: "text-xs text-green-600 hover:text-green-800 font-medium",
35
35
  data: { turbo_frame: "_top" } %>
36
36
  <% else %>
37
- <%= button_to "Pause", pgbus.pause_queue_path(name: q[:name]),
37
+ <%= button_to t("pgbus.queues.queues_list.pause"), pgbus.pause_queue_path(name: q[:name]),
38
38
  method: :post,
39
39
  class: "text-xs text-yellow-600 hover:text-yellow-800 font-medium",
40
- data: { turbo_confirm: "Pause processing for #{q[:name]}?", turbo_frame: "_top" } %>
40
+ data: { turbo_confirm: t("pgbus.queues.queues_list.pause_confirm", name: q[:name]), turbo_frame: "_top" } %>
41
41
  <% end %>
42
- <%= button_to "Purge", pgbus.purge_queue_path(name: q[:name]),
42
+ <%= button_to t("pgbus.queues.queues_list.purge"), pgbus.purge_queue_path(name: q[:name]),
43
43
  method: :post,
44
44
  class: "text-xs text-red-600 hover:text-red-800 font-medium",
45
- data: { turbo_confirm: "Purge all messages from #{q[:name]}?", turbo_frame: "_top" } %>
45
+ data: { turbo_confirm: t("pgbus.queues.queues_list.purge_confirm", name: q[:name]), turbo_frame: "_top" } %>
46
46
  </td>
47
47
  </tr>
48
48
  <% end %>
49
49
  <% if @queues.empty? %>
50
- <tr><td colspan="7" class="px-4 py-8 text-center text-sm text-gray-400">No queues found</td></tr>
50
+ <tr><td colspan="7" class="px-4 py-8 text-center text-sm text-gray-400"><%= t("pgbus.queues.queues_list.empty") %></td></tr>
51
51
  <% end %>
52
52
  </tbody>
53
53
  </table>
@@ -1,3 +1,3 @@
1
- <h1 class="text-2xl font-bold text-gray-900 dark:text-white mb-6">Queues</h1>
1
+ <h1 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%= t("pgbus.queues.index.title") %></h1>
2
2
 
3
3
  <%= render "pgbus/queues/queues_list" %>
@@ -3,17 +3,17 @@
3
3
  <h1 class="text-2xl font-bold text-gray-900 dark:text-white"><%= @queue&.dig(:name) || params[:name] %></h1>
4
4
  <% if @queue %>
5
5
  <p class="text-sm text-gray-500 mt-1">
6
- Depth: <span class="font-mono"><%= @queue[:queue_length] %></span> |
7
- Visible: <span class="font-mono"><%= @queue[:queue_visible_length] %></span> |
8
- Total: <span class="font-mono"><%= pgbus_number(@queue[:total_messages]) %></span>
6
+ <%= t("pgbus.queues.show.depth") %> <span class="font-mono"><%= @queue[:queue_length] %></span> |
7
+ <%= t("pgbus.queues.show.visible") %> <span class="font-mono"><%= @queue[:queue_visible_length] %></span> |
8
+ <%= t("pgbus.queues.show.total") %> <span class="font-mono"><%= pgbus_number(@queue[:total_messages]) %></span>
9
9
  </p>
10
10
  <% end %>
11
11
  </div>
12
12
  <div class="flex space-x-2">
13
- <%= button_to "Purge Queue", pgbus.purge_queue_path(name: params[:name]),
13
+ <%= button_to t("pgbus.queues.show.purge_queue"), pgbus.purge_queue_path(name: params[:name]),
14
14
  method: :post,
15
15
  class: "rounded-md bg-red-600 px-3 py-2 text-sm font-medium text-white hover:bg-red-500",
16
- data: { turbo_confirm: "Purge all messages?" } %>
16
+ data: { turbo_confirm: t("pgbus.queues.show.purge_confirm") } %>
17
17
  </div>
18
18
  </div>
19
19
 
@@ -22,11 +22,11 @@
22
22
  <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
23
23
  <thead class="bg-gray-50 dark:bg-gray-900">
24
24
  <tr>
25
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">ID</th>
26
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">Enqueued</th>
27
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">Reads</th>
28
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">VT</th>
29
- <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500">Payload</th>
25
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.headers.id") %></th>
26
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.headers.enqueued") %></th>
27
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.headers.reads") %></th>
28
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.headers.vt") %></th>
29
+ <th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.headers.payload") %></th>
30
30
  </tr>
31
31
  </thead>
32
32
  <tbody class="divide-y divide-gray-100 dark:divide-gray-700">
@@ -42,7 +42,7 @@
42
42
  </tr>
43
43
  <% end %>
44
44
  <% if @messages.empty? %>
45
- <tr><td colspan="5" class="px-4 py-8 text-center text-sm text-gray-400">Queue is empty</td></tr>
45
+ <tr><td colspan="5" class="px-4 py-8 text-center text-sm text-gray-400"><%= t("pgbus.queues.show.empty") %></td></tr>
46
46
  <% end %>
47
47
  </tbody>
48
48
  </table>
@@ -2,20 +2,20 @@
2
2
  <div class="rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
3
3
  <% if @recurring_tasks.empty? %>
4
4
  <div class="p-8 text-center text-gray-500">
5
- <p class="text-lg font-medium">No recurring tasks configured</p>
6
- <p class="mt-1 text-sm">Add tasks to <code class="bg-gray-100 px-1.5 py-0.5 rounded text-xs">config/recurring.yml</code></p>
5
+ <p class="text-lg font-medium"><%= t("pgbus.recurring_tasks.tasks_table.empty_title") %></p>
6
+ <p class="mt-1 text-sm"><%= t("pgbus.recurring_tasks.tasks_table.empty_hint") %></p>
7
7
  </div>
8
8
  <% else %>
9
9
  <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
10
10
  <thead class="bg-gray-50 dark:bg-gray-900">
11
11
  <tr>
12
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Task</th>
13
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Schedule</th>
14
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Queue</th>
15
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Last Run</th>
16
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Next Run</th>
17
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Status</th>
18
- <th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase">Actions</th>
12
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase"><%= t("pgbus.recurring_tasks.tasks_table.headers.task") %></th>
13
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase"><%= t("pgbus.recurring_tasks.tasks_table.headers.schedule") %></th>
14
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase"><%= t("pgbus.recurring_tasks.tasks_table.headers.queue") %></th>
15
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase"><%= t("pgbus.recurring_tasks.tasks_table.headers.last_run") %></th>
16
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase"><%= t("pgbus.recurring_tasks.tasks_table.headers.next_run") %></th>
17
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase"><%= t("pgbus.recurring_tasks.tasks_table.headers.status") %></th>
18
+ <th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase"><%= t("pgbus.recurring_tasks.tasks_table.headers.actions") %></th>
19
19
  </tr>
20
20
  </thead>
21
21
  <tbody class="divide-y divide-gray-200 dark:divide-gray-700">
@@ -38,10 +38,10 @@
38
38
  <% end %>
39
39
  </td>
40
40
  <td class="px-4 py-3 text-sm text-gray-600">
41
- <%= task[:queue_name] || "default" %>
41
+ <%= task[:queue_name] || t("pgbus.recurring_tasks.tasks_table.default_queue") %>
42
42
  </td>
43
43
  <td class="px-4 py-3 text-sm text-gray-600">
44
- <%= task[:last_run_at] ? pgbus_time_ago(task[:last_run_at]) : "Never" %>
44
+ <%= task[:last_run_at] ? pgbus_time_ago(task[:last_run_at]) : t("pgbus.recurring_tasks.tasks_table.never") %>
45
45
  </td>
46
46
  <td class="px-4 py-3 text-sm text-gray-600">
47
47
  <% if task[:enabled] && task[:next_run_at] %>
@@ -55,17 +55,17 @@
55
55
  <%= pgbus_recurring_health_badge(task) %>
56
56
  <% else %>
57
57
  <span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600">
58
- Disabled
58
+ <%= t("pgbus.recurring_tasks.tasks_table.disabled") %>
59
59
  </span>
60
60
  <% end %>
61
61
  </td>
62
62
  <td class="px-4 py-3 text-right space-x-1">
63
- <%= button_to task[:enabled] ? "Disable" : "Enable",
63
+ <%= button_to task[:enabled] ? t("pgbus.recurring_tasks.tasks_table.disable") : t("pgbus.recurring_tasks.tasks_table.enable"),
64
64
  pgbus.toggle_recurring_task_path(task[:id]),
65
65
  class: "inline-flex items-center rounded px-2 py-1 text-xs font-medium " \
66
66
  "#{task[:enabled] ? 'bg-yellow-100 text-yellow-700 hover:bg-yellow-200' : 'bg-green-100 text-green-700 hover:bg-green-200'}" %>
67
67
  <% if task[:enabled] %>
68
- <%= button_to "Run Now",
68
+ <%= button_to t("pgbus.recurring_tasks.tasks_table.run_now"),
69
69
  pgbus.enqueue_recurring_task_path(task[:id]),
70
70
  class: "inline-flex items-center rounded bg-blue-100 px-2 py-1 text-xs font-medium text-blue-700 hover:bg-blue-200" %>
71
71
  <% end %>
@@ -1,6 +1,6 @@
1
1
  <div class="flex items-center justify-between mb-6">
2
- <h1 class="text-2xl font-bold text-gray-900 dark:text-white">Recurring Tasks</h1>
3
- <span class="text-sm text-gray-500"><%= @recurring_tasks.size %> task(s) configured</span>
2
+ <h1 class="text-2xl font-bold text-gray-900 dark:text-white"><%= t("pgbus.recurring_tasks.index.title") %></h1>
3
+ <span class="text-sm text-gray-500"><%= t("pgbus.recurring_tasks.index.task_count", count: @recurring_tasks.size) %></span>
4
4
  </div>
5
5
 
6
6
  <%= render "pgbus/recurring_tasks/tasks_table" %>
@@ -5,16 +5,16 @@
5
5
  <p class="mt-1 text-sm text-gray-500"><%= @task[:class_name] || @task[:command] %></p>
6
6
  </div>
7
7
  <div class="flex space-x-2">
8
- <%= button_to @task[:enabled] ? "Disable" : "Enable",
8
+ <%= button_to @task[:enabled] ? t("pgbus.recurring_tasks.show.disable") : t("pgbus.recurring_tasks.show.enable"),
9
9
  pgbus.toggle_recurring_task_path(@task[:id]),
10
10
  class: "inline-flex items-center rounded-md px-3 py-2 text-sm font-medium " \
11
11
  "#{@task[:enabled] ? 'bg-yellow-100 text-yellow-700 hover:bg-yellow-200' : 'bg-green-100 text-green-700 hover:bg-green-200'}" %>
12
12
  <% if @task[:enabled] %>
13
- <%= button_to "Run Now",
13
+ <%= button_to t("pgbus.recurring_tasks.show.run_now"),
14
14
  pgbus.enqueue_recurring_task_path(@task[:id]),
15
15
  class: "inline-flex items-center rounded-md bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700" %>
16
16
  <% end %>
17
- <%= link_to "Back", pgbus.recurring_tasks_path,
17
+ <%= link_to t("pgbus.recurring_tasks.show.back"), pgbus.recurring_tasks_path,
18
18
  class: "inline-flex items-center rounded-md bg-gray-100 px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-200" %>
19
19
  </div>
20
20
  </div>
@@ -22,7 +22,7 @@
22
22
 
23
23
  <div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
24
24
  <div class="rounded-lg bg-white dark:bg-gray-800 p-5 shadow ring-1 ring-gray-200 dark:ring-gray-700">
25
- <p class="text-sm font-medium text-gray-500">Schedule</p>
25
+ <p class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.schedule") %></p>
26
26
  <p class="mt-1 text-lg font-semibold text-gray-900 dark:text-white"><%= @task[:schedule] %></p>
27
27
  <% if @task[:human_schedule] && @task[:human_schedule] != @task[:schedule] %>
28
28
  <p class="text-xs text-gray-400"><%= @task[:human_schedule] %></p>
@@ -30,7 +30,7 @@
30
30
  </div>
31
31
 
32
32
  <div class="rounded-lg bg-white dark:bg-gray-800 p-5 shadow ring-1 ring-gray-200 dark:ring-gray-700">
33
- <p class="text-sm font-medium text-gray-500">Next Run</p>
33
+ <p class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.next_run") %></p>
34
34
  <% if @task[:enabled] && @task[:next_run_at] %>
35
35
  <p class="mt-1 text-lg font-semibold text-gray-900 dark:text-white"><%= pgbus_time_ago_future(@task[:next_run_at]) %></p>
36
36
  <p class="text-xs text-gray-400"><%= @task[:next_run_at]&.strftime("%Y-%m-%d %H:%M:%S %Z") %></p>
@@ -40,50 +40,50 @@
40
40
  </div>
41
41
 
42
42
  <div class="rounded-lg bg-white dark:bg-gray-800 p-5 shadow ring-1 ring-gray-200 dark:ring-gray-700">
43
- <p class="text-sm font-medium text-gray-500">Status</p>
44
- <p class="mt-1"><%= @task[:enabled] ? pgbus_recurring_health_badge(@task) : raw('<span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600">Disabled</span>') %></p>
43
+ <p class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.status") %></p>
44
+ <p class="mt-1"><%= @task[:enabled] ? pgbus_recurring_health_badge(@task) : content_tag(:span, t("pgbus.recurring_tasks.show.disabled"), class: "inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600") %></p>
45
45
  </div>
46
46
  </div>
47
47
 
48
48
  <div class="rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700 mb-8">
49
49
  <div class="px-4 py-3 border-b border-gray-200">
50
- <h2 class="text-lg font-medium text-gray-900 dark:text-white">Configuration</h2>
50
+ <h2 class="text-lg font-medium text-gray-900 dark:text-white"><%= t("pgbus.recurring_tasks.show.configuration") %></h2>
51
51
  </div>
52
52
  <div class="p-4">
53
53
  <dl class="grid grid-cols-1 sm:grid-cols-2 gap-4">
54
54
  <div>
55
- <dt class="text-sm font-medium text-gray-500">Job Class</dt>
55
+ <dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.job_class") %></dt>
56
56
  <dd class="mt-1 text-sm text-gray-900 dark:text-white"><%= @task[:class_name] || "—" %></dd>
57
57
  </div>
58
58
  <% if @task[:command] %>
59
59
  <div>
60
- <dt class="text-sm font-medium text-gray-500">Command</dt>
60
+ <dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.command") %></dt>
61
61
  <dd class="mt-1 text-sm text-gray-900 dark:text-white font-mono text-xs"><%= @task[:command] %></dd>
62
62
  </div>
63
63
  <% end %>
64
64
  <div>
65
- <dt class="text-sm font-medium text-gray-500">Queue</dt>
66
- <dd class="mt-1 text-sm text-gray-900 dark:text-white"><%= @task[:queue_name] || "default" %></dd>
65
+ <dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.queue") %></dt>
66
+ <dd class="mt-1 text-sm text-gray-900 dark:text-white"><%= @task[:queue_name] || t("pgbus.recurring_tasks.show.default_queue") %></dd>
67
67
  </div>
68
68
  <div>
69
- <dt class="text-sm font-medium text-gray-500">Priority</dt>
69
+ <dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.priority") %></dt>
70
70
  <dd class="mt-1 text-sm text-gray-900 dark:text-white"><%= @task[:priority] %></dd>
71
71
  </div>
72
72
  <% if @task[:arguments]&.any? %>
73
73
  <div class="sm:col-span-2">
74
- <dt class="text-sm font-medium text-gray-500">Arguments</dt>
74
+ <dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.arguments") %></dt>
75
75
  <dd class="mt-1 text-sm text-gray-900 dark:text-white font-mono text-xs"><%= @task[:arguments].inspect %></dd>
76
76
  </div>
77
77
  <% end %>
78
78
  <% if @task[:description] %>
79
79
  <div class="sm:col-span-2">
80
- <dt class="text-sm font-medium text-gray-500">Description</dt>
80
+ <dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.description") %></dt>
81
81
  <dd class="mt-1 text-sm text-gray-900 dark:text-white"><%= @task[:description] %></dd>
82
82
  </div>
83
83
  <% end %>
84
84
  <div>
85
- <dt class="text-sm font-medium text-gray-500">Source</dt>
86
- <dd class="mt-1 text-sm text-gray-900 dark:text-white"><%= @task[:static] ? "Config file" : "Dynamic" %></dd>
85
+ <dt class="text-sm font-medium text-gray-500"><%= t("pgbus.recurring_tasks.show.labels.source") %></dt>
86
+ <dd class="mt-1 text-sm text-gray-900 dark:text-white"><%= @task[:static] ? t("pgbus.recurring_tasks.show.source_config") : t("pgbus.recurring_tasks.show.source_dynamic") %></dd>
87
87
  </div>
88
88
  </dl>
89
89
  </div>
@@ -91,14 +91,14 @@
91
91
 
92
92
  <div class="rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
93
93
  <div class="px-4 py-3 border-b border-gray-200">
94
- <h2 class="text-lg font-medium text-gray-900 dark:text-white">Recent Executions</h2>
94
+ <h2 class="text-lg font-medium text-gray-900 dark:text-white"><%= t("pgbus.recurring_tasks.show.recent_executions") %></h2>
95
95
  </div>
96
96
  <% if @task[:executions]&.any? %>
97
97
  <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
98
98
  <thead class="bg-gray-50 dark:bg-gray-900">
99
99
  <tr>
100
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Scheduled For</th>
101
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Enqueued At</th>
100
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase"><%= t("pgbus.recurring_tasks.show.execution_headers.scheduled_for") %></th>
101
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase"><%= t("pgbus.recurring_tasks.show.execution_headers.enqueued_at") %></th>
102
102
  </tr>
103
103
  </thead>
104
104
  <tbody class="divide-y divide-gray-200 dark:divide-gray-700">
@@ -116,7 +116,7 @@
116
116
  </table>
117
117
  <% else %>
118
118
  <div class="p-8 text-center text-gray-500">
119
- <p>No executions recorded yet</p>
119
+ <p><%= t("pgbus.recurring_tasks.show.no_executions") %></p>
120
120
  </div>
121
121
  <% end %>
122
122
  </div>
@@ -0,0 +1,41 @@
1
+ ---
2
+ # i18n-tasks configuration for Pgbus engine
3
+ # https://github.com/glebm/i18n-tasks
4
+
5
+ base_locale: en
6
+ locales: [en, da, de, es, fi, fr, it, ja, nb, nl, pt, sv]
7
+
8
+ data:
9
+ router: pattern_router
10
+ read:
11
+ - config/locales/%{locale}.yml
12
+ - config/locales/**/*.%{locale}.yml
13
+ write:
14
+ - config/locales/%{locale}.yml
15
+ yaml:
16
+ write:
17
+ line_width: -1
18
+
19
+ search:
20
+ paths:
21
+ - app/
22
+ exclude:
23
+ - "*.md"
24
+ - app/assets/images
25
+ strict: false
26
+
27
+ translation:
28
+ backend: openai
29
+ openai_api_key: <%= ENV["OPENAI_API_KEY"] %>
30
+ openai_model: gpt-4.1-mini
31
+
32
+ ignore_missing:
33
+ - "activerecord.*"
34
+
35
+ ignore_unused:
36
+ - "pgbus.helpers.*"
37
+ - "pgbus.insights.show.time_ranges.*"
38
+ - "pgbus.insights.show.charts.series_name"
39
+ - "pgbus.insights.show.charts.failed_to_load"
40
+ - "pgbus.insights.show.charts.no_data"
41
+ - "pgbus.recurring_tasks.index.task_count.*"