@seliseblocks/mailcraft 0.1.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.
- package/DOCS.md +557 -0
- package/LICENSE +21 -0
- package/README.md +126 -0
- package/dist/mailcraft-editor.bundle.js +519 -0
- package/dist/mailcraft-editor.bundle.js.map +7 -0
- package/examples/templates/activate-your-account.html +54 -0
- package/examples/templates/back-in-stock.html +63 -0
- package/examples/templates/cart-left-behind.html +74 -0
- package/examples/templates/community-giveaway.html +81 -0
- package/examples/templates/frontend-futures-invite.html +69 -0
- package/examples/templates/give-25-get-25.html +69 -0
- package/examples/templates/invoice-paid.html +77 -0
- package/examples/templates/meet-nova-launch.html +69 -0
- package/examples/templates/mega-weekend-sale.html +57 -0
- package/examples/templates/order-confirmed.html +80 -0
- package/examples/templates/rate-your-headphones.html +71 -0
- package/examples/templates/reset-your-password.html +54 -0
- package/examples/templates/thankyou-promo-code.html +68 -0
- package/examples/templates/the-sunday-brief.html +47 -0
- package/examples/templates/welcome-to-your-workspace.html +62 -0
- package/examples/templates/your-order-shipped.html +74 -0
- package/examples/templates/your-password-was-changed.html +58 -0
- package/examples/templates/your-signin-code.html +58 -0
- package/examples/vanilla.html +1574 -0
- package/package.json +66 -0
- package/src/core/accent.js +194 -0
- package/src/core/assets.js +15 -0
- package/src/core/binder.js +119 -0
- package/src/core/blocks.js +256 -0
- package/src/core/css-cascade.js +117 -0
- package/src/core/editor-core.js +1492 -0
- package/src/core/export.js +58 -0
- package/src/core/footer.js +73 -0
- package/src/core/i18n/ar.js +177 -0
- package/src/core/i18n/bg.js +152 -0
- package/src/core/i18n/bn.js +176 -0
- package/src/core/i18n/ca.js +152 -0
- package/src/core/i18n/cs.js +152 -0
- package/src/core/i18n/da.js +152 -0
- package/src/core/i18n/de-CH.js +152 -0
- package/src/core/i18n/de.js +152 -0
- package/src/core/i18n/dz.js +179 -0
- package/src/core/i18n/el.js +152 -0
- package/src/core/i18n/en.js +269 -0
- package/src/core/i18n/es.js +152 -0
- package/src/core/i18n/et.js +152 -0
- package/src/core/i18n/fi.js +152 -0
- package/src/core/i18n/fr.js +152 -0
- package/src/core/i18n/hr.js +152 -0
- package/src/core/i18n/hu.js +152 -0
- package/src/core/i18n/index.js +83 -0
- package/src/core/i18n/it.js +152 -0
- package/src/core/i18n/lt.js +152 -0
- package/src/core/i18n/lv.js +152 -0
- package/src/core/i18n/nb.js +152 -0
- package/src/core/i18n/nl.js +152 -0
- package/src/core/i18n/pl.js +152 -0
- package/src/core/i18n/pt.js +152 -0
- package/src/core/i18n/ro.js +152 -0
- package/src/core/i18n/ru.js +152 -0
- package/src/core/i18n/sk.js +152 -0
- package/src/core/i18n/sl.js +152 -0
- package/src/core/i18n/sv.js +152 -0
- package/src/core/i18n/tables.js +50 -0
- package/src/core/i18n/tr.js +152 -0
- package/src/core/i18n/uk.js +152 -0
- package/src/core/icons.js +235 -0
- package/src/core/ids.js +1 -0
- package/src/core/import-html.js +959 -0
- package/src/core/layout-style.js +115 -0
- package/src/core/parse.js +10 -0
- package/src/core/placeholder.js +15 -0
- package/src/core/sanitize.js +141 -0
- package/src/core/storage-limits.js +184 -0
- package/src/core/storage.js +85 -0
- package/src/core/theme.js +1 -0
- package/src/core/toolbar.js +67 -0
- package/src/core/variables.js +11 -0
- package/src/create-editor.js +109 -0
- package/src/index.js +9 -0
- package/src/mailcraft-editor.js +1862 -0
- package/src/render/block-body.js +295 -0
- package/src/render/canvas.js +284 -0
- package/src/render/fields.js +609 -0
- package/src/render/focus-preserve.js +158 -0
- package/src/render/rte.js +212 -0
- package/src/render/screenshot.js +132 -0
- package/src/render/story.js +415 -0
- package/src/render/style.js +452 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/** Greek (Ελληνικά) — `el`. AI-drafted, not reviewed by a native speaker. Correctable one key at a time via `.messages` overrides. */
|
|
2
|
+
export const EL = {
|
|
3
|
+
'action.undoHint': 'Αναίρεση — ⌘Z',
|
|
4
|
+
'action.redoHint': 'Επανάληψη — ⌘⇧Z',
|
|
5
|
+
'action.chromeToDark': 'Σκούρο',
|
|
6
|
+
'action.chromeToLight': 'Ανοιχτόχρωμο',
|
|
7
|
+
'action.chromeHint': 'Θέμα επεξεργαστή ανοιχτό / σκούρο',
|
|
8
|
+
'action.aiCopy': 'Κείμενο',
|
|
9
|
+
'action.aiCopyHint': 'Σύνταξη κειμένου με AI',
|
|
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': 'Δηλωμένες από την εφαρμογή σας — ο καμβάς εμφανίζει πάντα το token, ποτέ μια τιμή.',
|
|
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 email βασισμένο σε πίνακες',
|
|
98
|
+
'export.copy': 'Αντιγραφή',
|
|
99
|
+
'export.copied': 'Αντιγράφηκε',
|
|
100
|
+
'action.download': 'Λήψη',
|
|
101
|
+
'export.meta': '{kb} 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} 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': 'Για τι αφορά αυτό το email;',
|
|
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
|
+
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The English message table -- the only locale that ships inside the core
|
|
3
|
+
* bundle. Every other language is a separate module under this same folder
|
|
4
|
+
* that a host app imports and hands to the editor as `.messages` (see
|
|
5
|
+
* `index.js`'s `createTranslator`).
|
|
6
|
+
*
|
|
7
|
+
* Flat, not nested: keys are `<area>.<thing>` and nothing deeper, so the
|
|
8
|
+
* dotted prefix gives the grouping without a path-resolver. Scope is editor
|
|
9
|
+
* chrome only -- panel names, toolbar actions, empty states, modals, status
|
|
10
|
+
* and toast text. Block-type names, per-field inspector labels ("Padding
|
|
11
|
+
* top / bottom", etc.) and default email content are not translated here;
|
|
12
|
+
* those are either data (`core/blocks.js`) or a
|
|
13
|
+
* deliberately separate follow-up pass.
|
|
14
|
+
*/
|
|
15
|
+
export const EN = {
|
|
16
|
+
// Header
|
|
17
|
+
'action.undoHint': 'Undo — ⌘Z',
|
|
18
|
+
'action.redoHint': 'Redo — ⌘⇧Z',
|
|
19
|
+
'action.chromeToDark': 'Dark',
|
|
20
|
+
'action.chromeToLight': 'Light',
|
|
21
|
+
'action.chromeHint': 'Light / dark editor chrome',
|
|
22
|
+
'action.chromeHintToDark': 'Dark mode',
|
|
23
|
+
'action.chromeHintToLight': 'Light mode',
|
|
24
|
+
'action.aiCopy': 'Draft',
|
|
25
|
+
'action.aiCopyHint': 'Draft email content with AI',
|
|
26
|
+
'action.aiDraft': 'Draft',
|
|
27
|
+
'action.aiDraftHint': 'Draft email content with AI',
|
|
28
|
+
'action.code': 'Code',
|
|
29
|
+
'action.codeHint': 'Edit the raw HTML with a live preview',
|
|
30
|
+
'action.preview': 'Preview',
|
|
31
|
+
'action.previewHint': 'Preview the email',
|
|
32
|
+
'action.export': 'Export',
|
|
33
|
+
'action.exportHint': 'Export your email',
|
|
34
|
+
|
|
35
|
+
// Device segment (header, preview modal, code modal)
|
|
36
|
+
'device.desktop': 'Desktop',
|
|
37
|
+
'device.desktopHint': 'Desktop width',
|
|
38
|
+
'device.mobile': 'Mobile',
|
|
39
|
+
'device.mobileHint': 'Mobile width',
|
|
40
|
+
|
|
41
|
+
// Autosave status (header)
|
|
42
|
+
'status.autosaveOn': 'autosave on',
|
|
43
|
+
'status.saved': 'saved {time}',
|
|
44
|
+
'status.saveFailed': 'not saved — storage full',
|
|
45
|
+
|
|
46
|
+
// Main canvas dock pill
|
|
47
|
+
'canvas.meta': '{rows} rows · {blocks} blocks · {width}px',
|
|
48
|
+
|
|
49
|
+
// Tab bar
|
|
50
|
+
'tab.design': 'Design',
|
|
51
|
+
'tab.designHint': 'Style the selection',
|
|
52
|
+
'tab.blocks': 'Content blocks',
|
|
53
|
+
'tab.blocksHint': 'Content blocks and variables',
|
|
54
|
+
'tab.rows': 'Sections',
|
|
55
|
+
'tab.rowsHint': 'Section layouts and canvas model',
|
|
56
|
+
'tab.files': 'Assets',
|
|
57
|
+
'tab.filesHint': 'Asset library',
|
|
58
|
+
'tab.layers': 'Layers',
|
|
59
|
+
'tab.layersHint': 'Document structure',
|
|
60
|
+
// Renamed keys (were tab.theme/tab.themeHint "Theme / Global styles"): new
|
|
61
|
+
// key names on purpose, so locales that still carry the old translation
|
|
62
|
+
// fall back to this English name instead of showing the stale "Theme".
|
|
63
|
+
'tab.settings': 'Settings',
|
|
64
|
+
'tab.settingsHint': 'Email settings',
|
|
65
|
+
'tab.data': 'Variables',
|
|
66
|
+
'tab.dataHint': 'Variables provided by your code',
|
|
67
|
+
|
|
68
|
+
// Design tab
|
|
69
|
+
'inspector.blockProperties': 'Block properties',
|
|
70
|
+
'inspector.sectionProperties': 'Section properties',
|
|
71
|
+
'inspector.title': 'Inspector',
|
|
72
|
+
'inspector.sectionLabel': 'Section',
|
|
73
|
+
'inspector.nothingSelected': 'Nothing selected',
|
|
74
|
+
'action.duplicateHint': 'Duplicate — ⌘D',
|
|
75
|
+
'action.deleteHint': 'Delete — ⌫',
|
|
76
|
+
'inspector.emptyBody':
|
|
77
|
+
'Pick a row or block on the canvas to style it here. Drag blocks in from the <strong style="color: var(--ed-text); font-weight: 600;">Content blocks</strong> tab; double-click any text to edit it in place.',
|
|
78
|
+
'inspector.shortcuts': 'Shortcuts',
|
|
79
|
+
'shortcut.undoRedo': '⌘Z / ⌘⇧Z — undo, redo',
|
|
80
|
+
'shortcut.duplicate': '⌘D — duplicate selection',
|
|
81
|
+
'shortcut.delete': '⌫ — delete selection',
|
|
82
|
+
'shortcut.export': '⌘E — export email',
|
|
83
|
+
'shortcut.escape': 'ESC — deselect, close',
|
|
84
|
+
|
|
85
|
+
// Blocks tab
|
|
86
|
+
'blocks.dragHint': 'Drag a block onto the canvas',
|
|
87
|
+
'blocks.count': '{count} blocks',
|
|
88
|
+
|
|
89
|
+
// Rows (Sections) tab
|
|
90
|
+
'rows.sectionLayouts': 'Section layouts',
|
|
91
|
+
'rows.customMarkup': 'Custom markup',
|
|
92
|
+
'rows.htmlRowHint': 'Drag in, or click to append — a full-bleed row you fill with raw HTML',
|
|
93
|
+
'rows.rawHtmlSection': 'Raw HTML section',
|
|
94
|
+
'rows.rawHtmlDesc': 'Full-bleed section, your markup, still draggable',
|
|
95
|
+
'rows.canvasModel': 'Canvas model',
|
|
96
|
+
'rows.modeRowBased': 'Row based',
|
|
97
|
+
'rows.modeFreeStack': 'Free stack',
|
|
98
|
+
'rows.hintRows':
|
|
99
|
+
'Section based: drop a layout first, then drop blocks into its columns — every section carries its own background, border, flex or grid settings.',
|
|
100
|
+
'rows.hintStack': 'Free stack: skip layouts — every block you drop becomes its own full-width section, stacked in order.',
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
// Files tab (sidebar)
|
|
104
|
+
'files.libraryCount': 'Library — {count} files',
|
|
105
|
+
'files.openManager': 'Open file manager',
|
|
106
|
+
'files.dragToCanvas': 'Drag any file straight onto the canvas to place it as an image block.',
|
|
107
|
+
|
|
108
|
+
// Layers (Tree) tab
|
|
109
|
+
'layers.structure': 'Structure',
|
|
110
|
+
'layers.sectionSingle': 'Section',
|
|
111
|
+
'layers.sectionMulti': 'Section · {count} columns',
|
|
112
|
+
'layers.column': 'Column {index}',
|
|
113
|
+
'layers.blockCount': '{count} blocks',
|
|
114
|
+
|
|
115
|
+
// Theme tab
|
|
116
|
+
'theme.globalStyles': 'Global styles',
|
|
117
|
+
|
|
118
|
+
// Data (Vars) tab
|
|
119
|
+
'vars.title': 'Variables',
|
|
120
|
+
'vars.fromCode': '{count} from your code',
|
|
121
|
+
'vars.declaredNote': 'Declared by your application — the canvas always shows the token, never a value.',
|
|
122
|
+
'vars.filterPlaceholder': 'Filter variables…',
|
|
123
|
+
'vars.insertHint': 'Click to insert into the selected text, heading or button',
|
|
124
|
+
'vars.insert': 'insert',
|
|
125
|
+
'vars.noMatch': 'No variable matches that filter.',
|
|
126
|
+
'vars.noneDeclared': 'Your application has not declared any variables yet.',
|
|
127
|
+
'vars.rteHint': 'While editing text you can also pick a variable straight from the inline toolbar’s dropdown.',
|
|
128
|
+
|
|
129
|
+
// Library modal
|
|
130
|
+
'modal.fileManager': 'File manager',
|
|
131
|
+
'modal.assetsTitle': 'Assets',
|
|
132
|
+
'modal.replaceImage': 'Replace image',
|
|
133
|
+
'library.searchPlaceholder': 'Search files…',
|
|
134
|
+
'action.upload': 'Upload',
|
|
135
|
+
'library.clickToPlace': 'Click a file to place it · drag a file onto the canvas',
|
|
136
|
+
'library.clickToReplace': 'Click a file to replace the selected image',
|
|
137
|
+
'library.storageLabel': '{count} files · {size}',
|
|
138
|
+
'library.folders': 'Folders',
|
|
139
|
+
'library.dropHint': 'Drop image files here to upload — or use the Upload button.',
|
|
140
|
+
'library.deleteFileHint': 'Delete file',
|
|
141
|
+
'library.del': 'DEL',
|
|
142
|
+
'toast.assetDeleted': '{name} deleted',
|
|
143
|
+
'library.allFiles': 'All files',
|
|
144
|
+
'library.loadMore': 'Load more',
|
|
145
|
+
'library.empty': 'No files here yet.',
|
|
146
|
+
|
|
147
|
+
// Host-supplied storage (core/storage-limits.js, core/storage.js). The
|
|
148
|
+
// limits are the host app's to set -- these strings only report them.
|
|
149
|
+
'storage.loading': 'Loading files…',
|
|
150
|
+
'storage.uploading': 'Uploading {count}…',
|
|
151
|
+
'storage.errLoadFailed': 'The file library could not be loaded — {reason}',
|
|
152
|
+
'storage.errNoLimits': 'Uploads are switched off: this app has not set any upload limits.',
|
|
153
|
+
'storage.errNoAccept': 'Uploads are switched off: no file formats have been allowed.',
|
|
154
|
+
'storage.errNoMaxBytes': 'Uploads are switched off: no maximum file size has been set.',
|
|
155
|
+
'storage.errTooLarge': '{name} is {size} — the limit is {max}.',
|
|
156
|
+
'storage.errFormat': '{name} is a {type} file, which is not allowed here.',
|
|
157
|
+
'storage.errSvg': '{name} is an SVG, which this app does not accept.',
|
|
158
|
+
'storage.errDimensions': '{name} is {w}×{ht}px — the limit is {maxW}×{maxH}px.',
|
|
159
|
+
'storage.errTooMany': 'Only {max} files can be uploaded at once.',
|
|
160
|
+
'storage.errUnreadable': '{name} is not a readable image.',
|
|
161
|
+
'storage.errUploadFailed': '{name} could not be uploaded — {reason}',
|
|
162
|
+
'storage.errDeleteFailed': '{name} could not be deleted — {reason}',
|
|
163
|
+
|
|
164
|
+
// Export modal
|
|
165
|
+
'modal.export': 'Export',
|
|
166
|
+
'modal.exportTitle': 'Your email is ready',
|
|
167
|
+
'export.copy': 'Copy email',
|
|
168
|
+
'export.copied': 'Copied',
|
|
169
|
+
'action.download': 'Download',
|
|
170
|
+
'export.meta': '{kb} KB · ready to copy or download',
|
|
171
|
+
|
|
172
|
+
// Code modal
|
|
173
|
+
'modal.rawHtmlTitle': 'Raw HTML, live preview',
|
|
174
|
+
'code.statusEdited': 'Code view — edited — preview live, not yet applied',
|
|
175
|
+
'code.statusSynced': 'Code view — in sync with the canvas',
|
|
176
|
+
'action.reload': 'Reload',
|
|
177
|
+
'action.reloadHint': 'Reload the source from the canvas',
|
|
178
|
+
'action.applyToCanvas': 'Apply to canvas',
|
|
179
|
+
'action.applyToCanvasHint': 'Parse the source back into editable rows',
|
|
180
|
+
'action.closeWithoutApplyingHint': 'Close without applying',
|
|
181
|
+
'code.source': 'Source',
|
|
182
|
+
'code.livePreview': 'Live preview',
|
|
183
|
+
'code.liveHtmlPreviewTitle': 'Live HTML preview',
|
|
184
|
+
'code.applyNote':
|
|
185
|
+
'Apply parses each top-level table row back into a canvas row you can still select, reorder and delete — hand-written markup survives the round trip.',
|
|
186
|
+
'code.meta': '{kb} KB · {lines} lines',
|
|
187
|
+
'toast.sourceReloaded': 'Source reloaded from canvas',
|
|
188
|
+
'toast.sourceAppliedOne': 'Source applied — 1 row back on the canvas',
|
|
189
|
+
'toast.sourceAppliedMany': 'Source applied — {rows} rows back on the canvas',
|
|
190
|
+
'toast.parseError': 'Could not parse that HTML',
|
|
191
|
+
|
|
192
|
+
// AI copy modal
|
|
193
|
+
'modal.copyAssist': 'AI writing assistant',
|
|
194
|
+
'modal.draftCopyTitle': 'Draft your email with AI',
|
|
195
|
+
'modal.aiDraft': 'AI writing assistant',
|
|
196
|
+
'modal.aiDraftTitle': 'Draft your email with AI',
|
|
197
|
+
'ai.disclosure': 'AI creates suggestions from your brief. Review and edit the result before sending.',
|
|
198
|
+
'ai.goal': 'Goal',
|
|
199
|
+
'ai.tone': 'Tone',
|
|
200
|
+
'ai.briefLabel': 'What is this email about?',
|
|
201
|
+
'ai.briefPlaceholder': 'e.g. Autumn outerwear drop, 15% for subscribers, free shipping over $150',
|
|
202
|
+
'ai.generate': 'Generate draft with AI',
|
|
203
|
+
'ai.writing': 'Writing…',
|
|
204
|
+
'ai.kindHeadline': 'Headline',
|
|
205
|
+
'ai.kindBody': 'Body copy',
|
|
206
|
+
'ai.kindButton': 'Button label',
|
|
207
|
+
'ai.actionInsertHeading': 'Insert as heading',
|
|
208
|
+
'ai.actionInsertText': 'Insert as text block',
|
|
209
|
+
'ai.actionInsertButton': 'Insert as button',
|
|
210
|
+
'toast.headingAdded': 'Heading added',
|
|
211
|
+
'toast.textBlockAdded': 'Text block added',
|
|
212
|
+
'toast.buttonAdded': 'Button added',
|
|
213
|
+
|
|
214
|
+
// Preview modal
|
|
215
|
+
'preview.kickerMobile': 'Preview — mobile 375px',
|
|
216
|
+
'preview.kickerDesktop': 'Preview — desktop {width}px',
|
|
217
|
+
'action.close': 'Close',
|
|
218
|
+
|
|
219
|
+
// General toasts (editor-core.js)
|
|
220
|
+
'toast.duplicated': 'Duplicated',
|
|
221
|
+
'toast.fileUploadedOne': '1 file uploaded',
|
|
222
|
+
'toast.fileUploadedMany': '{count} files uploaded',
|
|
223
|
+
'toast.imageReplaced': 'Image replaced',
|
|
224
|
+
'toast.imageAdded': 'Image added to canvas',
|
|
225
|
+
'toast.htmlCopied': 'HTML copied to clipboard',
|
|
226
|
+
'toast.templateLoaded': '{name} loaded',
|
|
227
|
+
'toast.snippetDefaultLabel': 'Snippet',
|
|
228
|
+
'toast.snippetInserted': '{name} inserted',
|
|
229
|
+
'toast.snippetCopied': '{name} copied — select a text block to insert it',
|
|
230
|
+
|
|
231
|
+
// Inline rich text toolbar (render/rte.js)
|
|
232
|
+
'rte.textStyle': 'Text style',
|
|
233
|
+
'rte.mergeTags': 'Merge Tags',
|
|
234
|
+
'rte.noMergeTags': 'No merge tags available',
|
|
235
|
+
'rte.textColor': 'Text color',
|
|
236
|
+
'rte.highlightColor': 'Highlight color',
|
|
237
|
+
'rte.removeHighlight': 'Remove highlight',
|
|
238
|
+
'rte.clearFormatting': 'Clear formatting',
|
|
239
|
+
|
|
240
|
+
// Screenshot export (export modal / element `screenshotPng()`)
|
|
241
|
+
'action.downloadPng': 'Download PNG',
|
|
242
|
+
'action.screenshot': 'Screenshot',
|
|
243
|
+
'action.screenshotHint': 'Preview the full template as an image, then download it',
|
|
244
|
+
'toast.pngSaved': 'Screenshot downloaded',
|
|
245
|
+
'toast.pngFailed': 'Screenshot failed — an external image could not be loaded',
|
|
246
|
+
'toast.pngCopied': 'Screenshot copied to clipboard',
|
|
247
|
+
'toast.pngCopyFailed': 'This browser would not accept an image on the clipboard',
|
|
248
|
+
|
|
249
|
+
// Story-style screenshot viewer (render/story.js)
|
|
250
|
+
'story.kicker': 'Screenshot',
|
|
251
|
+
'story.rendering': 'Rendering the screenshot',
|
|
252
|
+
'story.renderingHint': 'Painting every block at 2× — this takes a moment on a long template.',
|
|
253
|
+
'story.failed': 'Screenshot failed',
|
|
254
|
+
'story.failedHint': 'An image in the template could not be loaded for capture.',
|
|
255
|
+
'story.retry': 'Try again',
|
|
256
|
+
'story.play': 'Play',
|
|
257
|
+
'story.pause': 'Pause',
|
|
258
|
+
'story.replay': 'Replay',
|
|
259
|
+
'story.copy': 'Copy',
|
|
260
|
+
'story.meta': '{w}×{h} · screen {i} of {n}',
|
|
261
|
+
|
|
262
|
+
// Footer strip (core/footer.js). One string, so a translator localizes
|
|
263
|
+
// "Powered by" while the product name and year travel with it; a host that
|
|
264
|
+
// wants different wording sets `footer` rather than translating this.
|
|
265
|
+
'footer.poweredBy': 'Powered by SELISE Blocks © 2026',
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
/** Every key the editor asks for. Exported so a translator can diff a custom table against it. */
|
|
269
|
+
export const MESSAGE_KEYS = Object.keys(EN).sort();
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/** Spanish (Español) — `es`. AI-drafted, not reviewed by a native speaker. Correctable one key at a time via `.messages` overrides. */
|
|
2
|
+
export const ES = {
|
|
3
|
+
'action.undoHint': 'Deshacer — ⌘Z',
|
|
4
|
+
'action.redoHint': 'Rehacer — ⌘⇧Z',
|
|
5
|
+
'action.chromeToDark': 'Oscuro',
|
|
6
|
+
'action.chromeToLight': 'Claro',
|
|
7
|
+
'action.chromeHint': 'Tema del editor claro / oscuro',
|
|
8
|
+
'action.aiCopy': 'Texto',
|
|
9
|
+
'action.aiCopyHint': 'Redactar texto con IA',
|
|
10
|
+
'action.code': 'Código',
|
|
11
|
+
'action.codeHint': 'Editar el HTML sin procesar con vista previa en vivo',
|
|
12
|
+
'action.preview': 'Vista previa',
|
|
13
|
+
'action.export': 'Exportar',
|
|
14
|
+
'device.desktop': 'Escritorio',
|
|
15
|
+
'device.desktopHint': 'Ancho de escritorio',
|
|
16
|
+
'device.mobile': 'Móvil',
|
|
17
|
+
'device.mobileHint': 'Ancho móvil',
|
|
18
|
+
'device.dark': 'Oscuro',
|
|
19
|
+
'device.darkHint': 'Bandeja de entrada oscura',
|
|
20
|
+
'status.autosaveOn': 'guardado automático activado',
|
|
21
|
+
'status.saved': 'guardado {time}',
|
|
22
|
+
'status.saveFailed': 'no guardado — almacenamiento lleno',
|
|
23
|
+
'canvas.meta': '{rows} filas · {blocks} bloques · {width}px',
|
|
24
|
+
'tab.design': 'Estilo',
|
|
25
|
+
'tab.designHint': 'Aplicar estilo a la selección',
|
|
26
|
+
'tab.blocks': 'Bloques',
|
|
27
|
+
'tab.blocksHint': 'Bloques de contenido y variables',
|
|
28
|
+
'tab.rows': 'Secc.',
|
|
29
|
+
'tab.rowsHint': 'Diseños de sección y modelo de lienzo',
|
|
30
|
+
'tab.files': 'Archivos',
|
|
31
|
+
'tab.filesHint': 'Biblioteca de recursos',
|
|
32
|
+
'tab.layers': 'Estruct.',
|
|
33
|
+
'tab.layersHint': 'Estructura del documento',
|
|
34
|
+
'tab.theme': 'Tema',
|
|
35
|
+
'tab.themeHint': 'Estilos globales',
|
|
36
|
+
'tab.data': 'Var.',
|
|
37
|
+
'tab.dataHint': 'Variables proporcionadas por tu código',
|
|
38
|
+
'inspector.blockProperties': 'Propiedades del bloque',
|
|
39
|
+
'inspector.sectionProperties': 'Propiedades de la sección',
|
|
40
|
+
'inspector.title': 'Inspector',
|
|
41
|
+
'inspector.sectionLabel': 'Sección',
|
|
42
|
+
'inspector.nothingSelected': 'Nada seleccionado',
|
|
43
|
+
'action.duplicateHint': 'Duplicar — ⌘D',
|
|
44
|
+
'action.deleteHint': 'Eliminar — ⌫',
|
|
45
|
+
'inspector.emptyBody':
|
|
46
|
+
'Selecciona una fila o un bloque en el lienzo para darle estilo aquí. Arrastra bloques desde la pestaña <strong style="color: var(--ed-text); font-weight: 600;">Bloques</strong>; haz doble clic en cualquier texto para editarlo directamente.',
|
|
47
|
+
'inspector.shortcuts': 'Atajos',
|
|
48
|
+
'shortcut.undoRedo': '⌘Z / ⌘⇧Z — deshacer, rehacer',
|
|
49
|
+
'shortcut.duplicate': '⌘D — duplicar selección',
|
|
50
|
+
'shortcut.delete': '⌫ — eliminar selección',
|
|
51
|
+
'shortcut.export': '⌘E — exportar HTML',
|
|
52
|
+
'shortcut.escape': 'ESC — deseleccionar, cerrar',
|
|
53
|
+
'blocks.dragHint': 'Arrastra al lienzo',
|
|
54
|
+
'blocks.count': '{count} bloques',
|
|
55
|
+
'rows.sectionLayouts': 'Diseños de sección',
|
|
56
|
+
'rows.customMarkup': 'Marcado personalizado',
|
|
57
|
+
'rows.htmlRowHint': 'Arrastra para insertar, o haz clic para añadir — una fila a sangre completa que rellenas con HTML sin procesar',
|
|
58
|
+
'rows.rawHtmlSection': 'Sección de HTML sin procesar',
|
|
59
|
+
'rows.rawHtmlDesc': 'Sección a sangre completa, tu propio marcado, sigue siendo arrastrable',
|
|
60
|
+
'rows.canvasModel': 'Modelo de lienzo',
|
|
61
|
+
'rows.modeRowBased': 'Basado en filas',
|
|
62
|
+
'rows.modeFreeStack': 'Pila libre',
|
|
63
|
+
'rows.hintRows':
|
|
64
|
+
'Basado en secciones: primero suelta un diseño, luego suelta bloques en sus columnas — cada sección tiene su propio fondo, borde, ajustes flex o de cuadrícula.',
|
|
65
|
+
'rows.hintStack': 'Pila libre: sin diseños — cada bloque que sueltas se convierte en su propia sección de ancho completo, apilada en orden.',
|
|
66
|
+
'files.libraryCount': 'Biblioteca — {count} archivos',
|
|
67
|
+
'files.openManager': 'Abrir gestor de archivos',
|
|
68
|
+
'files.dragToCanvas': 'Arrastra cualquier archivo directamente al lienzo para colocarlo como bloque de imagen.',
|
|
69
|
+
'layers.structure': 'Estructura',
|
|
70
|
+
'layers.sectionSingle': 'Sección',
|
|
71
|
+
'layers.sectionMulti': 'Sección · {count} col.',
|
|
72
|
+
'layers.blockCount': '{count} bloq.',
|
|
73
|
+
'theme.globalStyles': 'Estilos globales',
|
|
74
|
+
'vars.title': 'Variables',
|
|
75
|
+
'vars.fromCode': '{count} de tu código',
|
|
76
|
+
'vars.declaredNote': 'Declaradas por tu aplicación — el lienzo siempre muestra el token, nunca un valor.',
|
|
77
|
+
'vars.filterPlaceholder': 'Filtrar variables…',
|
|
78
|
+
'vars.insertHint': 'Haz clic para insertar en el texto, título o botón seleccionado',
|
|
79
|
+
'vars.insert': 'insertar',
|
|
80
|
+
'vars.noMatch': 'Ninguna variable coincide con ese filtro.',
|
|
81
|
+
'vars.noneDeclared': 'Tu aplicación aún no ha declarado ninguna variable.',
|
|
82
|
+
'vars.rteHint': 'Al editar texto también puedes elegir una variable directamente desde el menú de la barra de herramientas en línea.',
|
|
83
|
+
'modal.fileManager': 'Gestor de archivos',
|
|
84
|
+
'modal.assetsTitle': 'Recursos',
|
|
85
|
+
'modal.replaceImage': 'Reemplazar imagen',
|
|
86
|
+
'library.searchPlaceholder': 'Buscar archivos…',
|
|
87
|
+
'action.upload': 'Subir',
|
|
88
|
+
'library.clickToPlace': 'Haz clic en un archivo para colocarlo · o arrastra un archivo al lienzo',
|
|
89
|
+
'library.clickToReplace': 'Haz clic en un archivo para reemplazar la imagen seleccionada',
|
|
90
|
+
'library.storageLabel': '{count} archivos · {size}',
|
|
91
|
+
'library.folders': 'Carpetas',
|
|
92
|
+
'library.dropHint': 'Suelta archivos de imagen aquí para subirlos — o usa el botón Subir.',
|
|
93
|
+
'library.deleteFileHint': 'Eliminar archivo',
|
|
94
|
+
'library.del': 'BORR',
|
|
95
|
+
'toast.assetDeleted': '{name} eliminado',
|
|
96
|
+
'modal.export': 'Exportar',
|
|
97
|
+
'modal.exportTitle': 'HTML de correo basado en tablas',
|
|
98
|
+
'export.copy': 'Copiar',
|
|
99
|
+
'export.copied': 'Copiado',
|
|
100
|
+
'action.download': 'Descargar',
|
|
101
|
+
'export.meta': '{kb} KB · tablas + estilos en línea · anchos seguros para Outlook',
|
|
102
|
+
'modal.rawHtmlTitle': 'HTML sin procesar, vista previa en vivo',
|
|
103
|
+
'code.statusEdited': 'Vista de código — editado — vista previa en vivo, aún no aplicado',
|
|
104
|
+
'code.statusSynced': 'Vista de código — sincronizado con el lienzo',
|
|
105
|
+
'action.reload': 'Recargar',
|
|
106
|
+
'action.reloadHint': 'Recargar el origen desde el lienzo',
|
|
107
|
+
'action.applyToCanvas': 'Aplicar al lienzo',
|
|
108
|
+
'action.applyToCanvasHint': 'Analizar el origen de nuevo en filas editables',
|
|
109
|
+
'action.closeWithoutApplyingHint': 'Cerrar sin aplicar',
|
|
110
|
+
'code.source': 'Origen',
|
|
111
|
+
'code.livePreview': 'Vista previa en vivo',
|
|
112
|
+
'code.liveHtmlPreviewTitle': 'Vista previa de HTML en vivo',
|
|
113
|
+
'code.applyNote':
|
|
114
|
+
'Aplicar analiza cada fila de tabla de nivel superior en una fila de lienzo que aún puedes seleccionar, reordenar y eliminar — el marcado escrito a mano sobrevive el proceso.',
|
|
115
|
+
'code.meta': '{kb} KB · {lines} líneas',
|
|
116
|
+
'toast.sourceReloaded': 'Origen recargado desde el lienzo',
|
|
117
|
+
'toast.sourceAppliedOne': 'Origen aplicado — 1 fila en el lienzo',
|
|
118
|
+
'toast.sourceAppliedMany': 'Origen aplicado — {rows} filas en el lienzo',
|
|
119
|
+
'toast.parseError': 'No se pudo analizar ese HTML',
|
|
120
|
+
'modal.copyAssist': 'Asistente de redacción',
|
|
121
|
+
'modal.draftCopyTitle': 'Redactar texto para esta campaña',
|
|
122
|
+
'ai.goal': 'Objetivo',
|
|
123
|
+
'ai.tone': 'Tono',
|
|
124
|
+
'ai.briefLabel': '¿De qué trata este correo?',
|
|
125
|
+
'ai.briefPlaceholder': 'p. ej. Colección de otoño, 15% para suscriptores, envío gratis desde $150',
|
|
126
|
+
'ai.generate': 'Generar texto',
|
|
127
|
+
'ai.writing': 'Escribiendo…',
|
|
128
|
+
'ai.kindHeadline': 'Titular',
|
|
129
|
+
'ai.kindBody': 'Cuerpo del texto',
|
|
130
|
+
'ai.kindButton': 'Texto del botón',
|
|
131
|
+
'ai.actionInsertHeading': 'Insertar como encabezado',
|
|
132
|
+
'ai.actionInsertText': 'Insertar como bloque de texto',
|
|
133
|
+
'ai.actionInsertButton': 'Insertar como botón',
|
|
134
|
+
'toast.headingAdded': 'Encabezado añadido',
|
|
135
|
+
'toast.textBlockAdded': 'Bloque de texto añadido',
|
|
136
|
+
'toast.buttonAdded': 'Botón añadido',
|
|
137
|
+
'preview.kickerMobile': 'Vista previa — móvil 375px',
|
|
138
|
+
'preview.kickerDark': 'Vista previa — bandeja oscura',
|
|
139
|
+
'preview.kickerDesktop': 'Vista previa — escritorio {width}px',
|
|
140
|
+
'action.close': 'Cerrar',
|
|
141
|
+
'toast.duplicated': 'Duplicado',
|
|
142
|
+
'toast.fileUploadedOne': '1 archivo subido',
|
|
143
|
+
'toast.fileUploadedMany': '{count} archivos subidos',
|
|
144
|
+
'toast.imageReplaced': 'Imagen reemplazada',
|
|
145
|
+
'toast.imageAdded': 'Imagen añadida al lienzo',
|
|
146
|
+
'toast.htmlCopied': 'HTML copiado al portapapeles',
|
|
147
|
+
'toast.templateLoaded': '{name} cargado',
|
|
148
|
+
'toast.snippetDefaultLabel': 'Fragmento',
|
|
149
|
+
'toast.snippetInserted': '{name} insertado',
|
|
150
|
+
'toast.snippetCopied': '{name} copiado — selecciona un bloque de texto para insertarlo',
|
|
151
|
+
};
|
|
152
|
+
|