@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
- /** Ukrainian (Українська) — `uk`. AI-drafted, not reviewed by a native speaker. Correctable one key at a time via `.messages` overrides. */
2
- export const UK = {
3
- 'action.undoHint': 'Скасувати — ⌘Z',
4
- 'action.redoHint': 'Повторити — ⌘⇧Z',
5
- 'action.chromeToDark': 'Темна',
6
- 'action.chromeToLight': 'Світла',
7
- 'action.chromeHint': 'Тема редактора світла / темна',
8
- 'action.aiCopy': 'Текст',
9
- 'action.aiCopyHint': 'Скласти текст за допомогою ШІ',
10
- 'action.code': 'Код',
11
- 'action.codeHint': 'Редагувати вихідний HTML із живим переглядом',
12
- 'action.preview': 'Перегляд',
13
- 'action.export': 'Експорт',
14
- 'device.desktop': 'Комп’ютер',
15
- 'device.desktopHint': 'Ширина для комп’ютера',
16
- 'device.mobile': 'Телефон',
17
- 'device.mobileHint': 'Ширина для телефона',
18
- 'device.dark': 'Темна',
19
- 'device.darkHint': 'Темний режим вхідних',
20
- 'status.autosaveOn': 'автозбереження увімкнено',
21
- 'status.saved': 'збережено {time}',
22
- 'status.saveFailed': 'не збережено — сховище заповнено',
23
- 'canvas.meta': '{rows} рядків · {blocks} блоків · {width}px',
24
- 'tab.design': 'Стиль',
25
- 'tab.designHint': 'Оформити виділене',
26
- 'tab.blocks': 'Блоки',
27
- 'tab.blocksHint': 'Блоки вмісту та змінні',
28
- 'tab.rows': 'Секції',
29
- 'tab.rowsHint': 'Макети секцій і модель полотна',
30
- 'tab.files': 'Файли',
31
- 'tab.filesHint': 'Бібліотека файлів',
32
- 'tab.layers': 'Структура',
33
- 'tab.layersHint': 'Структура документа',
34
- 'tab.theme': 'Тема',
35
- 'tab.themeHint': 'Глобальні стилі',
36
- 'tab.data': 'Змін.',
37
- 'tab.dataHint': 'Змінні, надані вашим кодом',
38
- 'inspector.blockProperties': 'Властивості блока',
39
- 'inspector.sectionProperties': 'Властивості секції',
40
- 'inspector.title': 'Інспектор',
41
- 'inspector.sectionLabel': 'Секція',
42
- 'inspector.nothingSelected': 'Нічого не вибрано',
43
- 'action.duplicateHint': 'Дублювати — ⌘D',
44
- 'action.deleteHint': 'Видалити ',
45
- 'inspector.emptyBody':
46
- 'Виберіть рядок або блок на полотні, щоб оформити його тут. Перетягніть блоки з вкладки <strong style="color: var(--ed-text); font-weight: 600;">Блоки</strong>; двічі клацніть текст, щоб редагувати його на місці.',
47
- 'inspector.shortcuts': 'Гарячі клавіші',
48
- 'shortcut.undoRedo': '⌘Z / ⌘⇧Z скасувати, повторити',
49
- 'shortcut.duplicate': '⌘D — дублювати виділене',
50
- 'shortcut.delete': 'видалити виділене',
51
- 'shortcut.export': '⌘Eекспортувати HTML',
52
- 'shortcut.escape': 'ESCзняти виділення, закрити',
53
- 'blocks.dragHint': 'Перетягніть на полотно',
54
- 'blocks.count': '{count} блоків',
55
- 'rows.sectionLayouts': 'Макети секцій',
56
- 'rows.customMarkup': 'Власна розмітка',
57
- 'rows.htmlRowHint': 'Перетягніть, щоб вставити, або клацніть, щоб додати — рядок на всю ширину, який ви заповнюєте вихідним HTML',
58
- 'rows.rawHtmlSection': 'Секція з вихідним HTML',
59
- 'rows.rawHtmlDesc': 'Секція на всю ширину, ваша власна розмітка, все ще перетягується',
60
- 'rows.canvasModel': 'Модель полотна',
61
- 'rows.modeRowBased': 'На основі рядків',
62
- 'rows.modeFreeStack': 'Вільний стек',
63
- 'rows.hintRows':
64
- 'На основі секцій: спочатку розмістіть макет, потім блоки в його колонках — кожна секція має власний фон, межу, налаштування flex або сітки.',
65
- 'rows.hintStack': 'Вільний стек: без макетів — кожен доданий блок стає власною секцією на всю ширину, укладеною по порядку.',
66
- 'files.libraryCount': 'Бібліотека{count} файлів',
67
- 'files.openManager': 'Відкрити файловий менеджер',
68
- 'files.dragToCanvas': 'Перетягніть будь-який файл прямо на полотно, щоб розмістити його як блок зображення.',
69
- 'layers.structure': 'Структура',
70
- 'layers.sectionSingle': 'Секція',
71
- 'layers.sectionMulti': 'Секція · {count} кол.',
72
- 'layers.blockCount': '{count} бл.',
73
- 'theme.globalStyles': 'Глобальні стилі',
74
- 'vars.title': 'Змінні',
75
- 'vars.fromCode': '{count} з вашого коду',
76
- 'vars.declaredNote': 'Оголошені вашим застосунком — полотно завжди показує токен, ніколи значення.',
77
- 'vars.filterPlaceholder': 'Фільтр змінних…',
78
- 'vars.insertHint': 'Натисніть, щоб вставити у вибраний текст, заголовок або кнопку',
79
- 'vars.insert': 'вставити',
80
- 'vars.noMatch': 'Немає змінних, що відповідають цьому фільтру.',
81
- 'vars.noneDeclared': 'Ваш застосунок ще не оголосив жодних змінних.',
82
- 'vars.rteHint': 'Під час редагування тексту ви також можете вибрати змінну прямо з випадного списку вбудованої панелі інструментів.',
83
- 'modal.fileManager': 'Файловий менеджер',
84
- 'modal.assetsTitle': 'Файли',
85
- 'modal.replaceImage': 'Замінити зображення',
86
- 'library.searchPlaceholder': 'Пошук файлів…',
87
- 'action.upload': 'Завантажити',
88
- 'library.clickToPlace': 'Натисніть на файл, щоб розмістити · або перетягніть файл на полотно',
89
- 'library.clickToReplace': 'Натисніть на файл, щоб замінити вибране зображення',
90
- 'library.storageLabel': '{count} файлів · {size}',
91
- 'library.folders': 'Папки',
92
- 'library.dropHint': 'Перетягніть файли зображень сюди для завантаження — або скористайтеся кнопкою «Завантажити».',
93
- 'library.deleteFileHint': 'Видалити файл',
94
- 'library.del': 'ВИДАЛ',
95
- 'toast.assetDeleted': '{name} видалено',
96
- 'modal.export': 'Експорт',
97
- 'modal.exportTitle': 'HTML листа на основі таблиць',
98
- 'export.copy': 'Копіювати',
99
- 'export.copied': 'Скопійовано',
100
- 'action.download': 'Завантажити',
101
- 'export.meta': '{kb} КБ · таблиці + вбудовані стилі · ширини, безпечні для Outlook',
102
- 'modal.rawHtmlTitle': 'Вихідний HTML, живий перегляд',
103
- 'code.statusEdited': 'Перегляд коду зміненоперегляд наживо, ще не застосовано',
104
- 'code.statusSynced': 'Перегляд коду синхронізовано з полотном',
105
- 'action.reload': 'Оновити',
106
- 'action.reloadHint': 'Оновити джерело з полотна',
107
- 'action.applyToCanvas': 'Застосувати до полотна',
108
- 'action.applyToCanvasHint': 'Розібрати джерело назад у редаговані рядки',
109
- 'action.closeWithoutApplyingHint': 'Закрити без застосування',
110
- 'code.source': 'Джерело',
111
- 'code.livePreview': 'Живий перегляд',
112
- 'code.liveHtmlPreviewTitle': 'Живий перегляд HTML',
113
- 'code.applyNote':
114
- 'Застосування розбирає кожен рядок таблиці верхнього рівня в рядок полотна, який ви все ще можете вибирати, переупорядковувати та видаляти розмітка, написана вручну, переживає цей процес.',
115
- 'code.meta': '{kb} КБ · {lines} рядків',
116
- 'toast.sourceReloaded': 'Джерело оновлено з полотна',
117
- 'toast.sourceAppliedOne': 'Джерело застосовано — 1 рядок на полотні',
118
- 'toast.sourceAppliedMany': 'Джерело застосовано — {rows} рядків на полотні',
119
- 'toast.parseError': 'Не вдалося розібрати цей HTML',
120
- 'modal.copyAssist': 'Помічник із текстом',
121
- 'modal.draftCopyTitle': 'Скласти текст для цієї кампанії',
122
- 'ai.goal': 'Мета',
123
- 'ai.tone': 'Тон',
124
- 'ai.briefLabel': 'Про що цей лист?',
125
- 'ai.briefPlaceholder': 'напр. Осіння колекція, 15% для підписників, безкоштовна доставка від 150$',
126
- 'ai.generate': 'Згенерувати текст',
127
- 'ai.writing': 'Пишемо…',
128
- 'ai.kindHeadline': 'Заголовок',
129
- 'ai.kindBody': 'Основний текст',
130
- 'ai.kindButton': 'Текст кнопки',
131
- 'ai.actionInsertHeading': 'Вставити як заголовок',
132
- 'ai.actionInsertText': 'Вставити як текстовий блок',
133
- 'ai.actionInsertButton': 'Вставити як кнопку',
134
- 'toast.headingAdded': 'Заголовок додано',
135
- 'toast.textBlockAdded': 'Текстовий блок додано',
136
- 'toast.buttonAdded': 'Кнопку додано',
137
- 'preview.kickerMobile': 'Переглядтелефон 375px',
138
- 'preview.kickerDark': 'Перегляд темні вхідні',
139
- 'preview.kickerDesktop': 'Перегляд комп’ютер {width}px',
140
- 'action.close': 'Закрити',
141
- 'toast.duplicated': 'Продубльовано',
142
- 'toast.fileUploadedOne': 'Завантажено 1 файл',
143
- 'toast.fileUploadedMany': 'Завантажено файлів: {count}',
144
- 'toast.imageReplaced': 'Зображення замінено',
145
- 'toast.imageAdded': 'Зображення додано на полотно',
146
- 'toast.htmlCopied': 'HTML скопійовано в буфер обміну',
147
- 'toast.templateLoaded': '{name} завантажено',
148
- 'toast.snippetDefaultLabel': 'Фрагмент',
149
- 'toast.snippetInserted': '{name} вставлено',
150
- 'toast.snippetCopied': '{name} скопійовано — виберіть текстовий блок, щоб вставити',
151
- };
152
-
1
+ /** Ukrainian (Українська) — `uk`. AI-drafted, not reviewed by a native speaker. Correctable one key at a time via `.messages` overrides. */
2
+ export const UK = {
3
+ 'action.undoHint': 'Скасувати — ⌘Z',
4
+ 'action.redoHint': 'Повторити — ⌘⇧Z',
5
+ 'action.chromeToDark': 'Темна',
6
+ 'action.chromeToLight': 'Світла',
7
+ 'action.chromeHint': 'Тема редактора світла / темна',
8
+ 'action.chromeHintToDark': 'Темний режим',
9
+ 'action.chromeHintToLight': 'Світлий режим',
10
+ 'action.aiDraft': 'Чернетка',
11
+ 'action.aiDraftHint': 'Написати вміст листа за допомогою ШІ',
12
+ 'action.code': 'Код',
13
+ 'action.codeHint': 'Редагувати вихідний HTML із живим переглядом',
14
+ 'action.preview': 'Перегляд',
15
+ 'action.previewHint': 'Переглянути лист',
16
+ 'action.export': 'Експорт',
17
+ 'action.exportHint': 'Експортувати ваш лист',
18
+ 'device.desktop': 'Комп’ютер',
19
+ 'device.desktopHint': 'Ширина для комп’ютера',
20
+ 'device.mobile': 'Телефон',
21
+ 'device.mobileHint': 'Ширина для телефона',
22
+ 'status.autosaveOn': 'автозбереження увімкнено',
23
+ 'status.saved': 'збережено {time}',
24
+ 'status.saveFailed': 'не збережено — сховище заповнено',
25
+ 'canvas.meta': '{rows} рядків · {blocks} блоків · {width}px',
26
+ 'tab.design': 'Стиль',
27
+ 'tab.designHint': 'Оформити виділене',
28
+ 'tab.blocks': 'Блоки',
29
+ 'tab.blocksHint': 'Блоки вмісту та змінні',
30
+ 'tab.rows': 'Секції',
31
+ 'tab.rowsHint': 'Макети секцій і модель полотна',
32
+ 'tab.files': 'Файли',
33
+ 'tab.filesHint': 'Бібліотека файлів',
34
+ 'tab.layers': 'Структура',
35
+ 'tab.layersHint': 'Структура документа',
36
+ 'tab.settings': 'Налаштування',
37
+ 'tab.settingsHint': 'Налаштування листа',
38
+ 'tab.data': 'Змін.',
39
+ 'tab.dataHint': 'Змінні, надані вашим кодом',
40
+ 'inspector.blockProperties': 'Властивості блока',
41
+ 'inspector.sectionProperties': 'Властивості секції',
42
+ 'inspector.title': 'Інспектор',
43
+ 'inspector.sectionLabel': 'Секція',
44
+ 'inspector.nothingSelected': 'Нічого не вибрано',
45
+ 'action.duplicateHint': 'Дублювати — ⌘D',
46
+ 'action.deleteHint': 'Видалити ',
47
+ 'inspector.emptyBody':
48
+ 'Виберіть рядок або блок на полотні, щоб оформити його тут. Перетягніть блоки з вкладки <strong style="color: var(--ed-text); font-weight: 600;">Блоки</strong>; двічі клацніть текст, щоб редагувати його на місці.',
49
+ 'inspector.shortcuts': 'Гарячі клавіші',
50
+ 'shortcut.undoRedo': '⌘Z / ⌘⇧Z скасувати, повторити',
51
+ 'shortcut.duplicate': '⌘Dдублювати виділене',
52
+ 'shortcut.delete': 'видалити виділене',
53
+ 'shortcut.export': '⌘E експортувати HTML',
54
+ 'shortcut.escape': 'ESC — зняти виділення, закрити',
55
+ 'blocks.dragHint': 'Перетягніть на полотно',
56
+ 'blocks.count': '{count} блоків',
57
+ 'rows.sectionLayouts': 'Макети секцій',
58
+ 'rows.customMarkup': 'Власна розмітка',
59
+ 'rows.htmlRowHint': 'Перетягніть, щоб вставити, або клацніть, щоб додати — рядок на всю ширину, який ви заповнюєте вихідним HTML',
60
+ 'rows.rawHtmlSection': 'Секція з вихідним HTML',
61
+ 'rows.rawHtmlDesc': 'Секція на всю ширину, ваша власна розмітка, все ще перетягується',
62
+ 'rows.canvasModel': 'Модель полотна',
63
+ 'rows.modeRowBased': 'На основі рядків',
64
+ 'rows.modeFreeStack': 'Вільний стек',
65
+ 'rows.hintRows':
66
+ 'На основі секцій: спочатку розмістіть макет, потім блоки в його колонках кожна секція має власний фон, межу, налаштування flex або сітки.',
67
+ 'rows.hintStack': 'Вільний стек: без макетів — кожен доданий блок стає власною секцією на всю ширину, укладеною по порядку.',
68
+ 'files.libraryCount': 'Бібліотека {count} файлів',
69
+ 'files.openManager': 'Відкрити файловий менеджер',
70
+ 'files.dragToCanvas': 'Перетягніть будь-який файл прямо на полотно, щоб розмістити його як блок зображення.',
71
+ 'layers.structure': 'Структура',
72
+ 'layers.sectionSingle': 'Секція',
73
+ 'layers.sectionMulti': 'Секція · {count} кол.',
74
+ 'layers.column': 'Колонка {index}',
75
+ 'layers.blockCount': '{count} бл.',
76
+ 'vars.title': 'Змінні',
77
+ 'vars.fromCode': '{count} з вашого коду',
78
+ 'vars.declaredNote': 'Оголошені вашим застосунком полотно завжди показує токен, ніколи значення.',
79
+ 'vars.filterPlaceholder': 'Фільтр змінних…',
80
+ 'vars.insertHint': 'Натисніть, щоб вставити у вибраний текст, заголовок або кнопку',
81
+ 'vars.insert': 'вставити',
82
+ 'vars.noMatch': 'Немає змінних, що відповідають цьому фільтру.',
83
+ 'vars.noneDeclared': 'Ваш застосунок ще не оголосив жодних змінних.',
84
+ 'vars.rteHint': 'Під час редагування тексту ви також можете вибрати змінну прямо з випадного списку вбудованої панелі інструментів.',
85
+ 'modal.fileManager': 'Файловий менеджер',
86
+ 'modal.assetsTitle': 'Файли',
87
+ 'modal.replaceImage': 'Замінити зображення',
88
+ 'library.searchPlaceholder': 'Пошук файлів…',
89
+ 'action.upload': 'Завантажити',
90
+ 'library.clickToPlace': 'Натисніть на файл, щоб розмістити · або перетягніть файл на полотно',
91
+ 'library.clickToReplace': 'Натисніть на файл, щоб замінити вибране зображення',
92
+ 'library.storageLabel': '{count} файлів · {size}',
93
+ 'library.folders': 'Папки',
94
+ 'library.dropHint': 'Перетягніть файли зображень сюди для завантаження — або скористайтеся кнопкою «Завантажити».',
95
+ 'library.deleteFileHint': 'Видалити файл',
96
+ 'library.del': 'ВИДАЛ',
97
+ 'toast.assetDeleted': '{name} видалено',
98
+ 'library.allFiles': 'Усі файли',
99
+ 'library.loadMore': 'Завантажити ще',
100
+ 'library.empty': 'Тут ще немає файлів.',
101
+ 'storage.loading': 'Завантаження файлів…',
102
+ 'storage.uploading': 'Завантаження {count}…',
103
+ 'storage.errLoadFailed': 'Не вдалося завантажити бібліотеку файлів {reason}',
104
+ 'storage.errNoLimits': 'Завантаження вимкнено: цей застосунок не задав обмежень на завантаження.',
105
+ 'storage.errNoAccept': 'Завантаження вимкнено: не дозволено жодного формату файлів.',
106
+ 'storage.errNoMaxBytes': 'Завантаження вимкнено: не задано максимальний розмір файлу.',
107
+ 'storage.errTooLarge': '{name} важить {size} — обмеження {max}.',
108
+ 'storage.errFormat': '{name} файл {type}, який тут не дозволено.',
109
+ 'storage.errSvg': '{name} SVG, який цей застосунок не приймає.',
110
+ 'storage.errDimensions': '{name} має {w}×{ht}px — обмеження {maxW}×{maxH}px.',
111
+ 'storage.errTooMany': 'За один раз можна завантажити лише {max} файлів.',
112
+ 'storage.errUnreadable': '{name} не є придатним для читання зображенням.',
113
+ 'storage.errUploadFailed': 'Не вдалося завантажити {name} — {reason}',
114
+ 'storage.errDeleteFailed': 'Не вдалося видалити {name}{reason}',
115
+ 'modal.export': 'Експорт',
116
+ 'modal.exportTitle': 'HTML листа на основі таблиць',
117
+ 'export.copy': 'Копіювати',
118
+ 'export.copied': 'Скопійовано',
119
+ 'action.download': 'Завантажити',
120
+ 'export.meta': '{kb} КБ · таблиці + вбудовані стилі · ширини, безпечні для Outlook',
121
+ 'modal.rawHtmlTitle': 'Вихідний HTML, живий перегляд',
122
+ 'code.statusEdited': 'Перегляд коду — змінено — перегляд наживо, ще не застосовано',
123
+ 'code.statusSynced': 'Перегляд коду — синхронізовано з полотном',
124
+ 'action.reload': 'Оновити',
125
+ 'action.reloadHint': 'Оновити джерело з полотна',
126
+ 'action.applyToCanvas': 'Застосувати до полотна',
127
+ 'action.applyToCanvasHint': 'Розібрати джерело назад у редаговані рядки',
128
+ 'action.closeWithoutApplyingHint': 'Закрити без застосування',
129
+ 'code.source': 'Джерело',
130
+ 'code.livePreview': 'Живий перегляд',
131
+ 'code.liveHtmlPreviewTitle': 'Живий перегляд HTML',
132
+ 'code.applyNote':
133
+ 'Застосування розбирає кожен рядок таблиці верхнього рівня в рядок полотна, який ви все ще можете вибирати, переупорядковувати та видаляти — розмітка, написана вручну, переживає цей процес.',
134
+ 'code.meta': '{kb} КБ · {lines} рядків',
135
+ 'toast.sourceReloaded': 'Джерело оновлено з полотна',
136
+ 'toast.sourceAppliedOne': 'Джерело застосовано — 1 рядок на полотні',
137
+ 'toast.sourceAppliedMany': 'Джерело застосовано {rows} рядків на полотні',
138
+ 'toast.parseError': 'Не вдалося розібрати цей HTML',
139
+ 'modal.aiDraft': 'ШІ-помічник із написання',
140
+ 'modal.aiDraftTitle': 'Напишіть свій лист за допомогою ШІ',
141
+ 'ai.disclosure': 'ШІ створює пропозиції за вашим брифом. Перегляньте та відредагуйте результат перед надсиланням.',
142
+ 'ai.goal': 'Мета',
143
+ 'ai.tone': 'Тон',
144
+ 'ai.briefLabel': 'Про що цей лист?',
145
+ 'ai.briefPlaceholder': 'напр. Осіння колекція, 15% для підписників, безкоштовна доставка від 150$',
146
+ 'ai.generate': 'Згенерувати текст',
147
+ 'ai.writing': 'Пишемо…',
148
+ 'ai.kindHeadline': 'Заголовок',
149
+ 'ai.kindBody': 'Основний текст',
150
+ 'ai.kindButton': 'Текст кнопки',
151
+ 'ai.actionInsertHeading': 'Вставити як заголовок',
152
+ 'ai.actionInsertText': 'Вставити як текстовий блок',
153
+ 'ai.actionInsertButton': 'Вставити як кнопку',
154
+ 'toast.headingAdded': 'Заголовок додано',
155
+ 'toast.textBlockAdded': 'Текстовий блок додано',
156
+ 'toast.buttonAdded': 'Кнопку додано',
157
+ 'preview.kickerMobile': 'Перегляд — телефон 375px',
158
+ 'preview.kickerDesktop': 'Перегляд — комп’ютер {width}px',
159
+ 'action.close': 'Закрити',
160
+ 'toast.duplicated': 'Продубльовано',
161
+ 'toast.fileUploadedOne': 'Завантажено 1 файл',
162
+ 'toast.fileUploadedMany': 'Завантажено файлів: {count}',
163
+ 'toast.imageReplaced': 'Зображення замінено',
164
+ 'toast.imageAdded': 'Зображення додано на полотно',
165
+ 'toast.htmlCopied': 'HTML скопійовано в буфер обміну',
166
+ 'toast.templateLoaded': '{name} завантажено',
167
+ 'toast.snippetDefaultLabel': 'Фрагмент',
168
+ 'toast.snippetInserted': '{name} вставлено',
169
+ 'toast.snippetCopied': '{name} скопійовано — виберіть текстовий блок, щоб вставити',
170
+ 'rte.textStyle': 'Стиль тексту',
171
+ 'rte.mergeTags': 'Поля злиття',
172
+ 'rte.noMergeTags': 'Полів злиття немає',
173
+ 'rte.textColor': 'Колір тексту',
174
+ 'rte.highlightColor': 'Колір виділення',
175
+ 'rte.removeHighlight': 'Прибрати виділення',
176
+ 'rte.clearFormatting': 'Очистити форматування',
177
+ 'action.downloadPng': 'Завантажити PNG',
178
+ 'action.screenshot': 'Знімок екрана',
179
+ 'action.screenshotHint': 'Переглянути весь шаблон як зображення та завантажити його',
180
+ 'toast.pngSaved': 'Знімок завантажено',
181
+ 'toast.pngFailed': 'Знімок не вдався — не вдалося завантажити зовнішнє зображення',
182
+ 'toast.pngCopied': 'Знімок скопійовано в буфер обміну',
183
+ 'toast.pngCopyFailed': 'Цей браузер не прийняв зображення в буфер обміну',
184
+ 'story.kicker': 'Знімок екрана',
185
+ 'story.rendering': 'Створення знімка',
186
+ 'story.renderingHint': 'Кожен блок малюється в 2× — на довгому шаблоні це триває мить.',
187
+ 'story.failed': 'Знімок не вдався',
188
+ 'story.failedHint': 'Зображення в шаблоні не вдалося завантажити для знімка.',
189
+ 'story.retry': 'Спробувати ще раз',
190
+ 'story.play': 'Відтворити',
191
+ 'story.pause': 'Пауза',
192
+ 'story.replay': 'Відтворити ще раз',
193
+ 'story.copy': 'Копіювати',
194
+ 'story.meta': '{w}×{h} · екран {i} з {n}',
195
+ 'footer.poweredBy': 'Працює на SELISE Blocks © 2026',
196
+ };