@seliseblocks/mailcraft 0.1.1 → 0.2.1

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 (86) hide show
  1. package/DOCS.md +243 -16
  2. package/README.md +15 -6
  3. package/README.md.txt +135 -0
  4. package/dist/mailcraft-editor.bundle.js +87 -47
  5. package/dist/mailcraft-editor.bundle.js.map +3 -3
  6. package/examples/templates/activate-your-account.html +1 -1
  7. package/examples/templates/back-in-stock.html +1 -1
  8. package/examples/templates/cart-left-behind.html +1 -1
  9. package/examples/templates/community-giveaway.html +1 -1
  10. package/examples/templates/frontend-futures-invite.html +1 -1
  11. package/examples/templates/give-25-get-25.html +1 -1
  12. package/examples/templates/invoice-paid.html +1 -1
  13. package/examples/templates/meet-nova-launch.html +1 -1
  14. package/examples/templates/mega-weekend-sale.html +1 -1
  15. package/examples/templates/order-confirmed.html +80 -80
  16. package/examples/templates/rate-your-headphones.html +1 -1
  17. package/examples/templates/reset-your-password.html +1 -1
  18. package/examples/templates/thankyou-promo-code.html +1 -1
  19. package/examples/templates/the-sunday-brief.html +1 -1
  20. package/examples/templates/welcome-to-your-workspace.html +1 -1
  21. package/examples/templates/your-order-shipped.html +1 -1
  22. package/examples/templates/your-password-was-changed.html +1 -1
  23. package/examples/templates/your-signin-code.html +1 -1
  24. package/examples/vanilla.html +261 -47
  25. package/package.json +7 -2
  26. package/src/core/assets.js +10 -15
  27. package/src/core/binder.js +140 -118
  28. package/src/core/blocks.js +14 -1
  29. package/src/core/css-cascade.js +117 -117
  30. package/src/core/editor-core.js +1540 -1492
  31. package/src/core/export.js +158 -55
  32. package/src/core/i18n/ar.js +218 -177
  33. package/src/core/i18n/bg.js +195 -152
  34. package/src/core/i18n/bn.js +217 -176
  35. package/src/core/i18n/ca.js +195 -152
  36. package/src/core/i18n/cs.js +195 -152
  37. package/src/core/i18n/da.js +195 -152
  38. package/src/core/i18n/de-CH.js +195 -152
  39. package/src/core/i18n/de.js +195 -152
  40. package/src/core/i18n/dz.js +220 -179
  41. package/src/core/i18n/el.js +195 -152
  42. package/src/core/i18n/en.js +3 -11
  43. package/src/core/i18n/es.js +195 -152
  44. package/src/core/i18n/et.js +195 -152
  45. package/src/core/i18n/fi.js +195 -152
  46. package/src/core/i18n/fr.js +195 -152
  47. package/src/core/i18n/hr.js +195 -152
  48. package/src/core/i18n/hu.js +195 -152
  49. package/src/core/i18n/index.js +83 -83
  50. package/src/core/i18n/it.js +195 -152
  51. package/src/core/i18n/lt.js +195 -152
  52. package/src/core/i18n/lv.js +195 -152
  53. package/src/core/i18n/nb.js +195 -152
  54. package/src/core/i18n/nl.js +195 -152
  55. package/src/core/i18n/pl.js +195 -152
  56. package/src/core/i18n/pt.js +195 -152
  57. package/src/core/i18n/ro.js +195 -152
  58. package/src/core/i18n/ru.js +195 -152
  59. package/src/core/i18n/sk.js +195 -152
  60. package/src/core/i18n/sl.js +195 -152
  61. package/src/core/i18n/sv.js +195 -152
  62. package/src/core/i18n/tables.js +50 -50
  63. package/src/core/i18n/tr.js +195 -152
  64. package/src/core/i18n/uk.js +195 -152
  65. package/src/core/icons.js +237 -235
  66. package/src/core/ids.js +1 -1
  67. package/src/core/import-html.js +1047 -959
  68. package/src/core/layout-style.js +100 -100
  69. package/src/core/parse.js +10 -10
  70. package/src/core/placeholder.js +15 -15
  71. package/src/core/sanitize.js +141 -141
  72. package/src/core/storage-limits.js +189 -184
  73. package/src/core/storage.js +85 -85
  74. package/src/core/theme.js +15 -1
  75. package/src/core/variables.js +11 -11
  76. package/src/index.js +9 -9
  77. package/src/mailcraft-editor.js +64 -25
  78. package/src/render/block-body.js +49 -6
  79. package/src/render/canvas.js +74 -8
  80. package/src/render/fields.js +619 -588
  81. package/src/render/focus-preserve.js +158 -158
  82. package/src/render/rte.js +241 -212
  83. package/src/render/screenshot.js +138 -132
  84. package/src/render/story.js +415 -415
  85. package/src/render/style.js +44 -8
  86. package/types/index.d.ts +422 -0
@@ -1,152 +1,195 @@
1
- /** French (Français) — `fr`. AI-drafted, not reviewed by a native speaker. Correctable one key at a time via `.messages` overrides. */
2
- export const FR = {
3
- 'action.undoHint': 'Annuler — ⌘Z',
4
- 'action.redoHint': 'Rétablir — ⌘⇧Z',
5
- 'action.chromeToDark': 'Sombre',
6
- 'action.chromeToLight': 'Clair',
7
- 'action.chromeHint': 'Thème de l’éditeur clair / sombre',
8
- 'action.aiCopy': 'Texte',
9
- 'action.aiCopyHint': 'Rédiger un texte avec l’IA',
10
- 'action.code': 'Code',
11
- 'action.codeHint': 'Modifier le HTML brut avec aperçu en direct',
12
- 'action.preview': 'Aperçu',
13
- 'action.export': 'Exporter',
14
- 'device.desktop': 'Bureau',
15
- 'device.desktopHint': 'Largeur bureau',
16
- 'device.mobile': 'Mobile',
17
- 'device.mobileHint': 'Largeur mobile',
18
- 'device.dark': 'Sombre',
19
- 'device.darkHint': 'Boîte de réception sombre',
20
- 'status.autosaveOn': 'sauvegarde automatique activée',
21
- 'status.saved': 'enregistré {time}',
22
- 'status.saveFailed': 'non enregistré — stockage plein',
23
- 'canvas.meta': '{rows} lignes · {blocks} blocs · {width}px',
24
- 'tab.design': 'Style',
25
- 'tab.designHint': 'Styliser la sélection',
26
- 'tab.blocks': 'Blocs',
27
- 'tab.blocksHint': 'Blocs de contenu et variables',
28
- 'tab.rows': 'Sect.',
29
- 'tab.rowsHint': 'Mises en page de section et modèle de canevas',
30
- 'tab.files': 'Fichiers',
31
- 'tab.filesHint': 'Bibliothèque de ressources',
32
- 'tab.layers': 'Structure',
33
- 'tab.layersHint': 'Structure du document',
34
- 'tab.theme': 'Thème',
35
- 'tab.themeHint': 'Styles globaux',
36
- 'tab.data': 'Var.',
37
- 'tab.dataHint': 'Variables fournies par votre code',
38
- 'inspector.blockProperties': 'Propriétés du bloc',
39
- 'inspector.sectionProperties': 'Propriétés de la section',
40
- 'inspector.title': 'Inspecteur',
41
- 'inspector.sectionLabel': 'Section',
42
- 'inspector.nothingSelected': 'Rien n’est sélectionné',
43
- 'action.duplicateHint': 'Dupliquer — ⌘D',
44
- 'action.deleteHint': 'Supprimer ',
45
- 'inspector.emptyBody':
46
- 'Sélectionnez une ligne ou un bloc sur le canevas pour le styliser ici. Glissez des blocs depuis l’onglet <strong style="color: var(--ed-text); font-weight: 600;">Blocs</strong> ; double-cliquez sur un texte pour le modifier directement.',
47
- 'inspector.shortcuts': 'Raccourcis',
48
- 'shortcut.undoRedo': '⌘Z / ⌘⇧Z annuler, rétablir',
49
- 'shortcut.duplicate': '⌘D — dupliquer la sélection',
50
- 'shortcut.delete': 'supprimer la sélection',
51
- 'shortcut.export': '⌘Eexporter le HTML',
52
- 'shortcut.escape': 'ESCdésélectionner, fermer',
53
- 'blocks.dragHint': 'Glisser sur le canevas',
54
- 'blocks.count': '{count} blocs',
55
- 'rows.sectionLayouts': 'Mises en page de section',
56
- 'rows.customMarkup': 'Balisage personnalisé',
57
- 'rows.htmlRowHint': 'Glissez pour insérer, ou cliquez pour ajouter — une ligne pleine largeur que vous remplissez de HTML brut',
58
- 'rows.rawHtmlSection': 'Section HTML brut',
59
- 'rows.rawHtmlDesc': 'Section pleine largeur, votre propre balisage, toujours déplaçable',
60
- 'rows.canvasModel': 'Modèle de canevas',
61
- 'rows.modeRowBased': 'Basé sur les lignes',
62
- 'rows.modeFreeStack': 'Pile libre',
63
- 'rows.hintRows':
64
- 'Basé sur les sections : déposez d’abord une mise en page, puis des blocs dans ses colonnes — chaque section a son propre arrière-plan, sa bordure, ses réglages flex ou grille.',
65
- 'rows.hintStack': 'Pile libre : sans mise en page — chaque bloc déposé devient sa propre section pleine largeur, empilée dans l’ordre.',
66
- 'files.libraryCount': 'Bibliothèque{count} fichiers',
67
- 'files.openManager': 'Ouvrir le gestionnaire de fichiers',
68
- 'files.dragToCanvas': 'Glissez un fichier directement sur le canevas pour le placer comme bloc image.',
69
- 'layers.structure': 'Structure',
70
- 'layers.sectionSingle': 'Section',
71
- 'layers.sectionMulti': 'Section · {count} col.',
72
- 'layers.blockCount': '{count} blocs',
73
- 'theme.globalStyles': 'Styles globaux',
74
- 'vars.title': 'Variables',
75
- 'vars.fromCode': '{count} provenant de votre code',
76
- 'vars.declaredNote': 'Déclarées par votre application — le canevas affiche toujours le jeton, jamais une valeur.',
77
- 'vars.filterPlaceholder': 'Filtrer les variables…',
78
- 'vars.insertHint': 'Cliquer pour insérer dans le texte, le titre ou le bouton sélectionné',
79
- 'vars.insert': 'insérer',
80
- 'vars.noMatch': 'Aucune variable ne correspond à ce filtre.',
81
- 'vars.noneDeclared': 'Votre application n’a encore déclaré aucune variable.',
82
- 'vars.rteHint': 'En modifiant du texte, vous pouvez aussi choisir une variable directement dans le menu de la barre d’outils.',
83
- 'modal.fileManager': 'Gestionnaire de fichiers',
84
- 'modal.assetsTitle': 'Ressources',
85
- 'modal.replaceImage': 'Remplacer l’image',
86
- 'library.searchPlaceholder': 'Rechercher des fichiers…',
87
- 'action.upload': 'Téléverser',
88
- 'library.clickToPlace': 'Cliquez sur un fichier pour le placer · ou glissez un fichier sur le canevas',
89
- 'library.clickToReplace': 'Cliquez sur un fichier pour remplacer l’image sélectionnée',
90
- 'library.storageLabel': '{count} fichiers · {size}',
91
- 'library.folders': 'Dossiers',
92
- 'library.dropHint': 'Déposez des fichiers image ici pour les téléverser — ou utilisez le bouton Téléverser.',
93
- 'library.deleteFileHint': 'Supprimer le fichier',
94
- 'library.del': 'SUPPR',
95
- 'toast.assetDeleted': '{name} supprimé',
96
- 'modal.export': 'Exporter',
97
- 'modal.exportTitle': 'HTML d’e-mail basé sur des tableaux',
98
- 'export.copy': 'Copier',
99
- 'export.copied': 'Copié',
100
- 'action.download': 'Télécharger',
101
- 'export.meta': '{kb} Ko · tableaux + styles en ligne · largeurs sûres pour Outlook',
102
- 'modal.rawHtmlTitle': 'HTML brut, aperçu en direct',
103
- 'code.statusEdited': 'Vue du code modifié aperçu en direct, pas encore appliqué',
104
- 'code.statusSynced': 'Vue du code synchronisé avec le canevas',
105
- 'action.reload': 'Recharger',
106
- 'action.reloadHint': 'Recharger la source depuis le canevas',
107
- 'action.applyToCanvas': 'Appliquer au canevas',
108
- 'action.applyToCanvasHint': 'Analyser la source pour la reconvertir en lignes modifiables',
109
- 'action.closeWithoutApplyingHint': 'Fermer sans appliquer',
110
- 'code.source': 'Source',
111
- 'code.livePreview': 'Aperçu en direct',
112
- 'code.liveHtmlPreviewTitle': 'Aperçu HTML en direct',
113
- 'code.applyNote':
114
- 'Appliquer analyse chaque ligne de tableau de premier niveau en une ligne de canevas que vous pouvez toujours sélectionner, réorganiser et supprimer — le balisage écrit à la main survit à l’aller-retour.',
115
- 'code.meta': '{kb} Ko · {lines} lignes',
116
- 'toast.sourceReloaded': 'Source rechargée depuis le canevas',
117
- 'toast.sourceAppliedOne': 'Source appliquée — 1 ligne sur le canevas',
118
- 'toast.sourceAppliedMany': 'Source appliquée — {rows} lignes sur le canevas',
119
- 'toast.parseError': 'Impossible d’analyser ce HTML',
120
- 'modal.copyAssist': 'Assistant de rédaction',
121
- 'modal.draftCopyTitle': 'Rédiger le texte de cette campagne',
122
- 'ai.goal': 'Objectif',
123
- 'ai.tone': 'Ton',
124
- 'ai.briefLabel': 'De quoi parle cet e-mail ?',
125
- 'ai.briefPlaceholder': 'ex. Collection automne, 15 % pour les abonnés, livraison gratuite dès 150 €',
126
- 'ai.generate': 'Générer le texte',
127
- 'ai.writing': 'Rédaction en cours…',
128
- 'ai.kindHeadline': 'Titre',
129
- 'ai.kindBody': 'Corps du texte',
130
- 'ai.kindButton': 'Texte du bouton',
131
- 'ai.actionInsertHeading': 'Insérer comme titre',
132
- 'ai.actionInsertText': 'Insérer comme bloc de texte',
133
- 'ai.actionInsertButton': 'Insérer comme bouton',
134
- 'toast.headingAdded': 'Titre ajouté',
135
- 'toast.textBlockAdded': 'Bloc de texte ajouté',
136
- 'toast.buttonAdded': 'Bouton ajouté',
137
- 'preview.kickerMobile': 'Aperçu mobile 375px',
138
- 'preview.kickerDark': 'Aperçu — boîte de réception sombre',
139
- 'preview.kickerDesktop': 'Aperçu bureau {width}px',
140
- 'action.close': 'Fermer',
141
- 'toast.duplicated': 'Dupliqué',
142
- 'toast.fileUploadedOne': '1 fichier téléversé',
143
- 'toast.fileUploadedMany': '{count} fichiers téléversés',
144
- 'toast.imageReplaced': 'Image remplacée',
145
- 'toast.imageAdded': 'Image ajoutée au canevas',
146
- 'toast.htmlCopied': 'HTML copié dans le presse-papiers',
147
- 'toast.templateLoaded': '{name} chargé',
148
- 'toast.snippetDefaultLabel': 'Extrait',
149
- 'toast.snippetInserted': '{name} inséré',
150
- 'toast.snippetCopied': '{name} copié — sélectionnez un bloc de texte pour l’insérer',
151
- };
152
-
1
+ /** French (Français) — `fr`. AI-drafted, not reviewed by a native speaker. Correctable one key at a time via `.messages` overrides. */
2
+ export const FR = {
3
+ 'action.undoHint': 'Annuler — ⌘Z',
4
+ 'action.redoHint': 'Rétablir — ⌘⇧Z',
5
+ 'action.chromeToDark': 'Sombre',
6
+ 'action.chromeToLight': 'Clair',
7
+ 'action.chromeHint': 'Thème de l’éditeur clair / sombre',
8
+ 'action.chromeHintToDark': 'Mode sombre',
9
+ 'action.chromeHintToLight': 'Mode clair',
10
+ 'action.aiDraft': 'Brouillon',
11
+ 'action.aiDraftHint': 'Rédiger le contenu de l’e-mail avec l’IA',
12
+ 'action.code': 'Code',
13
+ 'action.codeHint': 'Modifier le HTML brut avec aperçu en direct',
14
+ 'action.preview': 'Aperçu',
15
+ 'action.previewHint': 'Prévisualiser l’e-mail',
16
+ 'action.export': 'Exporter',
17
+ 'action.exportHint': 'Exporter votre e-mail',
18
+ 'device.desktop': 'Bureau',
19
+ 'device.desktopHint': 'Largeur bureau',
20
+ 'device.mobile': 'Mobile',
21
+ 'device.mobileHint': 'Largeur mobile',
22
+ 'status.autosaveOn': 'sauvegarde automatique activée',
23
+ 'status.saved': 'enregistré {time}',
24
+ 'status.saveFailed': 'non enregistré — stockage plein',
25
+ 'canvas.meta': '{rows} lignes · {blocks} blocs · {width}px',
26
+ 'tab.design': 'Style',
27
+ 'tab.designHint': 'Styliser la sélection',
28
+ 'tab.blocks': 'Blocs',
29
+ 'tab.blocksHint': 'Blocs de contenu et variables',
30
+ 'tab.rows': 'Sect.',
31
+ 'tab.rowsHint': 'Mises en page de section et modèle de canevas',
32
+ 'tab.files': 'Fichiers',
33
+ 'tab.filesHint': 'Bibliothèque de ressources',
34
+ 'tab.layers': 'Structure',
35
+ 'tab.layersHint': 'Structure du document',
36
+ 'tab.settings': 'Paramètres',
37
+ 'tab.settingsHint': 'Paramètres de l’e-mail',
38
+ 'tab.data': 'Var.',
39
+ 'tab.dataHint': 'Variables fournies par votre code',
40
+ 'inspector.blockProperties': 'Propriétés du bloc',
41
+ 'inspector.sectionProperties': 'Propriétés de la section',
42
+ 'inspector.title': 'Inspecteur',
43
+ 'inspector.sectionLabel': 'Section',
44
+ 'inspector.nothingSelected': 'Rien n’est sélectionné',
45
+ 'action.duplicateHint': 'Dupliquer — ⌘D',
46
+ 'action.deleteHint': 'Supprimer ',
47
+ 'inspector.emptyBody':
48
+ 'Sélectionnez une ligne ou un bloc sur le canevas pour le styliser ici. Glissez des blocs depuis l’onglet <strong style="color: var(--ed-text); font-weight: 600;">Blocs</strong> ; double-cliquez sur un texte pour le modifier directement.',
49
+ 'inspector.shortcuts': 'Raccourcis',
50
+ 'shortcut.undoRedo': '⌘Z / ⌘⇧Z annuler, rétablir',
51
+ 'shortcut.duplicate': '⌘Ddupliquer la sélection',
52
+ 'shortcut.delete': 'supprimer la sélection',
53
+ 'shortcut.export': '⌘E exporter le HTML',
54
+ 'shortcut.escape': 'ESC — désélectionner, fermer',
55
+ 'blocks.dragHint': 'Glisser sur le canevas',
56
+ 'blocks.count': '{count} blocs',
57
+ 'rows.sectionLayouts': 'Mises en page de section',
58
+ 'rows.customMarkup': 'Balisage personnalisé',
59
+ 'rows.htmlRowHint': 'Glissez pour insérer, ou cliquez pour ajouter — une ligne pleine largeur que vous remplissez de HTML brut',
60
+ 'rows.rawHtmlSection': 'Section HTML brut',
61
+ 'rows.rawHtmlDesc': 'Section pleine largeur, votre propre balisage, toujours déplaçable',
62
+ 'rows.canvasModel': 'Modèle de canevas',
63
+ 'rows.modeRowBased': 'Basé sur les lignes',
64
+ 'rows.modeFreeStack': 'Pile libre',
65
+ 'rows.hintRows':
66
+ 'Basé sur les sections : déposez d’abord une mise en page, puis des blocs dans ses colonnes chaque section a son propre arrière-plan, sa bordure, ses réglages flex ou grille.',
67
+ 'rows.hintStack': 'Pile libre : sans mise en page — chaque bloc déposé devient sa propre section pleine largeur, empilée dans l’ordre.',
68
+ 'files.libraryCount': 'Bibliothèque {count} fichiers',
69
+ 'files.openManager': 'Ouvrir le gestionnaire de fichiers',
70
+ 'files.dragToCanvas': 'Glissez un fichier directement sur le canevas pour le placer comme bloc image.',
71
+ 'layers.structure': 'Structure',
72
+ 'layers.sectionSingle': 'Section',
73
+ 'layers.sectionMulti': 'Section · {count} col.',
74
+ 'layers.column': 'Colonne {index}',
75
+ 'layers.blockCount': '{count} blocs',
76
+ 'vars.title': 'Variables',
77
+ 'vars.fromCode': '{count} provenant de votre code',
78
+ 'vars.declaredNote': 'Déclarées par votre application le canevas affiche toujours le jeton, jamais une valeur.',
79
+ 'vars.filterPlaceholder': 'Filtrer les variables…',
80
+ 'vars.insertHint': 'Cliquer pour insérer dans le texte, le titre ou le bouton sélectionné',
81
+ 'vars.insert': 'insérer',
82
+ 'vars.noMatch': 'Aucune variable ne correspond à ce filtre.',
83
+ 'vars.noneDeclared': 'Votre application n’a encore déclaré aucune variable.',
84
+ 'vars.rteHint': 'En modifiant du texte, vous pouvez aussi choisir une variable directement dans le menu de la barre d’outils.',
85
+ 'modal.fileManager': 'Gestionnaire de fichiers',
86
+ 'modal.assetsTitle': 'Ressources',
87
+ 'modal.replaceImage': 'Remplacer l’image',
88
+ 'library.searchPlaceholder': 'Rechercher des fichiers…',
89
+ 'action.upload': 'Téléverser',
90
+ 'library.clickToPlace': 'Cliquez sur un fichier pour le placer · ou glissez un fichier sur le canevas',
91
+ 'library.clickToReplace': 'Cliquez sur un fichier pour remplacer l’image sélectionnée',
92
+ 'library.storageLabel': '{count} fichiers · {size}',
93
+ 'library.folders': 'Dossiers',
94
+ 'library.dropHint': 'Déposez des fichiers image ici pour les téléverser — ou utilisez le bouton Téléverser.',
95
+ 'library.deleteFileHint': 'Supprimer le fichier',
96
+ 'library.del': 'SUPPR',
97
+ 'toast.assetDeleted': '{name} supprimé',
98
+ 'library.allFiles': 'Tous les fichiers',
99
+ 'library.loadMore': 'Charger plus',
100
+ 'library.empty': 'Aucun fichier ici pour l’instant.',
101
+ 'storage.loading': 'Chargement des fichiers…',
102
+ 'storage.uploading': 'Envoi de {count}…',
103
+ 'storage.errLoadFailed': 'La bibliothèque de fichiers n’a pas pu être chargée {reason}',
104
+ 'storage.errNoLimits': 'Les envois sont désactivés : cette application n’a défini aucune limite d’envoi.',
105
+ 'storage.errNoMaxBytes': 'Les envois sont désactivés : aucune taille maximale de fichier n’a été définie.',
106
+ 'storage.errTooLarge': '{name} fait {size} — la limite est {max}.',
107
+ 'storage.errFormat': '{name} est un fichier {type}, non autorisé ici.',
108
+ 'storage.errSvg': '{name} est un SVG, que cette application n’accepte pas.',
109
+ 'storage.errDimensions': '{name} fait {w}×{ht}px — la limite est {maxW}×{maxH}px.',
110
+ 'storage.errTooMany': 'Seuls {max} fichiers peuvent être envoyés à la fois.',
111
+ 'storage.errUnreadable': '{name} n’est pas une image lisible.',
112
+ 'storage.errUploadFailed': '{name} n’a pas pu être envoyé — {reason}',
113
+ 'storage.errDeleteFailed': '{name} n’a pas pu être supprimé — {reason}',
114
+ 'modal.export': 'Exporter',
115
+ 'modal.exportTitle': 'HTML d’e-mail basé sur des tableaux',
116
+ 'export.copy': 'Copier',
117
+ 'export.copied': 'Copié',
118
+ 'action.download': 'Télécharger',
119
+ 'export.meta': '{kb} Ko · tableaux + styles en ligne · largeurs sûres pour Outlook',
120
+ 'modal.rawHtmlTitle': 'HTML brut, aperçu en direct',
121
+ 'code.statusEdited': 'Vue du code modifié — aperçu en direct, pas encore appliqué',
122
+ 'code.statusSynced': 'Vue du code — synchronisé avec le canevas',
123
+ 'action.reload': 'Recharger',
124
+ 'action.reloadHint': 'Recharger la source depuis le canevas',
125
+ 'action.applyToCanvas': 'Appliquer au canevas',
126
+ 'action.applyToCanvasHint': 'Analyser la source pour la reconvertir en lignes modifiables',
127
+ 'action.closeWithoutApplyingHint': 'Fermer sans appliquer',
128
+ 'code.source': 'Source',
129
+ 'code.livePreview': 'Aperçu en direct',
130
+ 'code.liveHtmlPreviewTitle': 'Aperçu HTML en direct',
131
+ 'code.applyNote':
132
+ 'Appliquer analyse chaque ligne de tableau de premier niveau en une ligne de canevas que vous pouvez toujours sélectionner, réorganiser et supprimer — le balisage écrit à la main survit à l’aller-retour.',
133
+ 'code.meta': '{kb} Ko · {lines} lignes',
134
+ 'toast.sourceReloaded': 'Source rechargée depuis le canevas',
135
+ 'toast.sourceAppliedOne': 'Source appliquée 1 ligne sur le canevas',
136
+ 'toast.sourceAppliedMany': 'Source appliquée — {rows} lignes sur le canevas',
137
+ 'toast.parseError': 'Impossible d’analyser ce HTML',
138
+ 'modal.aiDraft': 'Assistant de rédaction IA',
139
+ 'modal.aiDraftTitle': 'Rédigez votre e-mail avec l’IA',
140
+ 'ai.disclosure': 'L’IA crée des suggestions à partir de votre brief. Relisez et modifiez le résultat avant l’envoi.',
141
+ 'ai.goal': 'Objectif',
142
+ 'ai.tone': 'Ton',
143
+ 'ai.briefLabel': 'De quoi parle cet e-mail ?',
144
+ 'ai.briefPlaceholder': 'ex. Collection automne, 15 % pour les abonnés, livraison gratuite dès 150 €',
145
+ 'ai.generate': 'Générer le texte',
146
+ 'ai.writing': 'Rédaction en cours…',
147
+ 'ai.kindHeadline': 'Titre',
148
+ 'ai.kindBody': 'Corps du texte',
149
+ 'ai.kindButton': 'Texte du bouton',
150
+ 'ai.actionInsertHeading': 'Insérer comme titre',
151
+ 'ai.actionInsertText': 'Insérer comme bloc de texte',
152
+ 'ai.actionInsertButton': 'Insérer comme bouton',
153
+ 'toast.headingAdded': 'Titre ajouté',
154
+ 'toast.textBlockAdded': 'Bloc de texte ajouté',
155
+ 'toast.buttonAdded': 'Bouton ajouté',
156
+ 'preview.kickerMobile': 'Aperçu — mobile 375px',
157
+ 'preview.kickerDesktop': 'Aperçu — bureau {width}px',
158
+ 'action.close': 'Fermer',
159
+ 'toast.duplicated': 'Dupliqué',
160
+ 'toast.fileUploadedOne': '1 fichier téléversé',
161
+ 'toast.fileUploadedMany': '{count} fichiers téléversés',
162
+ 'toast.imageReplaced': 'Image remplacée',
163
+ 'toast.imageAdded': 'Image ajoutée au canevas',
164
+ 'toast.htmlCopied': 'HTML copié dans le presse-papiers',
165
+ 'toast.templateLoaded': '{name} chargé',
166
+ 'toast.snippetDefaultLabel': 'Extrait',
167
+ 'toast.snippetInserted': '{name} inséré',
168
+ 'toast.snippetCopied': '{name} copié — sélectionnez un bloc de texte pour l’insérer',
169
+ 'rte.textStyle': 'Style de texte',
170
+ 'rte.mergeTags': 'Champs de fusion',
171
+ 'rte.noMergeTags': 'Aucun champ de fusion disponible',
172
+ 'rte.textColor': 'Couleur du texte',
173
+ 'rte.highlightColor': 'Couleur de surlignage',
174
+ 'rte.removeHighlight': 'Supprimer le surlignage',
175
+ 'rte.clearFormatting': 'Effacer la mise en forme',
176
+ 'action.downloadPng': 'Télécharger le PNG',
177
+ 'action.screenshot': 'Capture',
178
+ 'action.screenshotHint': 'Voir tout le modèle sous forme d’image, puis le télécharger',
179
+ 'toast.pngSaved': 'Capture téléchargée',
180
+ 'toast.pngFailed': 'Échec de la capture — une image externe n’a pas pu être chargée',
181
+ 'toast.pngCopied': 'Capture copiée dans le presse-papiers',
182
+ 'toast.pngCopyFailed': 'Ce navigateur n’a pas accepté d’image dans le presse-papiers',
183
+ 'story.kicker': 'Capture',
184
+ 'story.rendering': 'Génération de la capture',
185
+ 'story.renderingHint': 'Chaque bloc est dessiné en 2× — sur un long modèle, cela prend un moment.',
186
+ 'story.failed': 'Échec de la capture',
187
+ 'story.failedHint': 'Une image du modèle n’a pas pu être chargée pour la capture.',
188
+ 'story.retry': 'Réessayer',
189
+ 'story.play': 'Lecture',
190
+ 'story.pause': 'Pause',
191
+ 'story.replay': 'Revoir',
192
+ 'story.copy': 'Copier',
193
+ 'story.meta': '{w}×{h} · écran {i} sur {n}',
194
+ 'footer.poweredBy': 'Propulsé par SELISE Blocks © 2026',
195
+ };