spectoflow 0.17.1 → 0.18.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.
@@ -0,0 +1,607 @@
1
+ 'use strict';
2
+ /*
3
+ * Dashboard UI translations. `config.json`'s `language` governs BOTH the agent's own output (specs,
4
+ * plans, code comments — per AGENTS.md) AND, from here, this dashboard's chrome — so picking a
5
+ * language actually changes what you see, not just what the agent writes.
6
+ *
7
+ * t(key, vars?) looks up I18N[currentLang][key], falls back to I18N.en[key], then to the key itself
8
+ * (so a missing translation never breaks the UI — it just shows English or the raw key). {placeholder}
9
+ * tokens in a string are substituted from `vars`. currentLang is set by i18nSetLang(), called from
10
+ * render() on every tick (app.js) — so language changes apply live, no reload, no separate wiring.
11
+ *
12
+ * applyI18nStatic() walks two attributes on the static markup (index.html):
13
+ * data-i18n="key" → element.textContent = t(key)
14
+ * data-i18n-html="key" → element.innerHTML = t(key) (for strings authored with inline <em>/<code>)
15
+ * data-i18n-ph="key" → element.placeholder = t(key)
16
+ * data-i18n-title="key" → element.title = t(key)
17
+ * data-i18n-aria="key" → element.setAttribute('aria-label', t(key))
18
+ * It's called once at boot and again at the end of every render() tick.
19
+ */
20
+ const I18N = {
21
+ en: {
22
+ 'nav.board':'Board','nav.requests':'Requests','nav.attention':'Attention','nav.backlog':'Backlog',
23
+ 'nav.workflow':'Workflow','nav.team':'Agents & Skills','nav.chat':'Chat','nav.info':'Info','nav.settings':'Settings',
24
+ 'status.todo':'To do','status.in_progress':'In progress','status.to_validate':'To validate',
25
+ 'status.to_analyze':'To analyze','status.done':'Done','status.blocked':'Blocked',
26
+ 'filter.all':'All','filter.open':'Open','filter.resolved':'Resolved',
27
+ 'action.run':'Run','action.send':'Send','action.orchestrate':'Orchestrate','action.approve':'Approve',
28
+ 'action.cancel':'Cancel','action.add':'Add','action.edit':'Edit','action.delete':'Delete',
29
+ 'action.resolve':'Resolve','action.reopen':'Reopen','action.validateToTask':'Validate → task',
30
+ 'action.addToAnalyze':'Add + to analyze',
31
+ 'topbar.navToggle':'Toggle menu','topbar.run.title':'Open the run chat',
32
+ 'topbar.theme.toggle':'Toggle light / dark theme','topbar.theme.toggle.title':'Toggle light / dark',
33
+ 'topbar.mode.title':'Autonomy mode — change from here or in Settings',
34
+ 'topbar.lang.title':'Output language — change from here or in Settings',
35
+ 'board.filterPlaceholder':'Filter tasks…','board.expandAll':'Expand all','board.collapseAll':'Collapse all',
36
+ 'board.expandAllTitle':'Expand or collapse all phases','board.viewList':'List','board.viewKanban':'Kanban',
37
+ 'board.viewList.title':'Grouped by phase','board.viewKanban.title':'Columns by status',
38
+ 'board.noTasksMatch':'No tasks match this filter.',
39
+ 'board.noPlans':'No plans yet. Ask your agent to build something — it will run Intake and write plans/*.md.',
40
+ 'board.noAgentRunning':'no agent running','board.noneYet':'none yet',
41
+ 'board.workflowGlance':'Workflow at a glance','board.noWorkflow':'No workflow defined.',
42
+ 'board.phaseProgress':'Phase progress ({n})',
43
+ 'rail.journal':'Journal','rail.specs':'Specs','rail.running':'Running',
44
+ 'journal.empty':'No activity yet.','journal.seeMore':'See more','journal.seeLess':'See less',
45
+ 'chart.scope':'Scope','chart.delivered':'Delivered','chart.statusDistribution':'Status distribution',
46
+ 'chart.scopeVsDelivered':'Scope vs delivered','chart.noHistory':'No history yet.','chart.tasksSub':'tasks',
47
+ 'kpi.globalProgress':'Global progress','kpi.tasksLabel':'tasks','kpi.awaitingReview':'awaiting review',
48
+ 'kpi.running':'Running','kpi.noRunsYet':'no runs yet','kpi.agentsActive':'agents active',
49
+ 'kpi.orchestration':'orchestration','kpi.lastPrefix':'last: ',
50
+ 'requests.sub':'Tasks awaiting your input — status <em>to validate</em> or <em>to analyze</em>.',
51
+ 'requests.empty':'Nothing awaiting you.',
52
+ 'attn.title':'Points of attention',
53
+ 'attn.sub':'Things the agent flagged during work — or you noted — that deserve a look. <em>Validate</em> one to turn it into a task.',
54
+ 'attn.inputPlaceholder':'Note something to keep an eye on…','attn.addNote':'Add note',
55
+ 'attn.emptyOpen':'No points of attention. The agent surfaces them here as it works — or add your own note above.',
56
+ 'attn.emptyResolved':'Nothing resolved yet.','attn.you':'you','attn.agentFallback':'agent',
57
+ 'attn.resolvedChip':'resolved',
58
+ 'backlog.sub':'Every task, across every plan, in one flat table.',
59
+ 'backlog.searchPlaceholder':'Filter by id or title…',
60
+ 'col.id':'ID','col.title':'Title','col.phase':'Phase','col.status':'Status','col.owner':'Owner','col.level':'Level',
61
+ 'backlog.pagerTask':'{n} task','backlog.pagerTasks':'{n} tasks',
62
+ 'backlog.pagerRange':'{from}–{to} of {total} · page {page}/{pages}',
63
+ 'backlog.prev':'‹ Prev','backlog.next':'Next ›',
64
+ 'workflow.title':'Active workflow',
65
+ 'workflow.sub':'The pipeline your requests flow through — from idea to shipped, spec-driven. <strong>Click a step</strong> to see what it does and turn it on or off (this edits <code>.spectoflow/workflow.md</code>). Enabled steps run in order; the orchestrator gates each one by your <em>mode</em> and <em>policy</em>. Optional steps stay off until you switch them on.',
66
+ 'workflow.stepsEnabled':'{enabled} of {total} steps enabled — click a step to see what it does',
67
+ 'workflow.optional':'optional','workflow.enabled':'enabled','workflow.disabled':'disabled',
68
+ 'workflow.capability':'Capability','workflow.handledBy':'Handled by','workflow.skill':'Skill',
69
+ 'workflow.standard':'Standard','workflow.flow':'Flow','workflow.enableStep':'Enable step',
70
+ 'workflow.disableStep':'Disable step','workflow.skillPrefix':'The “{name}” skill — ',
71
+ 'wf.desc.brainstorm':'Explore the request before committing to it — clarify the goal, constraints and success criteria, and shape a raw idea into something worth building.',
72
+ 'wf.desc.analysis':'Break the idea down: study the existing code and requirements, surface risks and ambiguities, and pin down clear, testable acceptance criteria.',
73
+ 'wf.desc.spec':'Write the specification — the versioned, plain-markdown source of truth for what to build and why, before any code is written.',
74
+ 'wf.desc.plan':'Turn the spec into an ordered plan of small, checkbox tasks — each one testable and executable on its own by a developer or an agent.',
75
+ 'wf.desc.develop':'Implement the plan task by task, writing the code (and the tests that pin it down) to satisfy each checkbox.',
76
+ 'wf.desc.integration':'Check that the pieces work together — modules, services and data paths across component boundaries, not just in isolation.',
77
+ 'wf.desc.e2e':'Exercise the whole product the way a real user would, through the actual UI and end-to-end flows.',
78
+ 'wf.desc.unit':'Verify each unit in isolation — fast, focused tests that lock in behaviour and catch regressions early.',
79
+ 'wf.desc.review':'A final quality pass — correctness, security and standards — before the work is considered done.',
80
+ 'wf.desc.deploy':'Release the delivered work — ship it to its target environment.',
81
+ 'wf.desc.fallback':'A step in the delivery pipeline.',
82
+ 'team.agentsTitle':'Agents','team.agentsSub':'Stable team personas — the <em>who</em>.',
83
+ 'team.skillsTitle':'Skills','team.skillsSub':'Evolving procedures — the <em>how</em>.',
84
+ 'team.standardsLabel':'standards','team.usesLabel':'uses','team.standardLabel':'standard',
85
+ 'drawer.agent':'Agent','drawer.skill':'Skill','drawer.file':'File · {rel}',
86
+ 'drawer.loading':'Loading…','drawer.loadError':'Could not load this file.',
87
+ 'chat.widgetTitle':'Run an agent','chat.widgetSub':'Quick access · full view in the Chat tab',
88
+ 'chat.tabSub':'Full conversation with the runner — the same run as the widget, more room to read it.',
89
+ 'chat.idle':'Type a request — the agent runs headless in this project with full memory (<code>CLAUDE.md → AGENTS.md</code>) and updates the board live.',
90
+ 'chat.inputPlaceholder':'e.g. Add a login feature with email + password',
91
+ 'chat.orchestrateTitle':'Walk the enabled workflow',
92
+ 'chat.warn':'⚠ Launches a real agent (<code>config.json → runners</code>) that can modify files &amp; run commands.',
93
+ 'info.title':'Info','info.sub':'Project overview — configuration, counts, specs and active workflow.',
94
+ 'info.project':'Project','info.projectType':'Project type','info.mode':'Mode','info.language':'Language',
95
+ 'info.activeAgent':'Active agent','info.runners':'Runners','info.noRunners':'No runners configured.',
96
+ 'info.counts':'Counts','info.tasksLabel':'Tasks','info.doneSub':'{pct}% done','info.specsLabel':'Specs',
97
+ 'info.filesSub':'files','info.agentsLabel':'Agents','info.personasSub':'personas','info.skillsLabel':'Skills',
98
+ 'info.proceduresSub':'procedures','info.workflowLabel':'Workflow','info.stepsEnabledSub':'steps enabled',
99
+ 'info.noEnabledSteps':'No enabled workflow steps.',
100
+ 'settings.sub':'Change how spectoflow runs. Writes <code>.spectoflow/config.json</code> — the agent picks it up on its next run.',
101
+ 'field.design':'Dashboard design','field.mode':'Autonomy mode','field.lang':'Output language',
102
+ 'mode.autopilot.desc':'autopilot — run freely, ask only on policy gates',
103
+ 'mode.semi.desc':'semi — autopilot + policy approvals','mode.manual.desc':'manual — approve every step',
104
+ 'settings.saved':'✓ saved','field.plansFolder':'Plans folder','field.specsFolder':'Specs folder',
105
+ 'field.frameworkVersion':'Framework version',
106
+ 'task.status':'Status','task.tests':'Tests','task.failing':'{n} failing','task.passing':'{n} passing',
107
+ 'task.failingPassing':'{f} failing, {p} passing','task.comments':'Comments','task.noComments':'No comments.',
108
+ 'task.addCommentPlaceholder':'Add a comment, a remark, feedback…',
109
+ 'task.toAnalyzeHint':'"To analyze" moves the task back so the agent picks it up next round.',
110
+ 'customize.title':'Customize','customize.sub':'Add project-specific dashboards, skills and agents — describe what you want, or let Auto propose candidates from this project.',
111
+ 'customize.dashboards':'Dashboards','customize.skills':'Skills','customize.agents':'Agents',
112
+ 'customize.add.dashboard':'Add dashboard','customize.add.skill':'Add skill','customize.add.agent':'Add agent',
113
+ 'customize.empty.dashboard':'No custom dashboards yet.','customize.empty.skill':'No custom skills yet.','customize.empty.agent':'No custom agents yet.',
114
+ 'customize.describePh':'Describe what you want…','customize.auto':'Auto','customize.generate':'Generate','customize.blocksSub':'block(s)',
115
+ },
116
+ fr: {
117
+ 'nav.board':'Tableau','nav.requests':'Demandes','nav.attention':'Attention','nav.backlog':'Backlog',
118
+ 'nav.workflow':'Workflow','nav.team':'Agents et compétences','nav.chat':'Chat','nav.info':'Infos','nav.settings':'Réglages',
119
+ 'status.todo':'À faire','status.in_progress':'En cours','status.to_validate':'À valider',
120
+ 'status.to_analyze':'À analyser','status.done':'Terminé','status.blocked':'Bloqué',
121
+ 'filter.all':'Tous','filter.open':'Ouverts','filter.resolved':'Résolus',
122
+ 'action.run':'Lancer','action.send':'Envoyer','action.orchestrate':'Orchestrer','action.approve':'Approuver',
123
+ 'action.cancel':'Annuler','action.add':'Ajouter','action.edit':'Modifier','action.delete':'Supprimer',
124
+ 'action.resolve':'Résoudre','action.reopen':'Rouvrir','action.validateToTask':'Valider → tâche',
125
+ 'action.addToAnalyze':'Ajouter + à analyser',
126
+ 'topbar.navToggle':'Afficher le menu','topbar.run.title':'Ouvrir le chat d’exécution',
127
+ 'topbar.theme.toggle':'Basculer thème clair / sombre','topbar.theme.toggle.title':'Basculer clair / sombre',
128
+ 'topbar.mode.title':'Mode d’autonomie — modifiable ici ou dans Réglages',
129
+ 'topbar.lang.title':'Langue de sortie — modifiable ici ou dans Réglages',
130
+ 'board.filterPlaceholder':'Filtrer les tâches…','board.expandAll':'Tout déplier','board.collapseAll':'Tout replier',
131
+ 'board.expandAllTitle':'Déplier ou replier toutes les phases','board.viewList':'Liste','board.viewKanban':'Kanban',
132
+ 'board.viewList.title':'Regroupé par phase','board.viewKanban.title':'Colonnes par statut',
133
+ 'board.noTasksMatch':'Aucune tâche ne correspond à ce filtre.',
134
+ 'board.noPlans':'Aucun plan pour l’instant. Demandez à votre agent de construire quelque chose — il lancera l’Intake et écrira plans/*.md.',
135
+ 'board.noAgentRunning':'aucun agent en cours','board.noneYet':'aucun pour l’instant',
136
+ 'board.workflowGlance':'Workflow en un coup d’œil','board.noWorkflow':'Aucun workflow défini.',
137
+ 'board.phaseProgress':'Progression des phases ({n})',
138
+ 'rail.journal':'Journal','rail.specs':'Specs','rail.running':'En cours',
139
+ 'journal.empty':'Aucune activité pour l’instant.','journal.seeMore':'Voir plus','journal.seeLess':'Voir moins',
140
+ 'chart.scope':'Périmètre','chart.delivered':'Livré','chart.statusDistribution':'Répartition des statuts',
141
+ 'chart.scopeVsDelivered':'Périmètre vs livré','chart.noHistory':'Pas encore d’historique.','chart.tasksSub':'tâches',
142
+ 'kpi.globalProgress':'Progression globale','kpi.tasksLabel':'tâches','kpi.awaitingReview':'en attente de revue',
143
+ 'kpi.running':'Exécution','kpi.noRunsYet':'aucune exécution','kpi.agentsActive':'agents actifs',
144
+ 'kpi.orchestration':'orchestration','kpi.lastPrefix':'dernier : ',
145
+ 'requests.sub':'Tâches en attente de votre action — statut <em>à valider</em> ou <em>à analyser</em>.',
146
+ 'requests.empty':'Rien ne vous attend.',
147
+ 'attn.title':'Points d’attention',
148
+ 'attn.sub':'Ce que l’agent a signalé pendant son travail — ou que vous avez noté — et qui mérite un regard. <em>Validez</em> un point pour en faire une tâche.',
149
+ 'attn.inputPlaceholder':'Notez quelque chose à surveiller…','attn.addNote':'Ajouter une note',
150
+ 'attn.emptyOpen':'Aucun point d’attention. L’agent les fait apparaître ici pendant son travail — ou ajoutez votre propre note ci-dessus.',
151
+ 'attn.emptyResolved':'Rien de résolu pour l’instant.','attn.you':'vous','attn.agentFallback':'agent',
152
+ 'attn.resolvedChip':'résolu',
153
+ 'backlog.sub':'Toutes les tâches, tous plans confondus, dans un seul tableau.',
154
+ 'backlog.searchPlaceholder':'Filtrer par id ou titre…',
155
+ 'col.id':'ID','col.title':'Titre','col.phase':'Phase','col.status':'Statut','col.owner':'Responsable','col.level':'Niveau',
156
+ 'backlog.pagerTask':'{n} tâche','backlog.pagerTasks':'{n} tâches',
157
+ 'backlog.pagerRange':'{from}–{to} sur {total} · page {page}/{pages}',
158
+ 'backlog.prev':'‹ Précédent','backlog.next':'Suivant ›',
159
+ 'workflow.title':'Workflow actif',
160
+ 'workflow.sub':'Le pipeline que suivent vos demandes — de l’idée jusqu’à la livraison, spec-driven. <strong>Cliquez sur une étape</strong> pour voir ce qu’elle fait et l’activer ou la désactiver (cela modifie <code>.spectoflow/workflow.md</code>). Les étapes activées s’exécutent dans l’ordre ; l’orchestrateur filtre chacune selon votre <em>mode</em> et votre <em>policy</em>. Les étapes optionnelles restent désactivées tant que vous ne les activez pas.',
161
+ 'workflow.stepsEnabled':'{enabled} étape(s) activée(s) sur {total} — cliquez sur une étape pour voir ce qu’elle fait',
162
+ 'workflow.optional':'optionnel','workflow.enabled':'activé','workflow.disabled':'désactivé',
163
+ 'workflow.capability':'Capacité','workflow.handledBy':'Pris en charge par','workflow.skill':'Compétence',
164
+ 'workflow.standard':'Standard','workflow.flow':'Flux','workflow.enableStep':'Activer l’étape',
165
+ 'workflow.disableStep':'Désactiver l’étape','workflow.skillPrefix':'La compétence « {name} » — ',
166
+ 'wf.desc.brainstorm':'Explorer la demande avant de s’y engager — clarifier l’objectif, les contraintes et les critères de succès, et transformer une idée brute en quelque chose qui vaut la peine d’être construit.',
167
+ 'wf.desc.analysis':'Décomposer l’idée : étudier le code et les besoins existants, faire remonter les risques et les ambiguïtés, et fixer des critères d’acceptation clairs et testables.',
168
+ 'wf.desc.spec':'Rédiger la spécification — la source de vérité versionnée, en markdown, de ce qu’il faut construire et pourquoi, avant d’écrire la moindre ligne de code.',
169
+ 'wf.desc.plan':'Transformer la spec en un plan ordonné de petites tâches à cocher — chacune testable et exécutable seule par un développeur ou un agent.',
170
+ 'wf.desc.develop':'Implémenter le plan tâche par tâche, en écrivant le code (et les tests qui le verrouillent) pour satisfaire chaque case.',
171
+ 'wf.desc.integration':'Vérifier que les pièces fonctionnent ensemble — modules, services et flux de données au-delà des frontières de chaque composant, pas seulement isolément.',
172
+ 'wf.desc.e2e':'Faire fonctionner le produit dans son ensemble comme un vrai utilisateur le ferait, via l’interface réelle et des parcours de bout en bout.',
173
+ 'wf.desc.unit':'Vérifier chaque unité isolément — des tests rapides et ciblés qui figent le comportement et attrapent les régressions tôt.',
174
+ 'wf.desc.review':'Une dernière passe qualité — justesse, sécurité et standards — avant que le travail soit considéré comme terminé.',
175
+ 'wf.desc.deploy':'Livrer le travail réalisé — le déployer vers son environnement cible.',
176
+ 'wf.desc.fallback':'Une étape du pipeline de livraison.',
177
+ 'team.agentsTitle':'Agents','team.agentsSub':'Personas d’équipe stables — le <em>qui</em>.',
178
+ 'team.skillsTitle':'Compétences','team.skillsSub':'Procédures évolutives — le <em>comment</em>.',
179
+ 'team.standardsLabel':'standards','team.usesLabel':'utilise','team.standardLabel':'standard',
180
+ 'drawer.agent':'Agent','drawer.skill':'Compétence','drawer.file':'Fichier · {rel}',
181
+ 'drawer.loading':'Chargement…','drawer.loadError':'Impossible de charger ce fichier.',
182
+ 'chat.widgetTitle':'Lancer un agent','chat.widgetSub':'Accès rapide · vue complète dans l’onglet Chat',
183
+ 'chat.tabSub':'Conversation complète avec l’exécuteur — la même exécution que le widget, avec plus de place pour la lire.',
184
+ 'chat.idle':'Tapez une demande — l’agent s’exécute sans supervision dans ce projet avec toute sa mémoire (<code>CLAUDE.md → AGENTS.md</code>) et met le tableau à jour en direct.',
185
+ 'chat.inputPlaceholder':'ex. Ajouter une fonctionnalité de connexion par email + mot de passe',
186
+ 'chat.orchestrateTitle':'Parcourir le workflow activé',
187
+ 'chat.warn':'⚠ Lance un agent réel (<code>config.json → runners</code>) qui peut modifier des fichiers et exécuter des commandes.',
188
+ 'info.title':'Infos','info.sub':'Vue d’ensemble du projet — configuration, comptages, specs et workflow actif.',
189
+ 'info.project':'Projet','info.projectType':'Type de projet','info.mode':'Mode','info.language':'Langue',
190
+ 'info.activeAgent':'Agent actif','info.runners':'Runners','info.noRunners':'Aucun runner configuré.',
191
+ 'info.counts':'Comptages','info.tasksLabel':'Tâches','info.doneSub':'{pct}% terminé','info.specsLabel':'Specs',
192
+ 'info.filesSub':'fichiers','info.agentsLabel':'Agents','info.personasSub':'personas','info.skillsLabel':'Compétences',
193
+ 'info.proceduresSub':'procédures','info.workflowLabel':'Workflow','info.stepsEnabledSub':'étapes activées',
194
+ 'info.noEnabledSteps':'Aucune étape de workflow activée.',
195
+ 'settings.sub':'Changez la façon dont spectoflow fonctionne. Écrit dans <code>.spectoflow/config.json</code> — l’agent le lit à sa prochaine exécution.',
196
+ 'field.design':'Design du tableau de bord','field.mode':'Mode d’autonomie','field.lang':'Langue de sortie',
197
+ 'mode.autopilot.desc':'autopilot — s’exécute librement, ne demande qu’aux points de policy',
198
+ 'mode.semi.desc':'semi — autopilot + approbations de policy','mode.manual.desc':'manual — approuve chaque étape',
199
+ 'settings.saved':'✓ enregistré','field.plansFolder':'Dossier des plans','field.specsFolder':'Dossier des specs',
200
+ 'field.frameworkVersion':'Version du framework',
201
+ 'task.status':'Statut','task.tests':'Tests','task.failing':'{n} en échec','task.passing':'{n} réussi(s)',
202
+ 'task.failingPassing':'{f} en échec, {p} réussi(s)','task.comments':'Commentaires','task.noComments':'Aucun commentaire.',
203
+ 'task.addCommentPlaceholder':'Ajouter un commentaire, une remarque, un retour…',
204
+ 'task.toAnalyzeHint':'« À analyser » renvoie la tâche pour que l’agent la reprenne au tour suivant.',
205
+ 'customize.title':'Personnaliser','customize.sub':'Ajoutez des dashboards, compétences et agents propres au projet — décrivez ce que vous voulez, ou laissez Auto proposer des pistes à partir de ce projet.',
206
+ 'customize.dashboards':'Dashboards','customize.skills':'Compétences','customize.agents':'Agents',
207
+ 'customize.add.dashboard':'Ajouter un dashboard','customize.add.skill':'Ajouter une compétence','customize.add.agent':'Ajouter un agent',
208
+ 'customize.empty.dashboard':'Aucun dashboard personnalisé pour l’instant.','customize.empty.skill':'Aucune compétence personnalisée pour l’instant.','customize.empty.agent':'Aucun agent personnalisé pour l’instant.',
209
+ 'customize.describePh':'Décrivez ce que vous voulez…','customize.auto':'Auto','customize.generate':'Générer','customize.blocksSub':'bloc(s)',
210
+ },
211
+ es: {
212
+ 'nav.board':'Tablero','nav.requests':'Solicitudes','nav.attention':'Atención','nav.backlog':'Backlog',
213
+ 'nav.workflow':'Workflow','nav.team':'Agentes y habilidades','nav.chat':'Chat','nav.info':'Info','nav.settings':'Ajustes',
214
+ 'status.todo':'Por hacer','status.in_progress':'En curso','status.to_validate':'Por validar',
215
+ 'status.to_analyze':'Por analizar','status.done':'Hecho','status.blocked':'Bloqueado',
216
+ 'filter.all':'Todos','filter.open':'Abiertos','filter.resolved':'Resueltos',
217
+ 'action.run':'Ejecutar','action.send':'Enviar','action.orchestrate':'Orquestar','action.approve':'Aprobar',
218
+ 'action.cancel':'Cancelar','action.add':'Añadir','action.edit':'Editar','action.delete':'Eliminar',
219
+ 'action.resolve':'Resolver','action.reopen':'Reabrir','action.validateToTask':'Validar → tarea',
220
+ 'action.addToAnalyze':'Añadir + por analizar',
221
+ 'topbar.navToggle':'Mostrar menú','topbar.run.title':'Abrir el chat de ejecución',
222
+ 'topbar.theme.toggle':'Cambiar tema claro / oscuro','topbar.theme.toggle.title':'Cambiar claro / oscuro',
223
+ 'topbar.mode.title':'Modo de autonomía — se cambia aquí o en Ajustes',
224
+ 'topbar.lang.title':'Idioma de salida — se cambia aquí o en Ajustes',
225
+ 'board.filterPlaceholder':'Filtrar tareas…','board.expandAll':'Expandir todo','board.collapseAll':'Colapsar todo',
226
+ 'board.expandAllTitle':'Expandir o colapsar todas las fases','board.viewList':'Lista','board.viewKanban':'Kanban',
227
+ 'board.viewList.title':'Agrupado por fase','board.viewKanban.title':'Columnas por estado',
228
+ 'board.noTasksMatch':'Ninguna tarea coincide con este filtro.',
229
+ 'board.noPlans':'Aún no hay planes. Pide a tu agente que construya algo — ejecutará Intake y escribirá plans/*.md.',
230
+ 'board.noAgentRunning':'ningún agente en ejecución','board.noneYet':'ninguno todavía',
231
+ 'board.workflowGlance':'Workflow de un vistazo','board.noWorkflow':'No hay workflow definido.',
232
+ 'board.phaseProgress':'Progreso de fases ({n})',
233
+ 'rail.journal':'Diario','rail.specs':'Specs','rail.running':'En ejecución',
234
+ 'journal.empty':'Aún no hay actividad.','journal.seeMore':'Ver más','journal.seeLess':'Ver menos',
235
+ 'chart.scope':'Alcance','chart.delivered':'Entregado','chart.statusDistribution':'Distribución de estados',
236
+ 'chart.scopeVsDelivered':'Alcance vs entregado','chart.noHistory':'Aún no hay historial.','chart.tasksSub':'tareas',
237
+ 'kpi.globalProgress':'Progreso global','kpi.tasksLabel':'tareas','kpi.awaitingReview':'a la espera de revisión',
238
+ 'kpi.running':'En ejecución','kpi.noRunsYet':'sin ejecuciones aún','kpi.agentsActive':'agentes activos',
239
+ 'kpi.orchestration':'orquestación','kpi.lastPrefix':'última: ',
240
+ 'requests.sub':'Tareas a la espera de tu acción — estado <em>por validar</em> o <em>por analizar</em>.',
241
+ 'requests.empty':'Nada te está esperando.',
242
+ 'attn.title':'Puntos de atención',
243
+ 'attn.sub':'Lo que el agente señaló durante su trabajo — o lo que anotaste — y que merece una mirada. <em>Valida</em> uno para convertirlo en tarea.',
244
+ 'attn.inputPlaceholder':'Anota algo a vigilar…','attn.addNote':'Añadir nota',
245
+ 'attn.emptyOpen':'No hay puntos de atención. El agente los muestra aquí mientras trabaja — o añade tu propia nota arriba.',
246
+ 'attn.emptyResolved':'Aún no hay nada resuelto.','attn.you':'tú','attn.agentFallback':'agente',
247
+ 'attn.resolvedChip':'resuelto',
248
+ 'backlog.sub':'Todas las tareas, de todos los planes, en una sola tabla.',
249
+ 'backlog.searchPlaceholder':'Filtrar por id o título…',
250
+ 'col.id':'ID','col.title':'Título','col.phase':'Fase','col.status':'Estado','col.owner':'Responsable','col.level':'Nivel',
251
+ 'backlog.pagerTask':'{n} tarea','backlog.pagerTasks':'{n} tareas',
252
+ 'backlog.pagerRange':'{from}–{to} de {total} · página {page}/{pages}',
253
+ 'backlog.prev':'‹ Anterior','backlog.next':'Siguiente ›',
254
+ 'workflow.title':'Workflow activo',
255
+ 'workflow.sub':'El pipeline por el que fluyen tus solicitudes — de la idea a la entrega, guiado por especificaciones. <strong>Haz clic en un paso</strong> para ver qué hace y activarlo o desactivarlo (esto edita <code>.spectoflow/workflow.md</code>). Los pasos activados se ejecutan en orden; el orquestador filtra cada uno según tu <em>modo</em> y tu <em>policy</em>. Los pasos opcionales permanecen desactivados hasta que los actives.',
256
+ 'workflow.stepsEnabled':'{enabled} de {total} pasos activados — haz clic en un paso para ver qué hace',
257
+ 'workflow.optional':'opcional','workflow.enabled':'activado','workflow.disabled':'desactivado',
258
+ 'workflow.capability':'Capacidad','workflow.handledBy':'Gestionado por','workflow.skill':'Habilidad',
259
+ 'workflow.standard':'Estándar','workflow.flow':'Flujo','workflow.enableStep':'Activar paso',
260
+ 'workflow.disableStep':'Desactivar paso','workflow.skillPrefix':'La habilidad «{name}» — ',
261
+ 'wf.desc.brainstorm':'Explorar la solicitud antes de comprometerse con ella — aclarar el objetivo, las restricciones y los criterios de éxito, y convertir una idea sin pulir en algo que merezca construirse.',
262
+ 'wf.desc.analysis':'Descomponer la idea: estudiar el código y los requisitos existentes, sacar a la luz riesgos y ambigüedades, y fijar criterios de aceptación claros y comprobables.',
263
+ 'wf.desc.spec':'Escribir la especificación — la fuente de verdad versionada, en markdown plano, de qué construir y por qué, antes de escribir ningún código.',
264
+ 'wf.desc.plan':'Convertir la especificación en un plan ordenado de tareas pequeñas y verificables — cada una comprobable y ejecutable por sí sola por un desarrollador o un agente.',
265
+ 'wf.desc.develop':'Implementar el plan tarea a tarea, escribiendo el código (y las pruebas que lo aseguran) para cumplir cada tarea.',
266
+ 'wf.desc.integration':'Comprobar que las piezas funcionan juntas — módulos, servicios y flujos de datos entre componentes, no solo de forma aislada.',
267
+ 'wf.desc.e2e':'Ejercitar el producto completo como lo haría un usuario real, a través de la interfaz real y flujos de extremo a extremo.',
268
+ 'wf.desc.unit':'Verificar cada unidad de forma aislada — pruebas rápidas y precisas que fijan el comportamiento y atrapan regresiones pronto.',
269
+ 'wf.desc.review':'Una última pasada de calidad — corrección, seguridad y estándares — antes de dar el trabajo por terminado.',
270
+ 'wf.desc.deploy':'Publicar el trabajo entregado — llevarlo a su entorno de destino.',
271
+ 'wf.desc.fallback':'Un paso del pipeline de entrega.',
272
+ 'team.agentsTitle':'Agentes','team.agentsSub':'Personas de equipo estables — el <em>quién</em>.',
273
+ 'team.skillsTitle':'Habilidades','team.skillsSub':'Procedimientos en evolución — el <em>cómo</em>.',
274
+ 'team.standardsLabel':'estándares','team.usesLabel':'usa','team.standardLabel':'estándar',
275
+ 'drawer.agent':'Agente','drawer.skill':'Habilidad','drawer.file':'Archivo · {rel}',
276
+ 'drawer.loading':'Cargando…','drawer.loadError':'No se pudo cargar este archivo.',
277
+ 'chat.widgetTitle':'Ejecutar un agente','chat.widgetSub':'Acceso rápido · vista completa en la pestaña Chat',
278
+ 'chat.tabSub':'Conversación completa con el ejecutor — la misma ejecución que el widget, con más espacio para leerla.',
279
+ 'chat.idle':'Escribe una solicitud — el agente se ejecuta sin supervisión en este proyecto con toda su memoria (<code>CLAUDE.md → AGENTS.md</code>) y actualiza el tablero en vivo.',
280
+ 'chat.inputPlaceholder':'p. ej. Añadir un inicio de sesión con email + contraseña',
281
+ 'chat.orchestrateTitle':'Recorrer el workflow activado',
282
+ 'chat.warn':'⚠ Lanza un agente real (<code>config.json → runners</code>) que puede modificar archivos y ejecutar comandos.',
283
+ 'info.title':'Info','info.sub':'Visión general del proyecto — configuración, recuentos, specs y workflow activo.',
284
+ 'info.project':'Proyecto','info.projectType':'Tipo de proyecto','info.mode':'Modo','info.language':'Idioma',
285
+ 'info.activeAgent':'Agente activo','info.runners':'Runners','info.noRunners':'No hay runners configurados.',
286
+ 'info.counts':'Recuentos','info.tasksLabel':'Tareas','info.doneSub':'{pct}% hecho','info.specsLabel':'Specs',
287
+ 'info.filesSub':'archivos','info.agentsLabel':'Agentes','info.personasSub':'personas','info.skillsLabel':'Habilidades',
288
+ 'info.proceduresSub':'procedimientos','info.workflowLabel':'Workflow','info.stepsEnabledSub':'pasos activados',
289
+ 'info.noEnabledSteps':'No hay pasos de workflow activados.',
290
+ 'settings.sub':'Cambia cómo funciona spectoflow. Escribe en <code>.spectoflow/config.json</code> — el agente lo aplica en su próxima ejecución.',
291
+ 'field.design':'Diseño del panel','field.mode':'Modo de autonomía','field.lang':'Idioma de salida',
292
+ 'mode.autopilot.desc':'autopilot — actúa con libertad, solo pregunta en los puntos de policy',
293
+ 'mode.semi.desc':'semi — autopilot + aprobaciones de policy','mode.manual.desc':'manual — aprueba cada paso',
294
+ 'settings.saved':'✓ guardado','field.plansFolder':'Carpeta de planes','field.specsFolder':'Carpeta de specs',
295
+ 'field.frameworkVersion':'Versión del framework',
296
+ 'task.status':'Estado','task.tests':'Pruebas','task.failing':'{n} fallando','task.passing':'{n} superadas',
297
+ 'task.failingPassing':'{f} fallando, {p} superadas','task.comments':'Comentarios','task.noComments':'Sin comentarios.',
298
+ 'task.addCommentPlaceholder':'Añade un comentario, una observación, feedback…',
299
+ 'task.toAnalyzeHint':'«Por analizar» devuelve la tarea para que el agente la retome en la siguiente ronda.',
300
+ 'customize.title':'Personalizar','customize.sub':'Añade dashboards, habilidades y agentes propios del proyecto — describe lo que quieres, o deja que Auto proponga candidatos a partir de este proyecto.',
301
+ 'customize.dashboards':'Dashboards','customize.skills':'Habilidades','customize.agents':'Agentes',
302
+ 'customize.add.dashboard':'Añadir dashboard','customize.add.skill':'Añadir habilidad','customize.add.agent':'Añadir agente',
303
+ 'customize.empty.dashboard':'Aún no hay dashboards personalizados.','customize.empty.skill':'Aún no hay habilidades personalizadas.','customize.empty.agent':'Aún no hay agentes personalizados.',
304
+ 'customize.describePh':'Describe lo que quieres…','customize.auto':'Auto','customize.generate':'Generar','customize.blocksSub':'bloque(s)',
305
+ },
306
+ de: {
307
+ 'nav.board':'Board','nav.requests':'Anfragen','nav.attention':'Hinweise','nav.backlog':'Backlog',
308
+ 'nav.workflow':'Workflow','nav.team':'Agenten & Skills','nav.chat':'Chat','nav.info':'Info','nav.settings':'Einstellungen',
309
+ 'status.todo':'Offen','status.in_progress':'In Arbeit','status.to_validate':'Zu prüfen',
310
+ 'status.to_analyze':'Zu analysieren','status.done':'Erledigt','status.blocked':'Blockiert',
311
+ 'filter.all':'Alle','filter.open':'Offen','filter.resolved':'Erledigt',
312
+ 'action.run':'Start','action.send':'Senden','action.orchestrate':'Orchestrieren','action.approve':'Freigeben',
313
+ 'action.cancel':'Abbrechen','action.add':'Hinzufügen','action.edit':'Bearbeiten','action.delete':'Löschen',
314
+ 'action.resolve':'Erledigen','action.reopen':'Wieder öffnen','action.validateToTask':'Bestätigen → Aufgabe',
315
+ 'action.addToAnalyze':'Hinzufügen + zu analysieren',
316
+ 'topbar.navToggle':'Menü anzeigen','topbar.run.title':'Ausführungs-Chat öffnen',
317
+ 'topbar.theme.toggle':'Hell-/Dunkelmodus umschalten','topbar.theme.toggle.title':'Hell / Dunkel umschalten',
318
+ 'topbar.mode.title':'Autonomiemodus — hier oder in den Einstellungen änderbar',
319
+ 'topbar.lang.title':'Ausgabesprache — hier oder in den Einstellungen änderbar',
320
+ 'board.filterPlaceholder':'Aufgaben filtern…','board.expandAll':'Alle ausklappen','board.collapseAll':'Alle einklappen',
321
+ 'board.expandAllTitle':'Alle Phasen ein- oder ausklappen','board.viewList':'Liste','board.viewKanban':'Kanban',
322
+ 'board.viewList.title':'Nach Phase gruppiert','board.viewKanban.title':'Spalten nach Status',
323
+ 'board.noTasksMatch':'Keine Aufgabe entspricht diesem Filter.',
324
+ 'board.noPlans':'Noch keine Pläne. Bitten Sie Ihren Agenten, etwas zu bauen — er startet die Aufnahme und schreibt plans/*.md.',
325
+ 'board.noAgentRunning':'kein Agent aktiv','board.noneYet':'noch keine',
326
+ 'board.workflowGlance':'Workflow auf einen Blick','board.noWorkflow':'Kein Workflow definiert.',
327
+ 'board.phaseProgress':'Phasenfortschritt ({n})',
328
+ 'rail.journal':'Journal','rail.specs':'Specs','rail.running':'Aktiv',
329
+ 'journal.empty':'Noch keine Aktivität.','journal.seeMore':'Mehr anzeigen','journal.seeLess':'Weniger anzeigen',
330
+ 'chart.scope':'Umfang','chart.delivered':'Geliefert','chart.statusDistribution':'Statusverteilung',
331
+ 'chart.scopeVsDelivered':'Umfang vs. geliefert','chart.noHistory':'Noch keine Historie.','chart.tasksSub':'Aufgaben',
332
+ 'kpi.globalProgress':'Gesamtfortschritt','kpi.tasksLabel':'Aufgaben','kpi.awaitingReview':'wartet auf Prüfung',
333
+ 'kpi.running':'Aktiv','kpi.noRunsYet':'noch keine Läufe','kpi.agentsActive':'aktive Agenten',
334
+ 'kpi.orchestration':'Orchestrierung','kpi.lastPrefix':'zuletzt: ',
335
+ 'requests.sub':'Aufgaben, die auf Ihre Eingabe warten — Status <em>zu prüfen</em> oder <em>zu analysieren</em>.',
336
+ 'requests.empty':'Nichts wartet auf Sie.',
337
+ 'attn.title':'Hinweispunkte',
338
+ 'attn.sub':'Was der Agent während der Arbeit gemeldet hat — oder was Sie notiert haben — und einen Blick verdient. <em>Bestätigen</em> Sie einen Punkt, um daraus eine Aufgabe zu machen.',
339
+ 'attn.inputPlaceholder':'Etwas notieren, das Sie im Auge behalten wollen…','attn.addNote':'Notiz hinzufügen',
340
+ 'attn.emptyOpen':'Keine Hinweispunkte. Der Agent zeigt sie hier während der Arbeit an — oder fügen Sie oben eine eigene Notiz hinzu.',
341
+ 'attn.emptyResolved':'Noch nichts erledigt.','attn.you':'Sie','attn.agentFallback':'Agent',
342
+ 'attn.resolvedChip':'erledigt',
343
+ 'backlog.sub':'Alle Aufgaben, über alle Pläne hinweg, in einer flachen Tabelle.',
344
+ 'backlog.searchPlaceholder':'Nach ID oder Titel filtern…',
345
+ 'col.id':'ID','col.title':'Titel','col.phase':'Phase','col.status':'Status','col.owner':'Verantwortlich','col.level':'Stufe',
346
+ 'backlog.pagerTask':'{n} Aufgabe','backlog.pagerTasks':'{n} Aufgaben',
347
+ 'backlog.pagerRange':'{from}–{to} von {total} · Seite {page}/{pages}',
348
+ 'backlog.prev':'‹ Zurück','backlog.next':'Weiter ›',
349
+ 'workflow.title':'Aktiver Workflow',
350
+ 'workflow.sub':'Die Pipeline, die Ihre Anfragen durchlaufen — von der Idee bis zur Auslieferung, spezifikationsgetrieben. <strong>Klicken Sie auf einen Schritt</strong>, um zu sehen, was er tut, und ihn ein- oder auszuschalten (dies bearbeitet <code>.spectoflow/workflow.md</code>). Aktivierte Schritte laufen der Reihe nach; der Orchestrator prüft jeden anhand Ihres <em>Modus</em> und Ihrer <em>Policy</em>. Optionale Schritte bleiben aus, bis Sie sie einschalten.',
351
+ 'workflow.stepsEnabled':'{enabled} von {total} Schritten aktiviert — auf einen Schritt klicken, um zu sehen, was er tut',
352
+ 'workflow.optional':'optional','workflow.enabled':'aktiviert','workflow.disabled':'deaktiviert',
353
+ 'workflow.capability':'Capability','workflow.handledBy':'Zuständig','workflow.skill':'Skill',
354
+ 'workflow.standard':'Standard','workflow.flow':'Ablauf','workflow.enableStep':'Schritt aktivieren',
355
+ 'workflow.disableStep':'Schritt deaktivieren','workflow.skillPrefix':'Der Skill „{name}“ — ',
356
+ 'wf.desc.brainstorm':'Die Anfrage erkunden, bevor man sich festlegt — Ziel, Rahmenbedingungen und Erfolgskriterien klären und aus einer rohen Idee etwas Bauwürdiges formen.',
357
+ 'wf.desc.analysis':'Die Idee zerlegen: bestehenden Code und Anforderungen prüfen, Risiken und Unklarheiten aufdecken und klare, testbare Akzeptanzkriterien festlegen.',
358
+ 'wf.desc.spec':'Die Spezifikation schreiben — die versionierte, einfache Markdown-Quelle der Wahrheit für was gebaut wird und warum, bevor Code entsteht.',
359
+ 'wf.desc.plan':'Die Spezifikation in einen geordneten Plan kleiner, abhakbarer Aufgaben umwandeln — jede für sich testbar und von einem Entwickler oder Agenten ausführbar.',
360
+ 'wf.desc.develop':'Den Plan Aufgabe für Aufgabe umsetzen, den Code (und die ihn absichernden Tests) schreiben, um jeden Punkt zu erfüllen.',
361
+ 'wf.desc.integration':'Prüfen, ob die Teile zusammenspielen — Module, Dienste und Datenflüsse über Komponentengrenzen hinweg, nicht nur isoliert.',
362
+ 'wf.desc.e2e':'Das gesamte Produkt so nutzen, wie es ein echter Anwender täte, über die reale Oberfläche und durchgängige Abläufe.',
363
+ 'wf.desc.unit':'Jede Einheit isoliert prüfen — schnelle, gezielte Tests, die Verhalten festschreiben und Regressionen früh erkennen.',
364
+ 'wf.desc.review':'Eine abschließende Qualitätsprüfung — Korrektheit, Sicherheit und Standards — bevor die Arbeit als erledigt gilt.',
365
+ 'wf.desc.deploy':'Die fertige Arbeit ausliefern — in die Zielumgebung bringen.',
366
+ 'wf.desc.fallback':'Ein Schritt in der Auslieferungs-Pipeline.',
367
+ 'team.agentsTitle':'Agenten','team.agentsSub':'Stabile Teampersonas — das <em>Wer</em>.',
368
+ 'team.skillsTitle':'Skills','team.skillsSub':'Sich weiterentwickelnde Vorgehensweisen — das <em>Wie</em>.',
369
+ 'team.standardsLabel':'Standards','team.usesLabel':'nutzt','team.standardLabel':'Standard',
370
+ 'drawer.agent':'Agent','drawer.skill':'Skill','drawer.file':'Datei · {rel}',
371
+ 'drawer.loading':'Lädt…','drawer.loadError':'Diese Datei konnte nicht geladen werden.',
372
+ 'chat.widgetTitle':'Agenten ausführen','chat.widgetSub':'Schnellzugriff · vollständige Ansicht im Chat-Tab',
373
+ 'chat.tabSub':'Vollständiges Gespräch mit dem Runner — derselbe Lauf wie im Widget, mit mehr Platz zum Lesen.',
374
+ 'chat.idle':'Geben Sie eine Anfrage ein — der Agent läuft eigenständig in diesem Projekt mit vollem Gedächtnis (<code>CLAUDE.md → AGENTS.md</code>) und aktualisiert das Board live.',
375
+ 'chat.inputPlaceholder':'z. B. Login mit E-Mail + Passwort hinzufügen',
376
+ 'chat.orchestrateTitle':'Den aktivierten Workflow durchlaufen',
377
+ 'chat.warn':'⚠ Startet einen echten Agenten (<code>config.json → runners</code>), der Dateien ändern und Befehle ausführen kann.',
378
+ 'info.title':'Info','info.sub':'Projektübersicht — Konfiguration, Zahlen, Specs und aktiver Workflow.',
379
+ 'info.project':'Projekt','info.projectType':'Projekttyp','info.mode':'Modus','info.language':'Sprache',
380
+ 'info.activeAgent':'Aktiver Agent','info.runners':'Runner','info.noRunners':'Keine Runner konfiguriert.',
381
+ 'info.counts':'Zahlen','info.tasksLabel':'Aufgaben','info.doneSub':'{pct}% erledigt','info.specsLabel':'Specs',
382
+ 'info.filesSub':'Dateien','info.agentsLabel':'Agenten','info.personasSub':'Personas','info.skillsLabel':'Skills',
383
+ 'info.proceduresSub':'Vorgehensweisen','info.workflowLabel':'Workflow','info.stepsEnabledSub':'Schritte aktiviert',
384
+ 'info.noEnabledSteps':'Keine Workflow-Schritte aktiviert.',
385
+ 'settings.sub':'Ändert, wie spectoflow läuft. Schreibt in <code>.spectoflow/config.json</code> — der Agent übernimmt es beim nächsten Lauf.',
386
+ 'field.design':'Dashboard-Design','field.mode':'Autonomiemodus','field.lang':'Ausgabesprache',
387
+ 'mode.autopilot.desc':'autopilot — läuft frei, fragt nur an Policy-Punkten',
388
+ 'mode.semi.desc':'semi — autopilot + Policy-Freigaben','mode.manual.desc':'manual — jeden Schritt bestätigen',
389
+ 'settings.saved':'✓ gespeichert','field.plansFolder':'Plan-Ordner','field.specsFolder':'Spec-Ordner',
390
+ 'field.frameworkVersion':'Framework-Version',
391
+ 'task.status':'Status','task.tests':'Tests','task.failing':'{n} fehlgeschlagen','task.passing':'{n} bestanden',
392
+ 'task.failingPassing':'{f} fehlgeschlagen, {p} bestanden','task.comments':'Kommentare','task.noComments':'Keine Kommentare.',
393
+ 'task.addCommentPlaceholder':'Kommentar, Anmerkung oder Feedback hinzufügen…',
394
+ 'task.toAnalyzeHint':'„Zu analysieren“ gibt die Aufgabe zurück, damit der Agent sie in der nächsten Runde aufgreift.',
395
+ 'customize.title':'Anpassen','customize.sub':'Fügen Sie projektspezifische Dashboards, Skills und Agenten hinzu — beschreiben Sie, was Sie wollen, oder lassen Sie Auto Kandidaten aus diesem Projekt vorschlagen.',
396
+ 'customize.dashboards':'Dashboards','customize.skills':'Skills','customize.agents':'Agenten',
397
+ 'customize.add.dashboard':'Dashboard hinzufügen','customize.add.skill':'Skill hinzufügen','customize.add.agent':'Agent hinzufügen',
398
+ 'customize.empty.dashboard':'Noch keine eigenen Dashboards.','customize.empty.skill':'Noch keine eigenen Skills.','customize.empty.agent':'Noch keine eigenen Agenten.',
399
+ 'customize.describePh':'Beschreiben Sie, was Sie wollen…','customize.auto':'Auto','customize.generate':'Generieren','customize.blocksSub':'Block/Blöcke',
400
+ },
401
+ pt: {
402
+ 'nav.board':'Painel','nav.requests':'Pedidos','nav.attention':'Atenção','nav.backlog':'Backlog',
403
+ 'nav.workflow':'Workflow','nav.team':'Agentes e habilidades','nav.chat':'Chat','nav.info':'Info','nav.settings':'Definições',
404
+ 'status.todo':'A fazer','status.in_progress':'Em curso','status.to_validate':'Por validar',
405
+ 'status.to_analyze':'Por analisar','status.done':'Concluído','status.blocked':'Bloqueado',
406
+ 'filter.all':'Todos','filter.open':'Abertos','filter.resolved':'Resolvidos',
407
+ 'action.run':'Executar','action.send':'Enviar','action.orchestrate':'Orquestrar','action.approve':'Aprovar',
408
+ 'action.cancel':'Cancelar','action.add':'Adicionar','action.edit':'Editar','action.delete':'Eliminar',
409
+ 'action.resolve':'Resolver','action.reopen':'Reabrir','action.validateToTask':'Validar → tarefa',
410
+ 'action.addToAnalyze':'Adicionar + por analisar',
411
+ 'topbar.navToggle':'Mostrar menu','topbar.run.title':'Abrir o chat de execução',
412
+ 'topbar.theme.toggle':'Alternar tema claro / escuro','topbar.theme.toggle.title':'Alternar claro / escuro',
413
+ 'topbar.mode.title':'Modo de autonomia — altere aqui ou em Definições',
414
+ 'topbar.lang.title':'Idioma de saída — altere aqui ou em Definições',
415
+ 'board.filterPlaceholder':'Filtrar tarefas…','board.expandAll':'Expandir tudo','board.collapseAll':'Recolher tudo',
416
+ 'board.expandAllTitle':'Expandir ou recolher todas as fases','board.viewList':'Lista','board.viewKanban':'Kanban',
417
+ 'board.viewList.title':'Agrupado por fase','board.viewKanban.title':'Colunas por estado',
418
+ 'board.noTasksMatch':'Nenhuma tarefa corresponde a este filtro.',
419
+ 'board.noPlans':'Ainda não há planos. Peça ao seu agente para construir algo — ele vai correr o Intake e escrever plans/*.md.',
420
+ 'board.noAgentRunning':'nenhum agente em execução','board.noneYet':'nenhum ainda',
421
+ 'board.workflowGlance':'Workflow de relance','board.noWorkflow':'Nenhum workflow definido.',
422
+ 'board.phaseProgress':'Progresso das fases ({n})',
423
+ 'rail.journal':'Diário','rail.specs':'Specs','rail.running':'Em execução',
424
+ 'journal.empty':'Ainda sem atividade.','journal.seeMore':'Ver mais','journal.seeLess':'Ver menos',
425
+ 'chart.scope':'Âmbito','chart.delivered':'Entregue','chart.statusDistribution':'Distribuição de estados',
426
+ 'chart.scopeVsDelivered':'Âmbito vs entregue','chart.noHistory':'Ainda sem histórico.','chart.tasksSub':'tarefas',
427
+ 'kpi.globalProgress':'Progresso global','kpi.tasksLabel':'tarefas','kpi.awaitingReview':'a aguardar revisão',
428
+ 'kpi.running':'Em execução','kpi.noRunsYet':'ainda sem execuções','kpi.agentsActive':'agentes ativos',
429
+ 'kpi.orchestration':'orquestração','kpi.lastPrefix':'última: ',
430
+ 'requests.sub':'Tarefas à espera da sua ação — estado <em>por validar</em> ou <em>por analisar</em>.',
431
+ 'requests.empty':'Nada à sua espera.',
432
+ 'attn.title':'Pontos de atenção',
433
+ 'attn.sub':'O que o agente assinalou durante o trabalho — ou que você anotou — e que merece um olhar. <em>Valide</em> um ponto para o transformar numa tarefa.',
434
+ 'attn.inputPlaceholder':'Anote algo a vigiar…','attn.addNote':'Adicionar nota',
435
+ 'attn.emptyOpen':'Sem pontos de atenção. O agente mostra-os aqui à medida que trabalha — ou adicione a sua própria nota acima.',
436
+ 'attn.emptyResolved':'Ainda nada resolvido.','attn.you':'você','attn.agentFallback':'agente',
437
+ 'attn.resolvedChip':'resolvido',
438
+ 'backlog.sub':'Todas as tarefas, de todos os planos, numa única tabela.',
439
+ 'backlog.searchPlaceholder':'Filtrar por id ou título…',
440
+ 'col.id':'ID','col.title':'Título','col.phase':'Fase','col.status':'Estado','col.owner':'Responsável','col.level':'Nível',
441
+ 'backlog.pagerTask':'{n} tarefa','backlog.pagerTasks':'{n} tarefas',
442
+ 'backlog.pagerRange':'{from}–{to} de {total} · página {page}/{pages}',
443
+ 'backlog.prev':'‹ Anterior','backlog.next':'Seguinte ›',
444
+ 'workflow.title':'Workflow ativo',
445
+ 'workflow.sub':'O pipeline por onde os seus pedidos passam — da ideia à entrega, guiado por especificações. <strong>Clique numa etapa</strong> para ver o que faz e ativá-la ou desativá-la (isto edita <code>.spectoflow/workflow.md</code>). As etapas ativas correm em ordem; o orquestrador filtra cada uma segundo o seu <em>modo</em> e a sua <em>policy</em>. As etapas opcionais ficam desligadas até as ativar.',
446
+ 'workflow.stepsEnabled':'{enabled} de {total} etapas ativadas — clique numa etapa para ver o que faz',
447
+ 'workflow.optional':'opcional','workflow.enabled':'ativado','workflow.disabled':'desativado',
448
+ 'workflow.capability':'Capacidade','workflow.handledBy':'A cargo de','workflow.skill':'Habilidade',
449
+ 'workflow.standard':'Padrão','workflow.flow':'Fluxo','workflow.enableStep':'Ativar etapa',
450
+ 'workflow.disableStep':'Desativar etapa','workflow.skillPrefix':'A habilidade «{name}» — ',
451
+ 'wf.desc.brainstorm':'Explorar o pedido antes de se comprometer com ele — clarificar o objetivo, as restrições e os critérios de sucesso, e transformar uma ideia em bruto em algo que valha a pena construir.',
452
+ 'wf.desc.analysis':'Decompor a ideia: estudar o código e os requisitos existentes, trazer à superfície riscos e ambiguidades, e fixar critérios de aceitação claros e testáveis.',
453
+ 'wf.desc.spec':'Escrever a especificação — a fonte de verdade versionada, em markdown simples, do que construir e porquê, antes de escrever qualquer código.',
454
+ 'wf.desc.plan':'Transformar a especificação num plano ordenado de pequenas tarefas — cada uma testável e executável isoladamente por um developer ou um agente.',
455
+ 'wf.desc.develop':'Implementar o plano tarefa a tarefa, escrevendo o código (e os testes que o garantem) para satisfazer cada item.',
456
+ 'wf.desc.integration':'Verificar que as peças funcionam em conjunto — módulos, serviços e fluxos de dados entre componentes, não apenas isoladamente.',
457
+ 'wf.desc.e2e':'Exercitar o produto por completo como um utilizador real faria, através da interface real e de fluxos ponta a ponta.',
458
+ 'wf.desc.unit':'Verificar cada unidade isoladamente — testes rápidos e focados que fixam o comportamento e apanham regressões cedo.',
459
+ 'wf.desc.review':'Uma última passagem de qualidade — correção, segurança e padrões — antes de o trabalho ser dado como terminado.',
460
+ 'wf.desc.deploy':'Entregar o trabalho concluído — publicá-lo no seu ambiente de destino.',
461
+ 'wf.desc.fallback':'Uma etapa do pipeline de entrega.',
462
+ 'team.agentsTitle':'Agentes','team.agentsSub':'Personas de equipa estáveis — o <em>quem</em>.',
463
+ 'team.skillsTitle':'Habilidades','team.skillsSub':'Procedimentos em evolução — o <em>como</em>.',
464
+ 'team.standardsLabel':'padrões','team.usesLabel':'usa','team.standardLabel':'padrão',
465
+ 'drawer.agent':'Agente','drawer.skill':'Habilidade','drawer.file':'Ficheiro · {rel}',
466
+ 'drawer.loading':'A carregar…','drawer.loadError':'Não foi possível carregar este ficheiro.',
467
+ 'chat.widgetTitle':'Executar um agente','chat.widgetSub':'Acesso rápido · vista completa no separador Chat',
468
+ 'chat.tabSub':'Conversa completa com o executor — a mesma execução do widget, com mais espaço para ler.',
469
+ 'chat.idle':'Escreva um pedido — o agente corre sem supervisão neste projeto com toda a sua memória (<code>CLAUDE.md → AGENTS.md</code>) e atualiza o painel em direto.',
470
+ 'chat.inputPlaceholder':'ex. Adicionar login com email + palavra-passe',
471
+ 'chat.orchestrateTitle':'Percorrer o workflow ativado',
472
+ 'chat.warn':'⚠ Inicia um agente real (<code>config.json → runners</code>) que pode alterar ficheiros e executar comandos.',
473
+ 'info.title':'Info','info.sub':'Visão geral do projeto — configuração, contagens, specs e workflow ativo.',
474
+ 'info.project':'Projeto','info.projectType':'Tipo de projeto','info.mode':'Modo','info.language':'Idioma',
475
+ 'info.activeAgent':'Agente ativo','info.runners':'Runners','info.noRunners':'Nenhum runner configurado.',
476
+ 'info.counts':'Contagens','info.tasksLabel':'Tarefas','info.doneSub':'{pct}% concluído','info.specsLabel':'Specs',
477
+ 'info.filesSub':'ficheiros','info.agentsLabel':'Agentes','info.personasSub':'personas','info.skillsLabel':'Habilidades',
478
+ 'info.proceduresSub':'procedimentos','info.workflowLabel':'Workflow','info.stepsEnabledSub':'etapas ativadas',
479
+ 'info.noEnabledSteps':'Nenhuma etapa de workflow ativada.',
480
+ 'settings.sub':'Altera o modo de funcionamento do spectoflow. Escreve em <code>.spectoflow/config.json</code> — o agente aplica-o na próxima execução.',
481
+ 'field.design':'Design do painel','field.mode':'Modo de autonomia','field.lang':'Idioma de saída',
482
+ 'mode.autopilot.desc':'autopilot — corre livremente, só pergunta nos pontos de policy',
483
+ 'mode.semi.desc':'semi — autopilot + aprovações de policy','mode.manual.desc':'manual — aprova cada etapa',
484
+ 'settings.saved':'✓ guardado','field.plansFolder':'Pasta de planos','field.specsFolder':'Pasta de specs',
485
+ 'field.frameworkVersion':'Versão do framework',
486
+ 'task.status':'Estado','task.tests':'Testes','task.failing':'{n} a falhar','task.passing':'{n} bem-sucedido(s)',
487
+ 'task.failingPassing':'{f} a falhar, {p} bem-sucedido(s)','task.comments':'Comentários','task.noComments':'Sem comentários.',
488
+ 'task.addCommentPlaceholder':'Adicione um comentário, uma observação, feedback…',
489
+ 'task.toAnalyzeHint':'«Por analisar» devolve a tarefa para o agente a retomar na ronda seguinte.',
490
+ 'customize.title':'Personalizar','customize.sub':'Adicione dashboards, habilidades e agentes específicos do projeto — descreva o que quer, ou deixe o Auto propor candidatos a partir deste projeto.',
491
+ 'customize.dashboards':'Dashboards','customize.skills':'Habilidades','customize.agents':'Agentes',
492
+ 'customize.add.dashboard':'Adicionar dashboard','customize.add.skill':'Adicionar habilidade','customize.add.agent':'Adicionar agente',
493
+ 'customize.empty.dashboard':'Ainda sem dashboards personalizados.','customize.empty.skill':'Ainda sem habilidades personalizadas.','customize.empty.agent':'Ainda sem agentes personalizados.',
494
+ 'customize.describePh':'Descreva o que quer…','customize.auto':'Auto','customize.generate':'Gerar','customize.blocksSub':'bloco(s)',
495
+ },
496
+ it: {
497
+ 'nav.board':'Bacheca','nav.requests':'Richieste','nav.attention':'Attenzione','nav.backlog':'Backlog',
498
+ 'nav.workflow':'Workflow','nav.team':'Agenti e competenze','nav.chat':'Chat','nav.info':'Info','nav.settings':'Impostazioni',
499
+ 'status.todo':'Da fare','status.in_progress':'In corso','status.to_validate':'Da convalidare',
500
+ 'status.to_analyze':'Da analizzare','status.done':'Fatto','status.blocked':'Bloccato',
501
+ 'filter.all':'Tutti','filter.open':'Aperti','filter.resolved':'Risolti',
502
+ 'action.run':'Avvia','action.send':'Invia','action.orchestrate':'Orchestra','action.approve':'Approva',
503
+ 'action.cancel':'Annulla','action.add':'Aggiungi','action.edit':'Modifica','action.delete':'Elimina',
504
+ 'action.resolve':'Risolvi','action.reopen':'Riapri','action.validateToTask':'Convalida → attività',
505
+ 'action.addToAnalyze':'Aggiungi + da analizzare',
506
+ 'topbar.navToggle':'Mostra menu','topbar.run.title':'Apri la chat di esecuzione',
507
+ 'topbar.theme.toggle':'Passa a tema chiaro / scuro','topbar.theme.toggle.title':'Chiaro / scuro',
508
+ 'topbar.mode.title':'Modalità di autonomia — modificabile qui o nelle Impostazioni',
509
+ 'topbar.lang.title':'Lingua di output — modificabile qui o nelle Impostazioni',
510
+ 'board.filterPlaceholder':'Filtra attività…','board.expandAll':'Espandi tutto','board.collapseAll':'Comprimi tutto',
511
+ 'board.expandAllTitle':'Espandi o comprimi tutte le fasi','board.viewList':'Elenco','board.viewKanban':'Kanban',
512
+ 'board.viewList.title':'Raggruppato per fase','board.viewKanban.title':'Colonne per stato',
513
+ 'board.noTasksMatch':'Nessuna attività corrisponde a questo filtro.',
514
+ 'board.noPlans':'Ancora nessun piano. Chiedi al tuo agente di costruire qualcosa — avvierà l’Intake e scriverà plans/*.md.',
515
+ 'board.noAgentRunning':'nessun agente in esecuzione','board.noneYet':'ancora nessuno',
516
+ 'board.workflowGlance':'Workflow a colpo d’occhio','board.noWorkflow':'Nessun workflow definito.',
517
+ 'board.phaseProgress':'Avanzamento fasi ({n})',
518
+ 'rail.journal':'Diario','rail.specs':'Specs','rail.running':'In esecuzione',
519
+ 'journal.empty':'Ancora nessuna attività.','journal.seeMore':'Vedi altro','journal.seeLess':'Vedi meno',
520
+ 'chart.scope':'Ambito','chart.delivered':'Consegnato','chart.statusDistribution':'Distribuzione degli stati',
521
+ 'chart.scopeVsDelivered':'Ambito vs consegnato','chart.noHistory':'Ancora nessuno storico.','chart.tasksSub':'attività',
522
+ 'kpi.globalProgress':'Avanzamento complessivo','kpi.tasksLabel':'attività','kpi.awaitingReview':'in attesa di revisione',
523
+ 'kpi.running':'In esecuzione','kpi.noRunsYet':'ancora nessuna esecuzione','kpi.agentsActive':'agenti attivi',
524
+ 'kpi.orchestration':'orchestrazione','kpi.lastPrefix':'ultima: ',
525
+ 'requests.sub':'Attività in attesa del tuo intervento — stato <em>da convalidare</em> o <em>da analizzare</em>.',
526
+ 'requests.empty':'Niente ti aspetta.',
527
+ 'attn.title':'Punti di attenzione',
528
+ 'attn.sub':'Ciò che l’agente ha segnalato durante il lavoro — o che hai annotato tu — e che merita uno sguardo. <em>Convalida</em> un punto per trasformarlo in un’attività.',
529
+ 'attn.inputPlaceholder':'Annota qualcosa da tenere d’occhio…','attn.addNote':'Aggiungi nota',
530
+ 'attn.emptyOpen':'Nessun punto di attenzione. L’agente li mostra qui mentre lavora — oppure aggiungi una tua nota qui sopra.',
531
+ 'attn.emptyResolved':'Ancora niente di risolto.','attn.you':'tu','attn.agentFallback':'agente',
532
+ 'attn.resolvedChip':'risolto',
533
+ 'backlog.sub':'Tutte le attività, di ogni piano, in un’unica tabella.',
534
+ 'backlog.searchPlaceholder':'Filtra per id o titolo…',
535
+ 'col.id':'ID','col.title':'Titolo','col.phase':'Fase','col.status':'Stato','col.owner':'Responsabile','col.level':'Livello',
536
+ 'backlog.pagerTask':'{n} attività','backlog.pagerTasks':'{n} attività',
537
+ 'backlog.pagerRange':'{from}–{to} di {total} · pagina {page}/{pages}',
538
+ 'backlog.prev':'‹ Precedente','backlog.next':'Successiva ›',
539
+ 'workflow.title':'Workflow attivo',
540
+ 'workflow.sub':'La pipeline che seguono le tue richieste — dall’idea alla consegna, guidata dalle specifiche. <strong>Clicca su una fase</strong> per vedere cosa fa e attivarla o disattivarla (questo modifica <code>.spectoflow/workflow.md</code>). Le fasi attive vengono eseguite in ordine; l’orchestratore filtra ciascuna in base alla tua <em>modalità</em> e alla tua <em>policy</em>. Le fasi opzionali restano disattivate finché non le attivi.',
541
+ 'workflow.stepsEnabled':'{enabled} di {total} fasi attivate — clicca su una fase per vedere cosa fa',
542
+ 'workflow.optional':'opzionale','workflow.enabled':'attivata','workflow.disabled':'disattivata',
543
+ 'workflow.capability':'Capability','workflow.handledBy':'Gestita da','workflow.skill':'Skill',
544
+ 'workflow.standard':'Standard','workflow.flow':'Flusso','workflow.enableStep':'Attiva fase',
545
+ 'workflow.disableStep':'Disattiva fase','workflow.skillPrefix':'La skill «{name}» — ',
546
+ 'wf.desc.brainstorm':'Esplorare la richiesta prima di impegnarsi — chiarire l’obiettivo, i vincoli e i criteri di successo, e trasformare un’idea grezza in qualcosa che valga la pena costruire.',
547
+ 'wf.desc.analysis':'Scomporre l’idea: studiare il codice e i requisiti esistenti, far emergere rischi e ambiguità, e fissare criteri di accettazione chiari e verificabili.',
548
+ 'wf.desc.spec':'Scrivere la specifica — la fonte di verità versionata, in markdown semplice, di cosa costruire e perché, prima di scrivere codice.',
549
+ 'wf.desc.plan':'Trasformare la specifica in un piano ordinato di piccole attività a checkbox — ciascuna verificabile ed eseguibile da sola da uno sviluppatore o da un agente.',
550
+ 'wf.desc.develop':'Implementare il piano attività per attività, scrivendo il codice (e i test che lo bloccano) per soddisfare ogni checkbox.',
551
+ 'wf.desc.integration':'Verificare che i pezzi funzionino insieme — moduli, servizi e flussi di dati oltre i confini dei componenti, non solo isolatamente.',
552
+ 'wf.desc.e2e':'Esercitare l’intero prodotto come farebbe un utente reale, attraverso l’interfaccia reale e flussi end-to-end.',
553
+ 'wf.desc.unit':'Verificare ogni unità isolatamente — test rapidi e mirati che fissano il comportamento e intercettano presto le regressioni.',
554
+ 'wf.desc.review':'Un ultimo passaggio di qualità — correttezza, sicurezza e standard — prima che il lavoro sia considerato concluso.',
555
+ 'wf.desc.deploy':'Rilasciare il lavoro consegnato — pubblicarlo nell’ambiente di destinazione.',
556
+ 'wf.desc.fallback':'Una fase della pipeline di consegna.',
557
+ 'team.agentsTitle':'Agenti','team.agentsSub':'Personas di team stabili — il <em>chi</em>.',
558
+ 'team.skillsTitle':'Skill','team.skillsSub':'Procedure in evoluzione — il <em>come</em>.',
559
+ 'team.standardsLabel':'standard','team.usesLabel':'usa','team.standardLabel':'standard',
560
+ 'drawer.agent':'Agente','drawer.skill':'Skill','drawer.file':'File · {rel}',
561
+ 'drawer.loading':'Caricamento…','drawer.loadError':'Impossibile caricare questo file.',
562
+ 'chat.widgetTitle':'Avvia un agente','chat.widgetSub':'Accesso rapido · vista completa nella scheda Chat',
563
+ 'chat.tabSub':'Conversazione completa con l’esecutore — la stessa esecuzione del widget, con più spazio per leggerla.',
564
+ 'chat.idle':'Digita una richiesta — l’agente viene eseguito senza supervisione in questo progetto con tutta la sua memoria (<code>CLAUDE.md → AGENTS.md</code>) e aggiorna la bacheca in diretta.',
565
+ 'chat.inputPlaceholder':'es. Aggiungi un login con email + password',
566
+ 'chat.orchestrateTitle':'Percorri il workflow attivato',
567
+ 'chat.warn':'⚠ Avvia un agente reale (<code>config.json → runners</code>) che può modificare file ed eseguire comandi.',
568
+ 'info.title':'Info','info.sub':'Panoramica del progetto — configurazione, conteggi, specs e workflow attivo.',
569
+ 'info.project':'Progetto','info.projectType':'Tipo di progetto','info.mode':'Modalità','info.language':'Lingua',
570
+ 'info.activeAgent':'Agente attivo','info.runners':'Runner','info.noRunners':'Nessun runner configurato.',
571
+ 'info.counts':'Conteggi','info.tasksLabel':'Attività','info.doneSub':'{pct}% completato','info.specsLabel':'Specs',
572
+ 'info.filesSub':'file','info.agentsLabel':'Agenti','info.personasSub':'personas','info.skillsLabel':'Skill',
573
+ 'info.proceduresSub':'procedure','info.workflowLabel':'Workflow','info.stepsEnabledSub':'fasi attivate',
574
+ 'info.noEnabledSteps':'Nessuna fase del workflow attivata.',
575
+ 'settings.sub':'Cambia il modo in cui funziona spectoflow. Scrive in <code>.spectoflow/config.json</code> — l’agente lo applica alla prossima esecuzione.',
576
+ 'field.design':'Design della dashboard','field.mode':'Modalità di autonomia','field.lang':'Lingua di output',
577
+ 'mode.autopilot.desc':'autopilot — agisce liberamente, chiede solo ai punti di policy',
578
+ 'mode.semi.desc':'semi — autopilot + approvazioni di policy','mode.manual.desc':'manual — approva ogni fase',
579
+ 'settings.saved':'✓ salvato','field.plansFolder':'Cartella dei piani','field.specsFolder':'Cartella delle specs',
580
+ 'field.frameworkVersion':'Versione del framework',
581
+ 'task.status':'Stato','task.tests':'Test','task.failing':'{n} falliti','task.passing':'{n} superati',
582
+ 'task.failingPassing':'{f} falliti, {p} superati','task.comments':'Commenti','task.noComments':'Nessun commento.',
583
+ 'task.addCommentPlaceholder':'Aggiungi un commento, un’osservazione, un feedback…',
584
+ 'task.toAnalyzeHint':'«Da analizzare» rimanda l’attività così l’agente la riprende al giro successivo.',
585
+ 'customize.title':'Personalizza','customize.sub':'Aggiungi dashboard, skill e agenti specifici del progetto — descrivi cosa vuoi, oppure lascia che Auto proponga candidati a partire da questo progetto.',
586
+ 'customize.dashboards':'Dashboard','customize.skills':'Skill','customize.agents':'Agenti',
587
+ 'customize.add.dashboard':'Aggiungi dashboard','customize.add.skill':'Aggiungi skill','customize.add.agent':'Aggiungi agente',
588
+ 'customize.empty.dashboard':'Ancora nessuna dashboard personalizzata.','customize.empty.skill':'Ancora nessuna skill personalizzata.','customize.empty.agent':'Ancora nessun agente personalizzato.',
589
+ 'customize.describePh':'Descrivi cosa vuoi…','customize.auto':'Auto','customize.generate':'Genera','customize.blocksSub':'blocco/i',
590
+ },
591
+ };
592
+
593
+ let currentLang = 'en';
594
+ function i18nSetLang(lang){ currentLang = (I18N[lang]) ? lang : 'en'; document.documentElement.lang = currentLang; }
595
+ function t(key, vars){
596
+ let s = (I18N[currentLang] && I18N[currentLang][key]) || (I18N.en && I18N.en[key]) || key;
597
+ if (vars) for (const k in vars) s = s.split('{'+k+'}').join(String(vars[k]));
598
+ return s;
599
+ }
600
+ function applyI18nStatic(root){
601
+ const scope = root || document;
602
+ scope.querySelectorAll('[data-i18n]').forEach(el=>{ el.textContent = t(el.getAttribute('data-i18n')); });
603
+ scope.querySelectorAll('[data-i18n-html]').forEach(el=>{ el.innerHTML = t(el.getAttribute('data-i18n-html')); });
604
+ scope.querySelectorAll('[data-i18n-ph]').forEach(el=>{ el.placeholder = t(el.getAttribute('data-i18n-ph')); });
605
+ scope.querySelectorAll('[data-i18n-title]').forEach(el=>{ el.title = t(el.getAttribute('data-i18n-title')); });
606
+ scope.querySelectorAll('[data-i18n-aria]').forEach(el=>{ el.setAttribute('aria-label', t(el.getAttribute('data-i18n-aria'))); });
607
+ }