dayhand 0.0.0-stage → 0.14.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 (191) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +100 -2
  3. package/backend/convex/_generated/api.d.ts +181 -0
  4. package/backend/convex/_generated/api.js +23 -0
  5. package/backend/convex/_generated/dataModel.d.ts +60 -0
  6. package/backend/convex/_generated/server.d.ts +162 -0
  7. package/backend/convex/_generated/server.js +101 -0
  8. package/backend/convex/apiKeys.ts +171 -0
  9. package/backend/convex/app.ts +197 -0
  10. package/backend/convex/auth.config.ts +28 -0
  11. package/backend/convex/calendar.ts +61 -0
  12. package/backend/convex/calendarFeeds.ts +105 -0
  13. package/backend/convex/callLimits.ts +67 -0
  14. package/backend/convex/connections.ts +28 -0
  15. package/backend/convex/crons.ts +18 -0
  16. package/backend/convex/devices.ts +224 -0
  17. package/backend/convex/http.ts +56 -0
  18. package/backend/convex/lib/activity.ts +155 -0
  19. package/backend/convex/lib/agentControls.ts +146 -0
  20. package/backend/convex/lib/agentWork.ts +250 -0
  21. package/backend/convex/lib/appToken.ts +68 -0
  22. package/backend/convex/lib/approvals.ts +311 -0
  23. package/backend/convex/lib/args.ts +175 -0
  24. package/backend/convex/lib/backlogMd.ts +309 -0
  25. package/backend/convex/lib/backlogOps.ts +361 -0
  26. package/backend/convex/lib/brief.ts +132 -0
  27. package/backend/convex/lib/cimd.ts +57 -0
  28. package/backend/convex/lib/core.ts +380 -0
  29. package/backend/convex/lib/dates.ts +114 -0
  30. package/backend/convex/lib/env.ts +19 -0
  31. package/backend/convex/lib/exportPlan.ts +98 -0
  32. package/backend/convex/lib/findTasks.ts +119 -0
  33. package/backend/convex/lib/frontmatter.ts +165 -0
  34. package/backend/convex/lib/guide.ts +286 -0
  35. package/backend/convex/lib/health.ts +115 -0
  36. package/backend/convex/lib/http.ts +27 -0
  37. package/backend/convex/lib/ical.ts +243 -0
  38. package/backend/convex/lib/importFormats.ts +429 -0
  39. package/backend/convex/lib/importOps.ts +145 -0
  40. package/backend/convex/lib/jsonSchema.ts +50 -0
  41. package/backend/convex/lib/limits.ts +42 -0
  42. package/backend/convex/lib/mcpContent.ts +220 -0
  43. package/backend/convex/lib/mcpProtocol.ts +128 -0
  44. package/backend/convex/lib/mcpTools.ts +505 -0
  45. package/backend/convex/lib/oauthConfig.ts +59 -0
  46. package/backend/convex/lib/oauthPage.ts +125 -0
  47. package/backend/convex/lib/oauthRules.ts +159 -0
  48. package/backend/convex/lib/openapi.ts +230 -0
  49. package/backend/convex/lib/outputSchemas.ts +2901 -0
  50. package/backend/convex/lib/problem.ts +69 -0
  51. package/backend/convex/lib/proposals.ts +172 -0
  52. package/backend/convex/lib/repeat.ts +185 -0
  53. package/backend/convex/lib/restRoutes.ts +294 -0
  54. package/backend/convex/lib/rrule.ts +171 -0
  55. package/backend/convex/lib/secrets.ts +135 -0
  56. package/backend/convex/lib/settingsOps.ts +47 -0
  57. package/backend/convex/lib/taskOps.ts +304 -0
  58. package/backend/convex/lib/toolResults.ts +50 -0
  59. package/backend/convex/lib/validators.ts +143 -0
  60. package/backend/convex/lib/views.ts +145 -0
  61. package/backend/convex/lib/vtimezone.ts +151 -0
  62. package/backend/convex/lib/webhookEvents.ts +160 -0
  63. package/backend/convex/lib/webhookSign.ts +30 -0
  64. package/backend/convex/lib/webhookTarget.ts +75 -0
  65. package/backend/convex/mcp.ts +405 -0
  66. package/backend/convex/migrations.ts +91 -0
  67. package/backend/convex/oauth.ts +388 -0
  68. package/backend/convex/oauthHttp.ts +381 -0
  69. package/backend/convex/oauthOwner.ts +173 -0
  70. package/backend/convex/ops.ts +205 -0
  71. package/backend/convex/pairing.ts +178 -0
  72. package/backend/convex/rest.ts +254 -0
  73. package/backend/convex/restAccount.ts +56 -0
  74. package/backend/convex/restImport.ts +73 -0
  75. package/backend/convex/schema.ts +435 -0
  76. package/backend/convex/tsconfig.json +18 -0
  77. package/backend/convex/webhooks.ts +339 -0
  78. package/backend/package-lock.json +3068 -0
  79. package/backend/package.json +33 -0
  80. package/backend/scripts/app-token.mjs +79 -0
  81. package/backend/scripts/fetch-local-backend.mjs +72 -0
  82. package/backend/scripts/gen-output-schemas.mjs +60 -0
  83. package/backend/scripts/jwt.mjs +67 -0
  84. package/backend/scripts/local-backend-lib.mjs +123 -0
  85. package/backend/scripts/local-backend.mjs +81 -0
  86. package/backend/scripts/setup-convex.mjs +158 -0
  87. package/backend/scripts/setup-lib.mjs +338 -0
  88. package/backend/scripts/setup-output.mjs +108 -0
  89. package/backend/scripts/setup.mjs +344 -0
  90. package/backend/scripts/signing-key.mjs +61 -0
  91. package/backend/tsconfig.json +16 -0
  92. package/dist/backlog/folder.js +114 -0
  93. package/dist/bin/dayhand.js +10 -0
  94. package/dist/bin/hlm.js +12 -0
  95. package/dist/completion/cache.js +54 -0
  96. package/dist/completion/engine.js +187 -0
  97. package/dist/completion/scripts.js +82 -0
  98. package/dist/config/aliases.js +25 -0
  99. package/dist/config/env.js +68 -0
  100. package/dist/config/file.js +146 -0
  101. package/dist/config/paths.js +58 -0
  102. package/dist/config/resolve.js +53 -0
  103. package/dist/config/url.js +26 -0
  104. package/dist/core/editor.js +37 -0
  105. package/dist/core/exit.js +59 -0
  106. package/dist/core/io.js +14 -0
  107. package/dist/core/output.js +39 -0
  108. package/dist/core/prompt.js +55 -0
  109. package/dist/core/version.js +15 -0
  110. package/dist/core/words.js +36 -0
  111. package/dist/credentials/file.js +65 -0
  112. package/dist/credentials/index.js +29 -0
  113. package/dist/credentials/keychain.js +44 -0
  114. package/dist/credentials/store.js +39 -0
  115. package/dist/docs.js +116 -0
  116. package/dist/fields.js +33 -0
  117. package/dist/globals.js +16 -0
  118. package/dist/guide.js +36 -0
  119. package/dist/help.js +56 -0
  120. package/dist/i18n/dates.js +84 -0
  121. package/dist/i18n/de.js +240 -0
  122. package/dist/i18n/en.js +243 -0
  123. package/dist/i18n/es.js +240 -0
  124. package/dist/i18n/fr.js +240 -0
  125. package/dist/i18n/index.js +67 -0
  126. package/dist/i18n/ja.js +240 -0
  127. package/dist/i18n/pl.js +245 -0
  128. package/dist/i18n/pt-BR.js +240 -0
  129. package/dist/i18n/zh-Hans.js +240 -0
  130. package/dist/main.js +180 -0
  131. package/dist/man.js +56 -0
  132. package/dist/registry/agents.js +67 -0
  133. package/dist/registry/auth.js +168 -0
  134. package/dist/registry/backlog.js +106 -0
  135. package/dist/registry/calendar.js +103 -0
  136. package/dist/registry/dates.js +33 -0
  137. package/dist/registry/filters.js +98 -0
  138. package/dist/registry/index.js +24 -0
  139. package/dist/registry/integrations.js +245 -0
  140. package/dist/registry/local.js +89 -0
  141. package/dist/registry/model.js +104 -0
  142. package/dist/registry/ops.js +47 -0
  143. package/dist/registry/owner.js +349 -0
  144. package/dist/registry/packaged-backend.js +59 -0
  145. package/dist/registry/parse.js +129 -0
  146. package/dist/registry/server.js +252 -0
  147. package/dist/registry/system.js +220 -0
  148. package/dist/registry/tasks.js +512 -0
  149. package/dist/registry/types.js +1 -0
  150. package/dist/registry/ui.js +51 -0
  151. package/dist/registry/work.js +207 -0
  152. package/dist/render/format.js +146 -0
  153. package/dist/render/model.js +29 -0
  154. package/dist/render/style.js +24 -0
  155. package/dist/render/table.js +46 -0
  156. package/dist/render/views.js +256 -0
  157. package/dist/run.js +133 -0
  158. package/dist/setup.js +26 -0
  159. package/dist/skill.js +83 -0
  160. package/dist/topics.js +121 -0
  161. package/dist/transport/client.js +196 -0
  162. package/dist/ui/agents.js +12 -0
  163. package/dist/ui/api.js +99 -0
  164. package/dist/ui/app.js +62 -0
  165. package/dist/ui/budget.js +42 -0
  166. package/dist/ui/controller.js +368 -0
  167. package/dist/ui/effects.js +166 -0
  168. package/dist/ui/frame.js +206 -0
  169. package/dist/ui/handle.js +271 -0
  170. package/dist/ui/health.js +22 -0
  171. package/dist/ui/keys.js +120 -0
  172. package/dist/ui/line.js +56 -0
  173. package/dist/ui/lists.js +58 -0
  174. package/dist/ui/model.js +25 -0
  175. package/dist/ui/quickadd.js +66 -0
  176. package/dist/ui/rows.js +68 -0
  177. package/dist/ui/run.js +54 -0
  178. package/dist/ui/screens/agents.js +65 -0
  179. package/dist/ui/screens/board.js +41 -0
  180. package/dist/ui/screens/detail.js +142 -0
  181. package/dist/ui/screens/overlay.js +58 -0
  182. package/dist/ui/screens/screen.js +3 -0
  183. package/dist/ui/screens/today.js +60 -0
  184. package/dist/ui/screens/week.js +76 -0
  185. package/dist/ui/state.js +128 -0
  186. package/dist/ui/text.js +70 -0
  187. package/dist/when/calendar.js +95 -0
  188. package/dist/when/parse.js +314 -0
  189. package/man/dayhand.1 +1163 -0
  190. package/man/dh.1 +1 -0
  191. package/package.json +56 -4
@@ -0,0 +1,240 @@
1
+ export const es = {
2
+ "view.today": "Hoy",
3
+ "view.board": "Tablero",
4
+ "view.week": "Semana",
5
+ "view.trash": "Papelera",
6
+ "view.agents": "Agentes",
7
+ "section.pause": "PAUSA",
8
+ "section.approvals": "SOLICITUDES DE APROBACIÓN",
9
+ "section.proposals": "PROPUESTAS",
10
+ "agents.paused": "Agentes en pausa · p reanuda",
11
+ "agents.running": "Los agentes pueden hacer cambios · p pausa",
12
+ "agents.noApprovals": "(sin solicitudes de aprobación pendientes)",
13
+ "agents.noProposals": "(sin propuestas)",
14
+ "agents.requestTitle": "Solicitud de aprobación",
15
+ "agents.requestedBy": "Solicitada por {name}",
16
+ "agents.expires": "Decidir antes de {time}",
17
+ "agents.reversible": "Se puede deshacer",
18
+ "agents.irreversible": "No se puede deshacer",
19
+ "health.paused": "Agentes en pausa",
20
+ "health.overdue": "Atrasadas: {count}",
21
+ "health.blocked": "Bloqueadas: {count}",
22
+ "health.expiredClaims": "Asignaciones vencidas: {count}",
23
+ "health.approvals": "Solicitudes de aprobación pendientes: {count}",
24
+ "health.proposals": "Propuestas en la bandeja: {count}",
25
+ "health.withoutProof": "Hechas sin evidencia: {count}",
26
+ "health.dueToday": "Vencen hoy: {count}",
27
+ "health.inProgress": "En curso: {count}",
28
+ "health.completedToday": "Hechas hoy: {count}",
29
+ "prompt.reject": "Motivo del rechazo",
30
+ "prompt.reasonRequired": "Se requiere un motivo",
31
+ "confirm.approval": "¿Guardar la decisión? Enter confirma · Esc vuelve",
32
+ "hints.approval": "1–4 elige una opción · j/k desplaza · Esc vuelve",
33
+ "hints.approvalConfirm": "Enter confirma · Esc cambia la elección · j/k desplaza",
34
+ "hints.agents": "p pausa Enter opciones/detalles A aceptar X rechazar / filtrar ? ayuda q salir",
35
+ "hints.proposal": "A aceptar X rechazar con motivo j/k desplazar Esc volver ? ayuda",
36
+ "detail.claimedBy": "asignada a",
37
+ "detail.criteria": "criterios",
38
+ "detail.plan": "plan de trabajo",
39
+ "detail.proof": "evidencia",
40
+ "detail.dependsOn": "espera a",
41
+ "detail.blocked": "bloqueada",
42
+ "detail.claimUntil": "hasta {time}",
43
+ "detail.claimExpired": "asignación vencida",
44
+ "proof.pass": "superada",
45
+ "proof.fail": "fallida",
46
+ "done.agentsPaused": "Agentes pausados",
47
+ "done.agentsResumed": "Agentes reanudados",
48
+ "done.decided": "Decisión guardada: {label}",
49
+ "done.accepted": "Aceptada: {task}",
50
+ "done.rejected": "Rechazada: {task}",
51
+ "flash.proposal": "A acepta la propuesta; X la rechaza con un motivo",
52
+ "keys.agents": "Agentes",
53
+ "keys.agents.pause": "Agentes: pausar / reanudar cambios",
54
+ "keys.agents.open": "Agentes: abrir opciones de solicitud o detalles de propuesta",
55
+ "keys.agents.choose": "Solicitud: elegir una opción (aún sin guardar)",
56
+ "keys.agents.confirm": "Solicitud: confirmar la opción elegida / volver",
57
+ "keys.agents.accept": "Aceptar la propuesta seleccionada en el plan",
58
+ "keys.agents.reject": "Rechazar la propuesta seleccionada con un motivo obligatorio",
59
+ "section.now": "AHORA",
60
+ "section.overdue": "ATRASADAS",
61
+ "section.today": "HOY",
62
+ "section.doneToday": "HECHAS HOY",
63
+ "section.noMatch": "sin coincidencias",
64
+ "section.nothingPlanned": "nada previsto",
65
+ "column.todo": "POR HACER",
66
+ "column.doing": "EN CURSO",
67
+ "column.done": "HECHAS",
68
+ "column.empty": "(vacío)",
69
+ "status.todo": "por hacer",
70
+ "status.doing": "en curso",
71
+ "status.done": "hecha",
72
+ "day.today": "hoy",
73
+ "day.tomorrow": "mañana",
74
+ "day.yesterday": "ayer",
75
+ "day.none": "sin día",
76
+ "conn.saving": "● guardando… ",
77
+ "conn.connecting": "○ conectando ",
78
+ "conn.waiting": "● esperando ",
79
+ "conn.offline": "● sin conexión ",
80
+ "conn.rejected": "● clave rechazada ",
81
+ "conn.since": " · datos de las {time}",
82
+ "conn.login": "Ejecuta dayhand login en otra terminal y luego pulsa R.",
83
+ "conn.retrying": "Reintentando cada {seconds} s; R reintenta ahora, q sale.",
84
+ "conn.loading": "Cargando…",
85
+ "conn.notYet": "Aún sin conexión; inténtalo en un momento",
86
+ "conn.throttled": "Esperando {seconds} s para no superar los límites del servidor",
87
+ "heading.filter": "filtro: {filter}",
88
+ "heading.filterClears": " (Esc lo borra)",
89
+ "heading.details": "Detalles de la tarea · Esc vuelve",
90
+ "heading.today": "Hoy, {date} · {timezone}",
91
+ "heading.board": "Tablero · {todo} por hacer · {doing} en curso · {done} hechas (recientes)",
92
+ "heading.week": "Semana del {from} al {to}",
93
+ "heading.trash": { one: "Papelera · {count} tarea · se borran 30 días después de eliminarlas", other: "Papelera · {count} tareas · se borran 30 días después de eliminarlas" },
94
+ "prompt.add": "Añadir",
95
+ "prompt.move": "Mover a",
96
+ "prompt.note": "Dónde lo dejé",
97
+ "prompt.filter": "Filtro",
98
+ "prompt.makeNow": "Enter: trabajar en ella ahora",
99
+ "prompt.notADate": "aún no es una fecha",
100
+ "prompt.addExample": "p. ej. Llamar al contable fri 2pm #casa",
101
+ "prompt.doing": " · en curso",
102
+ "confirm.trash": " ¿Mover {ref} {title} a la papelera? ",
103
+ "hints.help": "cualquier tecla cierra · j/k desplaza",
104
+ "hints.typing": "Enter guarda · Esc cancela",
105
+ "hints.nextField": " · Tab campo siguiente",
106
+ "hints.confirm": "y la mueve a la papelera · otra tecla la conserva",
107
+ "hints.detail": "Esc volver j/k desplazar ␣ hecha s empezar n ahora e editar E editor m mover d papelera ? ayuda",
108
+ "hints.board": "? ayuda h/l columna H/L mover a añadir ␣ hecha e editar d papelera / filtro Tab vistas q salir",
109
+ "hints.week": "? ayuda h/l día H/L un día [ ] semanas t hoy a añadir ␣ hecha Enter abrir q salir",
110
+ "hints.trash": "? ayuda r restaurar Enter abrir / filtro Tab vistas q salir",
111
+ "hints.today": "? ayuda a añadir ␣ hecha s empezar n ahora e editar m mover d papelera / filtro Tab vistas q salir",
112
+ "small.title": "Terminal demasiado pequeña",
113
+ "small.size": "ahora {columns}×{rows}, necesita {minColumns}×{minRows}",
114
+ "small.quit": "q sale",
115
+ "detail.loading": "Cargando la tarea…",
116
+ "detail.status": "estado",
117
+ "detail.due": "vence",
118
+ "detail.repeat": "repite",
119
+ "detail.remind": "recuerda",
120
+ "detail.labels": "etiquetas",
121
+ "detail.links": "enlaces",
122
+ "detail.next": "sigue",
123
+ "detail.deleted": "eliminada",
124
+ "detail.archived": "archivada",
125
+ "detail.changed": "cambiada",
126
+ "detail.addedBy": "añadida",
127
+ "detail.now": " (ahora)",
128
+ "detail.overdue": ", atrasada",
129
+ "detail.none": "ninguno",
130
+ "detail.checklist": "lista {done}/{total}",
131
+ "detail.note": "nota",
132
+ "detail.history": "historial ({count}, recientes primero)",
133
+ "action.create": "añadida",
134
+ "action.update": "cambiada",
135
+ "action.complete": "hecha",
136
+ "action.repeat": "siguiente repetición",
137
+ "action.setStatus": "estado",
138
+ "action.setNow": "ahora",
139
+ "action.archive": "archivada",
140
+ "action.delete": "a la papelera",
141
+ "action.restore": "restaurada",
142
+ "today.next": "sigue: ",
143
+ "trash.empty": "(la papelera está vacía)",
144
+ "trash.deleted": "eliminada {time}",
145
+ "week.today": " · hoy",
146
+ "week.tasks": { one: " · {count} tarea", other: " · {count} tareas" },
147
+ "week.empty": "(nada este día; a añade una tarea aquí)",
148
+ "help.title": "Teclas",
149
+ "help.closes": " (otra tecla cierra; j/k desplaza)",
150
+ "edit.title": "Editar: ",
151
+ "edit.hintDue": "Vence: una expresión en inglés como fri 2pm, vacío para sin día · Etiquetas: casa, trabajo",
152
+ "edit.hintNote": "La nota: Esc y luego E abre $VISUAL / $EDITOR",
153
+ "field.title": "Título",
154
+ "field.due": "Vence",
155
+ "field.labels": "Etiquetas",
156
+ "field.resumeNote": "Dónde lo dejé",
157
+ "keys.move": "Moverse",
158
+ "keys.move.next": "Tarea siguiente / anterior",
159
+ "keys.move.column": "Columna del tablero, día de la semana",
160
+ "keys.move.ends": "Primera / última tarea",
161
+ "keys.move.page": "Media página abajo / arriba",
162
+ "keys.move.open": "Abrir una tarea (un día vacío: añadir)",
163
+ "keys.move.back": "Volver; borra el filtro",
164
+ "keys.views": "Vistas",
165
+ "keys.views.next": "Vista siguiente / anterior",
166
+ "keys.views.pick": "Hoy, Tablero, Semana, Papelera, Agentes",
167
+ "keys.views.filter": "Filtro: título, #etiqueta, nota, #42",
168
+ "keys.views.refresh": "Actualizar ahora (también cada 12 s)",
169
+ "keys.views.help": "Esta ayuda",
170
+ "keys.views.quit": "Salir (q en detalles: volver)",
171
+ "keys.tasks": "Tareas",
172
+ "keys.tasks.add": "Añadir: Pagar el alquiler fri 2pm #casa",
173
+ "keys.tasks.done": "Hecha / no hecha (las repeticiones siguen)",
174
+ "keys.tasks.start": "Empezar (en curso) / parar (por hacer)",
175
+ "keys.tasks.now": "Tarea de ahora, con nota de dónde lo dejé",
176
+ "keys.tasks.clearNow": "Quitar la tarea de ahora",
177
+ "keys.tasks.edit": "Editar título, vencimiento, etiquetas, nota",
178
+ "keys.tasks.editor": "Título y nota en $EDITOR",
179
+ "keys.tasks.move": "Mover: tomorrow, fri 9am, none",
180
+ "keys.tasks.trash": "A la papelera (pregunta); u deshace",
181
+ "keys.tasks.restore": "Restaurar (en la papelera)",
182
+ "keys.boardWeek": "Tablero y semana",
183
+ "keys.boardWeek.column": "Tablero: columna izquierda / derecha",
184
+ "keys.boardWeek.day": "Semana: un día antes / después",
185
+ "keys.boardWeek.weeks": "Semana: anterior / siguiente",
186
+ "keys.boardWeek.thisWeek": "Semana: esta semana",
187
+ "keys.typing": "Escribir",
188
+ "keys.typing.save": "Guardar / cancelar",
189
+ "keys.typing.field": "Campo siguiente / anterior (editar)",
190
+ "keys.typing.cursor": "Mover el cursor; inicio / fin",
191
+ "keys.typing.delete": "Borrar hasta el inicio / el fin / una palabra",
192
+ "done.added": "Añadida {task} · {when}",
193
+ "done.done": "Hecha: {task}",
194
+ "done.next": " · siguiente: {when}",
195
+ "done.notDone": "No hecha: {task}",
196
+ "done.started": "Empezada: {task}",
197
+ "done.stopped": "Parada: {task}",
198
+ "done.status": "{task} → {status}",
199
+ "done.nowCleared": "Tarea de ahora quitada",
200
+ "done.moved": "{task} movida a {when}",
201
+ "done.trashed": "{task} movida a la papelera · u deshace",
202
+ "done.restored": "Restaurada {task}",
203
+ "done.now": "Ahora: {task}",
204
+ "done.nowNext": " · sigue: {note}",
205
+ "done.saved": "Guardada {task}",
206
+ "done.noChanges": "Sin cambios",
207
+ "error.titleOnlyDate": "Una tarea necesita un título, no solo una fecha",
208
+ "error.notADate": "No es una fecha: escríbela en inglés, p. ej. tomorrow, fri 14:00, next mon, 23 oct o none",
209
+ "error.emptyTitle": "El título no puede estar vacío",
210
+ "error.due": "Vence: {message}",
211
+ "error.editorEmpty": "La primera línea (el título) está vacía; no se cambió nada",
212
+ "error.noEditor": "Aquí no hay editor",
213
+ "error.notSaved": "No guardado: {message}",
214
+ "flash.noTask": "Ninguna tarea seleccionada",
215
+ "flash.inTrash": "En la papelera: r la restaura",
216
+ "flash.restoreWhere": "r restaura una tarea de la papelera (4)",
217
+ "flash.nothingToUndo": "Nada que deshacer",
218
+ "flash.noDay": "La tarea no tiene día",
219
+ "flash.shiftWhere": "H y L funcionan en el tablero y en la semana",
220
+ "flash.kept": "Conservada",
221
+ "flash.editCancelled": "Edición cancelada",
222
+ "repeat.day": { one: "cada día", other: "cada {count} días" },
223
+ "repeat.week": { one: "cada semana", other: "cada {count} semanas" },
224
+ "repeat.month": { one: "cada mes", other: "cada {count} meses" },
225
+ "repeat.year": { one: "cada año", other: "cada {count} años" },
226
+ "repeat.on": "los {days}",
227
+ "repeat.lastDay": "el último día",
228
+ "repeat.monthDay": "el día {day}",
229
+ "repeat.nthWeekday": "el {weekday} n.º {nth}",
230
+ "repeat.lastWeekday": "el último {weekday}",
231
+ "repeat.fromEnd": "el {weekday} n.º {nth} desde el final",
232
+ "repeat.fromCompletion": "desde que se completa",
233
+ "repeat.until": "hasta el {date}",
234
+ "repeat.times": { one: "última vez", other: "{count} veces" },
235
+ "remind.atDue": "a la hora de vencimiento",
236
+ "remind.days": { one: "{count} día antes", other: "{count} días antes" },
237
+ "remind.hours": "{count} h antes",
238
+ "remind.minutes": "{count} min antes",
239
+ "remind.timeDaysBefore": "{time}, {days}",
240
+ };
@@ -0,0 +1,240 @@
1
+ export const fr = {
2
+ "view.today": "Aujourd’hui",
3
+ "view.board": "Tableau",
4
+ "view.week": "Semaine",
5
+ "view.trash": "Corbeille",
6
+ "view.agents": "Agents",
7
+ "section.pause": "EN PAUSE",
8
+ "section.approvals": "DEMANDES D’ACCORD",
9
+ "section.proposals": "PROPOSITIONS",
10
+ "agents.paused": "Les agents sont en pause · p reprend",
11
+ "agents.running": "Les agents peuvent modifier le plan · p suspend",
12
+ "agents.noApprovals": "(aucune demande d’accord en attente)",
13
+ "agents.noProposals": "(aucune proposition)",
14
+ "agents.requestTitle": "Demande d’accord",
15
+ "agents.requestedBy": "Demandé par {name}",
16
+ "agents.expires": "Décider avant {time}",
17
+ "agents.reversible": "Peut être annulé",
18
+ "agents.irreversible": "Ne peut pas être annulé",
19
+ "health.paused": "Les agents sont en pause",
20
+ "health.overdue": "En retard : {count}",
21
+ "health.blocked": "Bloquées : {count}",
22
+ "health.expiredClaims": "Prises en charge expirées : {count}",
23
+ "health.approvals": "Demandes d’accord en attente : {count}",
24
+ "health.proposals": "Propositions reçues : {count}",
25
+ "health.withoutProof": "Terminées sans preuve : {count}",
26
+ "health.dueToday": "À faire aujourd’hui : {count}",
27
+ "health.inProgress": "En cours : {count}",
28
+ "health.completedToday": "Terminées aujourd’hui : {count}",
29
+ "prompt.reject": "Motif du refus",
30
+ "prompt.reasonRequired": "Un motif est obligatoire",
31
+ "confirm.approval": "Enregistrer la décision ? Enter confirme · Esc revient",
32
+ "hints.approval": "1–4 choisit une option · j/k défile · Esc revient",
33
+ "hints.approvalConfirm": "Enter confirme · Esc change le choix · j/k défile",
34
+ "hints.agents": "p pause Enter options/détails A accepter X refuser / filtrer ? aide q quitter",
35
+ "hints.proposal": "A accepter X refuser avec un motif j/k défiler Esc retour ? aide",
36
+ "detail.claimedBy": "pris en charge par",
37
+ "detail.criteria": "critères",
38
+ "detail.plan": "plan de travail",
39
+ "detail.proof": "preuve",
40
+ "detail.dependsOn": "attend",
41
+ "detail.blocked": "bloqué",
42
+ "detail.claimUntil": "jusqu’à {time}",
43
+ "detail.claimExpired": "prise en charge expirée",
44
+ "proof.pass": "réussi",
45
+ "proof.fail": "échoué",
46
+ "done.agentsPaused": "Agents suspendus",
47
+ "done.agentsResumed": "Agents repris",
48
+ "done.decided": "Décision enregistrée : {label}",
49
+ "done.accepted": "Acceptée : {task}",
50
+ "done.rejected": "Refusée : {task}",
51
+ "flash.proposal": "A accepte la proposition ; X la refuse avec un motif",
52
+ "keys.agents": "Agents",
53
+ "keys.agents.pause": "Agents : suspendre / reprendre les modifications",
54
+ "keys.agents.open": "Agents : ouvrir les options de demande ou les détails de proposition",
55
+ "keys.agents.choose": "Demande : choisir une option (pas encore enregistrée)",
56
+ "keys.agents.confirm": "Demande : confirmer l’option choisie / revenir",
57
+ "keys.agents.accept": "Accepter la proposition sélectionnée dans le plan",
58
+ "keys.agents.reject": "Refuser la proposition sélectionnée avec un motif obligatoire",
59
+ "section.now": "MAINTENANT",
60
+ "section.overdue": "EN RETARD",
61
+ "section.today": "AUJOURD’HUI",
62
+ "section.doneToday": "TERMINÉES AUJOURD’HUI",
63
+ "section.noMatch": "aucun résultat",
64
+ "section.nothingPlanned": "rien de prévu",
65
+ "column.todo": "À FAIRE",
66
+ "column.doing": "EN COURS",
67
+ "column.done": "TERMINÉES",
68
+ "column.empty": "(vide)",
69
+ "status.todo": "à faire",
70
+ "status.doing": "en cours",
71
+ "status.done": "terminée",
72
+ "day.today": "aujourd’hui",
73
+ "day.tomorrow": "demain",
74
+ "day.yesterday": "hier",
75
+ "day.none": "aucun jour",
76
+ "conn.saving": "● enregistrement… ",
77
+ "conn.connecting": "○ connexion ",
78
+ "conn.waiting": "● en attente ",
79
+ "conn.offline": "● hors ligne ",
80
+ "conn.rejected": "● clé refusée ",
81
+ "conn.since": " · données de {time}",
82
+ "conn.login": "Lancez dayhand login dans un autre terminal, puis appuyez sur R.",
83
+ "conn.retrying": "Nouvel essai toutes les {seconds} s ; R réessaie, q quitte.",
84
+ "conn.loading": "Chargement…",
85
+ "conn.notYet": "Pas encore connecté ; réessayez dans un instant",
86
+ "conn.throttled": "Attente de {seconds} s pour rester sous les limites du serveur",
87
+ "heading.filter": "filtre : {filter}",
88
+ "heading.filterClears": " (Échap l’efface)",
89
+ "heading.details": "Détails de la tâche · Échap retour",
90
+ "heading.today": "Aujourd’hui, {date} · {timezone}",
91
+ "heading.board": "Tableau · {todo} à faire · {doing} en cours · {done} terminées (récentes)",
92
+ "heading.week": "Semaine du {from} au {to}",
93
+ "heading.trash": { one: "Corbeille · {count} tâche · effacée 30 jours après sa suppression", other: "Corbeille · {count} tâches · effacées 30 jours après leur suppression" },
94
+ "prompt.add": "Ajouter",
95
+ "prompt.move": "Déplacer à",
96
+ "prompt.note": "Où je me suis arrêté",
97
+ "prompt.filter": "Filtre",
98
+ "prompt.makeNow": "Entrée : m’y mettre maintenant",
99
+ "prompt.notADate": "pas encore une date",
100
+ "prompt.addExample": "ex. Appeler le comptable fri 2pm #maison",
101
+ "prompt.doing": " · en cours",
102
+ "confirm.trash": " Mettre {ref} {title} à la corbeille ? ",
103
+ "hints.help": "une touche ferme · j/k défile",
104
+ "hints.typing": "Entrée enregistre · Échap annule",
105
+ "hints.nextField": " · Tab champ suivant",
106
+ "hints.confirm": "y la met à la corbeille · une autre touche la garde",
107
+ "hints.detail": "Échap retour j/k défiler ␣ terminée s commencer n maintenant e modifier E éditeur m déplacer d corbeille ? aide",
108
+ "hints.board": "? aide h/l colonne H/L déplacer a ajouter ␣ terminée e modifier d corbeille / filtre Tab vues q quitter",
109
+ "hints.week": "? aide h/l jour H/L d’un jour [ ] semaines t aujourd’hui a ajouter ␣ terminée Entrée ouvrir q quitter",
110
+ "hints.trash": "? aide r restaurer Entrée ouvrir / filtre Tab vues q quitter",
111
+ "hints.today": "? aide a ajouter ␣ terminée s commencer n maintenant e modifier m déplacer d corbeille / filtre Tab vues q quitter",
112
+ "small.title": "Terminal trop petit",
113
+ "small.size": "actuellement {columns}×{rows}, il faut {minColumns}×{minRows}",
114
+ "small.quit": "q quitte",
115
+ "detail.loading": "Chargement de la tâche…",
116
+ "detail.status": "statut",
117
+ "detail.due": "échéance",
118
+ "detail.repeat": "répète",
119
+ "detail.remind": "rappel",
120
+ "detail.labels": "étiquettes",
121
+ "detail.links": "liens",
122
+ "detail.next": "ensuite",
123
+ "detail.deleted": "supprimée",
124
+ "detail.archived": "archivée",
125
+ "detail.changed": "modifiée",
126
+ "detail.addedBy": "ajoutée",
127
+ "detail.now": " (maintenant)",
128
+ "detail.overdue": ", en retard",
129
+ "detail.none": "aucun",
130
+ "detail.checklist": "liste {done}/{total}",
131
+ "detail.note": "note",
132
+ "detail.history": "historique ({count}, récents d’abord)",
133
+ "action.create": "ajoutée",
134
+ "action.update": "modifiée",
135
+ "action.complete": "terminée",
136
+ "action.repeat": "occurrence suivante",
137
+ "action.setStatus": "statut",
138
+ "action.setNow": "maintenant",
139
+ "action.archive": "archivée",
140
+ "action.delete": "à la corbeille",
141
+ "action.restore": "restaurée",
142
+ "today.next": "ensuite : ",
143
+ "trash.empty": "(la corbeille est vide)",
144
+ "trash.deleted": "supprimée {time}",
145
+ "week.today": " · aujourd’hui",
146
+ "week.tasks": { one: " · {count} tâche", other: " · {count} tâches" },
147
+ "week.empty": "(rien ce jour-là ; a ajoute une tâche ici)",
148
+ "help.title": "Touches",
149
+ "help.closes": " (une autre touche ferme ; j/k défile)",
150
+ "edit.title": "Modifier : ",
151
+ "edit.hintDue": "Échéance : une expression anglaise comme fri 2pm, vide pour aucun jour · Étiquettes : maison, travail",
152
+ "edit.hintNote": "La note : Échap, puis E ouvre $VISUAL / $EDITOR",
153
+ "field.title": "Titre",
154
+ "field.due": "Échéance",
155
+ "field.labels": "Étiquettes",
156
+ "field.resumeNote": "Où j’en suis",
157
+ "keys.move": "Déplacement",
158
+ "keys.move.next": "Tâche suivante / précédente",
159
+ "keys.move.column": "Colonne du tableau, jour de la semaine",
160
+ "keys.move.ends": "Première / dernière tâche",
161
+ "keys.move.page": "Demi-page vers le bas / le haut",
162
+ "keys.move.open": "Ouvrir une tâche (jour vide : ajouter)",
163
+ "keys.move.back": "Retour ; efface le filtre",
164
+ "keys.views": "Vues",
165
+ "keys.views.next": "Vue suivante / précédente",
166
+ "keys.views.pick": "Aujourd’hui, Tableau, Semaine, Corbeille, Agents",
167
+ "keys.views.filter": "Filtre : titre, #étiquette, note, #42",
168
+ "keys.views.refresh": "Actualiser (aussi toutes les 12 s)",
169
+ "keys.views.help": "Cette aide",
170
+ "keys.views.quit": "Quitter (q dans les détails : retour)",
171
+ "keys.tasks": "Tâches",
172
+ "keys.tasks.add": "Ajouter : Payer le loyer fri 2pm #maison",
173
+ "keys.tasks.done": "Terminée / non terminée (les répétitions continuent)",
174
+ "keys.tasks.start": "Commencer (en cours) / arrêter (à faire)",
175
+ "keys.tasks.now": "Tâche du moment, avec où j’en suis",
176
+ "keys.tasks.clearNow": "Retirer la tâche du moment",
177
+ "keys.tasks.edit": "Modifier titre, échéance, étiquettes, note",
178
+ "keys.tasks.editor": "Titre et note dans $EDITOR",
179
+ "keys.tasks.move": "Déplacer : tomorrow, fri 9am, none",
180
+ "keys.tasks.trash": "À la corbeille (demande) ; u annule",
181
+ "keys.tasks.restore": "Restaurer (dans la corbeille)",
182
+ "keys.boardWeek": "Tableau et semaine",
183
+ "keys.boardWeek.column": "Tableau : colonne à gauche / à droite",
184
+ "keys.boardWeek.day": "Semaine : un jour plus tôt / plus tard",
185
+ "keys.boardWeek.weeks": "Semaine : précédente / suivante",
186
+ "keys.boardWeek.thisWeek": "Semaine : cette semaine",
187
+ "keys.typing": "Saisie",
188
+ "keys.typing.save": "Enregistrer / annuler",
189
+ "keys.typing.field": "Champ suivant / précédent (modifier)",
190
+ "keys.typing.cursor": "Déplacer le curseur ; début / fin",
191
+ "keys.typing.delete": "Effacer jusqu’au début / à la fin / un mot",
192
+ "done.added": "Ajoutée : {task} · {when}",
193
+ "done.done": "Terminée : {task}",
194
+ "done.next": " · prochaine : {when}",
195
+ "done.notDone": "Non terminée : {task}",
196
+ "done.started": "Commencée : {task}",
197
+ "done.stopped": "Arrêtée : {task}",
198
+ "done.status": "{task} → {status}",
199
+ "done.nowCleared": "Tâche du moment retirée",
200
+ "done.moved": "{task} déplacée à {when}",
201
+ "done.trashed": "{task} mise à la corbeille · u annule",
202
+ "done.restored": "Restaurée : {task}",
203
+ "done.now": "Maintenant : {task}",
204
+ "done.nowNext": " · ensuite : {note}",
205
+ "done.saved": "Enregistrée : {task}",
206
+ "done.noChanges": "Aucune modification",
207
+ "error.titleOnlyDate": "Une tâche a besoin d’un titre, pas seulement d’une date",
208
+ "error.notADate": "Pas une date : écrivez-la en anglais, par ex. tomorrow, fri 14:00, next mon, 23 oct ou none",
209
+ "error.emptyTitle": "Le titre ne peut pas être vide",
210
+ "error.due": "Échéance : {message}",
211
+ "error.editorEmpty": "La première ligne (le titre) est vide ; rien n’a changé",
212
+ "error.noEditor": "Pas d’éditeur ici",
213
+ "error.notSaved": "Non enregistré : {message}",
214
+ "flash.noTask": "Aucune tâche sélectionnée",
215
+ "flash.inTrash": "Dans la corbeille : r la restaure",
216
+ "flash.restoreWhere": "r restaure une tâche de la corbeille (4)",
217
+ "flash.nothingToUndo": "Rien à annuler",
218
+ "flash.noDay": "La tâche n’a pas de jour",
219
+ "flash.shiftWhere": "H et L agissent sur le tableau et la semaine",
220
+ "flash.kept": "Conservée",
221
+ "flash.editCancelled": "Modification annulée",
222
+ "repeat.day": { one: "tous les jours", other: "tous les {count} jours" },
223
+ "repeat.week": { one: "toutes les semaines", other: "toutes les {count} semaines" },
224
+ "repeat.month": { one: "tous les mois", other: "tous les {count} mois" },
225
+ "repeat.year": { one: "tous les ans", other: "tous les {count} ans" },
226
+ "repeat.on": "le {days}",
227
+ "repeat.lastDay": "le dernier jour",
228
+ "repeat.monthDay": "le {day}",
229
+ "repeat.nthWeekday": "le {weekday} n° {nth}",
230
+ "repeat.lastWeekday": "le dernier {weekday}",
231
+ "repeat.fromEnd": "le {weekday} n° {nth} avant la fin",
232
+ "repeat.fromCompletion": "après achèvement",
233
+ "repeat.until": "jusqu’au {date}",
234
+ "repeat.times": { one: "dernière fois", other: "{count} fois" },
235
+ "remind.atDue": "à l’heure d’échéance",
236
+ "remind.days": { one: "{count} jour avant", other: "{count} jours avant" },
237
+ "remind.hours": "{count} h avant",
238
+ "remind.minutes": "{count} min avant",
239
+ "remind.timeDaysBefore": "{time}, {days}",
240
+ };
@@ -0,0 +1,67 @@
1
+ // The language of dayhand ui: its screens, keys help and status messages.
2
+ // Everything else the CLI prints stays English, and so does every contract
3
+ // agents and scripts read: --json, field names, error codes and exit codes.
4
+ //
5
+ // Messages are keyed by name; English (en.ts) is the source and every other
6
+ // catalog must have exactly its keys (the type checks that, a test checks the
7
+ // {placeholders} and plural forms). A plural message has one form per CLDR
8
+ // category of its language, chosen by its {count}.
9
+ import { de } from "./de.js";
10
+ import { en } from "./en.js";
11
+ import { es } from "./es.js";
12
+ import { fr } from "./fr.js";
13
+ import { ja } from "./ja.js";
14
+ import { pl } from "./pl.js";
15
+ import { ptBR } from "./pt-BR.js";
16
+ import { zhHans } from "./zh-Hans.js";
17
+ export const LANGUAGES = ["en", "pl", "de", "es", "fr", "pt-BR", "ja", "zh-Hans"];
18
+ export const CATALOGS = { en, pl, de, es, fr, "pt-BR": ptBR, ja, "zh-Hans": zhHans };
19
+ let current = "en";
20
+ /** The language until setLanguage: English, so tests and every other command read the same text everywhere. */
21
+ export const getLanguage = () => current;
22
+ export function setLanguage(language) {
23
+ current = language;
24
+ }
25
+ /** The message `key` in the current language, with its {placeholders} filled in. */
26
+ export const t = (key, params = {}) => tIn(current, key, params);
27
+ /** The message `key` in `language` (`dayhand help ui` stays English whatever the terminal speaks). */
28
+ export function tIn(language, key, params = {}) {
29
+ const message = CATALOGS[language][key];
30
+ const text = typeof message === "string" ? message : pluralForm(language, message, Number(params.count ?? 0));
31
+ return text.replace(/\{(\w+)\}/g, (all, name) => (name in params ? String(params[name]) : all));
32
+ }
33
+ function pluralForm(language, message, count) {
34
+ return message[new Intl.PluralRules(language).select(count)] ?? message.other;
35
+ }
36
+ /**
37
+ * The supported language of a locale name or language tag, or undefined:
38
+ * "pl_PL.UTF-8" and "pl" are Polish, any Portuguese is Brazilian, "zh_CN" and
39
+ * "zh-Hans" Simplified Chinese (Traditional Chinese is not), "C" and "POSIX" none.
40
+ */
41
+ export function matchLanguage(name) {
42
+ const tag = name?.trim().split(/[.@]/)[0]?.replace(/_/g, "-").toLowerCase();
43
+ if (!tag || tag === "c" || tag === "posix")
44
+ return undefined;
45
+ const [code, ...rest] = tag.split("-");
46
+ if (code === "pt")
47
+ return "pt-BR";
48
+ if (code === "zh") {
49
+ const traditional = rest.includes("hant") || (!rest.includes("hans") && rest.some((r) => ["tw", "hk", "mo"].includes(r)));
50
+ return traditional ? undefined : "zh-Hans";
51
+ }
52
+ return LANGUAGES.find((language) => language === code);
53
+ }
54
+ /**
55
+ * The language for dayhand ui: --lang, then DAYHAND_LANG, then the locale
56
+ * (LC_ALL, LC_MESSAGES, LANG, the first one set), else English. A --lang
57
+ * Dayhand does not speak is an error for the caller; the others fall through.
58
+ */
59
+ export function resolveLanguage(flag, env) {
60
+ if (flag !== undefined)
61
+ return matchLanguage(flag) ?? "en";
62
+ const named = matchLanguage(env.DAYHAND_LANG);
63
+ if (named)
64
+ return named;
65
+ const locale = [env.LC_ALL, env.LC_MESSAGES, env.LANG].find((value) => value && value.trim());
66
+ return matchLanguage(locale) ?? "en";
67
+ }