wizards 0.5.11 → 0.5.13

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 (91) hide show
  1. package/apps/runtime/dist/browser/fast/action-space.js +0 -2
  2. package/apps/runtime/dist/cli/mcp.js +2 -15
  3. package/apps/runtime/dist/cli/report.js +2 -15
  4. package/apps/runtime/dist/cli/start.js +28 -14
  5. package/apps/runtime/dist/cli/status.js +1 -1
  6. package/apps/runtime/dist/credits/credits.js +0 -3
  7. package/apps/runtime/dist/db/client.js +0 -7
  8. package/apps/runtime/dist/db/control-schema.js +10 -0
  9. package/apps/runtime/dist/db/migrations/control/0010_tan_snowbird.sql +6 -0
  10. package/apps/runtime/dist/db/migrations/control/meta/0010_snapshot.json +600 -0
  11. package/apps/runtime/dist/db/migrations/control/meta/_journal.json +7 -0
  12. package/apps/runtime/dist/db/migrations/tenant/0016_even_trish_tilby.sql +12 -0
  13. package/apps/runtime/dist/db/migrations/tenant/meta/0016_snapshot.json +3326 -0
  14. package/apps/runtime/dist/db/migrations/tenant/meta/_journal.json +7 -0
  15. package/apps/runtime/dist/db/schema.js +20 -0
  16. package/apps/runtime/dist/docs/user/build-a-wizard.md +1 -1
  17. package/apps/runtime/dist/engine/runner.js +31 -10
  18. package/apps/runtime/dist/engine/steps.js +15 -4
  19. package/apps/runtime/dist/harness/index.js +0 -4
  20. package/apps/runtime/dist/manage.js +7 -7
  21. package/apps/runtime/dist/model-errors.js +20 -7
  22. package/apps/runtime/dist/plugins/pro.js +0 -6
  23. package/apps/runtime/dist/render/convert.js +0 -3
  24. package/apps/runtime/dist/routes/runs.js +170 -23
  25. package/apps/runtime/dist/routes/studio.js +83 -9
  26. package/apps/runtime/dist/services/api.js +8 -6
  27. package/apps/runtime/dist/services/cloud.js +1 -0
  28. package/apps/runtime/dist/services/spaces.js +1 -0
  29. package/apps/runtime/dist/services/translations.js +303 -0
  30. package/apps/runtime/dist/services/wizards.js +3 -1
  31. package/apps/runtime/dist/store/index.js +0 -11
  32. package/apps/runtime/dist/texts.js +47 -39
  33. package/apps/web/dist/assets/{AboutDialog-L1hcshAX.js → AboutDialog-CkE7uZNL.js} +1 -1
  34. package/apps/web/dist/assets/{ChangelogDialog-DZLYVOkl.js → ChangelogDialog-BCS3WIRA.js} +1 -1
  35. package/apps/web/dist/assets/ChatView-DClGzMte.js +10 -0
  36. package/apps/web/dist/assets/EditorPage-Dg27sIZ7.js +3 -0
  37. package/apps/web/dist/assets/{FlowPreview-CTEJi5TQ.js → FlowPreview-D2haAZwo.js} +1 -1
  38. package/apps/web/dist/assets/{Harness-CApAHvJE.js → Harness-CGI6ZMTA.js} +2 -2
  39. package/apps/web/dist/assets/{NewWizardChannels-tst10rkV.js → NewWizardChannels-C4b_phHw.js} +1 -1
  40. package/apps/web/dist/assets/{NewWizardPage-BAKaUY1g.js → NewWizardPage-DhDXrjKX.js} +2 -2
  41. package/apps/web/dist/assets/OnboardingPage-DgySdBgo.js +1 -0
  42. package/apps/web/dist/assets/ProjectPage-dvtJn_3c.js +1 -0
  43. package/apps/web/dist/assets/PublicRunner-lP4sVF1q.js +1 -0
  44. package/apps/web/dist/assets/{ReadOnly-Bb8khbuH.js → ReadOnly-B-4l3bVt.js} +1 -1
  45. package/apps/web/dist/assets/RunDrawer-B2bsB9Z6.js +4 -0
  46. package/apps/web/dist/assets/RunnerView-BZ83HUnO.js +1 -0
  47. package/apps/web/dist/assets/SettingsPage-C0_wAa_j.js +1 -0
  48. package/apps/web/dist/assets/SetupPage-kuvBk0G0.js +1 -0
  49. package/apps/web/dist/assets/{SharePage-Bb-BIvAX.js → SharePage-COLVxXMI.js} +1 -1
  50. package/apps/web/dist/assets/changelog-CIYdRaa5.js +1 -0
  51. package/apps/web/dist/assets/{esm-pbWES-Cu.js → esm-BqbWrbsa.js} +1 -1
  52. package/apps/web/dist/assets/index-Da9Pvzpj.js +14 -0
  53. package/apps/web/dist/assets/index-DaKjB676.css +1 -0
  54. package/apps/web/dist/assets/{lock-C6LaSCq_.js → lock-BkN0Fai6.js} +1 -1
  55. package/apps/web/dist/assets/{phone-BUWpzNWn.js → phone-Dip_wSUZ.js} +1 -1
  56. package/apps/web/dist/assets/{settings-menu-yO8b8LjQ.js → settings-menu-B7eXkvba.js} +1 -1
  57. package/apps/web/dist/assets/ui-B9AOCT0v.js +134 -0
  58. package/apps/web/dist/assets/{upload-D89fyY2-.js → upload-DPQ4pwnl.js} +1 -1
  59. package/apps/web/dist/index.html +3 -3
  60. package/apps/web/dist/mcp/flow.html +54 -54
  61. package/node_modules/@engenty-wizards/plugin-sdk/dist/thread.js +34 -34
  62. package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +19 -6
  63. package/node_modules/@engenty-wizards/shared/dist/definition.js +51 -10
  64. package/node_modules/@engenty-wizards/shared/dist/features.d.ts +0 -1
  65. package/node_modules/@engenty-wizards/shared/dist/features.js +0 -1
  66. package/node_modules/@engenty-wizards/shared/dist/marketplace.d.ts +0 -5
  67. package/node_modules/@engenty-wizards/shared/dist/marketplace.js +0 -5
  68. package/node_modules/@engenty-wizards/shared/dist/providers.d.ts +1 -1
  69. package/node_modules/@engenty-wizards/shared/dist/providers.js +1 -1
  70. package/node_modules/@engenty-wizards/shared/dist/run.d.ts +46 -4
  71. package/node_modules/@engenty-wizards/shared/dist/run.js +24 -9
  72. package/node_modules/@engenty-wizards/shared/dist/runner-texts.d.ts +506 -0
  73. package/node_modules/@engenty-wizards/shared/dist/runner-texts.js +483 -0
  74. package/node_modules/@engenty-wizards/shared/dist/texts.d.ts +11 -2
  75. package/node_modules/@engenty-wizards/shared/dist/texts.js +16 -8
  76. package/node_modules/@engenty-wizards/shared/dist/translation.d.ts +23 -0
  77. package/node_modules/@engenty-wizards/shared/dist/translation.js +154 -0
  78. package/package.json +1 -1
  79. package/apps/web/dist/assets/ChatView-GNHi9ZnZ.js +0 -10
  80. package/apps/web/dist/assets/EditorPage-COJunH8K.js +0 -3
  81. package/apps/web/dist/assets/OnboardingPage-Di8AuZj_.js +0 -1
  82. package/apps/web/dist/assets/ProjectPage-DaerYm8A.js +0 -1
  83. package/apps/web/dist/assets/PublicRunner-Hms0Vi88.js +0 -1
  84. package/apps/web/dist/assets/RunDrawer-DWaC_ryo.js +0 -4
  85. package/apps/web/dist/assets/RunnerView-D5BQ99ah.js +0 -1
  86. package/apps/web/dist/assets/SettingsPage-CQX6fKsa.js +0 -1
  87. package/apps/web/dist/assets/SetupPage-BZkbpN_V.js +0 -1
  88. package/apps/web/dist/assets/changelog-BUHje4CT.js +0 -1
  89. package/apps/web/dist/assets/index-BVWLhiGX.js +0 -14
  90. package/apps/web/dist/assets/index-DmQEcSlY.css +0 -1
  91. package/apps/web/dist/assets/ui-i5saQjmD.js +0 -134
@@ -0,0 +1,483 @@
1
+ // Wording: docs/copy-style.md (voice, glossary, EN/DE mechanics). Write each language as its
2
+ // own sentence, not a word-for-word copy of the other. Check with `pnpm copy:check`.
3
+ /**
4
+ * What the runner says to the person running a wizard, in German and English. The studio spreads
5
+ * these into its own dictionary; a host without one (the WordPress plugin) uses them as they are.
6
+ */
7
+ const de = {
8
+ "result.translate": "Übersetzen",
9
+ "translation.working": "Wird übersetzt …",
10
+ "translation.machine": "Maschinell übersetzt",
11
+ "translation.showOriginal": "Original zeigen",
12
+ "translation.showTranslated": "Übersetzung zeigen",
13
+ "translation.failed": "Dieser Wizard lässt sich gerade nicht übersetzen.",
14
+ "share.copied": "Kopiert",
15
+ "run.closed": "Hier gerade nicht verfügbar, dafür fehlt: {list}",
16
+ "slot.later": "Spätere Termine zeigen",
17
+ "slot.none": "Gerade sind keine Termine frei.",
18
+ "cards.open": "Details",
19
+ "cards.picked": "Ausgewählt ✓",
20
+ "cards.pick": "Auswählen",
21
+ "run.cls.text": "Text",
22
+ "run.cls.image": "Bilder",
23
+ "run.cls.video": "Videos",
24
+ "run.cls.speech": "Sprachausgabe",
25
+ "run.cls.audio": "Sprachnotizen",
26
+ "run.cls.account": "ein engenty-Konto",
27
+ "run.next": "Weiter",
28
+ "run.back": "Zurück",
29
+ "run.accept": "Passt so",
30
+ "run.edit": "Bearbeiten",
31
+ "run.pickItem": "Nr. {n}",
32
+ "run.pickedItem": "Nr. {n} neu",
33
+ "run.regeneratePicked": "Nur Nr. {n} wird neu erstellt.",
34
+ "run.regenerateAll": "Alle werden neu erstellt. Tippe oben auf eine Nummer, um nur einzelne zu erneuern.",
35
+ "check.progress": "{done} von {total} geprüft",
36
+ "check.onlyOpen": "Nur offene",
37
+ "check.noFile": "Zu dieser Zeile gibt es keine Datei.",
38
+ "check.noPreview": "Für diese Datei gibt es keine Vorschau – öffne sie mit dem Link oben.",
39
+ "check.reopen": "Wieder öffnen",
40
+ "run.feedbackPlaceholder": "Passt etwas nicht? Schreib, was anders sein soll …",
41
+ "run.feedbackTarget": "Was soll sich ändern?",
42
+ "run.feedbackPick": "Wähle oben, was sich ändern soll.",
43
+ "ai.generated": "KI-generiert",
44
+ "ai.modified": "Mit KI verändert",
45
+ "ai.publish": "Mit KI erstellt: Wer das veröffentlicht, muss es als KI-generiert kennzeichnen (EU AI Act, Art. 50). Die Datei trägt die Kennzeichnung bereits in ihren Metadaten.",
46
+ "run.regenerateGo": "Neu erstellen",
47
+ "run.retry": "Erneut versuchen",
48
+ "run.again": "Nochmal",
49
+ "run.copy": "Text kopieren",
50
+ "run.failed": "Da hat etwas nicht geklappt.",
51
+ "run.notFound": "Diesen Wizard gibt es nicht, oder er wurde gelöscht.",
52
+ "run.working": "Einen Moment …",
53
+ "run.elapsed": "{s} s",
54
+ "run.cancelled": "Abgebrochen.",
55
+ "run.addRow": "Zeile hinzufügen",
56
+ "run.upload": "Datei wählen oder hierher ziehen",
57
+ "run.uploading": "Lädt hoch …",
58
+ "run.net": "Netto",
59
+ "run.vat": "USt. {r} %",
60
+ "run.total": "Gesamt",
61
+ "run.uploadMore": "Weitere Datei",
62
+ "run.camera": "Kamera",
63
+ "camera.title": "Mit der Kamera aufnehmen",
64
+ "camera.hint": "Gerade und gut beleuchtet ins Bild halten.",
65
+ "camera.taken": "{n} aufgenommen",
66
+ "camera.shoot": "Aufnehmen",
67
+ "camera.done": "Fertig",
68
+ "camera.denied": "Die Kamera ist für diese Seite nicht freigegeben. Erlaube sie in den Website-Einstellungen deines Browsers (Schloss-Symbol in der Adresszeile) – oder nimm das Foto mit der Kamera-App auf.",
69
+ "connect.go": "Verbinden",
70
+ "connect.connected": "Verbunden über {name}",
71
+ "connect.disconnect": "Trennen",
72
+ "connect.none": "Auf diesem Server ist noch kein Anbieter zum Verbinden eingerichtet.",
73
+ "connect.openLink": "Anmeldung in neuem Tab öffnen",
74
+ "list.empty": "Noch keine Einträge.",
75
+ "list.delete": "Zeile löschen",
76
+ "ask.typeInto": "Text in die Seite tippen …",
77
+ "ask.hide": "verdeckt",
78
+ "ask.up": "Nach oben",
79
+ "ask.down": "Nach unten",
80
+ "ask.pictureHint": "Hier siehst du live die Seite, die der Wizard geöffnet hat. Du kannst auch direkt hineinklicken und tippen.",
81
+ "ask.remember": "Anmeldung für nächstes Mal merken",
82
+ "ask.private": "Was du eingibst, geht direkt in die Seite. Die KI bekommt es nicht zu sehen. Gemerkte Anmeldungen werden verschlüsselt gespeichert.",
83
+ "ask.skip": "Überspringen",
84
+ "ask.done": "Ich bin angemeldet",
85
+ "ask.signIn": "Anmelden",
86
+ "ask.wants": "Der Wizard möchte in {service} Folgendes ausführen:",
87
+ "ask.allowRest": "Für den Rest dieses Laufs erlauben",
88
+ "ask.allow": "Erlauben",
89
+ "ask.deny": "Nicht erlauben",
90
+ "store.open": "Was dieser Wizard sich merkt",
91
+ "store.title": "Für dich gemerkt",
92
+ "store.explain": "Dieser Wizard merkt sich Listen, Dateien und verbundene Konten für deinen nächsten Lauf. Nur du siehst sie.",
93
+ "store.empty": "Noch nichts gespeichert.",
94
+ "store.rows": { one: "{n} Eintrag", other: "{n} Einträge" },
95
+ "store.signIns": "Gemerkte Anmeldungen im Browser",
96
+ "store.files": { one: "{n} Datei · {size}", other: "{n} Dateien · {size}" },
97
+ "store.delete": "Alles löschen",
98
+ "store.confirmDelete": "Ja, alles löschen",
99
+ "common.close": "Schließen",
100
+ "run.uploadTouch": "Datei wählen",
101
+ "run.maxFiles": {
102
+ one: "Hier geht höchstens {n} Datei – die übrigen sind weggelassen.",
103
+ other: "Hier gehen höchstens {n} Dateien – die übrigen sind weggelassen.",
104
+ },
105
+ "run.filesMin": "{n} von mindestens {min}",
106
+ "run.filesOf": "{n} von höchstens {max}",
107
+ "run.moveFile": "Nr. {n} verschieben",
108
+ "run.moveFileHint": "Ziehen, um die Reihenfolge zu ändern",
109
+ "run.removeFile": "Entfernen",
110
+ "run.awake": "Der Bildschirm bleibt an, solange der Wizard arbeitet.",
111
+ "run.openFull": "Groß öffnen",
112
+ "run.yes": "Ja",
113
+ "run.no": "Nein",
114
+ "run.share": "Teilen",
115
+ "run.shareNow": "Jetzt teilen",
116
+ "run.shareFile": "Als Datei teilen oder in einer App öffnen",
117
+ "run.print": "Drucken",
118
+ "camera.asking": "Dein Browser fragt gleich nach der Kamera. Das Bild bleibt in diesem Wizard.",
119
+ "camera.native": "Kamera-App öffnen",
120
+ "camera.pick": "Foto auswählen",
121
+ "camera.torch": "Licht",
122
+ "camera.flip": "Kamera wechseln",
123
+ "camera.photo": "Foto",
124
+ "camera.video": "Video",
125
+ "camera.record": "Aufnahme starten",
126
+ "camera.stop": "Aufnahme beenden",
127
+ "camera.recording": "Nimmt auf – tippe zum Beenden.",
128
+ "camera.clipHint": "Ein kurzer Clip, höchstens {s} Sekunden.",
129
+ "camera.hintMany": "Seite für Seite aufnehmen, dann „Fertig“.",
130
+ "scan.button": "Scannen",
131
+ "scan.title": "Code scannen",
132
+ "scan.asking": "Dein Browser fragt gleich nach der Kamera – sie liest nur den Code.",
133
+ "scan.hint": "Halte den QR- oder Barcode in den Rahmen.",
134
+ "scan.hintQr": "Halte den QR-Code in den Rahmen. Barcodes kann dieses Gerät hier nicht lesen.",
135
+ "scan.miss": "Auf dem Foto war kein Code zu erkennen. Versuch es näher und schärfer.",
136
+ "scan.fromPhoto": "Foto mit dem Code wählen",
137
+ "scan.typeInstead": "Lieber eintippen",
138
+ "location.use": "Meinen Standort verwenden",
139
+ "location.locating": "Standort wird bestimmt …",
140
+ "location.refining": "wird noch genauer …",
141
+ "location.accuracy": "auf etwa {m} m genau",
142
+ "location.map": "Karte",
143
+ "location.remove": "Standort entfernen",
144
+ "location.why": "Dein Browser fragt nach deinem Standort. Er wird nur für diesen Wizard verwendet. Du kannst auch einfach die Adresse eintippen.",
145
+ "location.denied": "Der Standort ist für diese Seite nicht freigegeben. Erlaube ihn in den Website-Einstellungen deines Browsers (Schloss-Symbol in der Adresszeile) – oder tippe die Adresse unten ein.",
146
+ "location.manual": "Adresse oder Ort eintippen",
147
+ "location.label": "Adresse oder Beschreibung des Orts",
148
+ "voice.start": "Sprachnotiz aufnehmen",
149
+ "voice.stop": "Stopp",
150
+ "voice.recording": "Aufnahme läuft …",
151
+ "voice.left": "noch {s} s",
152
+ "voice.again": "Neu aufnehmen",
153
+ "voice.remove": "Löschen",
154
+ "voice.pick": "Audiodatei wählen",
155
+ "voice.why": "Dein Browser fragt nach dem Mikrofon. Die Aufnahme wird danach in Text umgewandelt.",
156
+ "voice.denied": "Das Mikrofon ist für diese Seite nicht freigegeben. Erlaube es in den Website-Einstellungen deines Browsers – oder nimm die Notiz mit der Diktier-App auf und wähle die Datei.",
157
+ "voice.noRecorder": "Dieser Browser kann hier nicht aufnehmen. Nimm die Notiz mit der Diktier-App auf und wähle die Datei.",
158
+ "sign.open": "Hier unterschreiben",
159
+ "sign.hint": "Mit dem Finger unterschreiben",
160
+ "sign.pad": "Unterschriftsfeld",
161
+ "sign.clear": "Löschen",
162
+ "sign.accept": "Übernehmen",
163
+ "sign.again": "Neu unterschreiben",
164
+ "sign.remove": "Unterschrift entfernen",
165
+ "notify.ask": "Bescheid geben, wenn es fertig ist",
166
+ "notify.on": "Du bekommst Bescheid",
167
+ "notify.why": "Mit Ton, Vibration oder einer Mitteilung. Dein Browser fragt dafür einmal um Erlaubnis.",
168
+ "notify.onHint": "Du kannst die App wechseln – eine Mitteilung holt dich zurück.",
169
+ "notify.quiet": "Mit Ton und Vibration, solange diese Seite offen ist.",
170
+ "notify.blocked": "Mitteilungen sind für diese Seite blockiert – es gibt Ton und Vibration, solange sie offen ist. Erlauben kannst du sie in den Website-Einstellungen deines Browsers.",
171
+ "notify.done": "Dein Ergebnis ist fertig.",
172
+ "notify.next": "Es geht weiter – wirf einen Blick darauf.",
173
+ "notify.needsYou": "Der Wizard braucht dich kurz.",
174
+ "common.offline": "Keine Verbindung. Prüf dein Netz und versuch es noch einmal.",
175
+ "common.retry": "Erneut versuchen",
176
+ "common.cancel": "Abbrechen",
177
+ "run.start": "Los geht’s",
178
+ "run.unavailable": "Dieser Wizard ist gerade nicht verfügbar.",
179
+ "run.resume": "Letzten Lauf fortsetzen",
180
+ "output.preview": "Vorschau",
181
+ "package.newer": "Diese Wizard-Datei stammt aus einer neueren Version oder ist beschädigt. Aktualisiere engenty wizards oder exportiere den Wizard neu.",
182
+ "package.badJson": "Das ist keine Wizard-Datei: Die wizard.json darin lässt sich nicht lesen.",
183
+ "package.unreadable": "Die Wizard-Datei lässt sich nicht öffnen. Exportiere den Wizard neu und versuche es noch einmal.",
184
+ "package.noManifest": "Das ist keine Wizard-Datei: Die wizard.json fehlt.",
185
+ "browser.driving": "Du steuerst den Browser – klick und tipp in die Seite. Der Wizard wartet.",
186
+ "browser.handBack": "Zurückgeben",
187
+ "browser.takeOver": "Übernehmen",
188
+ "chat.above": "Antworte oben im Chat",
189
+ "chat.badEmail": "Das sieht nicht nach einer E-Mail-Adresse aus.",
190
+ "chat.badNumber": "Das sieht nicht nach einer Zahl aus.",
191
+ "chat.badUrl": "Das sieht nicht nach einer Webadresse aus.",
192
+ "chat.change": "Ändern",
193
+ "chat.checked": "Geprüft",
194
+ "chat.connected": "Verbunden",
195
+ "chat.dictate": "Diktieren (⌘⇧M)",
196
+ "chat.dictateStop": "Diktat beenden",
197
+ "chat.file": "1 Datei",
198
+ "chat.files": { one: "{n} Datei", other: "{n} Dateien" },
199
+ "chat.listening": "Ich höre zu …",
200
+ "chat.micDenied": "Das Mikrofon ist für diese Seite nicht freigegeben. Erlaube es in den Website-Einstellungen deines Browsers.",
201
+ "chat.placeholder": "Deine Antwort …",
202
+ "chat.readAloud": "Vorlesen",
203
+ "chat.readAloudOff": "Vorlesen beenden",
204
+ "chat.required": "Dafür brauche ich eine Antwort.",
205
+ "chat.rows": { one: "{n} Zeile", other: "{n} Zeilen" },
206
+ "chat.send": "Senden",
207
+ "chat.skip": "Überspringen",
208
+ "chat.skipped": "Übersprungen",
209
+ "chat.transcribing": "Wird in Text umgewandelt …",
210
+ "chat.voice": "Sprachnotiz",
211
+ "install.add": "Zum Startbildschirm hinzufügen",
212
+ "install.app": "In der App öffnen",
213
+ "install.bookmark": "Als Lesezeichen speichern",
214
+ "install.bookmark.mac": "Drücke ⌘ D, dann liegt dieser Wizard in deinen Lesezeichen.",
215
+ "install.bookmark.pc": "Drücke Strg + D, dann liegt dieser Wizard in deinen Lesezeichen.",
216
+ "install.ios": "Tippe unten auf „Teilen“ und dann auf „Zum Home-Bildschirm“.",
217
+ "run.madeWith": "Erstellt mit engenty wizards",
218
+ "run.orAs": "Oder: {label}",
219
+ "talk.camera": "Kamera einschalten",
220
+ "talk.cameraDenied": "Die Kamera ist für diese Seite nicht freigegeben. Erlaube sie in den Website-Einstellungen deines Browsers.",
221
+ "talk.cameraOff": "Kamera ausschalten",
222
+ "talk.connecting": "Verbindet …",
223
+ "talk.failed": "Das Gespräch ließ sich nicht starten.",
224
+ "talk.hint": "Sprich mit dem Wizard. Auf dem Bildschirm kannst du mitlesen.",
225
+ "talk.joinHint": "Beim Start fragt dein Browser nach dem Mikrofon, nach der Kamera erst, wenn du sie einschaltest. Im Chat daneben kannst du mitlesen und eingeben, was sich schlecht sagen lässt.",
226
+ "talk.listening": "Hört zu",
227
+ "talk.live": "Im Gespräch",
228
+ "talk.speaking": "Spricht",
229
+ "talk.start": "Gespräch beginnen",
230
+ "talk.stop": "Gespräch beenden",
231
+ "video.cameraOff": "Kamera aus",
232
+ "video.ended": "Anruf beendet",
233
+ "video.flip": "Kamera wechseln",
234
+ "video.hint": "Beim Beitreten fragt dein Browser nach Mikrofon und Kamera. Im Chat daneben kannst du mitlesen und eingeben, was sich schlecht sagen lässt.",
235
+ "video.join": "Beitreten",
236
+ "video.leave": "Verlassen",
237
+ "video.mute": "Stummschalten",
238
+ "video.rejoin": "Wieder beitreten",
239
+ "video.unmute": "Stummschaltung aufheben",
240
+ "video.you": "Du",
241
+ "nav.language": "Sprache",
242
+ };
243
+ const en = {
244
+ "result.translate": "Translate",
245
+ "translation.working": "Translating…",
246
+ "translation.machine": "Machine-translated",
247
+ "translation.showOriginal": "Show original",
248
+ "translation.showTranslated": "Show translation",
249
+ "translation.failed": "This wizard can’t be translated right now.",
250
+ "share.copied": "Copied",
251
+ "run.closed": "Not available here right now. It needs {list}.",
252
+ "slot.later": "Show later times",
253
+ "slot.none": "No times are free right now.",
254
+ "cards.open": "Details",
255
+ "cards.picked": "Chosen ✓",
256
+ "cards.pick": "Choose",
257
+ "run.cls.text": "text",
258
+ "run.cls.image": "images",
259
+ "run.cls.video": "video",
260
+ "run.cls.speech": "speech output",
261
+ "run.cls.audio": "voice notes",
262
+ "run.cls.account": "an engenty account",
263
+ "run.next": "Continue",
264
+ "run.back": "Back",
265
+ "run.accept": "Looks good",
266
+ "run.edit": "Edit",
267
+ "run.pickItem": "No. {n}",
268
+ "run.pickedItem": "No. {n} again",
269
+ "run.regeneratePicked": "Only no. {n} will be redone.",
270
+ "run.regenerateAll": "Applies to all. Tap a number to redo just that one.",
271
+ "check.progress": "{done} of {total} checked",
272
+ "check.onlyOpen": "Open only",
273
+ "check.noFile": "There’s no file for this row.",
274
+ "check.noPreview": "This file has no preview – open it with the link above.",
275
+ "check.reopen": "Open again",
276
+ "run.feedbackPlaceholder": "Something not right? Write what should be different…",
277
+ "run.feedbackTarget": "What should change?",
278
+ "run.feedbackPick": "Choose above what should change.",
279
+ "ai.generated": "AI-generated",
280
+ "ai.modified": "AI-modified",
281
+ "ai.publish": "Made with AI: whoever publishes this has to label it as AI-generated (EU AI Act, Art. 50). The file already carries the marking in its metadata.",
282
+ "run.regenerateGo": "Recreate",
283
+ "run.retry": "Try again",
284
+ "run.again": "Start over",
285
+ "run.copy": "Copy text",
286
+ "run.failed": "Something went wrong.",
287
+ "run.notFound": "This wizard doesn’t exist or was deleted.",
288
+ "run.working": "One moment…",
289
+ "run.elapsed": "{s} s",
290
+ "run.cancelled": "Cancelled.",
291
+ "run.addRow": "Add row",
292
+ "run.upload": "Choose a file or drop it here",
293
+ "run.uploading": "Uploading…",
294
+ "run.net": "Net",
295
+ "run.vat": "VAT {r}%",
296
+ "run.total": "Total",
297
+ "run.uploadMore": "Another file",
298
+ "run.camera": "Camera",
299
+ "camera.title": "Take a picture",
300
+ "camera.hint": "Hold it flat and well lit.",
301
+ "camera.taken": "{n} taken",
302
+ "camera.shoot": "Capture",
303
+ "camera.done": "Done",
304
+ "camera.denied": "The camera isn’t allowed for this page. Allow it in your browser’s site settings (the lock icon in the address bar) – or take the photo with your camera app.",
305
+ "connect.go": "Connect",
306
+ "connect.connected": "Connected through {name}",
307
+ "connect.disconnect": "Disconnect",
308
+ "connect.none": "This server has no provider for connecting accounts yet.",
309
+ "connect.openLink": "Click here to open the sign-in in a new tab",
310
+ "list.empty": "No entries yet.",
311
+ "list.delete": "Delete row",
312
+ "ask.typeInto": "Type into the page…",
313
+ "ask.hide": "hidden",
314
+ "ask.up": "Scroll up",
315
+ "ask.down": "Scroll down",
316
+ "ask.pictureHint": "This is the page the wizard has open, live. You can also click and type right in it.",
317
+ "ask.remember": "Remember this sign-in for next time",
318
+ "ask.private": "What you enter goes straight into the page. The AI never sees it. Remembered sign-ins are stored encrypted.",
319
+ "ask.skip": "Skip",
320
+ "ask.done": "I’m signed in",
321
+ "ask.signIn": "Sign in",
322
+ "ask.wants": "The wizard wants to run this in {service}:",
323
+ "ask.allowRest": "Allow for the rest of this run",
324
+ "ask.allow": "Allow",
325
+ "ask.deny": "Don’t allow",
326
+ "store.open": "What this wizard remembers",
327
+ "store.title": "Kept for you",
328
+ "store.explain": "This wizard keeps lists, files and connected accounts for your next run. Only you see them.",
329
+ "store.empty": "Nothing kept yet.",
330
+ "store.rows": { one: "{n} entry", other: "{n} entries" },
331
+ "store.signIns": "Remembered sign-ins in the browser",
332
+ "store.files": { one: "{n} file · {size}", other: "{n} files · {size}" },
333
+ "store.delete": "Delete everything",
334
+ "store.confirmDelete": "Yes, delete everything",
335
+ "common.close": "Close",
336
+ "run.uploadTouch": "Choose a file",
337
+ "run.maxFiles": {
338
+ one: "At most {n} fits here – the rest were left out.",
339
+ other: "At most {n} fit here – the rest were left out.",
340
+ },
341
+ "run.filesMin": "{n} of at least {min}",
342
+ "run.filesOf": "{n} of at most {max}",
343
+ "run.moveFile": "Move no. {n}",
344
+ "run.moveFileHint": "Drag to change the order",
345
+ "run.removeFile": "Remove",
346
+ "run.awake": "The screen stays on while the wizard works.",
347
+ "run.openFull": "Open full size",
348
+ "run.yes": "Yes",
349
+ "run.no": "No",
350
+ "run.share": "Share",
351
+ "run.shareNow": "Share now",
352
+ "run.shareFile": "Share as a file or open in an app",
353
+ "run.print": "Print",
354
+ "camera.asking": "Your browser is about to ask for the camera. The picture stays in this wizard.",
355
+ "camera.native": "Open the camera app",
356
+ "camera.pick": "Choose a photo",
357
+ "camera.torch": "Light",
358
+ "camera.flip": "Switch camera",
359
+ "camera.photo": "Photo",
360
+ "camera.video": "Video",
361
+ "camera.record": "Start recording",
362
+ "camera.stop": "Stop recording",
363
+ "camera.recording": "Recording – tap to stop.",
364
+ "camera.clipHint": "A short clip, {s} seconds at most.",
365
+ "camera.hintMany": "Capture page after page, then “Done”.",
366
+ "scan.button": "Scan",
367
+ "scan.title": "Scan a code",
368
+ "scan.asking": "Your browser is about to ask for the camera – it only reads the code.",
369
+ "scan.hint": "Hold the QR code or barcode inside the frame.",
370
+ "scan.hintQr": "Hold the QR code inside the frame. This device doesn’t read barcodes here.",
371
+ "scan.miss": "No code was found in the photo. Try closer and sharper.",
372
+ "scan.fromPhoto": "Choose a photo of the code",
373
+ "scan.typeInstead": "Type it instead",
374
+ "location.use": "Use my location",
375
+ "location.locating": "Finding your location…",
376
+ "location.refining": "getting more accurate…",
377
+ "location.accuracy": "accurate to about {m} m",
378
+ "location.map": "Map",
379
+ "location.remove": "Remove location",
380
+ "location.why": "Your browser asks for your location. It’s only used for this wizard. You can also just type the address.",
381
+ "location.denied": "Location isn’t allowed for this page. Allow it in your browser’s site settings (the lock icon in the address bar) – or type the address below.",
382
+ "location.manual": "Type an address or place",
383
+ "location.label": "Address or description of the place",
384
+ "voice.start": "Record a voice note",
385
+ "voice.stop": "Stop",
386
+ "voice.recording": "Recording…",
387
+ "voice.left": "{s} s left",
388
+ "voice.again": "Record again",
389
+ "voice.remove": "Delete",
390
+ "voice.pick": "Choose an audio file",
391
+ "voice.why": "Your browser asks for the microphone. The recording is turned into text afterwards.",
392
+ "voice.denied": "The microphone isn’t allowed for this page. Allow it in your browser’s site settings – or record the note with your voice memo app and choose the file.",
393
+ "voice.noRecorder": "This browser can’t record here. Record the note with your voice memo app and choose the file.",
394
+ "sign.open": "Sign here",
395
+ "sign.hint": "Sign with your finger",
396
+ "sign.pad": "Signature pad",
397
+ "sign.clear": "Clear",
398
+ "sign.accept": "Use it",
399
+ "sign.again": "Sign again",
400
+ "sign.remove": "Remove signature",
401
+ "notify.ask": "Tell me when it’s done",
402
+ "notify.on": "We’ll let you know",
403
+ "notify.why": "With a sound, a buzz or a notification. Your browser asks once for permission.",
404
+ "notify.onHint": "You can switch apps – a notification brings you back.",
405
+ "notify.quiet": "With a sound and a buzz while this page is open.",
406
+ "notify.blocked": "Notifications are blocked for this page – you get a sound and a buzz while it’s open. You can allow them in your browser’s site settings.",
407
+ "notify.done": "Your result is ready.",
408
+ "notify.next": "The next step is ready – have a look.",
409
+ "notify.needsYou": "The wizard needs you for a moment.",
410
+ "common.offline": "No connection. Check your network and try again.",
411
+ "common.retry": "Try again",
412
+ "common.cancel": "Cancel",
413
+ "run.start": "Let’s go",
414
+ "run.unavailable": "This wizard isn’t available right now.",
415
+ "run.resume": "Continue your last run",
416
+ "output.preview": "Preview",
417
+ "package.newer": "This wizard file comes from a newer version, or it’s damaged. Update engenty wizards or export the wizard again.",
418
+ "package.badJson": "This isn’t a wizard file: its wizard.json can’t be read.",
419
+ "package.unreadable": "The wizard file can’t be opened. Export the wizard again and try once more.",
420
+ "package.noManifest": "This isn’t a wizard file: wizard.json is missing.",
421
+ "browser.driving": "You’re in control of the browser – click and type in the page. The wizard waits.",
422
+ "browser.handBack": "Hand back",
423
+ "browser.takeOver": "Take over",
424
+ "chat.above": "Answer above in the chat",
425
+ "chat.badEmail": "That doesn’t look like an email address.",
426
+ "chat.badNumber": "Enter a number.",
427
+ "chat.badUrl": "That isn’t a valid address.",
428
+ "chat.change": "Change",
429
+ "chat.checked": "Checked",
430
+ "chat.connected": "Connected",
431
+ "chat.dictate": "Dictate (⌘⇧M)",
432
+ "chat.dictateStop": "Stop dictating",
433
+ "chat.file": "1 file",
434
+ "chat.files": { one: "{n} file", other: "{n} files" },
435
+ "chat.listening": "Listening…",
436
+ "chat.micDenied": "The microphone isn’t allowed for this page. Allow it in your browser’s site settings.",
437
+ "chat.placeholder": "Your answer…",
438
+ "chat.readAloud": "Read aloud",
439
+ "chat.readAloudOff": "Stop reading aloud",
440
+ "chat.required": "I need an answer for this one.",
441
+ "chat.rows": { one: "{n} row", other: "{n} rows" },
442
+ "chat.send": "Send",
443
+ "chat.skip": "Skip",
444
+ "chat.skipped": "Skipped",
445
+ "chat.transcribing": "Writing it down…",
446
+ "chat.voice": "Voice note",
447
+ "install.add": "Add to home screen",
448
+ "install.app": "Open in the app",
449
+ "install.bookmark": "Bookmark this wizard",
450
+ "install.bookmark.mac": "Press ⌘ D to keep this wizard in your bookmarks.",
451
+ "install.bookmark.pc": "Press Ctrl + D to keep this wizard in your bookmarks.",
452
+ "install.ios": "Tap “Share” below, then “Add to Home Screen”.",
453
+ "run.madeWith": "Made with engenty wizards",
454
+ "run.orAs": "Or: {label}",
455
+ "talk.camera": "Switch the camera on",
456
+ "talk.cameraDenied": "The camera isn’t allowed for this page. Allow it in your browser’s site settings.",
457
+ "talk.cameraOff": "Switch the camera off",
458
+ "talk.connecting": "Connecting…",
459
+ "talk.failed": "The conversation couldn’t start. Check your connection and try again.",
460
+ "talk.hint": "Talk to the wizard – the screen follows along.",
461
+ "talk.joinHint": "Your browser asks for the microphone when you start, and for the camera only when you switch it on. The chat beside it follows along and handles what voice can’t.",
462
+ "talk.listening": "Listening",
463
+ "talk.live": "In conversation",
464
+ "talk.speaking": "Speaking",
465
+ "talk.start": "Start talking",
466
+ "talk.stop": "End the conversation",
467
+ "video.cameraOff": "Camera off",
468
+ "video.ended": "Call ended",
469
+ "video.flip": "Switch camera",
470
+ "video.hint": "Your browser asks for the microphone and camera when you join. The chat beside it follows along and handles what voice can’t.",
471
+ "video.join": "Join",
472
+ "video.leave": "Leave",
473
+ "video.mute": "Mute",
474
+ "video.rejoin": "Rejoin",
475
+ "video.unmute": "Unmute",
476
+ "video.you": "You",
477
+ "nav.language": "Language",
478
+ };
479
+ /**
480
+ * The runner's words in each language. English has every one; another language may lack some,
481
+ * and those are said in English.
482
+ */
483
+ export const RUNNER_TEXTS = { en, de };
@@ -24,13 +24,22 @@ export type Texts<K extends string> = {
24
24
  };
25
25
  /** What fills a line's gaps: words, a number (written the language's way), or a list of them. */
26
26
  export type Gap = string | number | readonly Gap[];
27
+ /** The plural rules of a language: any language, by its code. */
28
+ export declare function pluralRules(lang: string): Intl.PluralRules;
27
29
  /** A gap's words in a language: numbers as the language writes them, lists joined. */
28
- export declare function gapText(value: Gap, lang: Lang): string;
30
+ export declare function gapText(value: Gap, lang: string): string;
29
31
  /** Fills `{name}` gaps; a gap with nothing for it stays as it is. */
30
- export declare function fillGaps(text: string, lang: Lang, params?: Record<string, Gap | undefined>): string;
32
+ export declare function fillGaps(text: string, lang: string, params?: Record<string, Gap | undefined>): string;
31
33
  /**
32
34
  * A line of a table in a language, its gaps filled and its plural form picked by `{count}`
33
35
  * (or `{n}`);
34
36
  * the English line where the language lacks one.
35
37
  */
36
38
  export declare function textOf<K extends string>(texts: Texts<K>, key: K, lang: Lang, params?: Record<string, Gap | undefined>): string;
39
+ /**
40
+ * A string table of one language outside `LANGS`, translated on request: lines by key, a plural
41
+ * line with the forms of that language's plural categories.
42
+ */
43
+ export type TextTable = Record<string, Line>;
44
+ /** A line of a table, in a language: its gaps filled and its plural form picked. */
45
+ export declare function lineText(line: Line, lang: string, params?: Record<string, Gap | undefined>): string;
@@ -1,6 +1,15 @@
1
1
  // SPDX-License-Identifier: FSL-1.1-MIT OR MIT
2
- import { LOCALES } from "./definition.js";
2
+ import { localeOf } from "./definition.js";
3
3
  const plurals = new Map();
4
+ /** The plural rules of a language: any language, by its code. */
5
+ export function pluralRules(lang) {
6
+ let rules = plurals.get(lang);
7
+ if (!rules) {
8
+ rules = new Intl.PluralRules(localeOf(lang));
9
+ plurals.set(lang, rules);
10
+ }
11
+ return rules;
12
+ }
4
13
  function form(line, lang, count) {
5
14
  if (typeof line === "string") {
6
15
  return line;
@@ -8,17 +17,12 @@ function form(line, lang, count) {
8
17
  if (typeof count !== "number") {
9
18
  return line.other;
10
19
  }
11
- let rules = plurals.get(lang);
12
- if (!rules) {
13
- rules = new Intl.PluralRules(LOCALES[lang]);
14
- plurals.set(lang, rules);
15
- }
16
- return line[rules.select(count)] ?? line.other;
20
+ return line[pluralRules(lang).select(count)] ?? line.other;
17
21
  }
18
22
  /** A gap's words in a language: numbers as the language writes them, lists joined. */
19
23
  export function gapText(value, lang) {
20
24
  if (typeof value === "number") {
21
- return value.toLocaleString(LOCALES[lang]);
25
+ return value.toLocaleString(localeOf(lang));
22
26
  }
23
27
  if (Array.isArray(value)) {
24
28
  return value.map((item) => gapText(item, lang)).join(", ");
@@ -44,3 +48,7 @@ export function textOf(texts, key, lang, params) {
44
48
  }
45
49
  return fillGaps(form(line, lang, params?.count ?? params?.n), lang, params);
46
50
  }
51
+ /** A line of a table, in a language: its gaps filled and its plural form picked. */
52
+ export function lineText(line, lang, params) {
53
+ return fillGaps(form(line, lang, params?.count ?? params?.n), lang, params);
54
+ }
@@ -0,0 +1,23 @@
1
+ import type { WizardDefinition } from "./definition.js";
2
+ /** The texts of a definition the person reads, each once, in the order they appear. */
3
+ export declare function wizardTexts(def: WizardDefinition): string[];
4
+ /** Whether a translated text keeps every placeholder and gap of its original, no more, no fewer. */
5
+ export declare function keepsPlaceholders(original: string, translated: string): boolean;
6
+ /** A translation as it is kept: each original text with its translation and who wrote it. */
7
+ export interface TranslationEntry {
8
+ text: string;
9
+ by: "machine" | "author";
10
+ }
11
+ export type TranslationMemory = Record<string, TranslationEntry>;
12
+ /** The texts of a definition a translation does not have yet. */
13
+ export declare function missingTexts(def: WizardDefinition, memory: TranslationMemory): string[];
14
+ /**
15
+ * The definition in the viewer's language: a copy with every text the memory has written in,
16
+ * and the labels of the choices beside it (`labels[value]`), the values untouched.
17
+ */
18
+ export declare function translateDefinition(def: WizardDefinition, memory: TranslationMemory): {
19
+ def: WizardDefinition;
20
+ labels: Record<string, string>;
21
+ };
22
+ /** Whether every text of the memory came from the author, or some from a model. */
23
+ export declare function machineTranslated(memory: TranslationMemory, def: WizardDefinition): boolean;