-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathi18n.h
More file actions
697 lines (679 loc) · 40.8 KB
/
Copy pathi18n.h
File metadata and controls
697 lines (679 loc) · 40.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
#ifndef I18N_H
#define I18N_H
// i18n.h
#include <string>
#include <unordered_map>
#include <cstdlib> // getenv
#include <windows.h> // GetUserDefaultUILanguage
// ── Alle Texte als IDs ────────────────────────────────────────────────
enum class Str {
// Statusmeldungen
STARTED, TIMER_COUNTER, TIMER_AT_TIME, TIMER_AT_DATETIME, TIMER_DAILY, TIMER_EVERY, TIMER_TARGET,
REMAINING, LOOP_PREFIX, TIMER_ENDED,
ASYNC_SUFFIX, ERROR_NO_TIME, ERROR_PAST_DATETIME,
ERROR_INVALID_AT, ERROR_INVALID_DAILY, ERROR_NO_DAILY_TIMES,
ERROR_UNKNOWN_OPTION, ERROR_UNKNOWN_UNIT, ERROR_NEXT_TIME,
ERROR_FILE_CONVERSION, ERROR_CMD_CONVERSION,
ERROR_DETACHED_UNIT,
ERROR_INVALID_EVERY,
NO_COMMAND,
// Alarm / Benachrichtigung
NOTIFY_TITLE, NOTIFY_MSG,
// Datei / Befehl
FILE_NOT_FOUND, FILE_NOT_FOUND_WARN, FILE_OPENED, FILE_ERROR,
CMD_STARTED, CMD_ERROR,
AUDIO_NOT_FOUND, AUDIO_PATH_ERROR,
FILE_SYSTEM_ERROR,
// Fenster-Fokus
WINDOW_NOT_FOUND_WARN,
// Hilfe
USAGE_HEADER,
TOMORROW_SUFFIX,
FOCUS_TARGET,
OPEN_TARGET,
STOPWATCH_LABEL,
ELAPSED,
STOPWATCH_HINT,
STOPWATCH_PAUSED,
// Makros
MACRO_ADDED,
MACRO_OVERWRITE_PROMPT,
MACRO_OVERWRITE_YES,
MACRO_REMOVED,
MACRO_NOT_FOUND,
MACRO_LIST_HEADER,
MACRO_LIST_EMPTY,
MACRO_INVALID_NAME,
MACRO_INVALID_SUBCMD,
MACRO_NAME_RESERVED,
MACRO_MISSING_NAME,
MACRO_MISSING_SUBCMD,
MACRO_MISSING_ARGS,
PRESS_ANY_KEY,
ERROR_FOR_REQUIRES_LOOP,
FOR_TARGET_OUTSIDE,
ERROR_INVALID_FOR,
WARN_ALARM_REPEAT_INVALID,
WARN_ALARM_REPEAT_TOO_LARGE,
WARN_PATH_TOO_LONG,
WARN_TIMER_PERIOD,
_COUNT
};
// ── Übersetzungstabelle ───────────────────────────────────────────────
using TranslationMap = std::unordered_map<Str, const char*>;
static const TranslationMap LANG_DE = {
{ Str::STARTED, "Teefax [v%s] gestartet" },
{ Str::TIMER_COUNTER, " mit Zaehler: %s" },
{ Str::TIMER_AT_TIME, " fuer Uhrzeit %02d:%02d:%02d" },
{ Str::TIMER_AT_DATETIME, " fuer Datum %04lld-%02d-%02d %02d:%02d:%02d" },
{ Str::TIMER_DAILY, " mit taeglichem Alarm." },
{ Str::TIMER_EVERY, " jeden %s um %02d:%02d:%02d" },
{ Str::TIMER_TARGET, " (bis %02d:%02d:%02d)" },
{ Str::REMAINING, "Verbleibend: %s" },
{ Str::LOOP_PREFIX, "Durchlauf %lld | " },
{ Str::TIMER_ENDED, "\nZaehler beendet." },
{ Str::ASYNC_SUFFIX, " (async sound)" },
{ Str::ERROR_NO_TIME, "Bitte eine gueltige Zeit oder --at angeben." },
{ Str::ERROR_PAST_DATETIME, "Datum/Zeit ungueltig oder Vergangenheit." },
{ Str::ERROR_INVALID_AT, "Ungueltiges Zeitformat fuer --at." },
{ Str::ERROR_INVALID_DAILY, "Ungueltige Uhrzeit: %s" },
{ Str::ERROR_NO_DAILY_TIMES, "Keine Uhrzeiten fuer --daily angegeben." },
{ Str::ERROR_UNKNOWN_OPTION, "Unbekannte Option: %s" },
{ Str::ERROR_DETACHED_UNIT, "Zeiteinheit ohne Zahl: '%s'. Einheiten direkt anhaengen (z. B. '5m', nicht '5 m')." },
{ Str::ERROR_INVALID_EVERY, "Ungueltiges --every Argument: %s" },
{ Str::NOTIFY_TITLE, "Teefax" },
{ Str::NOTIFY_MSG, "Die Zeit ist verstrichen!" },
{ Str::FILE_NOT_FOUND, "\nDatei nicht gefunden: %s" },
{ Str::FILE_NOT_FOUND_WARN, "Warnung: Datei \"%s\" nicht gefunden." },
{ Str::FILE_OPENED, "\nDatei geoeffnet: %s" },
{ Str::FILE_ERROR, "\nFehler beim Oeffnen (Code %d): %s" },
{ Str::CMD_STARTED, "Befehl gestartet: %s" },
{ Str::CMD_ERROR, "Fehler beim Ausfuehren (%d): %s" },
{ Str::ERROR_UNKNOWN_UNIT, "Unbekannte Einheit: %s" },
{ Str::ERROR_FILE_CONVERSION, "\nFehler bei der Pfad-Konvertierung: %s" },
{ Str::ERROR_CMD_CONVERSION, "\nFehler bei der Befehls-Konvertierung: %s" },
{ Str::NO_COMMAND, "\nKein Konsolenbefehl angegeben." },
{ Str::ERROR_NEXT_TIME, "\nFehler bei der Berechnung der naechsten Uhrzeit.\n" },
{ Str::AUDIO_NOT_FOUND, "\nAudiodatei nicht gefunden: %s" },
{ Str::AUDIO_PATH_ERROR, "\nFehler bei Pfad-Konvertierung fuer Audiodatei: %s" },
{ Str::WINDOW_NOT_FOUND_WARN, "Warnung: Fenster \"%s\" derzeit nicht gefunden." },
{ Str::USAGE_HEADER,
"Verwendung:\n"
" teefax [<Zeit>] [Notiz] [Optionen]\n\n"
"Optionen:\n"
" -m, --mute Kein Weckton abspielen\n"
" -l, --loop [Anzahl] Wiederhole den Timer\n"
" --for <Dauer> Schleife nach Gesamtlaufzeit beenden\n"
" -ar, --alarm-repeat <n> Anzahl der Weckton-Wiederholungen (Standard: 1)\n"
" -ai, --alarm-interval <s> Abstand in Sekunden (Standard: 2)\n"
" -a, --at HH:MM[:SS] Starte bis zur angegebenen Uhrzeit (Alias: --until)\n"
" -a, --at YYYY-MM-DD Bis zum angegebenen Datum zaehlen\n"
" -a, --at YYYY-MM-DD HH:MM Datum und Uhrzeit kombiniert\n"
" -as, --async Ton asynchron abspielen\n"
" -s, --sound <Datei> Benutzerdefinierte Sounddatei\n"
" -o, --open <Dateipfad> Datei nach Ablauf oeffnen\n"
" -c, --cmd <Befehl> Konsolenbefehl nach Ablauf ausfuehren\n"
" -ns, --nosleep Bildschirmschoner unterdruecken\n"
" --eco Energiesparmodus (empfohlen fuer Akkubetrieb und aelteres Windows)\n"
" --nomsg Kein Benachrichtigungsfenster\n"
" <Notiz> Eigene Notiz, in Anfuehrungszeichen (ohne Optionsname)\n"
" -pa, --prealarm <s> Sekuendlicher Beep X Sekunden vor Ablauf\n"
" -t, --time Direktanzeige Datum & Zeit\n"
" -sw, --stopwatch Stoppuhr starten (Beenden mit Strg+C)\n"
" -d, --daily HH:mm[:ss] Taeglicher Alarm\n"
" -e, --every <Tage> [HH:mm] Woechentlich/monatlich (z.B. mon,fri oder 1,15)\n"
" -f, --focus <Titel> Fenster nach Ablauf in Vordergrund holen\n"
" -la, --lang <Sprache> Sprache festlegen (de, en, fr, pt, ru)\n"
" -v, --version Versionsnummer anzeigen\n"
" -h, --help Diese Hilfe anzeigen\n"
" --macro list Alle Makros anzeigen\n"
" --macro add <N> <Args> Makro speichern\n"
" --macro remove <N> Makro entfernen\n\n"
"Beispiele:\n"
" teefax 5m\n"
" teefax 5m \"Tee fertig!\"\n"
" teefax 10s --loop\n"
" teefax --loop 5 3s\n"
" teefax --at 07:30\n"
" teefax --at 2030-1-1\n"
" teefax --at 2030-1-1 20:15\n"
" teefax --at 07:30:15 --sound \"C:\\Klang\\gong.wav\"\n"
" teefax 3s --async --sound \"C:\\Klang\\gong.wav\"\n"
" teefax 10s --cmd \"shutdown /s /t 0\"\n"
" teefax 5m -c \"start notepad.exe\"\n"
" teefax 20s --prealarm 5\n"
" teefax --daily 4:00 10:00 16:00 22:00\n"
" teefax 5m --focus \"Notepad\"\n"
"\nKonfigurationsdatei: teefax.ini (gleicher Ordner wie teefax.exe)\n"
"\nhttps://github.com/Alsweider/Teefax\n"
"MIT License - Copyright (c) 2026 Alsweider\n"
},
{ Str::FILE_SYSTEM_ERROR, "\nDateisystem-Fehler beim Oeffnen: %s" },
{ Str::TOMORROW_SUFFIX, " (morgen)" },
{ Str::FOCUS_TARGET, " | Fokus: \"%s\"" },
{ Str::OPEN_TARGET, " | Oeffnet: \"%s\"" },
{ Str::STOPWATCH_LABEL, "Stoppuhr" },
{ Str::ELAPSED, "Vergangen: %s" },
{ Str::STOPWATCH_HINT, "Leertaste oder P: Pause/Weiter | R: Zuruecksetzen | Strg+C: Beenden" },
{ Str::STOPWATCH_PAUSED, "[PAUSIERT]" },
{ Str::MACRO_ADDED, "Makro '%s' gespeichert." },
{ Str::MACRO_OVERWRITE_PROMPT,"Makro '%s' existiert bereits. Ueberschreiben? [j/n]: " },
{ Str::MACRO_OVERWRITE_YES, "jJ" },
{ Str::MACRO_REMOVED, "Makro '%s' entfernt." },
{ Str::MACRO_NOT_FOUND, "Makro '%s' nicht gefunden." },
{ Str::MACRO_LIST_HEADER, "Definierte Makros:" },
{ Str::MACRO_LIST_EMPTY, "Keine Makros definiert." },
{ Str::MACRO_INVALID_NAME, "Ungueltiger Makroname '%s'. Nur Buchstaben und Ziffern erlaubt." },
{ Str::MACRO_INVALID_SUBCMD, "Ungueltiger Makrobefehl '%s'. Bitte 'add', 'remove' oder 'list' angeben." },
{ Str::MACRO_NAME_RESERVED, "Name '%s' ist reserviert und kann nicht als Makroname verwendet werden." },
{ Str::MACRO_MISSING_NAME, "Bitte einen Makronamen angeben." },
{ Str::MACRO_MISSING_SUBCMD, "Bitte ein Makrokommando angeben." },
{ Str::MACRO_MISSING_ARGS, "Bitte Argumente fuer das Makro angeben." },
{ Str::PRESS_ANY_KEY, "Weiter mit beliebiger Taste ..." },
{ Str::ERROR_FOR_REQUIRES_LOOP, "--for erfordert --loop, --daily oder --every." },
{ Str::FOR_TARGET_OUTSIDE, "Schleife beendet: naechster Termin liegt ausserhalb der --for-Zeit." },
{ Str::ERROR_INVALID_FOR, "Ungueltiger Wert fuer --for: '%s'." },
{ Str::WARN_ALARM_REPEAT_INVALID, "Warnung: Ungueltiger --alarm-repeat-Wert '%s', verwende 1." },
{ Str::WARN_ALARM_REPEAT_TOO_LARGE, "Warnung: --alarm-repeat-Wert '%s' zu gross, verwende Maximum (%lld)." },
{ Str::WARN_PATH_TOO_LONG, "Warnung: Pfad zu teefax.exe zu lang (>=%d Zeichen). teefax.ini wird ignoriert." },
{ Str::WARN_TIMER_PERIOD, "Warnung: timeBeginPeriod(1) fehlgeschlagen. Schlafpraezision ca. ~15ms statt ~1ms." },
};
static const TranslationMap LANG_FR = {
{ Str::STARTED, "Teefax [v%s] demarre" },
{ Str::TIMER_COUNTER, " avec compteur: %s" },
{ Str::TIMER_AT_TIME, " jusqu'a %02d:%02d:%02d" },
{ Str::TIMER_AT_DATETIME, " jusqu'au %04lld-%02d-%02d a %02d:%02d:%02d" },
{ Str::TIMER_DAILY, " avec alarme quotidienne." },
{ Str::TIMER_EVERY, " chaque %s a %02d:%02d:%02d" },
{ Str::TIMER_TARGET, " (jusqu'a %02d:%02d:%02d)" },
{ Str::REMAINING, "Restant: %s" },
{ Str::LOOP_PREFIX, "Boucle %lld | " },
{ Str::TIMER_ENDED, "\nCompteur termine." },
{ Str::ASYNC_SUFFIX, " (son async)" },
{ Str::ERROR_NO_TIME, "Veuillez indiquer une duree valide ou --at." },
{ Str::ERROR_PAST_DATETIME, "Date/heure invalide ou dans le passe." },
{ Str::ERROR_INVALID_AT, "Format d'heure invalide pour --at." },
{ Str::ERROR_INVALID_DAILY, "Heure invalide: %s" },
{ Str::ERROR_NO_DAILY_TIMES, "Aucune heure indiquee pour --daily." },
{ Str::ERROR_UNKNOWN_OPTION, "Option inconnue: %s" },
{ Str::ERROR_DETACHED_UNIT, "Unite de temps sans nombre: '%s'. Accolez l'unite au nombre (ex. '5m', pas '5 m')." },
{ Str::ERROR_INVALID_EVERY, "Argument --every invalide: %s" },
{ Str::ERROR_UNKNOWN_UNIT, "Unite inconnue: %s" },
{ Str::ERROR_NEXT_TIME, "\nErreur lors du calcul de la prochaine heure.\n" },
{ Str::ERROR_FILE_CONVERSION,"\nErreur de conversion du chemin: %s" },
{ Str::ERROR_CMD_CONVERSION, "\nErreur de conversion de la commande: %s" },
{ Str::NO_COMMAND, "\nAucune commande specifiee." },
{ Str::NOTIFY_TITLE, "Teefax" },
{ Str::NOTIFY_MSG, "Le temps est ecoule!" },
{ Str::FILE_NOT_FOUND, "\nFichier introuvable: %s" },
{ Str::FILE_NOT_FOUND_WARN, "Avertissement: fichier \"%s\" introuvable." },
{ Str::FILE_OPENED, "\nFichier ouvert: %s" },
{ Str::FILE_ERROR, "\nErreur a l'ouverture (code %d): %s" },
{ Str::CMD_STARTED, "Commande lancee: %s" },
{ Str::CMD_ERROR, "Erreur lors de l'execution (%d): %s" },
{ Str::AUDIO_NOT_FOUND, "\nFichier audio introuvable: %s" },
{ Str::AUDIO_PATH_ERROR, "\nErreur de conversion du chemin audio: %s" },
{ Str::WINDOW_NOT_FOUND_WARN, "Avertissement: fenetre \"%s\" introuvable pour l'instant." },
{ Str::USAGE_HEADER,
"Utilisation:\n"
" teefax [<duree>] [note] [options]\n\n"
"Options:\n"
" -m, --mute Pas de son d'alarme\n"
" -l, --loop [nombre] Repeter le compteur\n"
" --for <duree> Arreter la boucle apres la duree totale\n"
" -ar, --alarm-repeat <n> Repetitions de l'alarme (defaut: 1)\n"
" -ai, --alarm-interval <s> Intervalle en secondes (defaut: 2)\n"
" -a, --at HH:MM[:SS] Compter jusqu'a l'heure indiquee (alias: --until)\n"
" -a, --at YYYY-MM-DD Compter jusqu'a la date indiquee\n"
" -a, --at YYYY-MM-DD HH:MM Date et heure combinees\n"
" -as, --async Jouer le son en mode asynchrone\n"
" -s, --sound <fichier> Son d'alarme personnalise\n"
" -o, --open <chemin> Ouvrir un fichier apres le compteur\n"
" -c, --cmd <commande> Executer une commande apres le compteur\n"
" -ns, --nosleep Empecher la mise en veille\n"
" --eco Mode eco (recommande sur batterie ou ancien Windows)\n"
" --nomsg Pas de fenetre de notification\n"
" <note> Note entre guillemets (sans nom d'option)\n"
" -pa, --prealarm <s> Bip chaque seconde X secondes avant la fin\n"
" -t, --time Affichage en direct de la date et l'heure\n"
" -sw, --stopwatch Demarrer le chronometre (Ctrl+C pour quitter)\n"
" -d, --daily HH:mm[:ss] Alarme quotidienne\n"
" -e, --every <jours> [HH:mm] Hebdomadaire/mensuel (ex. mon,fri ou 1,15)\n"
" -f, --focus <titre> Mettre une fenetre au premier plan apres le compte\n"
" -la, --lang <langue> Definir la langue (de, en, fr, pt, ru)\n"
" -v, --version Afficher le numero de version\n"
" -h, --help Afficher cette aide\n"
" --macro list Lister les macros\n"
" --macro add <N> <Args> Enregistrer un macro\n"
" --macro remove <N> Supprimer un macro\n\n"
"Exemples:\n"
" teefax 5m\n"
" teefax 5m \"Le the est pret!\"\n"
" teefax 10s --loop\n"
" teefax --loop 5 3s\n"
" teefax --at 07:30\n"
" teefax --at 2030-1-1\n"
" teefax --at 2030-1-1 20:15\n"
" teefax --at 07:30:15 --sound \"C:\\Sons\\gong.wav\"\n"
" teefax 3s --async --sound \"C:\\Sons\\gong.wav\"\n"
" teefax 10s --cmd \"shutdown /s /t 0\"\n"
" teefax 5m -c \"start notepad.exe\"\n"
" teefax 20s --prealarm 5\n"
" teefax --daily 4:00 10:00 16:00 22:00\n"
" teefax 5m --focus \"Notepad\"\n"
"\nFichier de configuration: teefax.ini (meme dossier que teefax.exe)\n"
"\nhttps://github.com/Alsweider/Teefax\n"
"MIT License - Copyright (c) 2026 Alsweider\n"
},
{ Str::FILE_SYSTEM_ERROR, "\nErreur systeme de fichiers: %s" },
{ Str::TOMORROW_SUFFIX, " (demain)" },
{ Str::FOCUS_TARGET, " | Cible: \"%s\"" },
{ Str::OPEN_TARGET, " | Ouvre: \"%s\"" },
{ Str::STOPWATCH_LABEL, "Chronometre" },
{ Str::ELAPSED, "Ecoule: %s" },
{ Str::STOPWATCH_HINT, "Espace ou P: Pause/Reprendre | R: Reinitialiser | Ctrl+C: Quitter" },
{ Str::STOPWATCH_PAUSED, "[EN PAUSE]" },
{ Str::MACRO_ADDED, "Macro '%s' enregistre." },
{ Str::MACRO_OVERWRITE_PROMPT,"Le macro '%s' existe deja. Ecraser? [o/n]: " },
{ Str::MACRO_OVERWRITE_YES, "oO" },
{ Str::MACRO_REMOVED, "Macro '%s' supprime." },
{ Str::MACRO_NOT_FOUND, "Macro '%s' introuvable." },
{ Str::MACRO_LIST_HEADER, "Macros definis:" },
{ Str::MACRO_LIST_EMPTY, "Aucun macro defini." },
{ Str::MACRO_INVALID_NAME, "Nom de macro invalide '%s'. Lettres et chiffres uniquement." },
{ Str::MACRO_INVALID_SUBCMD, "Commande de macro invalide '%s'. Veuillez indiquer 'add', 'remove' ou 'list'." },
{ Str::MACRO_NAME_RESERVED, "Le nom '%s' est reserve et ne peut pas etre utilise comme nom de macro." },
{ Str::MACRO_MISSING_NAME, "Veuillez indiquer un nom de macro." },
{ Str::MACRO_MISSING_SUBCMD, "Veuillez indiquer une commande de macro." },
{ Str::MACRO_MISSING_ARGS, "Veuillez indiquer des arguments pour le macro." },
{ Str::PRESS_ANY_KEY, "Appuyez sur une touche pour continuer ..." },
{ Str::ERROR_FOR_REQUIRES_LOOP, "--for necessite --loop, --daily ou --every." },
{ Str::FOR_TARGET_OUTSIDE, "Boucle terminee: la prochaine echeance est en dehors de la plage --for." },
{ Str::ERROR_INVALID_FOR, "Valeur invalide pour --for: '%s'." },
{ Str::WARN_ALARM_REPEAT_INVALID, "Avertissement: valeur --alarm-repeat invalide '%s', utilise 1." },
{ Str::WARN_ALARM_REPEAT_TOO_LARGE, "Avertissement: valeur --alarm-repeat '%s' trop grande, utilise le maximum (%lld)." },
{ Str::WARN_PATH_TOO_LONG, "Avertissement: chemin vers teefax.exe trop long (>=%d caracteres). teefax.ini sera ignore." },
{ Str::WARN_TIMER_PERIOD, "Avertissement: timeBeginPeriod(1) echoue. Precision du sommeil ~15ms au lieu de ~1ms." },
};
static const TranslationMap LANG_PT = {
{ Str::STARTED, "Teefax [v%s] iniciado" },
{ Str::TIMER_COUNTER, " com temporizador: %s" },
{ Str::TIMER_AT_TIME, " ate as %02d:%02d:%02d" },
{ Str::TIMER_AT_DATETIME, " ate %04lld-%02d-%02d %02d:%02d:%02d" },
{ Str::TIMER_DAILY, " com alarme diario." },
{ Str::TIMER_EVERY, " cada %s as %02d:%02d:%02d" },
{ Str::TIMER_TARGET, " (ate %02d:%02d:%02d)" },
{ Str::REMAINING, "Restante: %s" },
{ Str::LOOP_PREFIX, "Ciclo %lld | " },
{ Str::TIMER_ENDED, "\nTemporizador terminado." },
{ Str::ASYNC_SUFFIX, " (som async)" },
{ Str::ERROR_NO_TIME, "Indique uma duracao valida ou --at." },
{ Str::ERROR_PAST_DATETIME, "Data/hora invalida ou no passado." },
{ Str::ERROR_INVALID_AT, "Formato de hora invalido para --at." },
{ Str::ERROR_INVALID_DAILY, "Hora invalida: %s" },
{ Str::ERROR_NO_DAILY_TIMES, "Nenhuma hora indicada para --daily." },
{ Str::ERROR_UNKNOWN_OPTION, "Opcao desconhecida: %s" },
{ Str::ERROR_DETACHED_UNIT, "Unidade de tempo sem numero: '%s'. Junte a unidade ao numero (ex.: '5m', nao '5 m')." },
{ Str::ERROR_INVALID_EVERY, "Argumento --every invalido: %s" },
{ Str::ERROR_UNKNOWN_UNIT, "Unidade desconhecida: %s" },
{ Str::ERROR_NEXT_TIME, "\nErro ao calcular a proxima hora.\n" },
{ Str::ERROR_FILE_CONVERSION,"\nErro na conversao do caminho: %s" },
{ Str::ERROR_CMD_CONVERSION, "\nErro na conversao do comando: %s" },
{ Str::NO_COMMAND, "\nNenhum comando especificado." },
{ Str::NOTIFY_TITLE, "Teefax" },
{ Str::NOTIFY_MSG, "O tempo esgotou-se!" },
{ Str::FILE_NOT_FOUND, "\nFicheiro nao encontrado: %s" },
{ Str::FILE_NOT_FOUND_WARN, "Aviso: ficheiro \"%s\" nao encontrado." },
{ Str::FILE_OPENED, "\nFicheiro aberto: %s" },
{ Str::FILE_ERROR, "\nErro ao abrir o ficheiro (codigo %d): %s" },
{ Str::CMD_STARTED, "Comando iniciado: %s" },
{ Str::CMD_ERROR, "Erro ao executar o comando (%d): %s" },
{ Str::AUDIO_NOT_FOUND, "\nFicheiro de audio nao encontrado: %s" },
{ Str::AUDIO_PATH_ERROR, "\nErro na conversao do caminho do audio: %s" },
{ Str::WINDOW_NOT_FOUND_WARN, "Aviso: janela \"%s\" nao encontrada de momento." },
{ Str::USAGE_HEADER,
"Utilizacao:\n"
" teefax [<duracao>] [nota] [opcoes]\n\n"
"Opcoes:\n"
" -m, --mute Sem som de alarme\n"
" -l, --loop [numero] Repetir o temporizador\n"
" --for <duracao> Parar o ciclo apos a duracao total\n"
" -ar, --alarm-repeat <n> Repeticoes do alarme (padrao: 1)\n"
" -ai, --alarm-interval <s> Intervalo em segundos (padrao: 2)\n"
" -a, --at HH:MM[:SS] Contar ate a hora indicada (alias: --until)\n"
" -a, --at YYYY-MM-DD Contar ate a data indicada\n"
" -a, --at YYYY-MM-DD HH:MM Data e hora combinadas\n"
" -as, --async Reproduzir som de forma assincrona\n"
" -s, --sound <ficheiro> Som de alarme personalizado\n"
" -o, --open <caminho> Abrir ficheiro apos o temporizador\n"
" -c, --cmd <comando> Executar comando apos o temporizador\n"
" -ns, --nosleep Impedir a suspensao do sistema\n"
" --eco Modo economizador (recomendado em bateria ou Windows antigo)\n"
" --nomsg Sem janela de notificacao\n"
" <nota> Nota entre aspas (sem nome de opcao)\n"
" -pa, --prealarm <s> Bip por segundo X segundos antes do fim\n"
" -t, --time Mostrar data e hora em tempo real\n"
" -sw, --stopwatch Iniciar cronometro (sair com Ctrl+C)\n"
" -d, --daily HH:mm[:ss] Alarme diario\n"
" -e, --every <dias> [HH:mm] Semanal/mensal (ex. mon,fri ou 1,15)\n"
" -f, --focus <titulo> Trazer janela para o primeiro plano apos o temporizador\n"
" -la, --lang <lingua> Definir o idioma (de, en, fr, pt, ru)\n"
" -v, --version Mostrar numero de versao\n"
" -h, --help Mostrar esta ajuda\n"
" --macro list Listar macros\n"
" --macro add <N> <Args> Guardar um macro\n"
" --macro remove <N> Remover um macro\n\n"
"Exemplos:\n"
" teefax 5m\n"
" teefax 5m \"Cha pronto!\"\n"
" teefax 10s --loop\n"
" teefax --loop 5 3s\n"
" teefax --at 07:30\n"
" teefax --at 2030-1-1\n"
" teefax --at 2030-1-1 20:15\n"
" teefax --at 07:30:15 --sound \"C:\\Sons\\gong.wav\"\n"
" teefax 3s --async --sound \"C:\\Sons\\gong.wav\"\n"
" teefax 10s --cmd \"shutdown /s /t 0\"\n"
" teefax 5m -c \"start notepad.exe\"\n"
" teefax 20s --prealarm 5\n"
" teefax --daily 4:00 10:00 16:00 22:00\n"
" teefax 5m --focus \"Notepad\"\n"
"\nFicheiro de configuracao: teefax.ini (mesma pasta que teefax.exe)\n"
"\nhttps://github.com/Alsweider/Teefax\n"
"MIT License - Copyright (c) 2026 Alsweider\n"
},
{ Str::FILE_SYSTEM_ERROR, "\nErro no sistema de ficheiros: %s" },
{ Str::TOMORROW_SUFFIX, " (amanha)" },
{ Str::FOCUS_TARGET, " | Foco: \"%s\"" },
{ Str::OPEN_TARGET, " | Abre: \"%s\"" },
{ Str::STOPWATCH_LABEL, "Cronometro" },
{ Str::ELAPSED, "Decorrido: %s" },
{ Str::STOPWATCH_HINT, "Espaco ou P: Pausar/Continuar | R: Reset | Ctrl+C: Sair" },
{ Str::STOPWATCH_PAUSED, "[PAUSADO]" },
{ Str::MACRO_ADDED, "Macro '%s' guardado." },
{ Str::MACRO_OVERWRITE_PROMPT,"O macro '%s' ja existe. Substituir? [s/n]: " },
{ Str::MACRO_OVERWRITE_YES, "sS" },
{ Str::MACRO_REMOVED, "Macro '%s' removido." },
{ Str::MACRO_NOT_FOUND, "Macro '%s' nao encontrado." },
{ Str::MACRO_LIST_HEADER, "Macros definidos:" },
{ Str::MACRO_LIST_EMPTY, "Nenhum macro definido." },
{ Str::MACRO_INVALID_NAME, "Nome de macro invalido '%s'. Apenas letras e digitos." },
{ Str::MACRO_INVALID_SUBCMD, "Comando de macro invalido '%s'. Por favor especifique 'add', 'remove' ou 'list'." },
{ Str::MACRO_NAME_RESERVED, "O nome '%s' e reservado e nao pode ser usado como nome de macro." },
{ Str::MACRO_MISSING_NAME, "Indique um nome para o macro." },
{ Str::MACRO_MISSING_SUBCMD, "Por favor indique um comando de macro." },
{ Str::MACRO_MISSING_ARGS, "Indique argumentos para o macro." },
{ Str::PRESS_ANY_KEY, "Prima qualquer tecla para continuar ..." },
{ Str::ERROR_FOR_REQUIRES_LOOP, "--for requer --loop, --daily ou --every." },
{ Str::FOR_TARGET_OUTSIDE, "Ciclo terminado: o proximo horario esta fora do intervalo --for." },
{ Str::ERROR_INVALID_FOR, "Valor invalido para --for: '%s'." },
{ Str::WARN_ALARM_REPEAT_INVALID, "Aviso: valor --alarm-repeat invalido '%s', usando 1." },
{ Str::WARN_ALARM_REPEAT_TOO_LARGE, "Aviso: valor --alarm-repeat '%s' demasiado grande, usando maximo (%lld)." },
{ Str::WARN_PATH_TOO_LONG, "Aviso: caminho para teefax.exe demasiado longo (>=%d caracteres). teefax.ini sera ignorado." },
{ Str::WARN_TIMER_PERIOD, "Aviso: timeBeginPeriod(1) falhou. Precisao de espera ~15ms em vez de ~1ms." },
};
static const TranslationMap LANG_RU = {
{ Str::STARTED, "Teefax [v%s] zapushchen" },
{ Str::TIMER_COUNTER, " s tajmerom: %s" },
{ Str::TIMER_AT_TIME, " do %02d:%02d:%02d" },
{ Str::TIMER_AT_DATETIME, " do %04lld-%02d-%02d %02d:%02d:%02d" },
{ Str::TIMER_DAILY, " s ezhednevnym signalom." },
{ Str::TIMER_EVERY, " kazhdyj %s v %02d:%02d:%02d" },
{ Str::TIMER_TARGET, " (do %02d:%02d:%02d)" },
{ Str::REMAINING, "Ostalos': %s" },
{ Str::LOOP_PREFIX, "Krug %lld | " },
{ Str::TIMER_ENDED, "\nTajmer zavershyon." },
{ Str::ASYNC_SUFFIX, " (async zvuk)" },
{ Str::ERROR_NO_TIME, "Ukazhite vremya ili --at." },
{ Str::ERROR_PAST_DATETIME, "Data/vremya neverno ili v proshlom." },
{ Str::ERROR_INVALID_AT, "Nevernyi format vremeni dlya --at." },
{ Str::ERROR_INVALID_DAILY, "Nevernoe vremya: %s" },
{ Str::ERROR_NO_DAILY_TIMES, "Ne ukazano vremya dlya --daily." },
{ Str::ERROR_UNKNOWN_OPTION, "Neizvestnaya optsiya: %s" },
{ Str::ERROR_DETACHED_UNIT, "Edinitsa vremeni bez chisla: '%s'. Pishite edinitsu srazu posle chisla (napr. '5m', ne '5 m')." },
{ Str::ERROR_INVALID_EVERY, "Nevernyi argument --every: %s" },
{ Str::ERROR_UNKNOWN_UNIT, "Neizvestnaya edinitsa: %s" },
{ Str::ERROR_NEXT_TIME, "\nOshibka vychisleniya sleduyushchego vremeni.\n" },
{ Str::ERROR_FILE_CONVERSION,"\nOshibka preobrazovaniya puti: %s" },
{ Str::ERROR_CMD_CONVERSION, "\nOshibka preobrazovaniya komandy: %s" },
{ Str::NO_COMMAND, "\nKomanda ne ukazana." },
{ Str::NOTIFY_TITLE, "Teefax" },
{ Str::NOTIFY_MSG, "Vremya isteklo!" },
{ Str::FILE_NOT_FOUND, "\nFajl ne najden: %s" },
{ Str::FILE_NOT_FOUND_WARN, "Preduprezhdenie: fajl \"%s\" ne najden." },
{ Str::FILE_OPENED, "\nFajl otkryt: %s" },
{ Str::FILE_ERROR, "\nOshibka otkrytiya (kod %d): %s" },
{ Str::CMD_STARTED, "Komanda zapushchena: %s" },
{ Str::CMD_ERROR, "Oshibka vypolneniya (%d): %s" },
{ Str::AUDIO_NOT_FOUND, "\nAudiofajl ne najden: %s" },
{ Str::AUDIO_PATH_ERROR, "\nOshibka preobrazovaniya puti audio: %s" },
{ Str::WINDOW_NOT_FOUND_WARN, "Preduprezhdenie: okno \"%s\" poka ne najdeno." },
{ Str::USAGE_HEADER,
"Ispol'zovanie:\n"
" teefax [<vremya>] [zametka] [optsii]\n\n"
"Optsii:\n"
" -m, --mute Bez zvuka\n"
" -l, --loop [kolichestvo] Povtorit' tajmer\n"
" --for <vremya> Ostanovit' petlyu po istechenii obshhego vremeni\n"
" -ar, --alarm-repeat <n> Povtoreniya signala (po umolchaniyu: 1)\n"
" -ai, --alarm-interval <s> Interval v sekundakh (po umolchaniyu: 2)\n"
" -a, --at HH:MM[:SS] Otschet do ukazannogo vremeni (alias: --until)\n"
" -a, --at YYYY-MM-DD Otschet do ukazannoj daty\n"
" -a, --at YYYY-MM-DD HH:MM Data i vremya vmeste\n"
" -as, --async Vosproizvodit' zvuk asinkronno\n"
" -s, --sound <fajl> Sobstvennyj zvuk signala\n"
" -o, --open <put'> Otkryt' fajl posle tajmera\n"
" -c, --cmd <komanda> Vypolnit' komandu posle tajmera\n"
" -ns, --nosleep Zapretit' son sistemy\n"
" --eco Rezhim ekonomii (rekomendovan pri rabote na bataree ili starom Windows)\n"
" --nomsg Bez okna uvedomleniya\n"
" <zametka> Zametka v kavychkakh (bez imeni optsii)\n"
" -pa, --prealarm <s> Bip kazhduyu sekundu za X sekund do kontsa\n"
" -t, --time Pokazyvat' tekushchee vremya\n"
" -sw, --stopwatch Zapustit' sekundomer (vyjti Ctrl+C)\n"
" -d, --daily HH:mm[:ss] Ezhednevnyj signal\n"
" -e, --every <dni> [HH:mm] Ezhenedel'no/ezhemesyachno (napr. mon,fri ili 1,15)\n"
" -f, --focus <zagolovok> Vyvestu okno na peredni plan posle tajmera\n"
" -la, --lang <yazyk> Ustanovit' yazyk (de, en, fr, pt, ru)\n"
" -v, --version Pokazat' nomer versii\n"
" -h, --help Pokazat' etu spravku\n"
" --macro list Pokazat' makrosy\n"
" --macro add <N> <Args> Sokhranit' makros\n"
" --macro remove <N> Udalit' makros\n\n"
"Primery:\n"
" teefax 5m\n"
" teefax 5m \"Chaj gotov!\"\n"
" teefax 10s --loop\n"
" teefax --loop 5 3s\n"
" teefax --at 07:30\n"
" teefax --at 2030-1-1\n"
" teefax --at 2030-1-1 20:15\n"
" teefax --at 07:30:15 --sound \"C:\\Zvuki\\gong.wav\"\n"
" teefax 3s --async --sound \"C:\\Zvuki\\gong.wav\"\n"
" teefax 10s --cmd \"shutdown /s /t 0\"\n"
" teefax 5m -c \"start notepad.exe\"\n"
" teefax 20s --prealarm 5\n"
" teefax --daily 4:00 10:00 16:00 22:00\n"
" teefax 5m --focus \"Notepad\"\n"
"\nFajl konfiguratsii: teefax.ini (ta zhe papka, chto i teefax.exe)\n"
"\nhttps://github.com/Alsweider/Teefax\n"
"MIT License - Copyright (c) 2026 Alsweider\n"
},
{ Str::FILE_SYSTEM_ERROR, "\nOshibka fajlovoj sistemy: %s" },
{ Str::TOMORROW_SUFFIX, " (zavtra)" },
{ Str::FOCUS_TARGET, " | Okno: \"%s\"" },
{ Str::OPEN_TARGET, " | Otkryvaet: \"%s\"" },
{ Str::STOPWATCH_LABEL, "Sekundomer" },
{ Str::ELAPSED, "Proshlo: %s" },
{ Str::STOPWATCH_HINT, "Probel ili P: Pauza/Prodolzhit' | R: Reset | Ctrl+C: Vyjti" },
{ Str::STOPWATCH_PAUSED, "[PAUZA]" },
{ Str::MACRO_ADDED, "Makros '%s' sokhranyon." },
{ Str::MACRO_OVERWRITE_PROMPT,"Makros '%s' uzhe sushchestvuet. Perezapisat'? [d/n]: " },
{ Str::MACRO_OVERWRITE_YES, "dD" },
{ Str::MACRO_REMOVED, "Makros '%s' udalen." },
{ Str::MACRO_NOT_FOUND, "Makros '%s' ne najden." },
{ Str::MACRO_LIST_HEADER, "Opredelyonnye makrosy:" },
{ Str::MACRO_LIST_EMPTY, "Makrosy ne opredeleny." },
{ Str::MACRO_INVALID_NAME, "Nevernoe imya makrosa '%s'. Tol'ko bukvy i tsifry." },
{ Str::MACRO_INVALID_SUBCMD, "Invalidnaya makrokomanda '%s'. Pozhaluysta ukazhite 'add', 'remove' ili 'list'." },
{ Str::MACRO_NAME_RESERVED, "Imya '%s' zarezervrovano i ne mozhet ispol'zovat'sya kak imya makrosa." },
{ Str::MACRO_MISSING_NAME, "Ukazhite imya makrosa." },
{ Str::MACRO_MISSING_SUBCMD, "Pozhaluysta ukazhite makrokomandu." },
{ Str::MACRO_MISSING_ARGS, "Ukazhite argumenty dlya makrosa." },
{ Str::PRESS_ANY_KEY, "Nazhmite lyubuyu klavishu dlya prodolzheniya ..." },
{ Str::ERROR_FOR_REQUIRES_LOOP, "--for trebuet --loop, --daily ili --every." },
{ Str::FOR_TARGET_OUTSIDE, "Petlya zavershena: sleduyushchij termin vne diapazona --for." },
{ Str::ERROR_INVALID_FOR, "Nevernoe znachenie dlya --for: '%s'." },
{ Str::WARN_ALARM_REPEAT_INVALID, "Preduprezhdenie: neverno znachenie --alarm-repeat '%s', ispol'zuyu 1." },
{ Str::WARN_ALARM_REPEAT_TOO_LARGE, "Preduprezhdenie: znachenie --alarm-repeat '%s' slishkom veliko, ispol'zuyu maksimum (%lld)." },
{ Str::WARN_PATH_TOO_LONG, "Preduprezhdenie: put' k teefax.exe slishkom dlinnyj (>=%d simvolov). teefax.ini budet ignorirovan." },
{ Str::WARN_TIMER_PERIOD, "Preduprezhdenie: timeBeginPeriod(1) ne udalsya. Tochnost' sna ~15ms vmesto ~1ms." },
};
static const TranslationMap LANG_EN = {
{ Str::STARTED, "Teefax [v%s] started" },
{ Str::TIMER_COUNTER, " with timer: %s" },
{ Str::TIMER_AT_TIME, " for time %02d:%02d:%02d" },
{ Str::TIMER_AT_DATETIME, " for date %04lld-%02d-%02d %02d:%02d:%02d" },
{ Str::TIMER_DAILY, " with daily alarm." },
{ Str::TIMER_EVERY, " every %s at %02d:%02d:%02d" },
{ Str::TIMER_TARGET, " (until %02d:%02d:%02d)" },
{ Str::REMAINING, "Remaining: %s" },
{ Str::LOOP_PREFIX, "Loop %lld | " },
{ Str::TIMER_ENDED, "\nTimer finished." },
{ Str::ASYNC_SUFFIX, " (async sound)" },
{ Str::ERROR_NO_TIME, "Please provide a valid time or --at." },
{ Str::ERROR_PAST_DATETIME, "Date/time invalid or in the past." },
{ Str::ERROR_INVALID_AT, "Invalid time format for --at." },
{ Str::ERROR_INVALID_DAILY, "Invalid time: %s" },
{ Str::ERROR_NO_DAILY_TIMES, "No times given for --daily." },
{ Str::ERROR_UNKNOWN_OPTION, "Unknown option: %s" },
{ Str::ERROR_DETACHED_UNIT, "Time unit without number: '%s'. Attach units directly to the number (e.g. '5m', not '5 m')." },
{ Str::ERROR_INVALID_EVERY, "Invalid --every argument: %s" },
{ Str::NOTIFY_TITLE, "Teefax" },
{ Str::NOTIFY_MSG, "Time is up!" },
{ Str::FILE_NOT_FOUND, "\nFile not found: %s" },
{ Str::FILE_NOT_FOUND_WARN, "Warning: file \"%s\" not found." },
{ Str::FILE_OPENED, "\nFile opened: %s" },
{ Str::FILE_ERROR, "\nError opening file (code %d): %s" },
{ Str::CMD_STARTED, "Command started: %s" },
{ Str::CMD_ERROR, "Error running command (%d): %s" },
{ Str::ERROR_UNKNOWN_UNIT, "Unknown unit: %s" },
{ Str::ERROR_FILE_CONVERSION, "\nError converting path: %s" },
{ Str::ERROR_CMD_CONVERSION, "\nError converting command: %s" },
{ Str::NO_COMMAND, "\nNo command specified." },
{ Str::ERROR_NEXT_TIME, "\nError calculating next time.\n" },
{ Str::AUDIO_NOT_FOUND, "\nAudio file not found: %s" },
{ Str::AUDIO_PATH_ERROR, "\nPath conversion error for audio file: %s" },
{ Str::WINDOW_NOT_FOUND_WARN, "Warning: window \"%s\" not found at this time." },
{ Str::USAGE_HEADER,
"Usage:\n"
" teefax [<time>] [note] [options]\n\n"
"Options:\n"
" -m, --mute No alarm sound\n"
" -l, --loop [count] Repeat the timer\n"
" --for <duration> Stop loop after total elapsed time\n"
" -ar, --alarm-repeat <n> Alarm repetitions (default: 1)\n"
" -ai, --alarm-interval <s> Interval in seconds (default: 2)\n"
" -a, --at HH:MM[:SS] Count to specified time (alias: --until)\n"
" -a, --at YYYY-MM-DD Count to specified date\n"
" -a, --at YYYY-MM-DD HH:MM Date and time combined\n"
" -as, --async Play sound asynchronously\n"
" -s, --sound <file> Custom alarm sound\n"
" -o, --open <filepath> Open file after timer\n"
" -c, --cmd <command> Run console command after timer\n"
" -ns, --nosleep Suppress screensaver\n"
" --eco Power-saving mode (recommended on battery or older Windows)\n"
" --nomsg No notification popup\n"
" <note> Custom note, in quotes (no option name)\n"
" -pa, --prealarm <s> Beep every second X seconds before end\n"
" -t, --time Live date & time display\n"
" -sw, --stopwatch Start stopwatch (exit with Ctrl+C)\n"
" -d, --daily HH:mm[:ss] Daily alarm\n"
" -e, --every <days> [HH:mm] Weekly/monthly recurrence (e.g. mon,fri or 1,15)\n"
" -f, --focus <title> Bring window to foreground after timer\n"
" -la, --lang <language> Set language (de, en, fr, pt, ru)\n"
" -v, --version Show version number\n"
" -h, --help Show this help\n"
" --macro list List all macros\n"
" --macro add <N> <Args> Save a macro\n"
" --macro remove <N> Remove a macro\n\n"
"Examples:\n"
" teefax 5m\n"
" teefax 5m \"Tea is ready!\"\n"
" teefax 10s --loop\n"
" teefax --loop 5 3s\n"
" teefax --at 07:30\n"
" teefax --at 2030-1-1\n"
" teefax --at 2030-1-1 20:15\n"
" teefax --at 07:30:15 --sound \"C:\\Sounds\\gong.wav\"\n"
" teefax 3s --async --sound \"C:\\Sounds\\gong.wav\"\n"
" teefax 10s --cmd \"shutdown /s /t 0\"\n"
" teefax 5m -c \"start notepad.exe\"\n"
" teefax 20s --prealarm 5\n"
" teefax --daily 4:00 10:00 16:00 22:00\n"
" teefax 5m --focus \"Notepad\"\n"
"\nConfig file: teefax.ini (same folder as teefax.exe)\n"
"\nhttps://github.com/Alsweider/Teefax\n"
"MIT License - Copyright (c) 2026 Alsweider\n"
},
{ Str::FILE_SYSTEM_ERROR, "\nFilesystem error while opening: %s" },
{ Str::TOMORROW_SUFFIX, " (tomorrow)" },
{ Str::FOCUS_TARGET, " | Focus: \"%s\"" },
{ Str::OPEN_TARGET, " | Opens: \"%s\"" },
{ Str::STOPWATCH_LABEL, "Stopwatch" },
{ Str::ELAPSED, "Elapsed: %s" },
{ Str::STOPWATCH_HINT, "Space or P: Pause/Resume | R: Reset | Ctrl+C: Exit" },
{ Str::STOPWATCH_PAUSED, "[PAUSED]" },
{ Str::MACRO_ADDED, "Macro '%s' saved." },
{ Str::MACRO_OVERWRITE_PROMPT,"Macro '%s' already exists. Overwrite? [y/n]: " },
{ Str::MACRO_OVERWRITE_YES, "yY" },
{ Str::MACRO_REMOVED, "Macro '%s' removed." },
{ Str::MACRO_NOT_FOUND, "Macro '%s' not found." },
{ Str::MACRO_LIST_HEADER, "Defined macros:" },
{ Str::MACRO_LIST_EMPTY, "No macros defined." },
{ Str::MACRO_INVALID_NAME, "Invalid macro name '%s'. Only letters and digits allowed." },
{ Str::MACRO_INVALID_SUBCMD, "Invalid macro command '%s'. Please specify 'add', 'remove' or 'list'." },
{ Str::MACRO_NAME_RESERVED, "Name '%s' is reserved and cannot be used as a macro name." },
{ Str::MACRO_MISSING_NAME, "Please provide a macro name." },
{ Str::MACRO_MISSING_SUBCMD, "Please specify a macro command." },
{ Str::MACRO_MISSING_ARGS, "Please provide arguments for the macro." },
{ Str::PRESS_ANY_KEY, "Press any key to continue ..." },
{ Str::ERROR_FOR_REQUIRES_LOOP, "--for requires --loop, --daily or --every." },
{ Str::FOR_TARGET_OUTSIDE, "Loop ended: next scheduled time is outside the --for window." },
{ Str::ERROR_INVALID_FOR, "Invalid value for --for: '%s'." },
{ Str::WARN_ALARM_REPEAT_INVALID, "Warning: invalid --alarm-repeat value '%s', using 1." },
{ Str::WARN_ALARM_REPEAT_TOO_LARGE, "Warning: --alarm-repeat value '%s' is too large, using maximum (%lld)." },
{ Str::WARN_PATH_TOO_LONG, "Warning: path to teefax.exe is too long (>=%d chars). teefax.ini will be ignored." },
{ Str::WARN_TIMER_PERIOD, "Warning: timeBeginPeriod(1) failed. Sleep precision may be ~15ms instead of ~1ms." },
};
// ── Spracherkennung ───────────────────────────────────────────────────
inline const TranslationMap& detectLanguage() {
// 1. Umgebungsvariable TEEFAX_LANG hat Vorrang (z.B. "de", "en")
if (const char* env = getenv("TEEFAX_LANG")) {
std::string s(env);
if (s == "de") return LANG_DE;
if (s == "fr") return LANG_FR;
if (s == "pt") return LANG_PT;
if (s == "ru") return LANG_RU;
if (s == "en") return LANG_EN;
}
// 2. Windows-Systemsprache
LANGID id = GetUserDefaultUILanguage() & 0xFF; // Primärsprache
if (id == LANG_FRENCH) return LANG_FR;
if (id == LANG_PORTUGUESE) return LANG_PT;
if (id == LANG_RUSSIAN) return LANG_RU;
if (id == LANG_ENGLISH) return LANG_EN;
return LANG_DE; // Fallback
}
// ── Globale Instanz + Zugriffsfunktion ────────────────────────────────
inline const TranslationMap& currentLang() {
static const TranslationMap& lang = detectLanguage();
return lang;
}
// t() = translate - liefert den Rohstring für snprintf/printf
inline const char* t(Str id) {
const auto& m = currentLang();
auto it = m.find(id);
return it != m.end() ? it->second : "???";
}
#endif // I18N_H