kimal3 0.2.9 → 0.3.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 (67) hide show
  1. package/README.md +135 -0
  2. package/dist/api.js +16 -7
  3. package/dist/arbeitsplatz-dateien.js +62 -30
  4. package/dist/argumente.js +25 -97
  5. package/dist/befehle/arbeitsplatz.js +51 -68
  6. package/dist/befehle/firma-daten.js +24 -26
  7. package/dist/befehle/kontext-fragen.js +62 -44
  8. package/dist/befehle/kontext-gemeinsam.js +86 -43
  9. package/dist/befehle/kontext-hoch.js +40 -46
  10. package/dist/befehle/kontext-runter.js +70 -51
  11. package/dist/befehle/login.js +23 -9
  12. package/dist/befehle/logout.js +9 -4
  13. package/dist/befehle/projekt-liste.js +24 -29
  14. package/dist/befehle/projekt-neu.js +25 -31
  15. package/dist/befehle/skill-install.js +78 -49
  16. package/dist/befehle/skill-tausch.js +28 -0
  17. package/dist/befehle/wache.js +12 -6
  18. package/dist/befehle/werkbank.js +118 -88
  19. package/dist/befehle-katalog-en.js +185 -0
  20. package/dist/befehle-katalog.js +10 -49
  21. package/dist/befehlswoerter.js +69 -0
  22. package/dist/einstellungen-mischen.js +2 -2
  23. package/dist/einstellungen-schreiben.js +8 -5
  24. package/dist/fehler.js +5 -5
  25. package/dist/firmen-liste.js +42 -5
  26. package/dist/format.js +41 -0
  27. package/dist/fragen-lesen.js +3 -3
  28. package/dist/hilfe.js +24 -0
  29. package/dist/kimal3.js +77 -71
  30. package/dist/kontext-dateien.js +30 -23
  31. package/dist/kontext-hoch-zeile.js +5 -3
  32. package/dist/kontext-rat.js +151 -0
  33. package/dist/kontext-stand.js +68 -210
  34. package/dist/nachricht.js +39 -15
  35. package/dist/projekt-neu-firma.js +9 -9
  36. package/dist/projekt-zeilen.js +40 -54
  37. package/dist/slash-befehle.js +36 -0
  38. package/dist/sprache.js +114 -0
  39. package/dist/texte/allgemein.js +99 -0
  40. package/dist/texte/arbeitsplatz.js +135 -0
  41. package/dist/texte/kontext-hoch.js +128 -0
  42. package/dist/texte/kontext.js +171 -0
  43. package/dist/texte/projekte.js +126 -0
  44. package/dist/texte/skill.js +87 -0
  45. package/dist/texte/wache.js +36 -0
  46. package/dist/texte/werkbank.js +161 -0
  47. package/dist/wache-rechnung.js +27 -40
  48. package/dist/wache-schalter.js +40 -5
  49. package/dist/werkbank-name.js +28 -10
  50. package/dist/wort.js +98 -0
  51. package/package.json +27 -27
  52. package/skill/SKILL.md +18 -10
  53. package/skill/commands/k3.md +1 -1
  54. package/skill/commands/k3feierabend.md +99 -97
  55. package/skill/commands/k3kontext.md +2 -2
  56. package/skill/commands/k3kurs.md +6 -5
  57. package/skill/commands/k3start.md +2 -1
  58. package/skill/en/SKILL.md +451 -0
  59. package/skill/en/commands/k3.md +106 -0
  60. package/skill/en/commands/k3analyse.md +59 -0
  61. package/skill/en/commands/k3context.md +92 -0
  62. package/skill/en/commands/k3course.md +54 -0
  63. package/skill/en/commands/k3list.md +26 -0
  64. package/skill/en/commands/k3project.md +50 -0
  65. package/skill/en/commands/k3start.md +47 -0
  66. package/skill/en/commands/k3wrapup.md +99 -0
  67. package/dist/zz-kaputt.js +0 -1
@@ -4,8 +4,11 @@ import { fileURLToPath } from "node:url";
4
4
  import { join } from "node:path";
5
5
  import { einstellungenDatei, trageWacheEin } from "../einstellungen-schreiben.js";
6
6
  import { merkeSitzung, sitzungJetzt } from "../wache-schalter.js";
7
- import { STEMPEL_MARKE } from "../nachricht.js";
7
+ import { stempelZeile } from "../nachricht.js";
8
8
  import { eigeneVersion } from "../version.js";
9
+ import { sprache } from "../sprache.js";
10
+ import { andereSpracheZuRaeumen, skillQuelle } from "../slash-befehle.js";
11
+ import { SKILL_TEXTE } from "../texte/skill.js";
9
12
  export const VERALTETE_BEFEHLE = [
10
13
  /*
11
14
  🔴 **Der ERSTE Eintrag ueberhaupt** (2026-08-28). `/k3firma` heisst jetzt
@@ -45,7 +48,7 @@ export function skillOrdner() {
45
48
  return join(homedir(), ".claude", "skills", "kimal3");
46
49
  }
47
50
  export function skillDatei() {
48
- return join(skillOrdner(), "SKILL.md");
51
+ return join(skillOrdner(), "SKILL.md"); // kein-anzeigetext: Dateiname
49
52
  }
50
53
  /**
51
54
  * Haengt die eigene Versionsnummer ans ENDE des Skill-Textes.
@@ -77,12 +80,14 @@ export function skillDatei() {
77
80
  * ⚠️ Ohne eigene Nummer GAR KEIN Stempel. Ein erfundener Ersatzwert waere
78
81
  * schlimmer als keiner: Die CLI vergliche spaeter gegen ihre eigene Erfindung.
79
82
  * Ohne Stempel antwortet `skillZustand` "veraltet" -- die harmlose Seite.
83
+ *
84
+ * 🌐 Seit Teil 4 traegt der englische Stempel ` sprache=en`; der deutsche ist Zeichen fuer Zeichen der alte.
80
85
  */
81
- function mitStempel(inhalt) {
86
+ export function mitStempel(inhalt, s) {
82
87
  const eigene = eigeneVersion();
83
88
  if (eigene === null)
84
89
  return inhalt;
85
- return `${inhalt.trimEnd()}\n\n<!-- ${STEMPEL_MARKE}${eigene} -->\n`;
90
+ return `${inhalt.trimEnd()}\n\n${stempelZeile(eigene, s)}\n`;
86
91
  }
87
92
  /**
88
93
  * Legt das Skill UND die Slash-Befehle GLOBAL ab, damit Claude dieses Werkzeug
@@ -103,7 +108,9 @@ function mitStempel(inhalt) {
103
108
  * `dist/befehle/skill-install.js` -> zwei Ebenen hoch -> `skill/…`.
104
109
  */
105
110
  export async function skillInstall() {
106
- const quelle = fileURLToPath(new URL("../../skill/SKILL.md", import.meta.url));
111
+ const s = sprache();
112
+ const t = SKILL_TEXTE[s];
113
+ const quelle = fileURLToPath(new URL(`../../${skillQuelle(s).skill}`, import.meta.url)); // kein-anzeigetext: Paketpfad
107
114
  if (!existsSync(quelle)) {
108
115
  /*
109
116
  🔴 **`1`, nicht `3`** (Review-Befund, 2026-08-18). Ein unvollstaendiges
@@ -112,8 +119,8 @@ export async function skillInstall() {
112
119
  Text, und wuerde einen Rat geben, der garantiert nicht hilft. Genau der
113
120
  Fehlertyp, den dieser Zweig bei B-5, B-7 und L-7 behoben hat.
114
121
  */
115
- console.error("Das Skill liegt nicht im Paket. Bitte kimal3 neu installieren:");
116
- console.error(" npm install -g kimal3");
122
+ console.error(t.skillMissing);
123
+ console.error(" npm install -g kimal3"); // kein-anzeigetext: Befehlszeile zum Kopieren
117
124
  return 1;
118
125
  }
119
126
  // 🔑 GLOBAL, nicht projektlokal (Fund von Dennis, 2026-08-13).
@@ -161,15 +168,15 @@ export async function skillInstall() {
161
168
  Der Stempel spricht ueber die SKILL.md, nicht ueber den ganzen Lauf.
162
169
  */
163
170
  const inhalt = readFileSync(quelle, "utf8");
164
- writeFileSync(ziel, mitStempel(inhalt), "utf8");
171
+ writeFileSync(ziel, mitStempel(inhalt, s), "utf8");
165
172
  }
166
173
  catch (fehler) {
167
- console.error(`Das Skill liess sich nicht schreiben: ${String(fehler)}`);
174
+ console.error(t.skillWriteFailed(String(fehler)));
168
175
  return 3;
169
176
  }
170
- console.log(gabEsSchon ? "✓ Skill aktualisiert." : "✓ Skill angelegt.");
177
+ console.log(gabEsSchon ? t.skillUpdated : t.skillCreated);
171
178
  console.log(` ${ziel}`);
172
- const namen = slashBefehleInstallieren();
179
+ const namen = slashBefehleInstallieren(s, false);
173
180
  if (namen === "kaputt") {
174
181
  /*
175
182
  ⚠️ **Was hier zaehlt, ist die TEILWIRKUNG** (Review-Runde 2, 2026-08-18):
@@ -178,31 +185,31 @@ export async function skillInstall() {
178
185
  nun gilt. *Ein halber Erfolg ist weder ein Erfolg noch ein Totalausfall
179
186
  -- er ist ein eigener Zustand und braucht einen eigenen Satz.*
180
187
  */
181
- console.error(" Das Skill ist installiert, die Slash-Befehle sind es NICHT.");
188
+ console.error(t.skillOnlyInstalled);
182
189
  return 1;
183
190
  }
184
191
  const { geschrieben, uebersprungen, unlesbar, gestoert } = namen;
185
192
  if (geschrieben.length > 0) {
186
- console.log(`✓ ${geschrieben.length} Slash-Befehle: ${geschrieben.map((n) => `/${n}`).join(" · ")}`);
193
+ console.log(t.commandsInstalled(geschrieben.length, geschrieben.map((n) => `/${n}`).join(" · ")));
187
194
  console.log(` ${join(homedir(), ".claude", "commands")}`);
188
195
  }
189
196
  // ⚠️ Uebersprungene Dateien gehoeren in die AUSGABE, nicht nur in die Logik.
190
197
  // Ein Mensch, dem stillschweigend ein Befehl fehlt, sucht den Fehler bei
191
198
  // sich. (Review-Runde 2, 2026-08-18.)
192
199
  if (uebersprungen.length > 0) {
193
- console.log(`⚠ ${uebersprungen.length} übersprungen: ${uebersprungen.map((n) => `/${n}`).join(" · ")}`);
194
- console.log(" Dort liegt bereits eine Datei, die nicht von kimal3 stammt —");
195
- console.log(" sie bleibt unangetastet. Wer die kimal3-Fassung will, benennt");
196
- console.log(" die eigene um und führt den Befehl erneut aus.");
200
+ console.log(t.skipped(uebersprungen.length, uebersprungen.map((n) => `/${n}`).join(" · ")));
201
+ console.log(t.skipped1);
202
+ console.log(t.skipped2);
203
+ console.log(t.skipped3);
197
204
  }
198
205
  // 🔴 Ein LESEFEHLER bekommt einen eigenen Satz (Review-Runde 6): Er sieht
199
206
  // aus wie Fremdbesitz, ist aber keiner -- und der Rat "benenn deine Datei
200
207
  // um" waere hier falsch.
201
208
  if (unlesbar.length > 0) {
202
- console.log(`⚠ ${unlesbar.length} nicht lesbar: ${unlesbar.map((n) => `/${n}`).join(" · ")}`);
203
- console.log(" Diese Dateien liessen sich nicht öffnen — vielleicht sind sie");
204
- console.log(" gerade in Benutzung. Sie wurden nicht angefasst; ein zweiter");
205
- console.log(" Versuch gleich kann klappen.");
209
+ console.log(t.unreadable(unlesbar.length, unlesbar.map((n) => `/${n}`).join(" · ")));
210
+ console.log(t.unreadable1);
211
+ console.log(t.unreadable2);
212
+ console.log(t.unreadable3);
206
213
  }
207
214
  /*
208
215
  🔴 **Kein Slash-Befehl installiert ist kein Erfolg** (Review-Runde 5,
@@ -218,8 +225,8 @@ export async function skillInstall() {
218
225
  */
219
226
  if (geschrieben.length === 0) {
220
227
  const wiederholbar = gestoert || unlesbar.length > 0;
221
- console.error(" Es wurde KEIN Slash-Befehl installiert.");
222
- console.error(" Das Skill selbst ist installiert und funktioniert.");
228
+ console.error(t.noCommandInstalled1);
229
+ console.error(t.noCommandInstalled2);
223
230
  return wiederholbar ? 3 : 1;
224
231
  }
225
232
  /*
@@ -229,8 +236,8 @@ export async function skillInstall() {
229
236
  Teilwirkung weg und meldete alles als misslungen.
230
237
  */
231
238
  if (gestoert) {
232
- console.error(" Nicht alle Slash-Befehle konnten geschrieben werden.");
233
- console.error(" Die oben genannten stehen; ein zweiter Lauf holt den Rest.");
239
+ console.error(t.notAllWritten1);
240
+ console.error(t.notAllWritten2);
234
241
  return 3;
235
242
  }
236
243
  /*
@@ -246,7 +253,7 @@ export async function skillInstall() {
246
253
  Hinweis, den kein Befolgen aufloesen konnte.
247
254
  */
248
255
  if (unlesbar.length > 0) {
249
- console.error(" Der Lauf ist damit unvollstaendig -- ein zweiter Versuch holt den Rest.");
256
+ console.error(t.runIncomplete);
250
257
  return 3;
251
258
  }
252
259
  /*
@@ -283,33 +290,31 @@ export async function skillInstall() {
283
290
  merkeSitzung(sitzungJetzt());
284
291
  }
285
292
  if (wache.art === "eingetragen") {
286
- console.log(" Die taegliche kimal3-Pruefung ist eingetragen. Sie meldet sich nur, wenn etwas ansteht.");
293
+ console.log(t.watchSetUp);
287
294
  }
288
295
  else if (wache.art === "stand-schon") {
289
- console.log(" Die taegliche kimal3-Pruefung steht schon in deinen Einstellungen.");
296
+ console.log(t.watchAlready);
290
297
  }
291
298
  else if (wache.art === "abgelehnt") {
292
299
  console.error("");
293
- console.error(" Die taegliche kimal3-Pruefung konnte NICHT eingetragen werden.");
294
- console.error(` Deine Claude-Einstellungen sind nicht lesbar: ${einstellungenDatei()}`);
295
- console.error(wache.grund === "kein-gueltiges-json"
296
- ? " Die Datei ist kein gueltiges JSON. Sie wurde NICHT angefasst."
297
- : " Die Datei hat eine Form, die wir nicht verstehen. Sie wurde NICHT angefasst.");
298
- console.error(" Wiederholen hilft nicht -- erst die Datei in Ordnung bringen.");
300
+ console.error(t.watchFailed);
301
+ console.error(t.settingsUnreadable(einstellungenDatei()));
302
+ console.error(wache.grund === "kein-gueltiges-json" ? t.settingsNotJson : t.settingsStrangeShape);
303
+ console.error(t.settingsRetryNoHelp);
299
304
  return 1;
300
305
  }
301
306
  else if (wache.art === "gescheitert") {
302
307
  console.error("");
303
- console.error(" Die taegliche kimal3-Pruefung konnte NICHT eingetragen werden.");
304
- console.error(` ${einstellungenDatei()}: ${wache.grund}`);
305
- console.error(" Deine bisherigen Einstellungen sind unveraendert.");
308
+ console.error(t.watchFailed);
309
+ console.error(t.settingsFailedLine(einstellungenDatei(), ursacheDes(wache, t)));
310
+ console.error(t.settingsUnchanged);
306
311
  return 1;
307
312
  }
308
313
  if (geschrieben.includes("k3")) {
309
- console.log(" Tipp /k3 in Claude Code. (Taucht nichts auf, einmal neu starten.)");
314
+ console.log(t.tipK3);
310
315
  }
311
316
  else {
312
- console.log(` Tipp /${geschrieben[0]} in Claude Code. (Taucht nichts auf, einmal neu starten.)`);
317
+ console.log(t.tipOther(geschrieben[0]));
313
318
  }
314
319
  return 0;
315
320
  }
@@ -326,16 +331,22 @@ export async function skillInstall() {
326
331
  * Wiederholen hilft NIE) bzw. `"stoerung"` (Schreiben ging schief, Wiederholen
327
332
  * kann helfen). *Zwei Fehlerfaelle, die Gegenteiliges verlangen, duerfen nicht
328
333
  * denselben Namen tragen.*
334
+ *
335
+ * 🌐 `leise`: `kimal3 login` stellt den Satz nach der Anmeldung auf die Kontosprache um (`skill-tausch.ts`)
336
+ * und sagt dazu EINE Zeile -- die Einzelmeldungen dieses Laufs gehoeren dann nicht auf den Bildschirm.
329
337
  */
330
- function slashBefehleInstallieren() {
331
- const quellOrdner = fileURLToPath(new URL("../../skill/commands", import.meta.url));
338
+ export function slashBefehleInstallieren(s, leise) {
339
+ const t = SKILL_TEXTE[s];
340
+ const quellOrdner = fileURLToPath(new URL(`../../${skillQuelle(s).befehle}`, import.meta.url)); // kein-anzeigetext: Paketpfad
332
341
  if (!existsSync(quellOrdner)) {
333
- console.error("Die Slash-Befehle liegen nicht im Paket. Bitte kimal3 neu installieren.");
342
+ if (!leise)
343
+ console.error(t.commandsMissing);
334
344
  return "kaputt";
335
345
  }
336
346
  const dateien = readdirSync(quellOrdner).filter((n) => n.endsWith(".md")).sort();
337
347
  if (dateien.length === 0) {
338
- console.error("Im Paket liegt kein einziger Slash-Befehl. Bitte kimal3 neu installieren.");
348
+ if (!leise)
349
+ console.error(t.commandsNone);
339
350
  return "kaputt";
340
351
  }
341
352
  const zielOrdner = join(homedir(), ".claude", "commands");
@@ -390,7 +401,8 @@ function slashBefehleInstallieren() {
390
401
  `geschrieben` und `uebersprungen` sind ausserhalb des `try` deklariert,
391
402
  genau dafuer.
392
403
  */
393
- console.error(`Die Slash-Befehle liessen sich nicht alle schreiben: ${String(fehler)}`);
404
+ if (!leise)
405
+ console.error(t.commandsWriteFailed(String(fehler)));
394
406
  gestoert = true;
395
407
  }
396
408
  /*
@@ -426,9 +438,11 @@ function slashBefehleInstallieren() {
426
438
  immer den Dateinamen. Ohne die Angleichung schluege der Vergleich fehl, und
427
439
  ein Eintrag ohne `.md` bliebe fuer immer liegen.
428
440
  */
429
- const alsDatei = (n) => (n.endsWith(".md") ? n : `${n}.md`);
441
+ const alsDatei = (n) => (n.endsWith(".md") ? n : `${n}.md`); // kein-anzeigetext: Dateiname
430
442
  const ersatzLiegt = VERALTETE_BEFEHLE.filter((e) => e.ersetztDurch === null || geschrieben.includes(alsDatei(e.ersetztDurch))).map((e) => e.alt);
431
- raeumeVeralteteAuf(zielOrdner, ersatzLiegt);
443
+ // 🌐 Teil 4 (T4-3): Die eigenen Dateien der anderen Sprache gehen denselben Weg wie umbenannte Befehle --
444
+ // nur, wenn ihr Ersatz in diesem Lauf wirklich geschrieben wurde, und nur mit unserer Marke (`raeumeVeralteteAuf`).
445
+ raeumeVeralteteAuf(zielOrdner, [...ersatzLiegt, ...andereSpracheZuRaeumen(geschrieben, s)], leise);
432
446
  return {
433
447
  geschrieben: geschrieben.map((n) => n.replace(/\.md$/, "")),
434
448
  uebersprungen: uebersprungen.map((n) => n.replace(/\.md$/, "")),
@@ -436,6 +450,20 @@ function slashBefehleInstallieren() {
436
450
  gestoert,
437
451
  };
438
452
  }
453
+ /**
454
+ * Die Ursache, warum die Wache nicht eingetragen werden konnte, in der Sprache des Menschen.
455
+ * `einstellungen-schreiben.ts` nennt nur den SCHRITT (und die Meldung des Systems); den Satz dazu
456
+ * liefert die Textdatei -- dort steht er in beiden Sprachen.
457
+ */
458
+ export function ursacheDes(wache, t) {
459
+ if (wache.schritt === "kontrolle")
460
+ return t.stepCheck(wache.detail);
461
+ if (wache.schritt === "lesen")
462
+ return t.stepRead(wache.detail);
463
+ if (wache.schritt === "sichern")
464
+ return t.stepBackup(wache.detail);
465
+ return t.stepWrite(wache.detail);
466
+ }
439
467
  /** Liest eine Datei — `null`, wenn sie sich nicht lesen laesst. */
440
468
  function leseWennMoeglich(pfad) {
441
469
  try {
@@ -465,7 +493,7 @@ function leseWennMoeglich(pfad) {
465
493
  * Gibt zurueck, was wirklich entfernt wurde -- eine Behauptung waere hier
466
494
  * genau das Falsche.
467
495
  */
468
- export function raeumeVeralteteAuf(zielOrdner, veraltet) {
496
+ export function raeumeVeralteteAuf(zielOrdner, veraltet, leise = false) {
469
497
  const entfernt = [];
470
498
  for (const eintrag of veraltet) {
471
499
  /*
@@ -474,7 +502,7 @@ export function raeumeVeralteteAuf(zielOrdner, veraltet) {
474
502
  ein" -- gejoint wird aber ein DATEIname. Wer `"k3alt"` eintraegt, bekam
475
503
  keinen Fehler: nichts wird entfernt, nichts gemeldet.
476
504
  */
477
- const alt = eintrag.endsWith(".md") ? eintrag : `${eintrag}.md`;
505
+ const alt = eintrag.endsWith(".md") ? eintrag : `${eintrag}.md`; // kein-anzeigetext: Dateiname
478
506
  const weg = join(zielOrdner, alt);
479
507
  try {
480
508
  if (!existsSync(weg))
@@ -487,7 +515,8 @@ export function raeumeVeralteteAuf(zielOrdner, veraltet) {
487
515
  }
488
516
  rmSync(weg);
489
517
  entfernt.push(alt);
490
- console.log(` (veralteten Befehl /${alt.replace(/\.md$/, "")} entfernt)`);
518
+ if (!leise)
519
+ console.log(SKILL_TEXTE[sprache()].outdatedRemoved(alt.replace(/\.md$/, "")));
491
520
  }
492
521
  catch {
493
522
  // Bewusst still: Die Befehle sind installiert. Eine liegengebliebene
@@ -0,0 +1,28 @@
1
+ import { readFileSync, writeFileSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
3
+ import { skillTauschNoetig } from "../nachricht.js";
4
+ import { skillQuelle } from "../slash-befehle.js";
5
+ import { mitStempel, skillDatei, slashBefehleInstallieren } from "./skill-install.js";
6
+ export function stelleSkillUm(s) {
7
+ let vorhanden = null;
8
+ try {
9
+ vorhanden = readFileSync(skillDatei(), "utf8");
10
+ }
11
+ catch {
12
+ /* keine (lesbare) Datei: nichts umzustellen */
13
+ }
14
+ if (!skillTauschNoetig(vorhanden, s))
15
+ return "nichts";
16
+ try {
17
+ const quelle = fileURLToPath(new URL(`../../${skillQuelle(s).skill}`, import.meta.url)); // kein-anzeigetext: Paketpfad
18
+ writeFileSync(skillDatei(), mitStempel(readFileSync(quelle, "utf8"), s), "utf8");
19
+ const namen = slashBefehleInstallieren(s, true);
20
+ if (namen === "kaputt")
21
+ return "unvollstaendig";
22
+ const komplett = !namen.gestoert && namen.uebersprungen.length === 0 && namen.unlesbar.length === 0;
23
+ return komplett ? "umgestellt" : "unvollstaendig";
24
+ }
25
+ catch {
26
+ return "unvollstaendig";
27
+ }
28
+ }
@@ -4,6 +4,8 @@ import { lokalerKontextStandJetzt } from "../api.js";
4
4
  import { leseGesehen, merkeGesehen } from "../gesehen.js";
5
5
  import { heuteAus, sollZeigen, skillZustand } from "../nachricht.js";
6
6
  import { eigeneVersion } from "../version.js";
7
+ import { WACHE_TEXTE } from "../texte/wache.js";
8
+ import { KONTO_KOPF, SPRACH_KOPF, sprache, uebernimmKontosprache } from "../sprache.js";
7
9
  import { leseWacheDatei, merkeLauf, merkeSitzung, schonFuerDieseSitzung, setzeWache, sitzungJetzt, sollHeuteLaufen, } from "../wache-schalter.js";
8
10
  import { alsHookAusgabe, laufErledigt, wacheAntwortAusHttp, wacheBefunde, wacheBlock, } from "../wache-rechnung.js";
9
11
  import { skillDatei } from "./skill-install.js";
@@ -84,7 +86,7 @@ function skillIstVeraltet() {
84
86
  return false;
85
87
  const datei = skillDatei();
86
88
  const inhalt = existsSync(datei) ? readFileSync(datei, "utf8") : null;
87
- return skillZustand(inhalt, eigene) === "veraltet";
89
+ return skillZustand(inhalt, eigene, sprache()) === "veraltet";
88
90
  }
89
91
  /**
90
92
  * Der eine Anruf beim eigenen Server -- Zugang pruefen, Nachricht abholen.
@@ -114,10 +116,12 @@ async function frageServer(schluessel, heute) {
114
116
  // (live gemessen 17.09.). Faellt die Version aus, geht der Kopf nicht mit.
115
117
  const version = eigeneVersion();
116
118
  const antwort = await fetch(`${BASIS_URL}/api/cli/wache`, {
117
- method: "POST",
118
- headers: { Authorization: `Bearer ${schluessel}`, ...(version ? { "X-Kimal3-Version": version } : {}) },
119
+ method: "POST", // kein-anzeigetext: HTTP-Methode
120
+ headers: { Authorization: `Bearer ${schluessel}`, [SPRACH_KOPF]: sprache(), ...(version ? { "X-Kimal3-Version": version } : {}) }, // kein-anzeigetext: HTTP-Kopf
119
121
  signal: AbortSignal.timeout(ZEITGRENZE_MS),
120
122
  });
123
+ // 🌐 Die Wache baut ihre Zeilen NACH dieser Antwort -- eine neue Kontosprache gilt schon dafuer (L-5).
124
+ uebernimmKontosprache(antwort.headers.get(KONTO_KOPF));
121
125
  const koerper = await antwort.json().catch(() => null);
122
126
  const { zugangGilt, hinweis, bekannt } = wacheAntwortAusHttp(antwort.status, koerper);
123
127
  if (!hinweis)
@@ -205,13 +209,15 @@ export async function wache(alsHook) {
205
209
  frageServer(anmeldung.schluessel, heute),
206
210
  neuesteVonNpm(ZEITGRENZE_MS),
207
211
  ]);
212
+ // 🌐 Erst jetzt gelesen: eine Kontosprache aus der Antwort gilt schon (L-5); bei 401 und ohne
213
+ // Netz traegt der Merkzettel sie (L-7, L-8).
208
214
  const befunde = wacheBefunde({
209
215
  zugangGilt: vomServer.zugangGilt,
210
216
  nachricht: vomServer.hinweis?.text ?? null,
211
217
  eigeneVersion: eigeneVersion(),
212
218
  neuesteVersion: vonNpm,
213
219
  skillVeraltet: skillIstVeraltet(),
214
- });
220
+ }, sprache());
215
221
  const zeilen = befunde.map((b) => b.zeile);
216
222
  // 🔴 VOR der Ausgabe -- sonst spricht die Wache bei einem Fehler in der
217
223
  // Ausgabe morgen wieder und uebermorgen wieder.
@@ -231,7 +237,7 @@ export async function wache(alsHook) {
231
237
  merkeLauf(heute);
232
238
  if (zeilen.length === 0)
233
239
  return 0;
234
- console.log(alsHook ? alsHookAusgabe(zeilen) : wacheBlock(zeilen));
240
+ console.log(alsHook ? alsHookAusgabe(zeilen, sprache()) : wacheBlock(zeilen));
235
241
  // Erst NACH dem Drucken vermerken, dass die Nachricht heute schon lief --
236
242
  // dieselbe Reihenfolge wie beim Update-Kanal in kimal3.ts. Daran haengt
237
243
  // ihr Einmal-am-Tag, NICHT am Lauf-Stempel: Beim wiederholten Lauf kommt
@@ -253,6 +259,6 @@ export async function wache(alsHook) {
253
259
  */
254
260
  export function wacheSchalten(an) {
255
261
  setzeWache(an);
256
- console.log(an ? "✓ Wache eingeschaltet." : "✓ Wache ausgeschaltet.");
262
+ console.log(an ? WACHE_TEXTE[sprache()].watchOn : WACHE_TEXTE[sprache()].watchOff);
257
263
  return 0;
258
264
  }