@seliseblocks/mailcraft 0.1.1 → 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 +238 -10
  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 +234 -22
  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
- /** Russian (Русский) — `ru`. AI-drafted, not reviewed by a native speaker. Correctable one key at a time via `.messages` overrides. */
2
- export const RU = {
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
+ /** Russian (Русский) — `ru`. AI-drafted, not reviewed by a native speaker. Correctable one key at a time via `.messages` overrides. */
2
+ export const RU = {
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
+ };