@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.
- package/DOCS.md +240 -12
- package/README.md +11 -3
- package/README.md.txt +134 -0
- package/dist/mailcraft-editor.bundle.js +51 -39
- package/dist/mailcraft-editor.bundle.js.map +3 -3
- package/examples/templates/order-confirmed.html +80 -80
- package/examples/vanilla.html +242 -23
- package/package.json +7 -2
- package/src/core/assets.js +10 -15
- package/src/core/binder.js +120 -118
- package/src/core/blocks.js +14 -1
- package/src/core/css-cascade.js +117 -117
- package/src/core/editor-core.js +1530 -1492
- package/src/core/export.js +142 -55
- package/src/core/i18n/ar.js +219 -177
- package/src/core/i18n/bg.js +196 -152
- package/src/core/i18n/bn.js +218 -176
- package/src/core/i18n/ca.js +196 -152
- package/src/core/i18n/cs.js +196 -152
- package/src/core/i18n/da.js +196 -152
- package/src/core/i18n/de-CH.js +196 -152
- package/src/core/i18n/de.js +196 -152
- package/src/core/i18n/dz.js +221 -179
- package/src/core/i18n/el.js +196 -152
- package/src/core/i18n/en.js +3 -10
- package/src/core/i18n/es.js +196 -152
- package/src/core/i18n/et.js +196 -152
- package/src/core/i18n/fi.js +196 -152
- package/src/core/i18n/fr.js +196 -152
- package/src/core/i18n/hr.js +196 -152
- package/src/core/i18n/hu.js +196 -152
- package/src/core/i18n/index.js +83 -83
- package/src/core/i18n/it.js +196 -152
- package/src/core/i18n/lt.js +196 -152
- package/src/core/i18n/lv.js +196 -152
- package/src/core/i18n/nb.js +196 -152
- package/src/core/i18n/nl.js +196 -152
- package/src/core/i18n/pl.js +196 -152
- package/src/core/i18n/pt.js +196 -152
- package/src/core/i18n/ro.js +196 -152
- package/src/core/i18n/ru.js +196 -152
- package/src/core/i18n/sk.js +196 -152
- package/src/core/i18n/sl.js +196 -152
- package/src/core/i18n/sv.js +196 -152
- package/src/core/i18n/tables.js +50 -50
- package/src/core/i18n/tr.js +196 -152
- package/src/core/i18n/uk.js +196 -152
- package/src/core/icons.js +237 -235
- package/src/core/ids.js +1 -1
- package/src/core/import-html.js +1025 -959
- package/src/core/layout-style.js +100 -100
- package/src/core/parse.js +10 -10
- package/src/core/placeholder.js +15 -15
- package/src/core/sanitize.js +141 -141
- package/src/core/storage-limits.js +184 -184
- package/src/core/storage.js +85 -85
- package/src/core/theme.js +1 -1
- package/src/core/variables.js +11 -11
- package/src/index.js +9 -9
- package/src/mailcraft-editor.js +26 -14
- package/src/render/block-body.js +49 -6
- package/src/render/canvas.js +31 -2
- package/src/render/fields.js +602 -588
- package/src/render/focus-preserve.js +158 -158
- package/src/render/rte.js +241 -212
- package/src/render/screenshot.js +132 -132
- package/src/render/story.js +415 -415
- package/src/render/style.js +8 -0
- package/types/index.d.ts +419 -0
package/src/core/i18n/hu.js
CHANGED
|
@@ -1,152 +1,196 @@
|
|
|
1
|
-
/** Hungarian (Magyar) — `hu`. AI-drafted, not reviewed by a native speaker. Correctable one key at a time via `.messages` overrides. */
|
|
2
|
-
export const HU = {
|
|
3
|
-
'action.undoHint': 'Visszavonás — ⌘Z',
|
|
4
|
-
'action.redoHint': 'Ismétlés — ⌘⇧Z',
|
|
5
|
-
'action.chromeToDark': 'Sötét',
|
|
6
|
-
'action.chromeToLight': 'Világos',
|
|
7
|
-
'action.chromeHint': 'Szerkesztő téma világos / sötét',
|
|
8
|
-
'action.
|
|
9
|
-
'action.
|
|
10
|
-
'action.
|
|
11
|
-
'action.
|
|
12
|
-
'action.
|
|
13
|
-
'action.
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
'device.
|
|
19
|
-
'device.
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'status.
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
'tab.
|
|
27
|
-
'tab.
|
|
28
|
-
'tab.
|
|
29
|
-
'tab.
|
|
30
|
-
'tab.
|
|
31
|
-
'tab.
|
|
32
|
-
'tab.
|
|
33
|
-
'tab.
|
|
34
|
-
'tab.
|
|
35
|
-
'tab.
|
|
36
|
-
'tab.
|
|
37
|
-
'tab.
|
|
38
|
-
'
|
|
39
|
-
'
|
|
40
|
-
'inspector.
|
|
41
|
-
'inspector.
|
|
42
|
-
'inspector.
|
|
43
|
-
'
|
|
44
|
-
'
|
|
45
|
-
'
|
|
46
|
-
|
|
47
|
-
'inspector.
|
|
48
|
-
|
|
49
|
-
'
|
|
50
|
-
'shortcut.
|
|
51
|
-
'shortcut.
|
|
52
|
-
'shortcut.
|
|
53
|
-
'
|
|
54
|
-
'
|
|
55
|
-
'
|
|
56
|
-
'
|
|
57
|
-
'rows.
|
|
58
|
-
'rows.
|
|
59
|
-
'rows.
|
|
60
|
-
'rows.
|
|
61
|
-
'rows.
|
|
62
|
-
'rows.
|
|
63
|
-
'rows.
|
|
64
|
-
|
|
65
|
-
'rows.
|
|
66
|
-
|
|
67
|
-
'
|
|
68
|
-
'files.
|
|
69
|
-
'
|
|
70
|
-
'
|
|
71
|
-
'layers.
|
|
72
|
-
'layers.
|
|
73
|
-
'
|
|
74
|
-
'
|
|
75
|
-
'
|
|
76
|
-
'vars.
|
|
77
|
-
'vars.
|
|
78
|
-
'vars.
|
|
79
|
-
'vars.
|
|
80
|
-
'vars.
|
|
81
|
-
'vars.
|
|
82
|
-
'vars.
|
|
83
|
-
'
|
|
84
|
-
'
|
|
85
|
-
'modal.
|
|
86
|
-
'
|
|
87
|
-
'
|
|
88
|
-
'library.
|
|
89
|
-
'
|
|
90
|
-
'library.
|
|
91
|
-
'library.
|
|
92
|
-
'library.
|
|
93
|
-
'library.
|
|
94
|
-
'library.
|
|
95
|
-
'
|
|
96
|
-
'
|
|
97
|
-
'
|
|
98
|
-
'
|
|
99
|
-
'
|
|
100
|
-
'
|
|
101
|
-
'
|
|
102
|
-
'
|
|
103
|
-
'
|
|
104
|
-
'
|
|
105
|
-
'
|
|
106
|
-
'
|
|
107
|
-
'
|
|
108
|
-
'
|
|
109
|
-
'
|
|
110
|
-
'
|
|
111
|
-
'
|
|
112
|
-
'
|
|
113
|
-
'
|
|
114
|
-
|
|
115
|
-
'
|
|
116
|
-
'
|
|
117
|
-
'
|
|
118
|
-
'
|
|
119
|
-
'
|
|
120
|
-
'
|
|
121
|
-
'modal.
|
|
122
|
-
'
|
|
123
|
-
'
|
|
124
|
-
'
|
|
125
|
-
'
|
|
126
|
-
'
|
|
127
|
-
'
|
|
128
|
-
'
|
|
129
|
-
'
|
|
130
|
-
'
|
|
131
|
-
'
|
|
132
|
-
'
|
|
133
|
-
|
|
134
|
-
'
|
|
135
|
-
'toast.
|
|
136
|
-
'toast.
|
|
137
|
-
'
|
|
138
|
-
'
|
|
139
|
-
'
|
|
140
|
-
'
|
|
141
|
-
'
|
|
142
|
-
'
|
|
143
|
-
'
|
|
144
|
-
'
|
|
145
|
-
'
|
|
146
|
-
'
|
|
147
|
-
'
|
|
148
|
-
'
|
|
149
|
-
'
|
|
150
|
-
'
|
|
151
|
-
|
|
152
|
-
|
|
1
|
+
/** Hungarian (Magyar) — `hu`. AI-drafted, not reviewed by a native speaker. Correctable one key at a time via `.messages` overrides. */
|
|
2
|
+
export const HU = {
|
|
3
|
+
'action.undoHint': 'Visszavonás — ⌘Z',
|
|
4
|
+
'action.redoHint': 'Ismétlés — ⌘⇧Z',
|
|
5
|
+
'action.chromeToDark': 'Sötét',
|
|
6
|
+
'action.chromeToLight': 'Világos',
|
|
7
|
+
'action.chromeHint': 'Szerkesztő téma világos / sötét',
|
|
8
|
+
'action.chromeHintToDark': 'Sötét mód',
|
|
9
|
+
'action.chromeHintToLight': 'Világos mód',
|
|
10
|
+
'action.aiDraft': 'Vázlat',
|
|
11
|
+
'action.aiDraftHint': 'E-mail tartalmának megírása MI-vel',
|
|
12
|
+
'action.code': 'Kód',
|
|
13
|
+
'action.codeHint': 'Nyers HTML szerkesztése élő előnézettel',
|
|
14
|
+
'action.preview': 'Előnézet',
|
|
15
|
+
'action.previewHint': 'E-mail előnézete',
|
|
16
|
+
'action.export': 'Exportálás',
|
|
17
|
+
'action.exportHint': 'E-mail exportálása',
|
|
18
|
+
'device.desktop': 'Asztali',
|
|
19
|
+
'device.desktopHint': 'Asztali szélesség',
|
|
20
|
+
'device.mobile': 'Mobil',
|
|
21
|
+
'device.mobileHint': 'Mobil szélesség',
|
|
22
|
+
'status.autosaveOn': 'automatikus mentés bekapcsolva',
|
|
23
|
+
'status.saved': 'mentve {time}',
|
|
24
|
+
'status.saveFailed': 'nem mentve — a tárhely megtelt',
|
|
25
|
+
'canvas.meta': '{rows} sor · {blocks} blokk · {width}px',
|
|
26
|
+
'tab.design': 'Stílus',
|
|
27
|
+
'tab.designHint': 'Kijelölés stílusa',
|
|
28
|
+
'tab.blocks': 'Blokkok',
|
|
29
|
+
'tab.blocksHint': 'Tartalomblokkok és változók',
|
|
30
|
+
'tab.rows': 'Szakaszok',
|
|
31
|
+
'tab.rowsHint': 'Szakaszelrendezések és a rajzvászon modellje',
|
|
32
|
+
'tab.files': 'Fájlok',
|
|
33
|
+
'tab.filesHint': 'Erőforrás-könyvtár',
|
|
34
|
+
'tab.layers': 'Struktúra',
|
|
35
|
+
'tab.layersHint': 'A dokumentum szerkezete',
|
|
36
|
+
'tab.settings': 'Beállítások',
|
|
37
|
+
'tab.settingsHint': 'E-mail beállításai',
|
|
38
|
+
'tab.data': 'Vált.',
|
|
39
|
+
'tab.dataHint': 'A kódod által biztosított változók',
|
|
40
|
+
'inspector.blockProperties': 'A blokk tulajdonságai',
|
|
41
|
+
'inspector.sectionProperties': 'A szakasz tulajdonságai',
|
|
42
|
+
'inspector.title': 'Vizsgáló',
|
|
43
|
+
'inspector.sectionLabel': 'Szakasz',
|
|
44
|
+
'inspector.nothingSelected': 'Nincs kijelölés',
|
|
45
|
+
'action.duplicateHint': 'Kettőzés — ⌘D',
|
|
46
|
+
'action.deleteHint': 'Törlés — ⌫',
|
|
47
|
+
'inspector.emptyBody':
|
|
48
|
+
'Válassz ki egy sort vagy blokkot a rajzvásznon, hogy itt formázhasd. Húzz blokkokat a <strong style="color: var(--ed-text); font-weight: 600;">Blokkok</strong> fülről; kattints duplán bármely szövegre a helyben szerkesztéshez.',
|
|
49
|
+
'inspector.shortcuts': 'Billentyűparancsok',
|
|
50
|
+
'shortcut.undoRedo': '⌘Z / ⌘⇧Z — visszavonás, ismétlés',
|
|
51
|
+
'shortcut.duplicate': '⌘D — kijelölés kettőzése',
|
|
52
|
+
'shortcut.delete': '⌫ — kijelölés törlése',
|
|
53
|
+
'shortcut.export': '⌘E — HTML exportálása',
|
|
54
|
+
'shortcut.escape': 'ESC — kijelölés megszüntetése, bezárás',
|
|
55
|
+
'blocks.dragHint': 'Húzd a rajzvászonra',
|
|
56
|
+
'blocks.count': '{count} blokk',
|
|
57
|
+
'rows.sectionLayouts': 'Szakaszelrendezések',
|
|
58
|
+
'rows.customMarkup': 'Egyéni kód',
|
|
59
|
+
'rows.htmlRowHint': 'Húzd be, vagy kattints a hozzáadáshoz — egy teljes szélességű sor, amelyet nyers HTML-lel töltesz meg',
|
|
60
|
+
'rows.rawHtmlSection': 'Nyers HTML szakasz',
|
|
61
|
+
'rows.rawHtmlDesc': 'Teljes szélességű szakasz, saját kódod, továbbra is húzható',
|
|
62
|
+
'rows.canvasModel': 'Rajzvászon modellje',
|
|
63
|
+
'rows.modeRowBased': 'Soralapú',
|
|
64
|
+
'rows.modeFreeStack': 'Szabad halmozás',
|
|
65
|
+
'rows.hintRows':
|
|
66
|
+
'Szakaszalapú: először helyezz el egy elrendezést, majd blokkokat az oszlopaiba — minden szakasznak saját háttere, kerete, flex vagy rács beállításai vannak.',
|
|
67
|
+
'rows.hintStack': 'Szabad halmozás: elrendezések nélkül — minden elhelyezett blokk saját teljes szélességű szakasszá válik, sorrendben egymásra halmozva.',
|
|
68
|
+
'files.libraryCount': 'Könyvtár — {count} fájl',
|
|
69
|
+
'files.openManager': 'Fájlkezelő megnyitása',
|
|
70
|
+
'files.dragToCanvas': 'Húzz bármely fájlt közvetlenül a rajzvászonra, hogy képblokként helyezd el.',
|
|
71
|
+
'layers.structure': 'Struktúra',
|
|
72
|
+
'layers.sectionSingle': 'Szakasz',
|
|
73
|
+
'layers.sectionMulti': 'Szakasz · {count} oszlop',
|
|
74
|
+
'layers.column': '{index}. oszlop',
|
|
75
|
+
'layers.blockCount': '{count} blokk',
|
|
76
|
+
'vars.title': 'Változók',
|
|
77
|
+
'vars.fromCode': '{count} a kódodból',
|
|
78
|
+
'vars.declaredNote': 'Az alkalmazásod deklarálta — a rajzvászon mindig a tokent mutatja, sosem az értéket.',
|
|
79
|
+
'vars.filterPlaceholder': 'Változók szűrése…',
|
|
80
|
+
'vars.insertHint': 'Kattints a kijelölt szövegbe, címsorba vagy gombba való beszúráshoz',
|
|
81
|
+
'vars.insert': 'beszúrás',
|
|
82
|
+
'vars.noMatch': 'Egyetlen változó sem felel meg ennek a szűrőnek.',
|
|
83
|
+
'vars.noneDeclared': 'Az alkalmazásod még nem deklarált változókat.',
|
|
84
|
+
'vars.rteHint': 'Szöveg szerkesztése közben egy változót közvetlenül a beágyazott eszköztár legördülő menüjéből is kiválaszthatsz.',
|
|
85
|
+
'modal.fileManager': 'Fájlkezelő',
|
|
86
|
+
'modal.assetsTitle': 'Erőforrások',
|
|
87
|
+
'modal.replaceImage': 'Kép cseréje',
|
|
88
|
+
'library.searchPlaceholder': 'Fájlok keresése…',
|
|
89
|
+
'action.upload': 'Feltöltés',
|
|
90
|
+
'library.clickToPlace': 'Kattints egy fájlra az elhelyezéshez · vagy húzz egy fájlt a rajzvászonra',
|
|
91
|
+
'library.clickToReplace': 'Kattints egy fájlra a kijelölt kép cseréjéhez',
|
|
92
|
+
'library.storageLabel': '{count} fájl · {size}',
|
|
93
|
+
'library.folders': 'Mappák',
|
|
94
|
+
'library.dropHint': 'Húzz ide képfájlokat a feltöltéshez — vagy használd a Feltöltés gombot.',
|
|
95
|
+
'library.deleteFileHint': 'Fájl törlése',
|
|
96
|
+
'library.del': 'TÖRL',
|
|
97
|
+
'toast.assetDeleted': '{name} törölve',
|
|
98
|
+
'library.allFiles': 'Összes fájl',
|
|
99
|
+
'library.loadMore': 'Továbbiak betöltése',
|
|
100
|
+
'library.empty': 'Itt még nincsenek fájlok.',
|
|
101
|
+
'storage.loading': 'Fájlok betöltése…',
|
|
102
|
+
'storage.uploading': '{count} feltöltése…',
|
|
103
|
+
'storage.errLoadFailed': 'A fájlkönyvtár nem tölthető be — {reason}',
|
|
104
|
+
'storage.errNoLimits': 'A feltöltés ki van kapcsolva: ez az alkalmazás nem állított be feltöltési korlátokat.',
|
|
105
|
+
'storage.errNoAccept': 'A feltöltés ki van kapcsolva: nincs engedélyezett fájlformátum.',
|
|
106
|
+
'storage.errNoMaxBytes': 'A feltöltés ki van kapcsolva: nincs beállítva maximális fájlméret.',
|
|
107
|
+
'storage.errTooLarge': 'A(z) {name} mérete {size} — a korlát {max}.',
|
|
108
|
+
'storage.errFormat': 'A(z) {name} egy {type} fájl, ami itt nem engedélyezett.',
|
|
109
|
+
'storage.errSvg': 'A(z) {name} egy SVG, amit ez az alkalmazás nem fogad el.',
|
|
110
|
+
'storage.errDimensions': 'A(z) {name} mérete {w}×{ht}px — a korlát {maxW}×{maxH}px.',
|
|
111
|
+
'storage.errTooMany': 'Egyszerre csak {max} fájl tölthető fel.',
|
|
112
|
+
'storage.errUnreadable': 'A(z) {name} nem olvasható kép.',
|
|
113
|
+
'storage.errUploadFailed': 'A(z) {name} nem tölthető fel — {reason}',
|
|
114
|
+
'storage.errDeleteFailed': 'A(z) {name} nem törölhető — {reason}',
|
|
115
|
+
'modal.export': 'Exportálás',
|
|
116
|
+
'modal.exportTitle': 'Táblázat alapú e-mail HTML',
|
|
117
|
+
'export.copy': 'Másolás',
|
|
118
|
+
'export.copied': 'Másolva',
|
|
119
|
+
'action.download': 'Letöltés',
|
|
120
|
+
'export.meta': '{kb} KB · táblázatok + soron belüli stílusok · Outlook-biztos szélességek',
|
|
121
|
+
'modal.rawHtmlTitle': 'Nyers HTML, élő előnézet',
|
|
122
|
+
'code.statusEdited': 'Kódnézet — szerkesztve — élő előnézet, még nincs alkalmazva',
|
|
123
|
+
'code.statusSynced': 'Kódnézet — szinkronban a rajzvászonnal',
|
|
124
|
+
'action.reload': 'Újratöltés',
|
|
125
|
+
'action.reloadHint': 'Forrás újratöltése a rajzvászonról',
|
|
126
|
+
'action.applyToCanvas': 'Alkalmazás a rajzvászonra',
|
|
127
|
+
'action.applyToCanvasHint': 'A forrás visszaalakítása szerkeszthető sorokká',
|
|
128
|
+
'action.closeWithoutApplyingHint': 'Bezárás alkalmazás nélkül',
|
|
129
|
+
'code.source': 'Forrás',
|
|
130
|
+
'code.livePreview': 'Élő előnézet',
|
|
131
|
+
'code.liveHtmlPreviewTitle': 'Élő HTML előnézet',
|
|
132
|
+
'code.applyNote':
|
|
133
|
+
'Az alkalmazás minden legfelső szintű táblázatsort egy rajzvászon-sorrá alakít, amelyet továbbra is kijelölhetsz, átrendezhetsz és törölhetsz — a kézzel írt kód sértetlenül éli túl a folyamatot.',
|
|
134
|
+
'code.meta': '{kb} KB · {lines} sor',
|
|
135
|
+
'toast.sourceReloaded': 'A forrás újratöltve a rajzvászonról',
|
|
136
|
+
'toast.sourceAppliedOne': 'Forrás alkalmazva — 1 sor a rajzvásznon',
|
|
137
|
+
'toast.sourceAppliedMany': 'Forrás alkalmazva — {rows} sor a rajzvásznon',
|
|
138
|
+
'toast.parseError': 'Nem sikerült elemezni ezt a HTML-t',
|
|
139
|
+
'modal.aiDraft': 'MI írássegéd',
|
|
140
|
+
'modal.aiDraftTitle': 'Írd meg az e-mailed MI-vel',
|
|
141
|
+
'ai.disclosure': 'Az MI a rövid leírásod alapján készít javaslatokat. Küldés előtt nézd át és szerkeszd az eredményt.',
|
|
142
|
+
'ai.goal': 'Cél',
|
|
143
|
+
'ai.tone': 'Hangnem',
|
|
144
|
+
'ai.briefLabel': 'Miről szól ez az e-mail?',
|
|
145
|
+
'ai.briefPlaceholder': 'pl. Őszi kollekció, 15% kedvezmény feliratkozóknak, ingyenes szállítás 150 000 Ft felett',
|
|
146
|
+
'ai.generate': 'Szöveg generálása',
|
|
147
|
+
'ai.writing': 'Írás…',
|
|
148
|
+
'ai.kindHeadline': 'Címsor',
|
|
149
|
+
'ai.kindBody': 'Törzsszöveg',
|
|
150
|
+
'ai.kindButton': 'Gomb szövege',
|
|
151
|
+
'ai.actionInsertHeading': 'Beszúrás címsorként',
|
|
152
|
+
'ai.actionInsertText': 'Beszúrás szövegblokként',
|
|
153
|
+
'ai.actionInsertButton': 'Beszúrás gombként',
|
|
154
|
+
'toast.headingAdded': 'Címsor hozzáadva',
|
|
155
|
+
'toast.textBlockAdded': 'Szövegblokk hozzáadva',
|
|
156
|
+
'toast.buttonAdded': 'Gomb hozzáadva',
|
|
157
|
+
'preview.kickerMobile': 'Előnézet — mobil 375px',
|
|
158
|
+
'preview.kickerDesktop': 'Előnézet — asztali {width}px',
|
|
159
|
+
'action.close': 'Bezárás',
|
|
160
|
+
'toast.duplicated': 'Kettőzve',
|
|
161
|
+
'toast.fileUploadedOne': '1 fájl feltöltve',
|
|
162
|
+
'toast.fileUploadedMany': '{count} fájl feltöltve',
|
|
163
|
+
'toast.imageReplaced': 'Kép kicserélve',
|
|
164
|
+
'toast.imageAdded': 'Kép hozzáadva a rajzvászonhoz',
|
|
165
|
+
'toast.htmlCopied': 'HTML a vágólapra másolva',
|
|
166
|
+
'toast.templateLoaded': '{name} betöltve',
|
|
167
|
+
'toast.snippetDefaultLabel': 'Részlet',
|
|
168
|
+
'toast.snippetInserted': '{name} beszúrva',
|
|
169
|
+
'toast.snippetCopied': '{name} másolva — jelölj ki egy szövegblokkot a beszúráshoz',
|
|
170
|
+
'rte.textStyle': 'Szövegstílus',
|
|
171
|
+
'rte.mergeTags': 'Egyesítési mezők',
|
|
172
|
+
'rte.noMergeTags': 'Nincs elérhető egyesítési mező',
|
|
173
|
+
'rte.textColor': 'Szöveg színe',
|
|
174
|
+
'rte.highlightColor': 'Kiemelés színe',
|
|
175
|
+
'rte.removeHighlight': 'Kiemelés eltávolítása',
|
|
176
|
+
'rte.clearFormatting': 'Formázás törlése',
|
|
177
|
+
'action.downloadPng': 'PNG letöltése',
|
|
178
|
+
'action.screenshot': 'Képernyőkép',
|
|
179
|
+
'action.screenshotHint': 'A teljes sablon megtekintése képként, majd letöltése',
|
|
180
|
+
'toast.pngSaved': 'Képernyőkép letöltve',
|
|
181
|
+
'toast.pngFailed': 'A képernyőkép nem sikerült — egy külső képet nem sikerült betölteni',
|
|
182
|
+
'toast.pngCopied': 'Képernyőkép a vágólapra másolva',
|
|
183
|
+
'toast.pngCopyFailed': 'Ez a böngésző nem fogadott el képet a vágólapon',
|
|
184
|
+
'story.kicker': 'Képernyőkép',
|
|
185
|
+
'story.rendering': 'A képernyőkép készül',
|
|
186
|
+
'story.renderingHint': 'Minden blokk 2×-es méretben rajzolódik — hosszú sablonnál ez eltart egy pillanatig.',
|
|
187
|
+
'story.failed': 'A képernyőkép nem sikerült',
|
|
188
|
+
'story.failedHint': 'A sablon egyik képét nem sikerült betölteni a rögzítéshez.',
|
|
189
|
+
'story.retry': 'Próbáld újra',
|
|
190
|
+
'story.play': 'Lejátszás',
|
|
191
|
+
'story.pause': 'Szünet',
|
|
192
|
+
'story.replay': 'Újrajátszás',
|
|
193
|
+
'story.copy': 'Másolás',
|
|
194
|
+
'story.meta': '{w}×{h} · {i}/{n} képernyő',
|
|
195
|
+
'footer.poweredBy': 'Működteti a SELISE Blocks © 2026',
|
|
196
|
+
};
|
package/src/core/i18n/index.js
CHANGED
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
import { EN as ENBase } from './en.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Builds a translator. `overrides` is whatever a host passes as `.messages`
|
|
5
|
-
* on the element -- a host's own table, an imported locale, or both merged
|
|
6
|
-
* via `defineMessages` below.
|
|
7
|
-
*
|
|
8
|
-
* Three deliberate properties:
|
|
9
|
-
* 1. English always resolves. A locale is an overlay, never a replacement,
|
|
10
|
-
* so a partial or missing translation shows English rather than a gap.
|
|
11
|
-
* 2. Params interpolate `{name}`.
|
|
12
|
-
* 3. A truly missing key (not in `overrides`, not in `EN`) renders as the
|
|
13
|
-
* key itself, not an empty string -- a visible `toast.deleted` in the UI
|
|
14
|
-
* is obviously wrong and names the exact key to add, where blank text
|
|
15
|
-
* just looks like a broken build.
|
|
16
|
-
*/
|
|
17
|
-
export function createTranslator(overrides) {
|
|
18
|
-
const table = overrides || {};
|
|
19
|
-
return function t(key, params) {
|
|
20
|
-
const template = table[key] ?? ENBase[key] ?? key;
|
|
21
|
-
if (!params) return template;
|
|
22
|
-
return template.replace(/\{(\w+)\}/g, (whole, name) => (name in params ? String(params[name]) : whole));
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** Merges a locale over a base, for a host assembling its own table -- the documented way to combine a shipped locale with a few product-specific overrides. */
|
|
27
|
-
export function defineMessages(base, overrides) {
|
|
28
|
-
return Object.assign({}, base, overrides);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** Keys in `base` that `locale` does not translate. What a translator has left to do. */
|
|
32
|
-
export function missingKeys(locale, base) {
|
|
33
|
-
const source = base || ENBase;
|
|
34
|
-
return Object.keys(source).filter((key) => locale[key] === undefined).sort();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Every locale that ships, for a host building a language switcher.
|
|
39
|
-
* Metadata only -- no message tables -- so listing the locales never pulls
|
|
40
|
-
* every translation file into a consumer's bundle; a host deep-imports the
|
|
41
|
-
* one it wants, e.g. `mailcraft-editor/src/core/i18n/bn.js`.
|
|
42
|
-
*/
|
|
43
|
-
export const LOCALES = [
|
|
44
|
-
{ tag: 'en', name: 'English' },
|
|
45
|
-
{ tag: 'ar', name: 'Arabic', rtl: true },
|
|
46
|
-
{ tag: 'bn', name: 'Bangla' },
|
|
47
|
-
{ tag: 'dz', name: 'Dzongkha' },
|
|
48
|
-
{ tag: 'bg', name: 'Bulgarian' },
|
|
49
|
-
{ tag: 'ca', name: 'Catalan' },
|
|
50
|
-
{ tag: 'cs', name: 'Czech' },
|
|
51
|
-
{ tag: 'da', name: 'Danish' },
|
|
52
|
-
{ tag: 'de', name: 'German' },
|
|
53
|
-
{ tag: 'de-CH', name: 'Swiss German' },
|
|
54
|
-
{ tag: 'el', name: 'Greek' },
|
|
55
|
-
{ tag: 'es', name: 'Spanish' },
|
|
56
|
-
{ tag: 'et', name: 'Estonian' },
|
|
57
|
-
{ tag: 'fi', name: 'Finnish' },
|
|
58
|
-
{ tag: 'fr', name: 'French' },
|
|
59
|
-
{ tag: 'hr', name: 'Croatian' },
|
|
60
|
-
{ tag: 'hu', name: 'Hungarian' },
|
|
61
|
-
{ tag: 'it', name: 'Italian' },
|
|
62
|
-
{ tag: 'lt', name: 'Lithuanian' },
|
|
63
|
-
{ tag: 'lv', name: 'Latvian' },
|
|
64
|
-
{ tag: 'nb', name: 'Norwegian Bokmål' },
|
|
65
|
-
{ tag: 'nl', name: 'Dutch' },
|
|
66
|
-
{ tag: 'pl', name: 'Polish' },
|
|
67
|
-
{ tag: 'pt', name: 'Portuguese' },
|
|
68
|
-
{ tag: 'ro', name: 'Romanian' },
|
|
69
|
-
{ tag: 'ru', name: 'Russian' },
|
|
70
|
-
{ tag: 'sk', name: 'Slovak' },
|
|
71
|
-
{ tag: 'sl', name: 'Slovenian' },
|
|
72
|
-
{ tag: 'sv', name: 'Swedish' },
|
|
73
|
-
{ tag: 'tr', name: 'Turkish' },
|
|
74
|
-
{ tag: 'uk', name: 'Ukrainian' },
|
|
75
|
-
];
|
|
76
|
-
|
|
77
|
-
/** `true` when the tag is written right to left. Metadata only -- `dir` is still what actually flips the layout. */
|
|
78
|
-
export function isRtl(tag) {
|
|
79
|
-
const entry = LOCALES.find((l) => l.tag === tag);
|
|
80
|
-
return entry ? entry.rtl === true : false;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export { EN, MESSAGE_KEYS } from './en.js';
|
|
1
|
+
import { EN as ENBase } from './en.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Builds a translator. `overrides` is whatever a host passes as `.messages`
|
|
5
|
+
* on the element -- a host's own table, an imported locale, or both merged
|
|
6
|
+
* via `defineMessages` below.
|
|
7
|
+
*
|
|
8
|
+
* Three deliberate properties:
|
|
9
|
+
* 1. English always resolves. A locale is an overlay, never a replacement,
|
|
10
|
+
* so a partial or missing translation shows English rather than a gap.
|
|
11
|
+
* 2. Params interpolate `{name}`.
|
|
12
|
+
* 3. A truly missing key (not in `overrides`, not in `EN`) renders as the
|
|
13
|
+
* key itself, not an empty string -- a visible `toast.deleted` in the UI
|
|
14
|
+
* is obviously wrong and names the exact key to add, where blank text
|
|
15
|
+
* just looks like a broken build.
|
|
16
|
+
*/
|
|
17
|
+
export function createTranslator(overrides) {
|
|
18
|
+
const table = overrides || {};
|
|
19
|
+
return function t(key, params) {
|
|
20
|
+
const template = table[key] ?? ENBase[key] ?? key;
|
|
21
|
+
if (!params) return template;
|
|
22
|
+
return template.replace(/\{(\w+)\}/g, (whole, name) => (name in params ? String(params[name]) : whole));
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Merges a locale over a base, for a host assembling its own table -- the documented way to combine a shipped locale with a few product-specific overrides. */
|
|
27
|
+
export function defineMessages(base, overrides) {
|
|
28
|
+
return Object.assign({}, base, overrides);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Keys in `base` that `locale` does not translate. What a translator has left to do. */
|
|
32
|
+
export function missingKeys(locale, base) {
|
|
33
|
+
const source = base || ENBase;
|
|
34
|
+
return Object.keys(source).filter((key) => locale[key] === undefined).sort();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Every locale that ships, for a host building a language switcher.
|
|
39
|
+
* Metadata only -- no message tables -- so listing the locales never pulls
|
|
40
|
+
* every translation file into a consumer's bundle; a host deep-imports the
|
|
41
|
+
* one it wants, e.g. `mailcraft-editor/src/core/i18n/bn.js`.
|
|
42
|
+
*/
|
|
43
|
+
export const LOCALES = [
|
|
44
|
+
{ tag: 'en', name: 'English' },
|
|
45
|
+
{ tag: 'ar', name: 'Arabic', rtl: true },
|
|
46
|
+
{ tag: 'bn', name: 'Bangla' },
|
|
47
|
+
{ tag: 'dz', name: 'Dzongkha' },
|
|
48
|
+
{ tag: 'bg', name: 'Bulgarian' },
|
|
49
|
+
{ tag: 'ca', name: 'Catalan' },
|
|
50
|
+
{ tag: 'cs', name: 'Czech' },
|
|
51
|
+
{ tag: 'da', name: 'Danish' },
|
|
52
|
+
{ tag: 'de', name: 'German' },
|
|
53
|
+
{ tag: 'de-CH', name: 'Swiss German' },
|
|
54
|
+
{ tag: 'el', name: 'Greek' },
|
|
55
|
+
{ tag: 'es', name: 'Spanish' },
|
|
56
|
+
{ tag: 'et', name: 'Estonian' },
|
|
57
|
+
{ tag: 'fi', name: 'Finnish' },
|
|
58
|
+
{ tag: 'fr', name: 'French' },
|
|
59
|
+
{ tag: 'hr', name: 'Croatian' },
|
|
60
|
+
{ tag: 'hu', name: 'Hungarian' },
|
|
61
|
+
{ tag: 'it', name: 'Italian' },
|
|
62
|
+
{ tag: 'lt', name: 'Lithuanian' },
|
|
63
|
+
{ tag: 'lv', name: 'Latvian' },
|
|
64
|
+
{ tag: 'nb', name: 'Norwegian Bokmål' },
|
|
65
|
+
{ tag: 'nl', name: 'Dutch' },
|
|
66
|
+
{ tag: 'pl', name: 'Polish' },
|
|
67
|
+
{ tag: 'pt', name: 'Portuguese' },
|
|
68
|
+
{ tag: 'ro', name: 'Romanian' },
|
|
69
|
+
{ tag: 'ru', name: 'Russian' },
|
|
70
|
+
{ tag: 'sk', name: 'Slovak' },
|
|
71
|
+
{ tag: 'sl', name: 'Slovenian' },
|
|
72
|
+
{ tag: 'sv', name: 'Swedish' },
|
|
73
|
+
{ tag: 'tr', name: 'Turkish' },
|
|
74
|
+
{ tag: 'uk', name: 'Ukrainian' },
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
/** `true` when the tag is written right to left. Metadata only -- `dir` is still what actually flips the layout. */
|
|
78
|
+
export function isRtl(tag) {
|
|
79
|
+
const entry = LOCALES.find((l) => l.tag === tag);
|
|
80
|
+
return entry ? entry.rtl === true : false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { EN, MESSAGE_KEYS } from './en.js';
|