@seliseblocks/mailcraft 0.1.0 → 0.2.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 (69) hide show
  1. package/DOCS.md +240 -12
  2. package/README.md +11 -3
  3. package/README.md.txt +134 -0
  4. package/dist/mailcraft-editor.bundle.js +51 -39
  5. package/dist/mailcraft-editor.bundle.js.map +3 -3
  6. package/examples/templates/order-confirmed.html +80 -80
  7. package/examples/vanilla.html +242 -23
  8. package/package.json +7 -2
  9. package/src/core/assets.js +10 -15
  10. package/src/core/binder.js +120 -118
  11. package/src/core/blocks.js +14 -1
  12. package/src/core/css-cascade.js +117 -117
  13. package/src/core/editor-core.js +1530 -1492
  14. package/src/core/export.js +142 -55
  15. package/src/core/i18n/ar.js +219 -177
  16. package/src/core/i18n/bg.js +196 -152
  17. package/src/core/i18n/bn.js +218 -176
  18. package/src/core/i18n/ca.js +196 -152
  19. package/src/core/i18n/cs.js +196 -152
  20. package/src/core/i18n/da.js +196 -152
  21. package/src/core/i18n/de-CH.js +196 -152
  22. package/src/core/i18n/de.js +196 -152
  23. package/src/core/i18n/dz.js +221 -179
  24. package/src/core/i18n/el.js +196 -152
  25. package/src/core/i18n/en.js +3 -10
  26. package/src/core/i18n/es.js +196 -152
  27. package/src/core/i18n/et.js +196 -152
  28. package/src/core/i18n/fi.js +196 -152
  29. package/src/core/i18n/fr.js +196 -152
  30. package/src/core/i18n/hr.js +196 -152
  31. package/src/core/i18n/hu.js +196 -152
  32. package/src/core/i18n/index.js +83 -83
  33. package/src/core/i18n/it.js +196 -152
  34. package/src/core/i18n/lt.js +196 -152
  35. package/src/core/i18n/lv.js +196 -152
  36. package/src/core/i18n/nb.js +196 -152
  37. package/src/core/i18n/nl.js +196 -152
  38. package/src/core/i18n/pl.js +196 -152
  39. package/src/core/i18n/pt.js +196 -152
  40. package/src/core/i18n/ro.js +196 -152
  41. package/src/core/i18n/ru.js +196 -152
  42. package/src/core/i18n/sk.js +196 -152
  43. package/src/core/i18n/sl.js +196 -152
  44. package/src/core/i18n/sv.js +196 -152
  45. package/src/core/i18n/tables.js +50 -50
  46. package/src/core/i18n/tr.js +196 -152
  47. package/src/core/i18n/uk.js +196 -152
  48. package/src/core/icons.js +237 -235
  49. package/src/core/ids.js +1 -1
  50. package/src/core/import-html.js +1025 -959
  51. package/src/core/layout-style.js +100 -100
  52. package/src/core/parse.js +10 -10
  53. package/src/core/placeholder.js +15 -15
  54. package/src/core/sanitize.js +141 -141
  55. package/src/core/storage-limits.js +184 -184
  56. package/src/core/storage.js +85 -85
  57. package/src/core/theme.js +1 -1
  58. package/src/core/variables.js +11 -11
  59. package/src/index.js +9 -9
  60. package/src/mailcraft-editor.js +26 -14
  61. package/src/render/block-body.js +49 -6
  62. package/src/render/canvas.js +31 -2
  63. package/src/render/fields.js +602 -588
  64. package/src/render/focus-preserve.js +158 -158
  65. package/src/render/rte.js +241 -212
  66. package/src/render/screenshot.js +132 -132
  67. package/src/render/story.js +415 -415
  68. package/src/render/style.js +8 -0
  69. package/types/index.d.ts +419 -0
@@ -1,152 +1,196 @@
1
- /** Swiss High German (Schweizer Hochdeutsch) — `de-CH`. Same table as `de.js` with the Swiss orthography rule applied (ß → ss); Swiss keyboards and style guides don't use ß at all. AI-drafted, not reviewed by a native speaker. Correctable one key at a time via `.messages` overrides. */
2
- export const DE_CH = {
3
- 'action.undoHint': 'Rückgängig — ⌘Z',
4
- 'action.redoHint': 'Wiederholen — ⌘⇧Z',
5
- 'action.chromeToDark': 'Dunkel',
6
- 'action.chromeToLight': 'Hell',
7
- 'action.chromeHint': 'Editor-Design hell / dunkel',
8
- 'action.aiCopy': 'Text',
9
- 'action.aiCopyHint': 'Text mit KI entwerfen',
10
- 'action.code': 'Code',
11
- 'action.codeHint': 'Rohes HTML mit Live-Vorschau bearbeiten',
12
- 'action.preview': 'Vorschau',
13
- 'action.export': 'Exportieren',
14
- 'device.desktop': 'Desktop',
15
- 'device.desktopHint': 'Desktop-Breite',
16
- 'device.mobile': 'Mobil',
17
- 'device.mobileHint': 'Mobile Breite',
18
- 'device.dark': 'Dunkel',
19
- 'device.darkHint': 'Dunkler Posteingang',
20
- 'status.autosaveOn': 'Autospeichern aktiv',
21
- 'status.saved': 'gespeichert {time}',
22
- 'status.saveFailed': 'nicht gespeichert — Speicher voll',
23
- 'canvas.meta': '{rows} Zeilen · {blocks} Blöcke · {width}px',
24
- 'tab.design': 'Stil',
25
- 'tab.designHint': 'Auswahl gestalten',
26
- 'tab.blocks': 'Blöcke',
27
- 'tab.blocksHint': 'Inhaltsblöcke und Variablen',
28
- 'tab.rows': 'Abschn.',
29
- 'tab.rowsHint': 'Abschnittslayouts und Canvas-Modell',
30
- 'tab.files': 'Dateien',
31
- 'tab.filesHint': 'Asset-Bibliothek',
32
- 'tab.layers': 'Struktur',
33
- 'tab.layersHint': 'Dokumentstruktur',
34
- 'tab.theme': 'Thema',
35
- 'tab.themeHint': 'Globale Stile',
36
- 'tab.data': 'Var.',
37
- 'tab.dataHint': 'Von deinem Code bereitgestellte Variablen',
38
- 'inspector.blockProperties': 'Blockeigenschaften',
39
- 'inspector.sectionProperties': 'Abschnittseigenschaften',
40
- 'inspector.title': 'Inspektor',
41
- 'inspector.sectionLabel': 'Abschnitt',
42
- 'inspector.nothingSelected': 'Nichts ausgewählt',
43
- 'action.duplicateHint': 'Duplizieren — ⌘D',
44
- 'action.deleteHint': 'Löschen — ⌫',
45
- 'inspector.emptyBody':
46
- 'Wähle eine Zeile oder einen Block auf der Canvas aus, um ihn hier zu gestalten. Ziehe Blöcke aus dem Tab <strong style="color: var(--ed-text); font-weight: 600;">Blöcke</strong>; Doppelklick auf beliebigen Text, um ihn direkt zu bearbeiten.',
47
- 'inspector.shortcuts': 'Kurzbefehle',
48
- 'shortcut.undoRedo': '⌘Z / ⌘⇧Z Rückgängig, Wiederholen',
49
- 'shortcut.duplicate': '⌘D — Auswahl duplizieren',
50
- 'shortcut.delete': 'Auswahl löschen',
51
- 'shortcut.export': '⌘EHTML exportieren',
52
- 'shortcut.escape': 'ESC — Auswahl aufheben, schliessen',
53
- 'blocks.dragHint': 'Auf die Canvas ziehen',
54
- 'blocks.count': '{count} Blöcke',
55
- 'rows.sectionLayouts': 'Abschnittslayouts',
56
- 'rows.customMarkup': 'Eigenes Markup',
57
- 'rows.htmlRowHint': 'Zum Einfügen ziehen oder klicken — eine randlose Zeile, die du mit rohem HTML füllst',
58
- 'rows.rawHtmlSection': 'Roher HTML-Abschnitt',
59
- 'rows.rawHtmlDesc': 'Randloser Abschnitt, dein eigenes Markup, weiterhin ziehbar',
60
- 'rows.canvasModel': 'Canvas-Modell',
61
- 'rows.modeRowBased': 'Zeilenbasiert',
62
- 'rows.modeFreeStack': 'Freier Stapel',
63
- 'rows.hintRows':
64
- 'Abschnittsbasiert: Zuerst ein Layout ablegen, dann Blöcke in seine Spalten ziehen — jeder Abschnitt hat eigene Hintergrund-, Rahmen-, Flex- oder Grid-Einstellungen.',
65
- 'rows.hintStack': 'Freier Stapel: Ohne Layouts — jeder abgelegte Block wird zu einem eigenen, vollbreiten Abschnitt, der Reihe nach gestapelt.',
66
- 'files.libraryCount': 'Bibliothek{count} Dateien',
67
- 'files.openManager': 'Dateimanager öffnen',
68
- 'files.dragToCanvas': 'Ziehe eine beliebige Datei direkt auf die Canvas, um sie als Bildblock einzufügen.',
69
- 'layers.structure': 'Struktur',
70
- 'layers.sectionSingle': 'Abschnitt',
71
- 'layers.sectionMulti': 'Abschnitt · {count} Spalten',
72
- 'layers.blockCount': '{count} Blk.',
73
- 'theme.globalStyles': 'Globale Stile',
74
- 'vars.title': 'Variablen',
75
- 'vars.fromCode': '{count} aus deinem Code',
76
- 'vars.declaredNote': 'Von deiner Anwendung deklariert — die Canvas zeigt immer das Token, nie einen Wert.',
77
- 'vars.filterPlaceholder': 'Variablen filtern…',
78
- 'vars.insertHint': 'Klicken, um in ausgewählten Text, Überschrift oder Button einzufügen',
79
- 'vars.insert': 'einfügen',
80
- 'vars.noMatch': 'Keine Variable entspricht diesem Filter.',
81
- 'vars.noneDeclared': 'Deine Anwendung hat noch keine Variablen deklariert.',
82
- 'vars.rteHint': 'Beim Bearbeiten von Text kannst du eine Variable auch direkt aus dem Dropdown der Inline-Symbolleiste auswählen.',
83
- 'modal.fileManager': 'Dateimanager',
84
- 'modal.assetsTitle': 'Assets',
85
- 'modal.replaceImage': 'Bild ersetzen',
86
- 'library.searchPlaceholder': 'Dateien suchen…',
87
- 'action.upload': 'Hochladen',
88
- 'library.clickToPlace': 'Datei anklicken zum Platzieren · oder Datei auf die Canvas ziehen',
89
- 'library.clickToReplace': 'Datei anklicken, um das ausgewählte Bild zu ersetzen',
90
- 'library.storageLabel': '{count} Dateien · {size}',
91
- 'library.folders': 'Ordner',
92
- 'library.dropHint': 'Bilddateien hier zum Hochladen ablegen — oder den Hochladen-Button nutzen.',
93
- 'library.deleteFileHint': 'Datei löschen',
94
- 'library.del': 'LÖSCH',
95
- 'toast.assetDeleted': '{name} gelöscht',
96
- 'modal.export': 'Exportieren',
97
- 'modal.exportTitle': 'Tabellenbasiertes E-Mail-HTML',
98
- 'export.copy': 'Kopieren',
99
- 'export.copied': 'Kopiert',
100
- 'action.download': 'Herunterladen',
101
- 'export.meta': '{kb} KB · Tabellen + Inline-Stile · Outlook-sichere Breiten',
102
- 'modal.rawHtmlTitle': 'Rohes HTML, Live-Vorschau',
103
- 'code.statusEdited': 'Code-Ansicht bearbeitet Vorschau live, noch nicht übernommen',
104
- 'code.statusSynced': 'Code-Ansicht synchron mit der Canvas',
105
- 'action.reload': 'Neu laden',
106
- 'action.reloadHint': 'Quelltext aus der Canvas neu laden',
107
- 'action.applyToCanvas': 'Auf Canvas anwenden',
108
- 'action.applyToCanvasHint': 'Quelltext zurück in bearbeitbare Zeilen umwandeln',
109
- 'action.closeWithoutApplyingHint': 'Ohne Anwenden schliessen',
110
- 'code.source': 'Quelltext',
111
- 'code.livePreview': 'Live-Vorschau',
112
- 'code.liveHtmlPreviewTitle': 'Live-HTML-Vorschau',
113
- 'code.applyNote':
114
- 'Beim Anwenden wird jede oberste Tabellenzeile in eine Canvas-Zeile umgewandelt, die du weiterhin auswählen, neu anordnen und löschen kannst handgeschriebenes Markup übersteht den Vorgang unverändert.',
115
- 'code.meta': '{kb} KB · {lines} Zeilen',
116
- 'toast.sourceReloaded': 'Quelltext aus der Canvas neu geladen',
117
- 'toast.sourceAppliedOne': 'Quelltext angewendet — 1 Zeile auf der Canvas',
118
- 'toast.sourceAppliedMany': 'Quelltext angewendet — {rows} Zeilen auf der Canvas',
119
- 'toast.parseError': 'Dieses HTML konnte nicht verarbeitet werden',
120
- 'modal.copyAssist': 'Textassistent',
121
- 'modal.draftCopyTitle': 'Text für diese Kampagne entwerfen',
122
- 'ai.goal': 'Ziel',
123
- 'ai.tone': 'Ton',
124
- 'ai.briefLabel': 'Worum geht es in dieser E-Mail?',
125
- 'ai.briefPlaceholder': 'z. B. Herbstkollektion, 15 % für Abonnenten, kostenloser Versand ab 150 €',
126
- 'ai.generate': 'Text generieren',
127
- 'ai.writing': 'Wird geschrieben…',
128
- 'ai.kindHeadline': 'Überschrift',
129
- 'ai.kindBody': 'Fliesstext',
130
- 'ai.kindButton': 'Button-Text',
131
- 'ai.actionInsertHeading': 'Als Überschrift einfügen',
132
- 'ai.actionInsertText': 'Als Textblock einfügen',
133
- 'ai.actionInsertButton': 'Als Button einfügen',
134
- 'toast.headingAdded': 'Überschrift hinzugefügt',
135
- 'toast.textBlockAdded': 'Textblock hinzugefügt',
136
- 'toast.buttonAdded': 'Button hinzugefügt',
137
- 'preview.kickerMobile': 'VorschauMobil 375px',
138
- 'preview.kickerDark': 'Vorschau Dunkler Posteingang',
139
- 'preview.kickerDesktop': 'Vorschau — Desktop {width}px',
140
- 'action.close': 'Schliessen',
141
- 'toast.duplicated': 'Dupliziert',
142
- 'toast.fileUploadedOne': '1 Datei hochgeladen',
143
- 'toast.fileUploadedMany': '{count} Dateien hochgeladen',
144
- 'toast.imageReplaced': 'Bild ersetzt',
145
- 'toast.imageAdded': 'Bild zur Canvas hinzugefügt',
146
- 'toast.htmlCopied': 'HTML in die Zwischenablage kopiert',
147
- 'toast.templateLoaded': '{name} geladen',
148
- 'toast.snippetDefaultLabel': 'Snippet',
149
- 'toast.snippetInserted': '{name} eingefügt',
150
- 'toast.snippetCopied': '{name} kopiert — wähle einen Textblock zum Einfügen aus',
151
- };
152
-
1
+ /** Swiss High German (Schweizer Hochdeutsch) — `de-CH`. Same table as `de.js` with the Swiss orthography rule applied (ß → ss); Swiss keyboards and style guides don't use ß at all. AI-drafted, not reviewed by a native speaker. Correctable one key at a time via `.messages` overrides. */
2
+ export const DE_CH = {
3
+ 'action.undoHint': 'Rückgängig — ⌘Z',
4
+ 'action.redoHint': 'Wiederholen — ⌘⇧Z',
5
+ 'action.chromeToDark': 'Dunkel',
6
+ 'action.chromeToLight': 'Hell',
7
+ 'action.chromeHint': 'Editor-Design hell / dunkel',
8
+ 'action.chromeHintToDark': 'Dunkelmodus',
9
+ 'action.chromeHintToLight': 'Hellmodus',
10
+ 'action.aiDraft': 'Entwurf',
11
+ 'action.aiDraftHint': 'E-Mail-Inhalt mit KI entwerfen',
12
+ 'action.code': 'Code',
13
+ 'action.codeHint': 'Rohes HTML mit Live-Vorschau bearbeiten',
14
+ 'action.preview': 'Vorschau',
15
+ 'action.previewHint': 'E-Mail-Vorschau',
16
+ 'action.export': 'Exportieren',
17
+ 'action.exportHint': 'E-Mail exportieren',
18
+ 'device.desktop': 'Desktop',
19
+ 'device.desktopHint': 'Desktop-Breite',
20
+ 'device.mobile': 'Mobil',
21
+ 'device.mobileHint': 'Mobile Breite',
22
+ 'status.autosaveOn': 'Autospeichern aktiv',
23
+ 'status.saved': 'gespeichert {time}',
24
+ 'status.saveFailed': 'nicht gespeichert — Speicher voll',
25
+ 'canvas.meta': '{rows} Zeilen · {blocks} Blöcke · {width}px',
26
+ 'tab.design': 'Stil',
27
+ 'tab.designHint': 'Auswahl gestalten',
28
+ 'tab.blocks': 'Blöcke',
29
+ 'tab.blocksHint': 'Inhaltsblöcke und Variablen',
30
+ 'tab.rows': 'Abschn.',
31
+ 'tab.rowsHint': 'Abschnittslayouts und Canvas-Modell',
32
+ 'tab.files': 'Dateien',
33
+ 'tab.filesHint': 'Asset-Bibliothek',
34
+ 'tab.layers': 'Struktur',
35
+ 'tab.layersHint': 'Dokumentstruktur',
36
+ 'tab.settings': 'Einstellungen',
37
+ 'tab.settingsHint': 'E-Mail-Einstellungen',
38
+ 'tab.data': 'Var.',
39
+ 'tab.dataHint': 'Von deinem Code bereitgestellte Variablen',
40
+ 'inspector.blockProperties': 'Blockeigenschaften',
41
+ 'inspector.sectionProperties': 'Abschnittseigenschaften',
42
+ 'inspector.title': 'Inspektor',
43
+ 'inspector.sectionLabel': 'Abschnitt',
44
+ 'inspector.nothingSelected': 'Nichts ausgewählt',
45
+ 'action.duplicateHint': 'Duplizieren — ⌘D',
46
+ 'action.deleteHint': 'Löschen ',
47
+ 'inspector.emptyBody':
48
+ 'Wähle eine Zeile oder einen Block auf der Canvas aus, um ihn hier zu gestalten. Ziehe Blöcke aus dem Tab <strong style="color: var(--ed-text); font-weight: 600;">Blöcke</strong>; Doppelklick auf beliebigen Text, um ihn direkt zu bearbeiten.',
49
+ 'inspector.shortcuts': 'Kurzbefehle',
50
+ 'shortcut.undoRedo': '⌘Z / ⌘⇧Z Rückgängig, Wiederholen',
51
+ 'shortcut.duplicate': '⌘DAuswahl duplizieren',
52
+ 'shortcut.delete': ' — Auswahl löschen',
53
+ 'shortcut.export': '⌘E HTML exportieren',
54
+ 'shortcut.escape': 'ESC — Auswahl aufheben, schliessen',
55
+ 'blocks.dragHint': 'Auf die Canvas ziehen',
56
+ 'blocks.count': '{count} Blöcke',
57
+ 'rows.sectionLayouts': 'Abschnittslayouts',
58
+ 'rows.customMarkup': 'Eigenes Markup',
59
+ 'rows.htmlRowHint': 'Zum Einfügen ziehen oder klicken — eine randlose Zeile, die du mit rohem HTML füllst',
60
+ 'rows.rawHtmlSection': 'Roher HTML-Abschnitt',
61
+ 'rows.rawHtmlDesc': 'Randloser Abschnitt, dein eigenes Markup, weiterhin ziehbar',
62
+ 'rows.canvasModel': 'Canvas-Modell',
63
+ 'rows.modeRowBased': 'Zeilenbasiert',
64
+ 'rows.modeFreeStack': 'Freier Stapel',
65
+ 'rows.hintRows':
66
+ 'Abschnittsbasiert: Zuerst ein Layout ablegen, dann Blöcke in seine Spalten ziehen jeder Abschnitt hat eigene Hintergrund-, Rahmen-, Flex- oder Grid-Einstellungen.',
67
+ 'rows.hintStack': 'Freier Stapel: Ohne Layouts — jeder abgelegte Block wird zu einem eigenen, vollbreiten Abschnitt, der Reihe nach gestapelt.',
68
+ 'files.libraryCount': 'Bibliothek {count} Dateien',
69
+ 'files.openManager': 'Dateimanager öffnen',
70
+ 'files.dragToCanvas': 'Ziehe eine beliebige Datei direkt auf die Canvas, um sie als Bildblock einzufügen.',
71
+ 'layers.structure': 'Struktur',
72
+ 'layers.sectionSingle': 'Abschnitt',
73
+ 'layers.sectionMulti': 'Abschnitt · {count} Spalten',
74
+ 'layers.column': 'Spalte {index}',
75
+ 'layers.blockCount': '{count} Blk.',
76
+ 'vars.title': 'Variablen',
77
+ 'vars.fromCode': '{count} aus deinem Code',
78
+ 'vars.declaredNote': 'Von deiner Anwendung deklariert — die Canvas zeigt immer das Token, nie einen Wert.',
79
+ 'vars.filterPlaceholder': 'Variablen filtern…',
80
+ 'vars.insertHint': 'Klicken, um in ausgewählten Text, Überschrift oder Button einzufügen',
81
+ 'vars.insert': 'einfügen',
82
+ 'vars.noMatch': 'Keine Variable entspricht diesem Filter.',
83
+ 'vars.noneDeclared': 'Deine Anwendung hat noch keine Variablen deklariert.',
84
+ 'vars.rteHint': 'Beim Bearbeiten von Text kannst du eine Variable auch direkt aus dem Dropdown der Inline-Symbolleiste auswählen.',
85
+ 'modal.fileManager': 'Dateimanager',
86
+ 'modal.assetsTitle': 'Assets',
87
+ 'modal.replaceImage': 'Bild ersetzen',
88
+ 'library.searchPlaceholder': 'Dateien suchen…',
89
+ 'action.upload': 'Hochladen',
90
+ 'library.clickToPlace': 'Datei anklicken zum Platzieren · oder Datei auf die Canvas ziehen',
91
+ 'library.clickToReplace': 'Datei anklicken, um das ausgewählte Bild zu ersetzen',
92
+ 'library.storageLabel': '{count} Dateien · {size}',
93
+ 'library.folders': 'Ordner',
94
+ 'library.dropHint': 'Bilddateien hier zum Hochladen ablegen — oder den Hochladen-Button nutzen.',
95
+ 'library.deleteFileHint': 'Datei löschen',
96
+ 'library.del': 'LÖSCH',
97
+ 'toast.assetDeleted': '{name} gelöscht',
98
+ 'library.allFiles': 'Alle Dateien',
99
+ 'library.loadMore': 'Mehr laden',
100
+ 'library.empty': 'Hier gibt es noch keine Dateien.',
101
+ 'storage.loading': 'Dateien werden geladen…',
102
+ 'storage.uploading': '{count} werden hochgeladen…',
103
+ 'storage.errLoadFailed': 'Die Dateibibliothek konnte nicht geladen werden {reason}',
104
+ 'storage.errNoLimits': 'Uploads sind deaktiviert: Diese Anwendung hat keine Upload-Limiten gesetzt.',
105
+ 'storage.errNoAccept': 'Uploads sind deaktiviert: Es wurden keine Dateiformate freigegeben.',
106
+ 'storage.errNoMaxBytes': 'Uploads sind deaktiviert: Es wurde keine maximale Dateigrösse festgelegt.',
107
+ 'storage.errTooLarge': '{name} ist {size} gross — das Limit liegt bei {max}.',
108
+ 'storage.errFormat': '{name} ist eine {type}-Datei, die hier nicht erlaubt ist.',
109
+ 'storage.errSvg': '{name} ist eine SVG-Datei, die diese Anwendung nicht akzeptiert.',
110
+ 'storage.errDimensions': '{name} ist {w}×{ht}px — das Limit liegt bei {maxW}×{maxH}px.',
111
+ 'storage.errTooMany': 'Es können nur {max} Dateien aufs Mal hochgeladen werden.',
112
+ 'storage.errUnreadable': '{name} ist kein lesbares Bild.',
113
+ 'storage.errUploadFailed': '{name} konnte nicht hochgeladen werden — {reason}',
114
+ 'storage.errDeleteFailed': '{name} konnte nicht gelöscht werden{reason}',
115
+ 'modal.export': 'Exportieren',
116
+ 'modal.exportTitle': 'Tabellenbasiertes E-Mail-HTML',
117
+ 'export.copy': 'Kopieren',
118
+ 'export.copied': 'Kopiert',
119
+ 'action.download': 'Herunterladen',
120
+ 'export.meta': '{kb} KB · Tabellen + Inline-Stile · Outlook-sichere Breiten',
121
+ 'modal.rawHtmlTitle': 'Rohes HTML, Live-Vorschau',
122
+ 'code.statusEdited': 'Code-Ansicht — bearbeitet — Vorschau live, noch nicht übernommen',
123
+ 'code.statusSynced': 'Code-Ansicht — synchron mit der Canvas',
124
+ 'action.reload': 'Neu laden',
125
+ 'action.reloadHint': 'Quelltext aus der Canvas neu laden',
126
+ 'action.applyToCanvas': 'Auf Canvas anwenden',
127
+ 'action.applyToCanvasHint': 'Quelltext zurück in bearbeitbare Zeilen umwandeln',
128
+ 'action.closeWithoutApplyingHint': 'Ohne Anwenden schliessen',
129
+ 'code.source': 'Quelltext',
130
+ 'code.livePreview': 'Live-Vorschau',
131
+ 'code.liveHtmlPreviewTitle': 'Live-HTML-Vorschau',
132
+ 'code.applyNote':
133
+ 'Beim Anwenden wird jede oberste Tabellenzeile in eine Canvas-Zeile umgewandelt, die du weiterhin auswählen, neu anordnen und löschen kannst — handgeschriebenes Markup übersteht den Vorgang unverändert.',
134
+ 'code.meta': '{kb} KB · {lines} Zeilen',
135
+ 'toast.sourceReloaded': 'Quelltext aus der Canvas neu geladen',
136
+ 'toast.sourceAppliedOne': 'Quelltext angewendet — 1 Zeile auf der Canvas',
137
+ 'toast.sourceAppliedMany': 'Quelltext angewendet {rows} Zeilen auf der Canvas',
138
+ 'toast.parseError': 'Dieses HTML konnte nicht verarbeitet werden',
139
+ 'modal.aiDraft': 'KI-Schreibassistent',
140
+ 'modal.aiDraftTitle': 'E-Mail mit KI entwerfen',
141
+ 'ai.disclosure': 'Die KI erstellt Vorschläge aus Ihrem Briefing. Prüfen und bearbeiten Sie das Ergebnis vor dem Versand.',
142
+ 'ai.goal': 'Ziel',
143
+ 'ai.tone': 'Ton',
144
+ 'ai.briefLabel': 'Worum geht es in dieser E-Mail?',
145
+ 'ai.briefPlaceholder': 'z. B. Herbstkollektion, 15 % für Abonnenten, kostenloser Versand ab 150 €',
146
+ 'ai.generate': 'Text generieren',
147
+ 'ai.writing': 'Wird geschrieben…',
148
+ 'ai.kindHeadline': 'Überschrift',
149
+ 'ai.kindBody': 'Fliesstext',
150
+ 'ai.kindButton': 'Button-Text',
151
+ 'ai.actionInsertHeading': 'Als Überschrift einfügen',
152
+ 'ai.actionInsertText': 'Als Textblock einfügen',
153
+ 'ai.actionInsertButton': 'Als Button einfügen',
154
+ 'toast.headingAdded': 'Überschrift hinzugefügt',
155
+ 'toast.textBlockAdded': 'Textblock hinzugefügt',
156
+ 'toast.buttonAdded': 'Button hinzugefügt',
157
+ 'preview.kickerMobile': 'Vorschau — Mobil 375px',
158
+ 'preview.kickerDesktop': 'Vorschau — Desktop {width}px',
159
+ 'action.close': 'Schliessen',
160
+ 'toast.duplicated': 'Dupliziert',
161
+ 'toast.fileUploadedOne': '1 Datei hochgeladen',
162
+ 'toast.fileUploadedMany': '{count} Dateien hochgeladen',
163
+ 'toast.imageReplaced': 'Bild ersetzt',
164
+ 'toast.imageAdded': 'Bild zur Canvas hinzugefügt',
165
+ 'toast.htmlCopied': 'HTML in die Zwischenablage kopiert',
166
+ 'toast.templateLoaded': '{name} geladen',
167
+ 'toast.snippetDefaultLabel': 'Snippet',
168
+ 'toast.snippetInserted': '{name} eingefügt',
169
+ 'toast.snippetCopied': '{name} kopiert — wähle einen Textblock zum Einfügen aus',
170
+ 'rte.textStyle': 'Textstil',
171
+ 'rte.mergeTags': 'Platzhalter',
172
+ 'rte.noMergeTags': 'Keine Platzhalter verfügbar',
173
+ 'rte.textColor': 'Textfarbe',
174
+ 'rte.highlightColor': 'Markierungsfarbe',
175
+ 'rte.removeHighlight': 'Markierung entfernen',
176
+ 'rte.clearFormatting': 'Formatierung entfernen',
177
+ 'action.downloadPng': 'PNG herunterladen',
178
+ 'action.screenshot': 'Screenshot',
179
+ 'action.screenshotHint': 'Die ganze Vorlage als Bild ansehen und herunterladen',
180
+ 'toast.pngSaved': 'Screenshot heruntergeladen',
181
+ 'toast.pngFailed': 'Screenshot fehlgeschlagen — ein externes Bild konnte nicht geladen werden',
182
+ 'toast.pngCopied': 'Screenshot in die Zwischenablage kopiert',
183
+ 'toast.pngCopyFailed': 'Dieser Browser hat kein Bild in der Zwischenablage akzeptiert',
184
+ 'story.kicker': 'Screenshot',
185
+ 'story.rendering': 'Screenshot wird erstellt',
186
+ 'story.renderingHint': 'Jeder Block wird in 2× gezeichnet — bei einer langen Vorlage dauert das einen Moment.',
187
+ 'story.failed': 'Screenshot fehlgeschlagen',
188
+ 'story.failedHint': 'Ein Bild in der Vorlage konnte für die Aufnahme nicht geladen werden.',
189
+ 'story.retry': 'Nochmals versuchen',
190
+ 'story.play': 'Abspielen',
191
+ 'story.pause': 'Pause',
192
+ 'story.replay': 'Nochmals abspielen',
193
+ 'story.copy': 'Kopieren',
194
+ 'story.meta': '{w}×{h} · Ansicht {i} von {n}',
195
+ 'footer.poweredBy': 'Bereitgestellt von SELISE Blocks © 2026',
196
+ };