@lokascript/i18n 2.5.0 → 2.6.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/dist/browser.cjs +1274 -154
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +3 -3
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +1274 -155
- package/dist/browser.js.map +1 -1
- package/dist/dictionaries/index.cjs +364 -133
- package/dist/dictionaries/index.cjs.map +1 -1
- package/dist/dictionaries/index.d.cts +1 -1
- package/dist/dictionaries/index.d.ts +1 -1
- package/dist/dictionaries/index.js +364 -133
- package/dist/dictionaries/index.js.map +1 -1
- package/dist/index.cjs +8860 -7740
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +8860 -7741
- package/dist/index.js.map +1 -1
- package/dist/lokascript-i18n.min.js +1 -1
- package/dist/lokascript-i18n.min.js.map +1 -1
- package/dist/lokascript-i18n.mjs +1697 -146
- package/dist/lokascript-i18n.mjs.map +1 -1
- package/dist/plugins/vite.cjs +359 -132
- package/dist/plugins/vite.cjs.map +1 -1
- package/dist/plugins/vite.js +359 -132
- package/dist/plugins/vite.js.map +1 -1
- package/dist/plugins/webpack.cjs +359 -132
- package/dist/plugins/webpack.cjs.map +1 -1
- package/dist/plugins/webpack.js +359 -132
- package/dist/plugins/webpack.js.map +1 -1
- package/dist/{transformer-BLv389qz.d.ts → transformer-BA8YX9u1.d.ts} +120 -2
- package/dist/{transformer-PFsYELrc.d.cts → transformer-DM7iplCU.d.cts} +120 -2
- package/dist/{types-BcALAO6h.d.cts → types-BYtpqGq3.d.cts} +1 -1
- package/dist/{types-BcALAO6h.d.ts → types-BYtpqGq3.d.ts} +1 -1
- package/package.json +6 -6
- package/src/browser.ts +1 -0
- package/src/command-primary-roles.test.ts +59 -0
- package/src/constants.ts +51 -0
- package/src/dictionaries/ar.ts +8 -3
- package/src/dictionaries/bn.ts +3 -1
- package/src/dictionaries/de.ts +19 -4
- package/src/dictionaries/derive.ts +4 -0
- package/src/dictionaries/en.ts +9 -0
- package/src/dictionaries/es.ts +2 -2
- package/src/dictionaries/fr.ts +6 -2
- package/src/dictionaries/he.ts +7 -1
- package/src/dictionaries/hi.ts +17 -10
- package/src/dictionaries/id.ts +15 -8
- package/src/dictionaries/it.ts +6 -3
- package/src/dictionaries/ja.ts +10 -4
- package/src/dictionaries/ko.ts +9 -4
- package/src/dictionaries/ms.ts +2 -1
- package/src/dictionaries/pl.ts +11 -3
- package/src/dictionaries/pt.ts +10 -4
- package/src/dictionaries/qu.ts +46 -22
- package/src/dictionaries/ru.ts +14 -7
- package/src/dictionaries/sw.ts +37 -10
- package/src/dictionaries/th.ts +3 -1
- package/src/dictionaries/tl.ts +14 -7
- package/src/dictionaries/tr.ts +22 -9
- package/src/dictionaries/uk.ts +13 -7
- package/src/dictionaries/vi.ts +3 -3
- package/src/dictionaries/zh.ts +10 -2
- package/src/examples/new-languages.ts +1 -1
- package/src/grammar/grammar.test.ts +1242 -1
- package/src/grammar/index.ts +1 -0
- package/src/grammar/profiles/index.ts +358 -12
- package/src/grammar/transformer.ts +1053 -16
- package/src/grammar/types.ts +22 -1
- package/src/index.ts +1 -0
- package/src/new-languages.test.ts +7 -3
- package/src/parser/parser-integration.test.ts +5 -1
- package/src/positional-keyword-drift.test.ts +138 -0
package/dist/browser.cjs
CHANGED
|
@@ -12,6 +12,28 @@ var ENGLISH_MODIFIER_ROLES = {
|
|
|
12
12
|
over: "duration",
|
|
13
13
|
for: "duration"
|
|
14
14
|
};
|
|
15
|
+
var COMMAND_PRIMARY_ROLES = {
|
|
16
|
+
set: "destination",
|
|
17
|
+
on: "event",
|
|
18
|
+
trigger: "event",
|
|
19
|
+
send: "event",
|
|
20
|
+
wait: "duration",
|
|
21
|
+
fetch: "source",
|
|
22
|
+
get: "source",
|
|
23
|
+
if: "condition",
|
|
24
|
+
unless: "condition",
|
|
25
|
+
while: "condition",
|
|
26
|
+
repeat: "loopType",
|
|
27
|
+
go: "destination",
|
|
28
|
+
scroll: "destination",
|
|
29
|
+
tell: "destination",
|
|
30
|
+
default: "destination",
|
|
31
|
+
swap: "destination",
|
|
32
|
+
// morph deliberately absent: its schema primaryRole is `patient` (the
|
|
33
|
+
// element being morphed — aligned with the transformer's patient marking
|
|
34
|
+
// in the session-9 role-layout swap), and patient is the default.
|
|
35
|
+
bind: "destination"
|
|
36
|
+
};
|
|
15
37
|
var ENGLISH_MODIFIERS = /* @__PURE__ */ new Set([
|
|
16
38
|
"to",
|
|
17
39
|
"from",
|
|
@@ -90,7 +112,14 @@ var ENGLISH_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
90
112
|
"transition",
|
|
91
113
|
"trigger",
|
|
92
114
|
"unless",
|
|
93
|
-
"wait"
|
|
115
|
+
"wait",
|
|
116
|
+
// v2.x reactive + realtime + service-worker DSL commands
|
|
117
|
+
"live",
|
|
118
|
+
"bind",
|
|
119
|
+
"eventsource",
|
|
120
|
+
"socket",
|
|
121
|
+
"worker",
|
|
122
|
+
"intercept"
|
|
94
123
|
]);
|
|
95
124
|
var ENGLISH_KEYWORDS = /* @__PURE__ */ new Set([
|
|
96
125
|
// Flow control
|
|
@@ -529,7 +558,8 @@ var es = {
|
|
|
529
558
|
swap: "intercambiar",
|
|
530
559
|
morph: "transformar",
|
|
531
560
|
settle: "estabilizar",
|
|
532
|
-
append: "
|
|
561
|
+
append: "anexar",
|
|
562
|
+
// profile primary; 'añadir' is add's word (parsed as add)
|
|
533
563
|
exit: "salir",
|
|
534
564
|
install: "instalar",
|
|
535
565
|
breakpoint: "punto-interrupci\xF3n",
|
|
@@ -662,7 +692,7 @@ var es = {
|
|
|
662
692
|
prev: "ant",
|
|
663
693
|
at: "en",
|
|
664
694
|
random: "aleatorio",
|
|
665
|
-
closest: "
|
|
695
|
+
closest: "cercano",
|
|
666
696
|
parent: "padre",
|
|
667
697
|
children: "hijos",
|
|
668
698
|
within: "dentro",
|
|
@@ -701,7 +731,8 @@ var ja = {
|
|
|
701
731
|
hide: "\u96A0\u3059",
|
|
702
732
|
show: "\u8868\u793A",
|
|
703
733
|
if: "\u3082\u3057",
|
|
704
|
-
unless: "\
|
|
734
|
+
unless: "\u306A\u3044\u9650\u308A",
|
|
735
|
+
// not でなければ — leading で particle shatters the marker
|
|
705
736
|
repeat: "\u7E70\u308A\u8FD4\u3057",
|
|
706
737
|
for: "\u305F\u3081\u306B",
|
|
707
738
|
while: "\u306E\u9593",
|
|
@@ -710,7 +741,7 @@ var ja = {
|
|
|
710
741
|
break: "\u4E2D\u65AD",
|
|
711
742
|
halt: "\u505C\u6B62",
|
|
712
743
|
wait: "\u5F85\u3064",
|
|
713
|
-
fetch: "\
|
|
744
|
+
fetch: "\u30D5\u30A7\u30C3\u30C1",
|
|
714
745
|
call: "\u547C\u3073\u51FA\u3057",
|
|
715
746
|
return: "\u623B\u308B",
|
|
716
747
|
make: "\u4F5C\u308B",
|
|
@@ -735,7 +766,11 @@ var ja = {
|
|
|
735
766
|
morph: "\u5909\u5F62",
|
|
736
767
|
settle: "\u5B89\u5B9A",
|
|
737
768
|
append: "\u672B\u5C3E\u8FFD\u52A0",
|
|
738
|
-
exit:
|
|
769
|
+
// 終了 → 退出: realigned to the semantic profile primary (ja.ts `exit: 退出`).
|
|
770
|
+
// 終了 was the historic exit/end collision word (see isEndKeyword's ja note);
|
|
771
|
+
// rendered as 終了 it tokenized as a plain identifier, so a guard-clause
|
|
772
|
+
// `exit` inside `if … end` never parsed (behavior-sortable ja).
|
|
773
|
+
exit: "\u9000\u51FA",
|
|
739
774
|
install: "\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB",
|
|
740
775
|
breakpoint: "\u30D6\u30EC\u30FC\u30AF\u30DD\u30A4\u30F3\u30C8",
|
|
741
776
|
clear: "\u30AF\u30EA\u30A2",
|
|
@@ -743,7 +778,8 @@ var ja = {
|
|
|
743
778
|
open: "\u958B\u304F",
|
|
744
779
|
select: "\u9078\u629E",
|
|
745
780
|
clone: "\u8907\u88FD",
|
|
746
|
-
prepend: "\u5148\u982D\u8FFD\u52A0"
|
|
781
|
+
prepend: "\u5148\u982D\u8FFD\u52A0",
|
|
782
|
+
socket: "\u30BD\u30B1\u30C3\u30C8"
|
|
747
783
|
},
|
|
748
784
|
modifiers: {
|
|
749
785
|
to: "\u306B",
|
|
@@ -792,7 +828,7 @@ var ja = {
|
|
|
792
828
|
touchcancel: "\u30BF\u30C3\u30C1\u30AD\u30E3\u30F3\u30BB\u30EB"
|
|
793
829
|
},
|
|
794
830
|
logical: {
|
|
795
|
-
when: "\
|
|
831
|
+
when: "\u6642",
|
|
796
832
|
where: "\u3069\u3053",
|
|
797
833
|
and: "\u305D\u3057\u3066",
|
|
798
834
|
or: "\u307E\u305F\u306F",
|
|
@@ -810,6 +846,7 @@ var ja = {
|
|
|
810
846
|
otherwise: "\u305D\u3046\u3067\u306A\u3051\u308C\u3070",
|
|
811
847
|
end: "\u7D42\u308F\u308A",
|
|
812
848
|
live: "\u30E9\u30A4\u30D6",
|
|
849
|
+
bind: "\u30D0\u30A4\u30F3\u30C9",
|
|
813
850
|
changes: "\u5909\u308F\u3063\u305F\u3089"
|
|
814
851
|
},
|
|
815
852
|
temporal: {
|
|
@@ -903,6 +940,9 @@ var fr = {
|
|
|
903
940
|
add: "ajouter",
|
|
904
941
|
remove: "supprimer",
|
|
905
942
|
toggle: "basculer",
|
|
943
|
+
// command blur (the events section has the blur EVENT word; without this
|
|
944
|
+
// entry the transformer fell back to it and no profile read it as the verb)
|
|
945
|
+
blur: "d\xE9focaliser",
|
|
906
946
|
hide: "cacher",
|
|
907
947
|
show: "montrer",
|
|
908
948
|
if: "si",
|
|
@@ -939,7 +979,8 @@ var fr = {
|
|
|
939
979
|
swap: "\xE9changer",
|
|
940
980
|
morph: "transformer",
|
|
941
981
|
settle: "stabiliser",
|
|
942
|
-
append: "
|
|
982
|
+
append: "annexer",
|
|
983
|
+
// profile primary; 'ajouter' is add's word (parsed as add)
|
|
943
984
|
exit: "sortir",
|
|
944
985
|
install: "installer",
|
|
945
986
|
breakpoint: "point-arr\xEAt",
|
|
@@ -948,7 +989,8 @@ var fr = {
|
|
|
948
989
|
open: "ouvrir",
|
|
949
990
|
select: "s\xE9lectionner",
|
|
950
991
|
clone: "cloner",
|
|
951
|
-
prepend: "pr\xE9fixer"
|
|
992
|
+
prepend: "pr\xE9fixer",
|
|
993
|
+
focus: "focaliser"
|
|
952
994
|
},
|
|
953
995
|
modifiers: {
|
|
954
996
|
to: "\xE0",
|
|
@@ -1072,7 +1114,7 @@ var fr = {
|
|
|
1072
1114
|
prev: "pr\xE9c",
|
|
1073
1115
|
at: "\xE0",
|
|
1074
1116
|
random: "al\xE9atoire",
|
|
1075
|
-
closest: "
|
|
1117
|
+
closest: "proche",
|
|
1076
1118
|
parent: "parent",
|
|
1077
1119
|
children: "enfants",
|
|
1078
1120
|
within: "dans",
|
|
@@ -1108,9 +1150,17 @@ var de = {
|
|
|
1108
1150
|
add: "hinzuf\xFCgen",
|
|
1109
1151
|
remove: "entfernen",
|
|
1110
1152
|
toggle: "umschalten",
|
|
1153
|
+
// command blur (the events section has the blur EVENT word; without this
|
|
1154
|
+
// entry the transformer fell back to it and no profile read it as the verb)
|
|
1155
|
+
blur: "defokussieren",
|
|
1111
1156
|
hide: "verstecken",
|
|
1112
1157
|
show: "zeigen",
|
|
1113
|
-
if
|
|
1158
|
+
// Align with the semantic German profile's `if` primary (`falls`). The previous
|
|
1159
|
+
// `wenn` collides with the profile's `when` keyword (German `wenn` = both
|
|
1160
|
+
// "if" and "when"), so a transformed `if` resolved to `when` and the conditional
|
|
1161
|
+
// wrapper never formed (`if`/`put` dropped). Same dict↔profile alignment as id
|
|
1162
|
+
// `toggle` / get-value. `when` is unaffected (separate dict entry).
|
|
1163
|
+
if: "falls",
|
|
1114
1164
|
unless: "wennnicht",
|
|
1115
1165
|
repeat: "wiederholen",
|
|
1116
1166
|
for: "f\xFCr",
|
|
@@ -1120,7 +1170,7 @@ var de = {
|
|
|
1120
1170
|
break: "unterbrechen",
|
|
1121
1171
|
halt: "anhalten",
|
|
1122
1172
|
wait: "warten",
|
|
1123
|
-
fetch: "
|
|
1173
|
+
fetch: "abrufen",
|
|
1124
1174
|
call: "aufrufen",
|
|
1125
1175
|
return: "zur\xFCckgeben",
|
|
1126
1176
|
make: "erstellen",
|
|
@@ -1148,12 +1198,14 @@ var de = {
|
|
|
1148
1198
|
exit: "beenden",
|
|
1149
1199
|
install: "installieren",
|
|
1150
1200
|
breakpoint: "haltepunkt",
|
|
1151
|
-
clear: "
|
|
1201
|
+
clear: "bereinigen",
|
|
1202
|
+
// löschen is a remove alternative in the profile
|
|
1152
1203
|
close: "schlie\xDFen",
|
|
1153
1204
|
open: "\xF6ffnen",
|
|
1154
1205
|
select: "ausw\xE4hlen",
|
|
1155
1206
|
clone: "klonen",
|
|
1156
|
-
prepend: "voranstellen"
|
|
1207
|
+
prepend: "voranstellen",
|
|
1208
|
+
focus: "fokussieren"
|
|
1157
1209
|
},
|
|
1158
1210
|
modifiers: {
|
|
1159
1211
|
to: "zu",
|
|
@@ -1277,7 +1329,13 @@ var de = {
|
|
|
1277
1329
|
prev: "vorh",
|
|
1278
1330
|
at: "bei",
|
|
1279
1331
|
random: "zuf\xE4llig",
|
|
1280
|
-
|
|
1332
|
+
// `nächste` already serves `next` (line above). German `nächste` is
|
|
1333
|
+
// genuinely ambiguous (next/nearest), so emitting it for `closest` too
|
|
1334
|
+
// collided: the semantic tokenizer normalizes `nächste`→next (a deliberate
|
|
1335
|
+
// last-wins choice — see german.ts), and a closest reading is impossible to
|
|
1336
|
+
// recover. Use the unambiguous `nächstgelegene` ("nearest-located") for
|
|
1337
|
+
// closest so the two readings stay distinct end-to-end.
|
|
1338
|
+
closest: "n\xE4chstgelegene",
|
|
1281
1339
|
parent: "elternteil",
|
|
1282
1340
|
children: "kinder",
|
|
1283
1341
|
within: "innerhalb",
|
|
@@ -1316,7 +1374,10 @@ var ar = {
|
|
|
1316
1374
|
hide: "\u0627\u062E\u0641",
|
|
1317
1375
|
show: "\u0627\u0638\u0647\u0631",
|
|
1318
1376
|
if: "\u0625\u0630\u0627",
|
|
1319
|
-
|
|
1377
|
+
// Single-token form: the semantic ar tokenizer splits the two-word `إلا إذا`
|
|
1378
|
+
// into `إلا` + `إذا`(if), which derails the `unless` block. `إلا` alone is the
|
|
1379
|
+
// conventional Arabic shorthand and matches the ar profile's unless keyword.
|
|
1380
|
+
unless: "\u0625\u0644\u0627",
|
|
1320
1381
|
repeat: "\u0643\u0631\u0631",
|
|
1321
1382
|
for: "\u0644\u0643\u0644",
|
|
1322
1383
|
while: "\u0628\u064A\u0646\u0645\u0627",
|
|
@@ -1346,19 +1407,22 @@ var ar = {
|
|
|
1346
1407
|
js: "\u062C\u0627\u0641\u0627\u0633\u0643\u0631\u0628\u062A",
|
|
1347
1408
|
async: "\u0645\u062A\u0632\u0627\u0645\u0646",
|
|
1348
1409
|
render: "\u0627\u0631\u0633\u0645",
|
|
1349
|
-
swap: "\u0628\u062F\
|
|
1410
|
+
swap: "\u0627\u0633\u062A\u0628\u062F\u0644",
|
|
1411
|
+
// profile primary; 'بدّل' is toggle's word (parsed as toggle)
|
|
1350
1412
|
morph: "\u062D\u0648\u0651\u0644",
|
|
1351
1413
|
settle: "\u0627\u0633\u062A\u0642\u0631",
|
|
1352
1414
|
append: "\u0623\u0644\u062D\u0642",
|
|
1353
1415
|
exit: "\u0627\u062E\u0631\u062C",
|
|
1354
1416
|
install: "\u062B\u0628\u0651\u062A",
|
|
1355
1417
|
breakpoint: "\u0646\u0642\u0637\u0629-\u062A\u0648\u0642\u0641",
|
|
1356
|
-
clear: "\
|
|
1418
|
+
clear: "\u0646\u0638\u0651\u0641",
|
|
1419
|
+
// امسح is a remove alternative in the profile
|
|
1357
1420
|
close: "\u0623\u063A\u0644\u0642",
|
|
1358
1421
|
open: "\u0627\u0641\u062A\u062D",
|
|
1359
1422
|
select: "\u0627\u062E\u062A\u0631",
|
|
1360
1423
|
clone: "\u0627\u0633\u062A\u0646\u0633\u062E",
|
|
1361
|
-
prepend: "\u0633\u0628\u0642"
|
|
1424
|
+
prepend: "\u0633\u0628\u0642",
|
|
1425
|
+
socket: "\u0645\u0642\u0628\u0633"
|
|
1362
1426
|
},
|
|
1363
1427
|
modifiers: {
|
|
1364
1428
|
to: "\u0625\u0644\u0649",
|
|
@@ -1425,6 +1489,7 @@ var ar = {
|
|
|
1425
1489
|
otherwise: "\u062E\u0644\u0627\u0641 \u0630\u0644\u0643",
|
|
1426
1490
|
end: "\u0627\u0644\u0646\u0647\u0627\u064A\u0629",
|
|
1427
1491
|
live: "\u062D\u064A",
|
|
1492
|
+
bind: "\u0627\u0631\u0628\u0637",
|
|
1428
1493
|
changes: "\u064A\u062A\u063A\u064A\u0631"
|
|
1429
1494
|
},
|
|
1430
1495
|
temporal: {
|
|
@@ -1521,9 +1586,11 @@ var ko = {
|
|
|
1521
1586
|
hide: "\uC228\uAE30\uB2E4",
|
|
1522
1587
|
show: "\uBCF4\uC774\uB2E4",
|
|
1523
1588
|
if: "\uB9CC\uC57D",
|
|
1524
|
-
unless: "\uC544\uB2C8\uBA74",
|
|
1589
|
+
unless: "\uC544\uB2C8\uB77C\uBA74",
|
|
1590
|
+
// distinct from else `아니면` (line ~131) — was a homonym
|
|
1525
1591
|
repeat: "\uBC18\uBCF5",
|
|
1526
|
-
for: "\
|
|
1592
|
+
for: "\uAC01\uAC01",
|
|
1593
|
+
// profile's for word — 동안 is while (collision)
|
|
1527
1594
|
while: "\uB3D9\uC548",
|
|
1528
1595
|
until: "\uAE4C\uC9C0",
|
|
1529
1596
|
continue: "\uACC4\uC18D",
|
|
@@ -1554,8 +1621,12 @@ var ko = {
|
|
|
1554
1621
|
swap: "\uAD50\uD658",
|
|
1555
1622
|
morph: "\uBCC0\uD615",
|
|
1556
1623
|
settle: "\uC548\uC815",
|
|
1557
|
-
append: "\
|
|
1558
|
-
|
|
1624
|
+
append: "\uB367\uBD99\uC774\uB2E4",
|
|
1625
|
+
// profile primary; '추가' is add's word (parsed as add)
|
|
1626
|
+
// 종료 → 나가기: realigned to the semantic profile primary (ko.ts `exit: 나가기`,
|
|
1627
|
+
// whose comment already flags the 종료 end-collision). Rendered as 종료 it
|
|
1628
|
+
// tokenized as a plain identifier, so a guard-clause `exit` never parsed.
|
|
1629
|
+
exit: "\uB098\uAC00\uAE30",
|
|
1559
1630
|
install: "\uC124\uCE58",
|
|
1560
1631
|
breakpoint: "\uC911\uB2E8\uC810",
|
|
1561
1632
|
clear: "\uC9C0\uC6B0\uAE30",
|
|
@@ -1563,7 +1634,8 @@ var ko = {
|
|
|
1563
1634
|
open: "\uC5F4\uAE30",
|
|
1564
1635
|
select: "\uC120\uD0DD",
|
|
1565
1636
|
clone: "\uBCF5\uC81C",
|
|
1566
|
-
prepend: "\uC55E\uC5D0\uCD94\uAC00"
|
|
1637
|
+
prepend: "\uC55E\uC5D0\uCD94\uAC00",
|
|
1638
|
+
socket: "\uC18C\uCF13"
|
|
1567
1639
|
},
|
|
1568
1640
|
modifiers: {
|
|
1569
1641
|
to: "\uC5D0",
|
|
@@ -1630,6 +1702,7 @@ var ko = {
|
|
|
1630
1702
|
otherwise: "\uADF8\uB807\uC9C0\uC54A\uC73C\uBA74",
|
|
1631
1703
|
end: "\uB05D",
|
|
1632
1704
|
live: "\uB77C\uC774\uBE0C",
|
|
1705
|
+
bind: "\uBC14\uC778\uB4DC",
|
|
1633
1706
|
changes: "\uBCC0\uACBD\uB418\uBA74"
|
|
1634
1707
|
},
|
|
1635
1708
|
temporal: {
|
|
@@ -1716,7 +1789,11 @@ var zh = {
|
|
|
1716
1789
|
tell: "\u544A\u8BC9",
|
|
1717
1790
|
trigger: "\u89E6\u53D1",
|
|
1718
1791
|
send: "\u53D1\u9001",
|
|
1719
|
-
take
|
|
1792
|
+
// `拿取` (the semantic zh profile's take primary), not `获取` — `获取` is the
|
|
1793
|
+
// profile's GET primary, so emitting it for take made `take …` parse as get
|
|
1794
|
+
// (take-class-from-siblings: phantom get, take dropped). Exposed by the get-zh-ba
|
|
1795
|
+
// pattern; same dict↔profile homonym family as pl get/fetch.
|
|
1796
|
+
take: "\u62FF\u53D6",
|
|
1720
1797
|
put: "\u653E\u7F6E",
|
|
1721
1798
|
set: "\u8BBE\u7F6E",
|
|
1722
1799
|
get: "\u83B7\u5F97",
|
|
@@ -1735,7 +1812,10 @@ var zh = {
|
|
|
1735
1812
|
break: "\u4E2D\u65AD",
|
|
1736
1813
|
halt: "\u505C\u6B62",
|
|
1737
1814
|
wait: "\u7B49\u5F85",
|
|
1738
|
-
|
|
1815
|
+
// 抓取 (zhuāqǔ, "grab/scrape") is the semantic zh profile's `fetch` primary;
|
|
1816
|
+
// 获取 (huòqǔ) is its `get` primary, so emitting 获取 here made the semantic
|
|
1817
|
+
// parser read a transformed `fetch` as `get`. See ZH_BLOCK_BODY_SCOPE.md #3.
|
|
1818
|
+
fetch: "\u6293\u53D6",
|
|
1739
1819
|
call: "\u8C03\u7528",
|
|
1740
1820
|
return: "\u8FD4\u56DE",
|
|
1741
1821
|
make: "\u5236\u4F5C",
|
|
@@ -1835,6 +1915,7 @@ var zh = {
|
|
|
1835
1915
|
otherwise: "\u8981\u4E0D\u7136",
|
|
1836
1916
|
end: "\u7ED3\u675F",
|
|
1837
1917
|
live: "\u5B9E\u65F6",
|
|
1918
|
+
bind: "\u7ED1\u5B9A",
|
|
1838
1919
|
changes: "\u6539\u53D8\u65F6"
|
|
1839
1920
|
},
|
|
1840
1921
|
temporal: {
|
|
@@ -1921,7 +2002,8 @@ var tr = {
|
|
|
1921
2002
|
tell: "s\xF6yle",
|
|
1922
2003
|
trigger: "tetikle",
|
|
1923
2004
|
send: "g\xF6nder",
|
|
1924
|
-
take: "
|
|
2005
|
+
take: "tut",
|
|
2006
|
+
// auditor: dict emitted a word the profile reads differently
|
|
1925
2007
|
put: "koy",
|
|
1926
2008
|
set: "ayarla",
|
|
1927
2009
|
get: "al",
|
|
@@ -1934,7 +2016,11 @@ var tr = {
|
|
|
1934
2016
|
unless: "de\u011Filse",
|
|
1935
2017
|
repeat: "tekrarla",
|
|
1936
2018
|
for: "i\xE7in",
|
|
1937
|
-
while
|
|
2019
|
+
// `süresince` (the semantic tr profile's while primary), not `iken`: `iken`
|
|
2020
|
+
// is the profile's WHEN primary (logical.when below also emits it), so a
|
|
2021
|
+
// fronted repeat-while head tokenized as `when` and the condition dropped
|
|
2022
|
+
// wholesale. Same dict↔profile homonym disambiguation as pl get/pobierz.
|
|
2023
|
+
while: "s\xFCresince",
|
|
1938
2024
|
until: "kadar",
|
|
1939
2025
|
continue: "devam",
|
|
1940
2026
|
break: "dur",
|
|
@@ -1964,7 +2050,8 @@ var tr = {
|
|
|
1964
2050
|
swap: "takas",
|
|
1965
2051
|
morph: "d\xF6n\xFC\u015Ft\xFCr",
|
|
1966
2052
|
settle: "sabitlen",
|
|
1967
|
-
append: "
|
|
2053
|
+
append: "ili\u015Ftir",
|
|
2054
|
+
// profile primary; 'ekle' is add's word (parsed as add)
|
|
1968
2055
|
exit: "\xE7\u0131k",
|
|
1969
2056
|
install: "kur",
|
|
1970
2057
|
breakpoint: "kesme-noktas\u0131",
|
|
@@ -1973,7 +2060,8 @@ var tr = {
|
|
|
1973
2060
|
open: "a\xE7",
|
|
1974
2061
|
select: "se\xE7",
|
|
1975
2062
|
clone: "klonla",
|
|
1976
|
-
prepend: "ba\u015F\u0131naekle"
|
|
2063
|
+
prepend: "ba\u015F\u0131naekle",
|
|
2064
|
+
socket: "soket"
|
|
1977
2065
|
},
|
|
1978
2066
|
modifiers: {
|
|
1979
2067
|
to: "e",
|
|
@@ -1996,8 +2084,11 @@ var tr = {
|
|
|
1996
2084
|
events: {
|
|
1997
2085
|
click: "t\u0131klama",
|
|
1998
2086
|
dblclick: "\xE7ift_t\u0131klama",
|
|
1999
|
-
|
|
2000
|
-
|
|
2087
|
+
// Fused (no `_`): the semantic tokenizer splits on `_`, breaking event
|
|
2088
|
+
// recognition (mousedown → "bas" / mouseup mis-captured). Mirrors the #535
|
|
2089
|
+
// ru/uk fuse + #510 resize fix.
|
|
2090
|
+
mousedown: "farebas",
|
|
2091
|
+
mouseup: "fareb\u0131rak",
|
|
2001
2092
|
mouseenter: "fare_gir",
|
|
2002
2093
|
mouseleave: "fare_\xE7\u0131k",
|
|
2003
2094
|
mouseover: "fare_\xFCst\xFC",
|
|
@@ -2014,7 +2105,7 @@ var tr = {
|
|
|
2014
2105
|
reset: "s\u0131f\u0131rla",
|
|
2015
2106
|
load: "y\xFCkle",
|
|
2016
2107
|
unload: "y\xFCkle_kald\u0131r",
|
|
2017
|
-
resize: "
|
|
2108
|
+
resize: "boyutland\u0131rma",
|
|
2018
2109
|
scroll: "kayd\u0131r",
|
|
2019
2110
|
touchstart: "dokunma_ba\u015Fla",
|
|
2020
2111
|
touchend: "dokunma_bitir",
|
|
@@ -2035,7 +2126,7 @@ var tr = {
|
|
|
2035
2126
|
equals: "e\u015Fittir",
|
|
2036
2127
|
has: "var",
|
|
2037
2128
|
have: "var",
|
|
2038
|
-
then: "
|
|
2129
|
+
then: "ard\u0131ndan",
|
|
2039
2130
|
else: "yoksa",
|
|
2040
2131
|
otherwise: "aksi_halde",
|
|
2041
2132
|
end: "son",
|
|
@@ -2091,13 +2182,18 @@ var tr = {
|
|
|
2091
2182
|
},
|
|
2092
2183
|
expressions: {
|
|
2093
2184
|
first: "ilk",
|
|
2094
|
-
|
|
2185
|
+
// 'son' is also the END keyword emission (block terminator), and the
|
|
2186
|
+
// parser's end-recognizers match it by value — so a positional `last`
|
|
2187
|
+
// emission of 'son' terminated the enclosing block mid-condition
|
|
2188
|
+
// (focus-trap's `eşleşir son <button/>` dropped the branch body; the sw
|
|
2189
|
+
// mwisho class). 'sonuncu' ("the last one") is unambiguous.
|
|
2190
|
+
last: "sonuncu",
|
|
2095
2191
|
next: "sonraki",
|
|
2096
2192
|
previous: "\xF6nceki",
|
|
2097
2193
|
prev: "\xF6nc",
|
|
2098
2194
|
at: "de",
|
|
2099
2195
|
random: "rastgele",
|
|
2100
|
-
closest: "
|
|
2196
|
+
closest: "enyak\u0131n",
|
|
2101
2197
|
parent: "ebeveyn",
|
|
2102
2198
|
children: "\xE7ocuklar",
|
|
2103
2199
|
within: "i\xE7inde",
|
|
@@ -2132,7 +2228,7 @@ var id = {
|
|
|
2132
2228
|
get: "dapatkan",
|
|
2133
2229
|
add: "tambah",
|
|
2134
2230
|
remove: "hapus",
|
|
2135
|
-
toggle: "
|
|
2231
|
+
toggle: "alihkan",
|
|
2136
2232
|
hide: "sembunyikan",
|
|
2137
2233
|
show: "tampilkan",
|
|
2138
2234
|
if: "jika",
|
|
@@ -2145,7 +2241,10 @@ var id = {
|
|
|
2145
2241
|
break: "hentikan",
|
|
2146
2242
|
halt: "berhenti",
|
|
2147
2243
|
wait: "tunggu",
|
|
2148
|
-
fetch
|
|
2244
|
+
// profile primary; 'ambil' is take's word — emitting it for fetch made every
|
|
2245
|
+
// fetch parse as take once the fused take-event pattern came alive (the de
|
|
2246
|
+
// holen/abrufen bug class)
|
|
2247
|
+
fetch: "muat",
|
|
2149
2248
|
call: "panggil",
|
|
2150
2249
|
return: "kembali",
|
|
2151
2250
|
make: "buat",
|
|
@@ -2154,7 +2253,11 @@ var id = {
|
|
|
2154
2253
|
catch: "tangkap",
|
|
2155
2254
|
measure: "ukur",
|
|
2156
2255
|
transition: "transisi",
|
|
2157
|
-
|
|
2256
|
+
// naikkan (raise), not tambahkan — tambahkan is the semantic profile's
|
|
2257
|
+
// `add` alternative, so emitting it made increment-counter parse as ADD
|
|
2258
|
+
// (the #373 collision family). naikkan is the profile's increment
|
|
2259
|
+
// alternative, pairing naturally with the decrement side.
|
|
2260
|
+
increment: "naikkan",
|
|
2158
2261
|
decrement: "kurangi",
|
|
2159
2262
|
default: "bawaan",
|
|
2160
2263
|
go: "pergi",
|
|
@@ -2165,15 +2268,20 @@ var id = {
|
|
|
2165
2268
|
beep: "bunyi",
|
|
2166
2269
|
js: "js",
|
|
2167
2270
|
async: "asinkron",
|
|
2168
|
-
render: "
|
|
2271
|
+
render: "olah",
|
|
2272
|
+
// auditor: dict emitted a word the profile reads differently
|
|
2169
2273
|
swap: "tukar",
|
|
2170
|
-
morph: "
|
|
2171
|
-
|
|
2172
|
-
|
|
2274
|
+
morph: "ubah",
|
|
2275
|
+
// auditor: dict emitted a word the profile reads differently
|
|
2276
|
+
settle: "stabilkan",
|
|
2277
|
+
// auditor: dict emitted a word the profile reads differently
|
|
2278
|
+
append: "sisipkan",
|
|
2279
|
+
// profile primary; 'tambah_akhir' splits and is unrecognized
|
|
2173
2280
|
exit: "keluar",
|
|
2174
2281
|
install: "pasang",
|
|
2175
2282
|
breakpoint: "titik-henti",
|
|
2176
|
-
clear: "
|
|
2283
|
+
clear: "bersihkan",
|
|
2284
|
+
// hapus is the remove PRIMARY in the profile
|
|
2177
2285
|
close: "tutup",
|
|
2178
2286
|
open: "buka",
|
|
2179
2287
|
select: "pilih",
|
|
@@ -2331,20 +2439,34 @@ var qu = {
|
|
|
2331
2439
|
tell: "niy",
|
|
2332
2440
|
trigger: "kichay",
|
|
2333
2441
|
send: "kachay",
|
|
2334
|
-
take: "
|
|
2442
|
+
take: "hapiy",
|
|
2443
|
+
// auditor: dict emitted a word the profile reads differently
|
|
2335
2444
|
put: "churay",
|
|
2336
|
-
set
|
|
2337
|
-
|
|
2445
|
+
// churay is the semantic qu profile's `put` primary; `set` is churanay. Emitting
|
|
2446
|
+
// churay for set made the semantic parser read a transformed `set` as `put`.
|
|
2447
|
+
// See ZH_BLOCK_BODY_SCOPE.md (#2 sweep — keyword realignment, cf. zh fetch).
|
|
2448
|
+
set: "churanay",
|
|
2449
|
+
// Align with the semantic quechua profile's `get` primary (`taripay`); the
|
|
2450
|
+
// previous `chaskiy` had no profile entry, so the transformed `get` dropped
|
|
2451
|
+
// (get-value parsed degenerate). Same dict↔profile alignment as id `toggle`.
|
|
2452
|
+
get: "taripay",
|
|
2338
2453
|
add: "yapay",
|
|
2339
2454
|
remove: "qichuy",
|
|
2340
2455
|
toggle: "tikray",
|
|
2341
2456
|
hide: "pakay",
|
|
2342
2457
|
show: "rikuchiy",
|
|
2343
2458
|
if: "sichus",
|
|
2344
|
-
unless: "
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2459
|
+
unless: "mana sichus",
|
|
2460
|
+
// spaced phrase ("if not"); `_` form split to `mana`+`sichus`(=if) at parse time
|
|
2461
|
+
repeat: "kutipay",
|
|
2462
|
+
for: "sapankaq",
|
|
2463
|
+
// profile's for word — rayku doubles as `by`
|
|
2464
|
+
// `kaykamaqa` (the semantic qu profile's while primary), not `kay_kaq`: the
|
|
2465
|
+
// `_` form is unknown to the profile (and `_` words split at parse time, cf.
|
|
2466
|
+
// qhipaman_yapay), so the fronted repeat-while head never formed a `while`
|
|
2467
|
+
// node — the condition dropped wholesale. Same dict↔profile alignment as
|
|
2468
|
+
// vi render / de abrufen.
|
|
2469
|
+
while: "kaykamaqa",
|
|
2348
2470
|
until: "hayk_akama",
|
|
2349
2471
|
continue: "purichiy",
|
|
2350
2472
|
break: "p_akiy",
|
|
@@ -2354,12 +2476,18 @@ var qu = {
|
|
|
2354
2476
|
call: "qayay",
|
|
2355
2477
|
return: "kutimuy",
|
|
2356
2478
|
make: "ruray",
|
|
2357
|
-
log
|
|
2479
|
+
// qillqay is the semantic qu profile's `copy` primary; `log` is qillqakuy.
|
|
2480
|
+
// Emitting qillqay for log made the parser read every transformed log as
|
|
2481
|
+
// copy (log-value/log-element/get-value lossy) — same realign as set above.
|
|
2482
|
+
log: "qillqakuy",
|
|
2358
2483
|
throw: "wikchuy",
|
|
2359
2484
|
catch: "hapsiy",
|
|
2360
2485
|
measure: "tupuy",
|
|
2361
|
-
|
|
2362
|
-
|
|
2486
|
+
// pasay, not tikray: the semantic qu profile's toggle keyword is
|
|
2487
|
+
// t'ikray/tikray, so a tikray render collided with toggle and the
|
|
2488
|
+
// transition command never anchored (sw kama precedent, #569).
|
|
2489
|
+
transition: "pasay",
|
|
2490
|
+
increment: "yapachiy",
|
|
2363
2491
|
decrement: "pisiyachiy",
|
|
2364
2492
|
default: "\xF1awpaq_kaq",
|
|
2365
2493
|
go: "riy",
|
|
@@ -2370,20 +2498,26 @@ var qu = {
|
|
|
2370
2498
|
beep: "waqay",
|
|
2371
2499
|
js: "js",
|
|
2372
2500
|
async: "mana_suyaspa",
|
|
2373
|
-
render: "
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2501
|
+
render: "rikurichiy",
|
|
2502
|
+
// auditor: dict emitted a word the profile reads differently
|
|
2503
|
+
swap: "t'inkuy",
|
|
2504
|
+
// profile primary; 'rantin_tikray' splits, 'tikray' is toggle's word
|
|
2505
|
+
morph: "tukunay",
|
|
2506
|
+
// auditor: dict emitted a word the profile reads differently
|
|
2507
|
+
settle: "tiyakuy",
|
|
2508
|
+
// auditor: dict emitted a word the profile reads differently
|
|
2509
|
+
append: "qatichiy",
|
|
2510
|
+
// profile's append primary (single token); `qhipaman_yapay` `_`-split to qhipaman+yapay(=add) at parse time
|
|
2378
2511
|
exit: "lluqsiy",
|
|
2379
|
-
install: "
|
|
2512
|
+
install: "tarpuy",
|
|
2380
2513
|
breakpoint: "sayachinay",
|
|
2381
2514
|
clear: "pichay",
|
|
2382
2515
|
close: "wichqay",
|
|
2383
2516
|
open: "kichay",
|
|
2384
2517
|
select: "akllay",
|
|
2385
2518
|
clone: "kikinchay",
|
|
2386
|
-
prepend: "\xF1awpachiy"
|
|
2519
|
+
prepend: "\xF1awpachiy",
|
|
2520
|
+
socket: "tinkina"
|
|
2387
2521
|
},
|
|
2388
2522
|
modifiers: {
|
|
2389
2523
|
to: "man",
|
|
@@ -2406,8 +2540,10 @@ var qu = {
|
|
|
2406
2540
|
events: {
|
|
2407
2541
|
click: "\xF1itiy",
|
|
2408
2542
|
dblclick: "iskay_\xF1itiy",
|
|
2409
|
-
|
|
2410
|
-
|
|
2543
|
+
// Fused (no `_`): the semantic tokenizer splits on `_` — and `rat_ñitiy` then
|
|
2544
|
+
// mis-captured as the `click` event (ñitiy→click). Mirrors the #535 ru/uk fuse.
|
|
2545
|
+
mousedown: "rat\xF1itiy",
|
|
2546
|
+
mouseup: "rathuqariy",
|
|
2411
2547
|
mouseenter: "rat_yaykuy",
|
|
2412
2548
|
mouseleave: "rat_lluqsiy",
|
|
2413
2549
|
mouseover: "rat_hawapi",
|
|
@@ -2446,7 +2582,11 @@ var qu = {
|
|
|
2446
2582
|
has: "kachkan",
|
|
2447
2583
|
have: "kachkani",
|
|
2448
2584
|
then: "chayqa",
|
|
2449
|
-
else
|
|
2585
|
+
// Align to the semantic profile's else word `manachus`. The old `mana_chayqa`
|
|
2586
|
+
// tokenized as `mana`(false) + `_` + `chayqa`(then) — no else keyword formed,
|
|
2587
|
+
// so qu conditionals never split their else branch. `manachus` is a single
|
|
2588
|
+
// token the profile-derived keyword map reads as `else` (dict↔profile align).
|
|
2589
|
+
else: "manachus",
|
|
2450
2590
|
otherwise: "huk_kaqpi",
|
|
2451
2591
|
end: "tukuy",
|
|
2452
2592
|
live: "kawsay",
|
|
@@ -2469,7 +2609,7 @@ var qu = {
|
|
|
2469
2609
|
values: {
|
|
2470
2610
|
true: "cheqaq",
|
|
2471
2611
|
false: "llulla",
|
|
2472
|
-
null: "
|
|
2612
|
+
null: "chusaq",
|
|
2473
2613
|
undefined: "mana_riqsisqa",
|
|
2474
2614
|
it: "chay",
|
|
2475
2615
|
its: "chaypaq",
|
|
@@ -2507,12 +2647,12 @@ var qu = {
|
|
|
2507
2647
|
prev: "\xF1awpaq",
|
|
2508
2648
|
at: "pi",
|
|
2509
2649
|
random: "imaymanata",
|
|
2510
|
-
closest: "
|
|
2650
|
+
closest: "kaylla",
|
|
2511
2651
|
parent: "mama_tayta",
|
|
2512
2652
|
children: "wawakuna",
|
|
2513
2653
|
within: "ukupi",
|
|
2514
2654
|
no: "mana_kanchu",
|
|
2515
|
-
empty: "
|
|
2655
|
+
empty: "chusaq",
|
|
2516
2656
|
some: "wakin",
|
|
2517
2657
|
"starts with": "qallarisqa wan",
|
|
2518
2658
|
"ends with": "tukusqa wan",
|
|
@@ -2538,11 +2678,17 @@ var sw = {
|
|
|
2538
2678
|
send: "tuma",
|
|
2539
2679
|
take: "chukua",
|
|
2540
2680
|
put: "weka",
|
|
2541
|
-
set
|
|
2681
|
+
// weka is the semantic sw profile's `put` primary; `set` is seti. Emitting weka
|
|
2682
|
+
// for set made the semantic parser read a transformed `set` as `put`.
|
|
2683
|
+
// See ZH_BLOCK_BODY_SCOPE.md (#2 sweep — keyword realignment, cf. zh fetch).
|
|
2684
|
+
set: "seti",
|
|
2542
2685
|
get: "pata",
|
|
2543
2686
|
add: "ongeza",
|
|
2544
2687
|
remove: "ondoa",
|
|
2545
2688
|
toggle: "badilisha",
|
|
2689
|
+
// command blur (the events section has the blur EVENT word; without this
|
|
2690
|
+
// entry the transformer fell back to it and no profile read it as the verb)
|
|
2691
|
+
blur: "blur",
|
|
2546
2692
|
hide: "ficha",
|
|
2547
2693
|
show: "onyesha",
|
|
2548
2694
|
if: "kama",
|
|
@@ -2558,13 +2704,14 @@ var sw = {
|
|
|
2558
2704
|
fetch: "leta",
|
|
2559
2705
|
call: "ita",
|
|
2560
2706
|
return: "rudi",
|
|
2561
|
-
make: "
|
|
2707
|
+
make: "tengeneza",
|
|
2708
|
+
// auditor: dict emitted a word the profile reads differently
|
|
2562
2709
|
log: "andika",
|
|
2563
2710
|
throw: "tupa",
|
|
2564
2711
|
catch: "shika",
|
|
2565
2712
|
measure: "pima",
|
|
2566
2713
|
transition: "mpito",
|
|
2567
|
-
increment: "
|
|
2714
|
+
increment: "ongezeko",
|
|
2568
2715
|
decrement: "punguza",
|
|
2569
2716
|
default: "msingi",
|
|
2570
2717
|
go: "nenda",
|
|
@@ -2577,18 +2724,23 @@ var sw = {
|
|
|
2577
2724
|
async: "sainkroni",
|
|
2578
2725
|
render: "chora",
|
|
2579
2726
|
swap: "badilishana",
|
|
2580
|
-
morph: "
|
|
2727
|
+
morph: "geuza",
|
|
2728
|
+
// auditor: dict emitted a word the profile reads differently
|
|
2581
2729
|
settle: "tulia",
|
|
2582
|
-
append: "
|
|
2730
|
+
append: "ambatanisha",
|
|
2731
|
+
// profile primary; 'ongezaMwisho' is unrecognized
|
|
2583
2732
|
exit: "toka",
|
|
2584
2733
|
install: "sakinisha",
|
|
2585
2734
|
breakpoint: "nukta-simama",
|
|
2586
|
-
clear: "
|
|
2735
|
+
clear: "safisha",
|
|
2736
|
+
// futa is a remove alternative in the profile
|
|
2587
2737
|
close: "funga",
|
|
2588
2738
|
open: "fungua",
|
|
2589
2739
|
select: "chagua",
|
|
2590
2740
|
clone: "nakili",
|
|
2591
|
-
prepend: "tanguliza"
|
|
2741
|
+
prepend: "tanguliza",
|
|
2742
|
+
focus: "lenga",
|
|
2743
|
+
socket: "soketi"
|
|
2592
2744
|
},
|
|
2593
2745
|
modifiers: {
|
|
2594
2746
|
to: "kwa",
|
|
@@ -2598,7 +2750,14 @@ var sw = {
|
|
|
2598
2750
|
at: "katika",
|
|
2599
2751
|
in: "ndani",
|
|
2600
2752
|
of: "ya",
|
|
2601
|
-
|
|
2753
|
+
// `kuwa` ("to be/become" — the conversion sense, cf. `badilisha kuwa`), not
|
|
2754
|
+
// `kama`: sw `kama` is the IF keyword (commands.if above and the semantic sw
|
|
2755
|
+
// profile's if primary), so emitting it for `as` grew a phantom `if` command
|
|
2756
|
+
// out of every transformed `as <Type>` tail (`kama JSON`, `kama Number`) when
|
|
2757
|
+
// the semantic parser split event-body statements. Same dict↔profile homonym
|
|
2758
|
+
// disambiguation as pl get/pobierz. The semantic fetch-sw pattern still
|
|
2759
|
+
// tolerates hand-written `kama` in as-marker position.
|
|
2760
|
+
as: "kuwa",
|
|
2602
2761
|
by: "na",
|
|
2603
2762
|
before: "kabla",
|
|
2604
2763
|
after: "baada",
|
|
@@ -2654,7 +2813,7 @@ var sw = {
|
|
|
2654
2813
|
else: "sivyo",
|
|
2655
2814
|
otherwise: "vinginevyo",
|
|
2656
2815
|
end: "mwisho",
|
|
2657
|
-
live: "
|
|
2816
|
+
live: "mubashara",
|
|
2658
2817
|
changes: "inabadilika"
|
|
2659
2818
|
},
|
|
2660
2819
|
temporal: {
|
|
@@ -2706,13 +2865,25 @@ var sw = {
|
|
|
2706
2865
|
},
|
|
2707
2866
|
expressions: {
|
|
2708
2867
|
first: "kwanza",
|
|
2709
|
-
|
|
2868
|
+
// 'mwisho' is the END keyword (block terminator) — the tokenizer's keyword
|
|
2869
|
+
// map is last-wins, so a positional `last` emission of 'mwisho' reads as
|
|
2870
|
+
// `end` and terminates the enclosing block mid-condition (focus-trap's
|
|
2871
|
+
// `… inafanana mwisho <button/>` dropped the whole branch body). Emit the
|
|
2872
|
+
// concatenated adjective form instead (wa mwisho — the saufsi/wennnicht/
|
|
2873
|
+
// enyakın single-token class); the tokenizer reads it as `last`.
|
|
2874
|
+
last: "wamwisho",
|
|
2710
2875
|
next: "ijayo",
|
|
2711
2876
|
previous: "iliyopita",
|
|
2712
2877
|
prev: "awali",
|
|
2713
2878
|
at: "katika",
|
|
2714
2879
|
random: "nasibu",
|
|
2715
|
-
|
|
2880
|
+
// Natural Swahili: `karibu` ("near/close") is the ordinary word and already
|
|
2881
|
+
// maps to closest. The earlier `karibu_zaidi` ("nearer") underscore-split to
|
|
2882
|
+
// karibu/_/zaidi (the stray `_ zaidi` broke positional capture); the fused
|
|
2883
|
+
// `karibuzaidi` parsed but isn't real Swahili. `karibu` alone is both natural
|
|
2884
|
+
// and correct (the sw tokenizer is single-word-only, so a spaced `karibu
|
|
2885
|
+
// zaidi` would strand `zaidi` regardless).
|
|
2886
|
+
closest: "karibu",
|
|
2716
2887
|
parent: "mzazi",
|
|
2717
2888
|
children: "watoto",
|
|
2718
2889
|
within: "ndani_ya",
|
|
@@ -2748,17 +2919,22 @@ var pt = {
|
|
|
2748
2919
|
add: "adicionar",
|
|
2749
2920
|
remove: "remover",
|
|
2750
2921
|
toggle: "alternar",
|
|
2922
|
+
// command blur (the events section has the blur EVENT word; without this
|
|
2923
|
+
// entry the transformer fell back to it and no profile read it as the verb)
|
|
2924
|
+
blur: "desfocar",
|
|
2751
2925
|
hide: "esconder",
|
|
2752
2926
|
show: "mostrar",
|
|
2753
2927
|
if: "se",
|
|
2754
|
-
unless: "
|
|
2928
|
+
unless: "salvo",
|
|
2929
|
+
// a_menos splits at _ in the pt extractor (see profile)
|
|
2755
2930
|
repeat: "repetir",
|
|
2756
2931
|
for: "para",
|
|
2757
2932
|
while: "enquanto",
|
|
2758
2933
|
until: "at\xE9",
|
|
2759
2934
|
continue: "continuar",
|
|
2760
|
-
|
|
2761
|
-
|
|
2935
|
+
// un-crossed: the profile/tokenizer read parar=halt, interromper=break
|
|
2936
|
+
break: "interromper",
|
|
2937
|
+
halt: "parar",
|
|
2762
2938
|
wait: "esperar",
|
|
2763
2939
|
fetch: "buscar",
|
|
2764
2940
|
call: "chamar",
|
|
@@ -2793,7 +2969,9 @@ var pt = {
|
|
|
2793
2969
|
open: "abrir",
|
|
2794
2970
|
select: "selecionar",
|
|
2795
2971
|
clone: "clonar",
|
|
2796
|
-
prepend: "preceder"
|
|
2972
|
+
prepend: "preceder",
|
|
2973
|
+
focus: "focar",
|
|
2974
|
+
socket: "soquete"
|
|
2797
2975
|
},
|
|
2798
2976
|
modifiers: {
|
|
2799
2977
|
to: "para",
|
|
@@ -2917,7 +3095,7 @@ var pt = {
|
|
|
2917
3095
|
prev: "ant",
|
|
2918
3096
|
at: "em",
|
|
2919
3097
|
random: "aleat\xF3rio",
|
|
2920
|
-
closest: "
|
|
3098
|
+
closest: "maispr\xF3ximo",
|
|
2921
3099
|
parent: "pai",
|
|
2922
3100
|
children: "filhos",
|
|
2923
3101
|
within: "dentro",
|
|
@@ -2956,7 +3134,7 @@ var it = {
|
|
|
2956
3134
|
hide: "nascondere",
|
|
2957
3135
|
show: "mostrare",
|
|
2958
3136
|
if: "se",
|
|
2959
|
-
unless: "
|
|
3137
|
+
unless: "salvo",
|
|
2960
3138
|
repeat: "ripetere",
|
|
2961
3139
|
for: "per",
|
|
2962
3140
|
while: "mentre",
|
|
@@ -2989,7 +3167,8 @@ var it = {
|
|
|
2989
3167
|
swap: "scambiare",
|
|
2990
3168
|
morph: "trasformare",
|
|
2991
3169
|
settle: "stabilizzare",
|
|
2992
|
-
append: "
|
|
3170
|
+
append: "accodare",
|
|
3171
|
+
// profile primary; 'aggiungere' is add's word (parsed as add)
|
|
2993
3172
|
exit: "uscire",
|
|
2994
3173
|
install: "installare",
|
|
2995
3174
|
breakpoint: "punto-interruzione",
|
|
@@ -2998,7 +3177,10 @@ var it = {
|
|
|
2998
3177
|
open: "aprire",
|
|
2999
3178
|
select: "selezionare",
|
|
3000
3179
|
clone: "clonare",
|
|
3001
|
-
prepend: "anteporre"
|
|
3180
|
+
prepend: "anteporre",
|
|
3181
|
+
// profile primary; without a commands entry the transformer fell back to
|
|
3182
|
+
// the EVENTS noun 'fuoco', which generated focus patterns can't match
|
|
3183
|
+
focus: "focalizzare"
|
|
3002
3184
|
},
|
|
3003
3185
|
modifiers: {
|
|
3004
3186
|
to: "a",
|
|
@@ -3122,7 +3304,7 @@ var it = {
|
|
|
3122
3304
|
prev: "prec",
|
|
3123
3305
|
at: "a",
|
|
3124
3306
|
random: "casuale",
|
|
3125
|
-
closest: "
|
|
3307
|
+
closest: "vicino",
|
|
3126
3308
|
parent: "genitore",
|
|
3127
3309
|
children: "figli",
|
|
3128
3310
|
within: "dentro",
|
|
@@ -3190,7 +3372,8 @@ var vi = {
|
|
|
3190
3372
|
beep: "beep",
|
|
3191
3373
|
js: "js",
|
|
3192
3374
|
async: "b\u1EA5t \u0111\u1ED3ng b\u1ED9",
|
|
3193
|
-
render: "
|
|
3375
|
+
render: "k\u1EBFt xu\u1EA5t",
|
|
3376
|
+
// distinct from `show` (was `hiển thị`, which collides with show: the semantic profile reads `hiển thị` as show, `kết xuất` as render)
|
|
3194
3377
|
swap: "ho\xE1n \u0111\u1ED5i",
|
|
3195
3378
|
morph: "bi\u1EBFn \u0111\u1ED5i",
|
|
3196
3379
|
settle: "\u1ED5n \u0111\u1ECBnh",
|
|
@@ -3205,7 +3388,8 @@ var vi = {
|
|
|
3205
3388
|
prepend: "th\xEAm \u0111\u1EA7u",
|
|
3206
3389
|
else: "kh\xF4ng th\xEC",
|
|
3207
3390
|
breakpoint: "\u0111i\u1EC3m-d\u1EEBng",
|
|
3208
|
-
clear: "
|
|
3391
|
+
clear: "t\u1EA9y",
|
|
3392
|
+
// xóa is the remove PRIMARY in the profile
|
|
3209
3393
|
close: "\u0111\xF3ng",
|
|
3210
3394
|
open: "m\u1EDF",
|
|
3211
3395
|
select: "ch\u1ECDn"
|
|
@@ -3269,7 +3453,7 @@ var vi = {
|
|
|
3269
3453
|
else: "kh\xF4ng th\xEC",
|
|
3270
3454
|
end: "k\u1EBFt th\xFAc",
|
|
3271
3455
|
then: "r\u1ED3i",
|
|
3272
|
-
live: "
|
|
3456
|
+
live: "live",
|
|
3273
3457
|
changes: "thay \u0111\u1ED5i"
|
|
3274
3458
|
},
|
|
3275
3459
|
temporal: {
|
|
@@ -3356,15 +3540,23 @@ var pl = {
|
|
|
3356
3540
|
commands: {
|
|
3357
3541
|
on: "gdy",
|
|
3358
3542
|
tell: "powiedz",
|
|
3359
|
-
trigger: "
|
|
3543
|
+
trigger: "wyzw\xF3l",
|
|
3544
|
+
// auditor: dict emitted a word the profile reads differently
|
|
3360
3545
|
send: "wy\u015Blij",
|
|
3361
3546
|
take: "we\u017A",
|
|
3362
3547
|
put: "umie\u015B\u0107",
|
|
3363
3548
|
set: "ustaw",
|
|
3364
|
-
get
|
|
3549
|
+
// `uzyskaj` (the semantic pl profile's get primary), not `pobierz`: pl `pobierz`
|
|
3550
|
+
// ("download") is the profile's FETCH primary, so emitting it for get made the
|
|
3551
|
+
// parser read every transformed get as fetch (get-value lossy + a phantom fetch).
|
|
3552
|
+
// Same dict↔profile homonym disambiguation as tr load/install, qu get.
|
|
3553
|
+
get: "uzyskaj",
|
|
3365
3554
|
add: "dodaj",
|
|
3366
3555
|
remove: "usu\u0144",
|
|
3367
3556
|
toggle: "prze\u0142\u0105cz",
|
|
3557
|
+
// command blur (the events section has the blur EVENT word; without this
|
|
3558
|
+
// entry the transformer fell back to it and no profile read it as the verb)
|
|
3559
|
+
blur: "rozmyj",
|
|
3368
3560
|
hide: "ukryj",
|
|
3369
3561
|
show: "poka\u017C",
|
|
3370
3562
|
if: "je\u015Bli",
|
|
@@ -3405,12 +3597,14 @@ var pl = {
|
|
|
3405
3597
|
exit: "wyjd\u017A",
|
|
3406
3598
|
install: "zainstaluj",
|
|
3407
3599
|
breakpoint: "punkt-przerwania",
|
|
3408
|
-
clear: "
|
|
3600
|
+
clear: "zeruj",
|
|
3601
|
+
// wyczyść is a remove alternative in the profile
|
|
3409
3602
|
close: "zamknij",
|
|
3410
3603
|
open: "otw\xF3rz",
|
|
3411
3604
|
select: "wybierz",
|
|
3412
3605
|
clone: "sklonuj",
|
|
3413
|
-
prepend: "poprzed\u017A"
|
|
3606
|
+
prepend: "poprzed\u017A",
|
|
3607
|
+
focus: "skup"
|
|
3414
3608
|
},
|
|
3415
3609
|
modifiers: {
|
|
3416
3610
|
to: "do",
|
|
@@ -3561,7 +3755,8 @@ var russianDictionary = {
|
|
|
3561
3755
|
commands: {
|
|
3562
3756
|
on: "\u043F\u0440\u0438",
|
|
3563
3757
|
tell: "\u0441\u043A\u0430\u0437\u0430\u0442\u044C",
|
|
3564
|
-
trigger: "\
|
|
3758
|
+
trigger: "\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C",
|
|
3759
|
+
// auditor: dict emitted a word the profile reads differently
|
|
3565
3760
|
send: "\u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C",
|
|
3566
3761
|
take: "\u0432\u0437\u044F\u0442\u044C",
|
|
3567
3762
|
put: "\u043F\u043E\u043B\u043E\u0436\u0438\u0442\u044C",
|
|
@@ -3572,8 +3767,12 @@ var russianDictionary = {
|
|
|
3572
3767
|
toggle: "\u043F\u0435\u0440\u0435\u043A\u043B\u044E\u0447\u0438\u0442\u044C",
|
|
3573
3768
|
hide: "\u0441\u043A\u0440\u044B\u0442\u044C",
|
|
3574
3769
|
show: "\u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C",
|
|
3770
|
+
// command verb; the events section keeps the noun прокрутка for `on scroll`.
|
|
3771
|
+
// Without this entry the transformer fell back to the event noun, which the
|
|
3772
|
+
// parser doesn't read as the scroll command (#321 focus family).
|
|
3773
|
+
scroll: "\u043F\u0440\u043E\u043A\u0440\u0443\u0442\u0438\u0442\u044C",
|
|
3575
3774
|
if: "\u0435\u0441\u043B\u0438",
|
|
3576
|
-
unless: "\
|
|
3775
|
+
unless: "\u043A\u0440\u043E\u043C\u0435",
|
|
3577
3776
|
repeat: "\u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C",
|
|
3578
3777
|
for: "\u0434\u043B\u044F",
|
|
3579
3778
|
while: "\u043F\u043E\u043A\u0430",
|
|
@@ -3606,10 +3805,12 @@ var russianDictionary = {
|
|
|
3606
3805
|
swap: "\u043F\u043E\u043C\u0435\u043D\u044F\u0442\u044C",
|
|
3607
3806
|
morph: "\u0442\u0440\u0430\u043D\u0441\u0444\u043E\u0440\u043C\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
3608
3807
|
settle: "\u0441\u0442\u0430\u0431\u0438\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
3609
|
-
append: "\u0434\u043E\
|
|
3808
|
+
append: "\u0434\u043E\u043F\u0438\u0441\u0430\u0442\u044C",
|
|
3809
|
+
// profile alternative; the compound splits and добавить parses as add
|
|
3610
3810
|
exit: "\u0432\u044B\u0439\u0442\u0438",
|
|
3611
3811
|
else: "\u0438\u043D\u0430\u0447\u0435",
|
|
3612
|
-
install: "\
|
|
3812
|
+
install: "\u0438\u043D\u0441\u0442\u0430\u043B\u043B\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
3813
|
+
// loanword — `установить` is `set` (homonym); see russian profile
|
|
3613
3814
|
init: "\u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
3614
3815
|
behavior: "\u043F\u043E\u0432\u0435\u0434\u0435\u043D\u0438\u0435",
|
|
3615
3816
|
focus: "\u0441\u0444\u043E\u043A\u0443\u0441\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
@@ -3644,8 +3845,11 @@ var russianDictionary = {
|
|
|
3644
3845
|
events: {
|
|
3645
3846
|
click: "\u043A\u043B\u0438\u043A",
|
|
3646
3847
|
dblclick: "\u0434\u0432\u043E\u0439\u043D\u043E\u0439_\u043A\u043B\u0438\u043A",
|
|
3647
|
-
|
|
3648
|
-
|
|
3848
|
+
// Fused (no `_`): the semantic tokenizer splits on `_`, so an underscore form
|
|
3849
|
+
// breaks event recognition (mousedown → bare expression). Mirrors the #510 tr
|
|
3850
|
+
// resize fix (boyut_değiştir → boyutlandırma) and the enyakın superlative.
|
|
3851
|
+
mousedown: "\u043C\u044B\u0448\u044C\u0432\u043D\u0438\u0437",
|
|
3852
|
+
mouseup: "\u043C\u044B\u0448\u044C\u0432\u0432\u0435\u0440\u0445",
|
|
3649
3853
|
mouseenter: "\u043C\u044B\u0448\u044C_\u0432\u0445\u043E\u0434",
|
|
3650
3854
|
mouseleave: "\u043C\u044B\u0448\u044C_\u0432\u044B\u0445\u043E\u0434",
|
|
3651
3855
|
mouseover: "\u043D\u0430\u0432\u0435\u0434\u0435\u043D\u0438\u0435",
|
|
@@ -3662,7 +3866,8 @@ var russianDictionary = {
|
|
|
3662
3866
|
reset: "\u0441\u0431\u0440\u043E\u0441",
|
|
3663
3867
|
load: "\u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0430",
|
|
3664
3868
|
unload: "\u0432\u044B\u0433\u0440\u0443\u0437\u043A\u0430",
|
|
3665
|
-
resize: "\u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\
|
|
3869
|
+
resize: "\u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435\u0440\u0430\u0437\u043C\u0435\u0440\u0430",
|
|
3870
|
+
// fused (no `_`) — see mousedown note above
|
|
3666
3871
|
scroll: "\u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0430",
|
|
3667
3872
|
touchstart: "\u043A\u0430\u0441\u0430\u043D\u0438\u0435_\u043D\u0430\u0447\u0430\u043B\u043E",
|
|
3668
3873
|
touchend: "\u043A\u0430\u0441\u0430\u043D\u0438\u0435_\u043A\u043E\u043D\u0435\u0446",
|
|
@@ -3792,7 +3997,8 @@ var ukrainianDictionary = {
|
|
|
3792
3997
|
commands: {
|
|
3793
3998
|
on: "\u043F\u0440\u0438",
|
|
3794
3999
|
tell: "\u0441\u043A\u0430\u0437\u0430\u0442\u0438",
|
|
3795
|
-
trigger: "\
|
|
4000
|
+
trigger: "\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0438",
|
|
4001
|
+
// auditor: dict emitted a word the profile reads differently
|
|
3796
4002
|
send: "\u043D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438",
|
|
3797
4003
|
take: "\u0432\u0437\u044F\u0442\u0438",
|
|
3798
4004
|
put: "\u043F\u043E\u043A\u043B\u0430\u0441\u0442\u0438",
|
|
@@ -3803,8 +4009,12 @@ var ukrainianDictionary = {
|
|
|
3803
4009
|
toggle: "\u043F\u0435\u0440\u0435\u043C\u043A\u043D\u0443\u0442\u0438",
|
|
3804
4010
|
hide: "\u0441\u0445\u043E\u0432\u0430\u0442\u0438",
|
|
3805
4011
|
show: "\u043F\u043E\u043A\u0430\u0437\u0430\u0442\u0438",
|
|
4012
|
+
// command verb; the events section keeps the noun прокрутка for `on scroll`.
|
|
4013
|
+
// Without this entry the transformer fell back to the event noun, which the
|
|
4014
|
+
// parser doesn't read as the scroll command (#321 focus family).
|
|
4015
|
+
scroll: "\u043F\u0440\u043E\u043A\u0440\u0443\u0442\u0438\u0442\u0438",
|
|
3806
4016
|
if: "\u044F\u043A\u0449\u043E",
|
|
3807
|
-
unless: "\
|
|
4017
|
+
unless: "\u043A\u0440\u0456\u043C",
|
|
3808
4018
|
repeat: "\u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0438",
|
|
3809
4019
|
for: "\u0434\u043B\u044F",
|
|
3810
4020
|
while: "\u043F\u043E\u043A\u0438",
|
|
@@ -3837,10 +4047,12 @@ var ukrainianDictionary = {
|
|
|
3837
4047
|
swap: "\u043F\u043E\u043C\u0456\u043D\u044F\u0442\u0438",
|
|
3838
4048
|
morph: "\u0442\u0440\u0430\u043D\u0441\u0444\u043E\u0440\u043C\u0443\u0432\u0430\u0442\u0438",
|
|
3839
4049
|
settle: "\u0441\u0442\u0430\u0431\u0456\u043B\u0456\u0437\u0443\u0432\u0430\u0442\u0438",
|
|
3840
|
-
append: "\u0434\u043E\
|
|
4050
|
+
append: "\u0434\u043E\u043F\u0438\u0441\u0430\u0442\u0438",
|
|
4051
|
+
// profile alternative; the compound splits and додати parses as add
|
|
3841
4052
|
exit: "\u0432\u0438\u0439\u0442\u0438",
|
|
3842
4053
|
else: "\u0456\u043D\u0430\u043A\u0448\u0435",
|
|
3843
|
-
install: "\
|
|
4054
|
+
install: "\u0456\u043D\u0441\u0442\u0430\u043B\u044E\u0432\u0430\u0442\u0438",
|
|
4055
|
+
// loanword — `встановити` is `set` (homonym); see ukrainian profile
|
|
3844
4056
|
init: "\u0456\u043D\u0456\u0446\u0456\u0430\u043B\u0456\u0437\u0443\u0432\u0430\u0442\u0438",
|
|
3845
4057
|
behavior: "\u043F\u043E\u0432\u0435\u0434\u0456\u043D\u043A\u0430",
|
|
3846
4058
|
focus: "\u0441\u0444\u043E\u043A\u0443\u0441\u0443\u0432\u0430\u0442\u0438",
|
|
@@ -3875,8 +4087,10 @@ var ukrainianDictionary = {
|
|
|
3875
4087
|
events: {
|
|
3876
4088
|
click: "\u043A\u043B\u0456\u043A",
|
|
3877
4089
|
dblclick: "\u043F\u043E\u0434\u0432\u0456\u0439\u043D\u0438\u0439_\u043A\u043B\u0456\u043A",
|
|
3878
|
-
|
|
3879
|
-
|
|
4090
|
+
// Fused (no `_`): the semantic tokenizer splits on `_`, so an underscore form
|
|
4091
|
+
// breaks event recognition. Mirrors the #510 tr resize fix + enyakın.
|
|
4092
|
+
mousedown: "\u043C\u0438\u0448\u0430\u0432\u043D\u0438\u0437",
|
|
4093
|
+
mouseup: "\u043C\u0438\u0448\u0430\u0432\u0433\u043E\u0440\u0443",
|
|
3880
4094
|
mouseenter: "\u043C\u0438\u0448\u0430_\u0432\u0445\u0456\u0434",
|
|
3881
4095
|
mouseleave: "\u043C\u0438\u0448\u0430_\u0432\u0438\u0445\u0456\u0434",
|
|
3882
4096
|
mouseover: "\u043D\u0430\u0432\u0435\u0434\u0435\u043D\u043D\u044F",
|
|
@@ -3893,7 +4107,8 @@ var ukrainianDictionary = {
|
|
|
3893
4107
|
reset: "\u0441\u043A\u0438\u0434\u0430\u043D\u043D\u044F",
|
|
3894
4108
|
load: "\u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F",
|
|
3895
4109
|
unload: "\u0432\u0438\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F",
|
|
3896
|
-
resize: "\u0437\u043C\u0456\u043D\
|
|
4110
|
+
resize: "\u0437\u043C\u0456\u043D\u0430\u0440\u043E\u0437\u043C\u0456\u0440\u0443",
|
|
4111
|
+
// fused (no `_`) — see mousedown note above
|
|
3897
4112
|
scroll: "\u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0430",
|
|
3898
4113
|
touchstart: "\u0434\u043E\u0442\u0438\u043A_\u043F\u043E\u0447\u0430\u0442\u043E\u043A",
|
|
3899
4114
|
touchend: "\u0434\u043E\u0442\u0438\u043A_\u043A\u0456\u043D\u0435\u0446\u044C",
|
|
@@ -4035,10 +4250,12 @@ var hindiDictionary = {
|
|
|
4035
4250
|
hide: "\u091B\u093F\u092A\u093E\u090F\u0902",
|
|
4036
4251
|
show: "\u0926\u093F\u0916\u093E\u090F\u0902",
|
|
4037
4252
|
if: "\u0905\u0917\u0930",
|
|
4038
|
-
unless: "\u091C\
|
|
4253
|
+
unless: "\u091C\u092C \u0924\u0915 \u0928\u0939\u0940\u0902",
|
|
4254
|
+
// spaced (not जब_तक_नहीं) → one multi-word `unless` token
|
|
4039
4255
|
repeat: "\u0926\u094B\u0939\u0930\u093E\u090F\u0902",
|
|
4040
|
-
for: "\
|
|
4041
|
-
|
|
4256
|
+
for: "\u0939\u0947\u0924\u0941",
|
|
4257
|
+
// single token — के_लिए splits at _ in the hi extractor
|
|
4258
|
+
while: "\u091C\u092C \u0924\u0915",
|
|
4042
4259
|
until: "\u0924\u0915",
|
|
4043
4260
|
continue: "\u091C\u093E\u0930\u0940",
|
|
4044
4261
|
break: "\u0930\u094B\u0915\u0947\u0902",
|
|
@@ -4065,10 +4282,10 @@ var hindiDictionary = {
|
|
|
4065
4282
|
js: "\u091C\u0947\u090F\u0938",
|
|
4066
4283
|
async: "\u0905\u0938\u093F\u0902\u0915",
|
|
4067
4284
|
render: "\u0930\u0947\u0902\u0921\u0930",
|
|
4068
|
-
swap: "\
|
|
4285
|
+
swap: "\u0935\u093F\u0928\u093F\u092E\u092F",
|
|
4069
4286
|
morph: "\u0930\u0942\u092A\u093E\u0902\u0924\u0930",
|
|
4070
4287
|
settle: "\u0938\u094D\u0925\u093F\u0930",
|
|
4071
|
-
append: "\
|
|
4288
|
+
append: "\u0938\u0902\u0932\u0917\u094D\u0928",
|
|
4072
4289
|
exit: "\u092C\u093E\u0939\u0930",
|
|
4073
4290
|
else: "\u0935\u0930\u0928\u093E",
|
|
4074
4291
|
install: "\u0907\u0902\u0938\u094D\u091F\u0949\u0932",
|
|
@@ -4082,7 +4299,8 @@ var hindiDictionary = {
|
|
|
4082
4299
|
clear: "\u0938\u093E\u092B\u093C-\u0915\u0930\u0947\u0902",
|
|
4083
4300
|
close: "\u092C\u0902\u0926-\u0915\u0930\u0947\u0902",
|
|
4084
4301
|
open: "\u0916\u094B\u0932\u0947\u0902",
|
|
4085
|
-
select: "\u091A\u0941\u0928\u0947\u0902"
|
|
4302
|
+
select: "\u091A\u0941\u0928\u0947\u0902",
|
|
4303
|
+
socket: "\u0938\u0949\u0915\u0947\u091F"
|
|
4086
4304
|
},
|
|
4087
4305
|
modifiers: {
|
|
4088
4306
|
to: "\u0915\u094B",
|
|
@@ -4094,8 +4312,8 @@ var hindiDictionary = {
|
|
|
4094
4312
|
of: "\u0915\u093E",
|
|
4095
4313
|
as: "\u0915\u0947_\u0930\u0942\u092A_\u092E\u0947\u0902",
|
|
4096
4314
|
by: "\u0926\u094D\u0935\u093E\u0930\u093E",
|
|
4097
|
-
before: "\u0938\
|
|
4098
|
-
after: "\u0915\
|
|
4315
|
+
before: "\u0938\u0947 \u092A\u0939\u0932\u0947",
|
|
4316
|
+
after: "\u0915\u0947 \u092C\u093E\u0926",
|
|
4099
4317
|
over: "\u0915\u0947_\u090A\u092A\u0930",
|
|
4100
4318
|
under: "\u0915\u0947_\u0928\u0940\u091A\u0947",
|
|
4101
4319
|
between: "\u0915\u0947_\u092C\u0940\u091A",
|
|
@@ -4106,8 +4324,10 @@ var hindiDictionary = {
|
|
|
4106
4324
|
events: {
|
|
4107
4325
|
click: "\u0915\u094D\u0932\u093F\u0915",
|
|
4108
4326
|
dblclick: "\u0921\u092C\u0932_\u0915\u094D\u0932\u093F\u0915",
|
|
4109
|
-
|
|
4110
|
-
|
|
4327
|
+
// Fused (no `_`): the semantic tokenizer splits on `_`, breaking event
|
|
4328
|
+
// recognition (mousedown → "नीचे"). Mirrors the #535 ru/uk fuse.
|
|
4329
|
+
mousedown: "\u092E\u093E\u0909\u0938\u0928\u0940\u091A\u0947",
|
|
4330
|
+
mouseup: "\u092E\u093E\u0909\u0938\u090A\u092A\u0930",
|
|
4111
4331
|
mouseenter: "\u092E\u093E\u0909\u0938_\u092A\u094D\u0930\u0935\u0947\u0936",
|
|
4112
4332
|
mouseleave: "\u092E\u093E\u0909\u0938_\u092C\u093E\u0939\u0930",
|
|
4113
4333
|
mouseover: "\u092E\u093E\u0909\u0938_\u0913\u0935\u0930",
|
|
@@ -4139,7 +4359,11 @@ var hindiDictionary = {
|
|
|
4139
4359
|
not: "\u0928\u0939\u0940\u0902",
|
|
4140
4360
|
is: "\u0939\u0948",
|
|
4141
4361
|
exists: "\u092E\u094C\u091C\u0942\u0926",
|
|
4142
|
-
|
|
4362
|
+
// Natural spaced phrase `मेल खाता` ("matches") — how Hindi writes it. The base
|
|
4363
|
+
// tokenizer now matches multi-word profile keywords, so the hindi profile maps
|
|
4364
|
+
// `मेल खाता`→matches without the underscore (`मेल_खाता` split) or the
|
|
4365
|
+
// concatenated `मेलखाता` (parsed, but unnatural) workarounds.
|
|
4366
|
+
matches: "\u092E\u0947\u0932 \u0916\u093E\u0924\u093E",
|
|
4143
4367
|
contains: "\u0936\u093E\u092E\u093F\u0932",
|
|
4144
4368
|
includes: "\u092E\u0947\u0902_\u0939\u0948",
|
|
4145
4369
|
equals: "\u092C\u0930\u093E\u092C\u0930",
|
|
@@ -4281,7 +4505,7 @@ var bengaliDictionary = {
|
|
|
4281
4505
|
throw: "\u09A8\u09BF\u0995\u09CD\u09B7\u09C7\u09AA",
|
|
4282
4506
|
continue: "\u099A\u09BE\u09B2\u09BF\u09AF\u09BC\u09C7 \u09AF\u09BE\u09A8",
|
|
4283
4507
|
make: "\u09A4\u09C8\u09B0\u09BF \u0995\u09B0\u09C1\u09A8",
|
|
4284
|
-
append: "\
|
|
4508
|
+
append: "\u099C\u09C1\u09A1\u09BC\u09C1\u09A8",
|
|
4285
4509
|
prepend: "\u09B6\u09C1\u09B0\u09C1\u09A4\u09C7 \u09AF\u09CB\u0997",
|
|
4286
4510
|
focus: "\u09AB\u09CB\u0995\u09BE\u09B8",
|
|
4287
4511
|
blur: "\u099D\u09BE\u09AA\u09B8\u09BE",
|
|
@@ -4309,7 +4533,8 @@ var bengaliDictionary = {
|
|
|
4309
4533
|
clear: "\u09AA\u09B0\u09BF\u09B7\u09CD\u0995\u09BE\u09B0",
|
|
4310
4534
|
close: "\u09AC\u09A8\u09CD\u09A7",
|
|
4311
4535
|
open: "\u0996\u09C1\u09B2\u09C1\u09A8",
|
|
4312
|
-
select: "\u09A8\u09BF\u09B0\u09CD\u09AC\u09BE\u099A\u09A8"
|
|
4536
|
+
select: "\u09A8\u09BF\u09B0\u09CD\u09AC\u09BE\u099A\u09A8",
|
|
4537
|
+
socket: "\u09B8\u0995\u09C7\u099F"
|
|
4313
4538
|
},
|
|
4314
4539
|
modifiers: {
|
|
4315
4540
|
to: "\u0995\u09C7",
|
|
@@ -4368,6 +4593,7 @@ var bengaliDictionary = {
|
|
|
4368
4593
|
end: "\u09B6\u09C7\u09B7",
|
|
4369
4594
|
then: "\u09A4\u09BE\u09B0\u09AA\u09B0",
|
|
4370
4595
|
live: "\u09B2\u09BE\u0987\u09AD",
|
|
4596
|
+
bind: "\u09AC\u09BE\u0987\u09A8\u09CD\u09A1",
|
|
4371
4597
|
changes: "\u09AA\u09B0\u09BF\u09AC\u09B0\u09CD\u09A4\u09BF\u09A4 \u09B9\u09B2\u09C7"
|
|
4372
4598
|
},
|
|
4373
4599
|
temporal: {
|
|
@@ -4467,7 +4693,9 @@ var thaiDictionary = {
|
|
|
4467
4693
|
prepend: "\u0E40\u0E1E\u0E34\u0E48\u0E21\u0E2B\u0E19\u0E49\u0E32",
|
|
4468
4694
|
focus: "\u0E42\u0E1F\u0E01\u0E31\u0E2A",
|
|
4469
4695
|
blur: "\u0E40\u0E1A\u0E25\u0E2D",
|
|
4470
|
-
|
|
4696
|
+
// เปลี่ยนผ่าน, not เปลี่ยน: the semantic th profile's `change` keyword is
|
|
4697
|
+
// เปลี่ยน, so a เปลี่ยน render could never anchor a transition command.
|
|
4698
|
+
transition: "\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E1C\u0E48\u0E32\u0E19",
|
|
4471
4699
|
settle: "\u0E04\u0E07\u0E17\u0E35\u0E48",
|
|
4472
4700
|
measure: "\u0E27\u0E31\u0E14",
|
|
4473
4701
|
async: "\u0E2D\u0E30\u0E0B\u0E34\u0E07\u0E04\u0E4C",
|
|
@@ -4674,10 +4902,13 @@ var malayDictionary = {
|
|
|
4674
4902
|
init: "mula",
|
|
4675
4903
|
clone: "klon",
|
|
4676
4904
|
breakpoint: "titik-henti",
|
|
4677
|
-
clear: "
|
|
4905
|
+
clear: "bersihkan",
|
|
4906
|
+
// padam is a remove alternative in the profile
|
|
4678
4907
|
close: "tutup",
|
|
4679
4908
|
open: "buka",
|
|
4680
|
-
select: "pilih"
|
|
4909
|
+
select: "pilih",
|
|
4910
|
+
socket: "soket"
|
|
4911
|
+
// derived from the ms profile (socket.primary); see generate-i18n-dictionaries
|
|
4681
4912
|
},
|
|
4682
4913
|
modifiers: {
|
|
4683
4914
|
to: "ke",
|
|
@@ -4854,10 +5085,14 @@ var tagalogDictionary = {
|
|
|
4854
5085
|
tell: "sabihin",
|
|
4855
5086
|
trigger: "palitawin",
|
|
4856
5087
|
send: "ipadala",
|
|
4857
|
-
take: "
|
|
5088
|
+
take: "kumuha",
|
|
5089
|
+
// auditor: dict emitted a word the profile reads differently
|
|
4858
5090
|
put: "ilagay",
|
|
4859
5091
|
set: "itakda",
|
|
4860
|
-
get
|
|
5092
|
+
// Align with the semantic tl profile's `get` primary (`kunin`); the previous
|
|
5093
|
+
// `kuhanin` is the base of fetch's `kuhanin_mula`, so the transformed `get`
|
|
5094
|
+
// dropped (get-value parsed degenerate). Same dict↔profile alignment as id `toggle`.
|
|
5095
|
+
get: "kunin",
|
|
4861
5096
|
add: "idagdag",
|
|
4862
5097
|
remove: "alisin",
|
|
4863
5098
|
toggle: "palitan",
|
|
@@ -4881,7 +5116,7 @@ var tagalogDictionary = {
|
|
|
4881
5116
|
throw: "ihagis",
|
|
4882
5117
|
catch: "hulihin",
|
|
4883
5118
|
measure: "sukatin",
|
|
4884
|
-
transition: "
|
|
5119
|
+
transition: "lumipat",
|
|
4885
5120
|
increment: "dagdagan",
|
|
4886
5121
|
decrement: "bawasan",
|
|
4887
5122
|
default: "pamantayan",
|
|
@@ -4893,10 +5128,13 @@ var tagalogDictionary = {
|
|
|
4893
5128
|
beep: "tunog",
|
|
4894
5129
|
js: "js",
|
|
4895
5130
|
async: "sabay",
|
|
4896
|
-
render: "
|
|
5131
|
+
render: "irender",
|
|
5132
|
+
// auditor: dict emitted a word the profile reads differently
|
|
4897
5133
|
swap: "palitan_pwesto",
|
|
4898
|
-
morph: "
|
|
4899
|
-
|
|
5134
|
+
morph: "baguhin",
|
|
5135
|
+
// auditor: dict emitted a word the profile reads differently
|
|
5136
|
+
settle: "magpatahimik",
|
|
5137
|
+
// auditor: dict emitted a word the profile reads differently
|
|
4900
5138
|
append: "idagdag_sa_dulo",
|
|
4901
5139
|
prepend: "idagdag_sa_simula",
|
|
4902
5140
|
exit: "lumabas",
|
|
@@ -4924,7 +5162,11 @@ var tagalogDictionary = {
|
|
|
4924
5162
|
as: "bilang",
|
|
4925
5163
|
by: "sa_pamamagitan_ng",
|
|
4926
5164
|
before: "bago",
|
|
4927
|
-
after:
|
|
5165
|
+
// `matapos` (not `pagkatapos`) for the positional "after": `pagkatapos` is
|
|
5166
|
+
// also Tagalog "then", so emitting it for the position modifier collides with
|
|
5167
|
+
// the sequence connector. `matapos` is the unambiguous positional form and
|
|
5168
|
+
// matches the semantic tl profile's `after`.
|
|
5169
|
+
after: "matapos",
|
|
4928
5170
|
over: "sa_ibabaw",
|
|
4929
5171
|
under: "sa_ilalim",
|
|
4930
5172
|
between: "sa_pagitan",
|
|
@@ -5090,6 +5332,8 @@ var he = {
|
|
|
5090
5332
|
beep: "\u05D1\u05D9\u05E4",
|
|
5091
5333
|
break: "\u05E9\u05D1\u05D5\u05E8",
|
|
5092
5334
|
call: "\u05E7\u05E8\u05D0",
|
|
5335
|
+
clear: "\u05E0\u05E7\u05D4",
|
|
5336
|
+
// profile's clear word — was untranslated (parsed as nothing)
|
|
5093
5337
|
continue: "\u05D4\u05DE\u05E9\u05DA",
|
|
5094
5338
|
copy: "\u05D4\u05E2\u05EA\u05E7",
|
|
5095
5339
|
decrement: "\u05D4\u05E7\u05D8\u05DF",
|
|
@@ -5102,6 +5346,7 @@ var he = {
|
|
|
5102
5346
|
halt: "\u05E2\u05E6\u05D5\u05E8",
|
|
5103
5347
|
hide: "\u05D4\u05E1\u05EA\u05E8",
|
|
5104
5348
|
if: "\u05D0\u05DD",
|
|
5349
|
+
unless: "\u05D0\u05DC\u05D0",
|
|
5105
5350
|
increment: "\u05D4\u05D2\u05D3\u05DC",
|
|
5106
5351
|
install: "\u05D4\u05EA\u05E7\u05DF",
|
|
5107
5352
|
js: "js",
|
|
@@ -5116,6 +5361,7 @@ var he = {
|
|
|
5116
5361
|
render: "\u05E8\u05E0\u05D3\u05E8",
|
|
5117
5362
|
repeat: "\u05D7\u05D6\u05D5\u05E8",
|
|
5118
5363
|
return: "\u05D4\u05D7\u05D6\u05E8",
|
|
5364
|
+
scroll: "\u05D2\u05DC\u05D5\u05DC",
|
|
5119
5365
|
send: "\u05E9\u05DC\u05D7",
|
|
5120
5366
|
set: "\u05E7\u05D1\u05E2",
|
|
5121
5367
|
settle: "\u05D4\u05EA\u05D9\u05D9\u05E6\u05D1",
|
|
@@ -5153,6 +5399,7 @@ var he = {
|
|
|
5153
5399
|
end: "\u05E1\u05D5\u05E3",
|
|
5154
5400
|
then: "\u05D0\u05D6",
|
|
5155
5401
|
live: "\u05D7\u05D9",
|
|
5402
|
+
bind: "\u05E7\u05E9\u05D5\u05E8",
|
|
5156
5403
|
changes: "\u05DE\u05E9\u05EA\u05E0\u05D4",
|
|
5157
5404
|
when: "\u05DB\u05D0\u05E9\u05E8",
|
|
5158
5405
|
where: "\u05D0\u05D9\u05E4\u05D4"
|
|
@@ -5171,7 +5418,9 @@ var he = {
|
|
|
5171
5418
|
your: "\u05E9\u05DC\u05DA"
|
|
5172
5419
|
},
|
|
5173
5420
|
attributes: {},
|
|
5174
|
-
expressions: {
|
|
5421
|
+
expressions: {
|
|
5422
|
+
last: "\u05D0\u05D7\u05E8\u05D5\u05DF"
|
|
5423
|
+
}
|
|
5175
5424
|
};
|
|
5176
5425
|
|
|
5177
5426
|
// src/parser/he.ts
|
|
@@ -5352,6 +5601,13 @@ var en = {
|
|
|
5352
5601
|
increment: "increment",
|
|
5353
5602
|
decrement: "decrement",
|
|
5354
5603
|
default: "default",
|
|
5604
|
+
// Reactivity Commands
|
|
5605
|
+
bind: "bind",
|
|
5606
|
+
// Realtime / service-worker Commands
|
|
5607
|
+
eventsource: "eventsource",
|
|
5608
|
+
socket: "socket",
|
|
5609
|
+
worker: "worker",
|
|
5610
|
+
intercept: "intercept",
|
|
5355
5611
|
// Navigation Commands
|
|
5356
5612
|
go: "go",
|
|
5357
5613
|
pushUrl: "pushUrl",
|
|
@@ -5789,7 +6045,13 @@ function reorderRoles(roles, targetOrder) {
|
|
|
5789
6045
|
function insertMarkers(elements, markers, adpositionType) {
|
|
5790
6046
|
const result = [];
|
|
5791
6047
|
for (const element of elements) {
|
|
5792
|
-
|
|
6048
|
+
let marker = markers.find((m) => m.role === element.role);
|
|
6049
|
+
if (marker?.role === "event" && /^[#.<@[]/.test(element.translated || element.value)) {
|
|
6050
|
+
marker = void 0;
|
|
6051
|
+
}
|
|
6052
|
+
if (marker?.role === "duration" && /^(me|you|it)$/i.test(element.value)) {
|
|
6053
|
+
marker = void 0;
|
|
6054
|
+
}
|
|
5793
6055
|
if (marker) {
|
|
5794
6056
|
if (adpositionType === "preposition") {
|
|
5795
6057
|
if (marker.form) result.push(marker.form);
|
|
@@ -5913,6 +6175,41 @@ var japaneseProfile = {
|
|
|
5913
6175
|
roleOrder: ["patient", "destination", "action"],
|
|
5914
6176
|
insertMarkers: true
|
|
5915
6177
|
}
|
|
6178
|
+
},
|
|
6179
|
+
{
|
|
6180
|
+
name: "set-to",
|
|
6181
|
+
description: "Transform set X to Y to Japanese verb-final order",
|
|
6182
|
+
priority: 90,
|
|
6183
|
+
match: {
|
|
6184
|
+
commands: ["set", "\u8A2D\u5B9A"],
|
|
6185
|
+
requiredRoles: ["action", "patient", "destination"],
|
|
6186
|
+
// Skip a set whose value swept up a trailing block terminator (`set X to Y
|
|
6187
|
+
// end` — the body of an inline `if … then set … end`): verb-final reorder
|
|
6188
|
+
// would push the verb past `end` and break the block. These parse fine
|
|
6189
|
+
// verb-medial (the default).
|
|
6190
|
+
predicate: (parsed) => !/(^|\s)end$/i.test((parsed.original ?? "").trim())
|
|
6191
|
+
},
|
|
6192
|
+
transform: {
|
|
6193
|
+
// X を Y に 設定 — verb-final, matching the generated SOV set pattern
|
|
6194
|
+
// (markerOverride: を on the destination / に on the value). Default reorder
|
|
6195
|
+
// emitted verb-MEDIAL (`X を 設定 Y に`), unmatched by any set pattern.
|
|
6196
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6197
|
+
insertMarkers: true
|
|
6198
|
+
}
|
|
6199
|
+
},
|
|
6200
|
+
{
|
|
6201
|
+
name: "bind-to",
|
|
6202
|
+
description: "Transform bind $var to #el to Japanese verb-final order",
|
|
6203
|
+
priority: 90,
|
|
6204
|
+
match: {
|
|
6205
|
+
commands: ["bind", "\u30D0\u30A4\u30F3\u30C9"],
|
|
6206
|
+
requiredRoles: ["action", "patient", "destination"]
|
|
6207
|
+
},
|
|
6208
|
+
transform: {
|
|
6209
|
+
// $var を #el に バインド
|
|
6210
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6211
|
+
insertMarkers: true
|
|
6212
|
+
}
|
|
5916
6213
|
}
|
|
5917
6214
|
]
|
|
5918
6215
|
};
|
|
@@ -5929,6 +6226,10 @@ var koreanProfile = {
|
|
|
5929
6226
|
{ form: "\uB97C", role: "patient", position: "postposition", required: true, alternatives: ["\uC744"] },
|
|
5930
6227
|
{ form: "\uC5D0", role: "destination", position: "postposition", required: true },
|
|
5931
6228
|
{ form: "\uC5D0\uC11C", role: "source", position: "postposition", required: true },
|
|
6229
|
+
// Event marker — the semantic *-event-ko-sov-* patterns anchor on 할 때
|
|
6230
|
+
// (the generator profile's eventMarker); without it every ko handler
|
|
6231
|
+
// emitted a bare event name no fused pattern could anchor.
|
|
6232
|
+
{ form: "\uD560 \uB54C", role: "event", position: "postposition", required: true },
|
|
5932
6233
|
{
|
|
5933
6234
|
form: "\uB85C",
|
|
5934
6235
|
role: "style",
|
|
@@ -5959,6 +6260,56 @@ var koreanProfile = {
|
|
|
5959
6260
|
roleOrder: ["patient", "event", "action"],
|
|
5960
6261
|
insertMarkers: true
|
|
5961
6262
|
}
|
|
6263
|
+
},
|
|
6264
|
+
{
|
|
6265
|
+
name: "put-into",
|
|
6266
|
+
description: "Transform put X into Y to Korean verb-final order",
|
|
6267
|
+
priority: 90,
|
|
6268
|
+
match: {
|
|
6269
|
+
commands: ["put", "\uB123\uB2E4"],
|
|
6270
|
+
requiredRoles: ["action", "patient", "destination"],
|
|
6271
|
+
// Standalone put only (e.g. a then-chain clause): an event handler whose
|
|
6272
|
+
// action is `put` must keep the event mid-stream, so don't verb-final it.
|
|
6273
|
+
predicate: (parsed) => !parsed.roles.has("event")
|
|
6274
|
+
},
|
|
6275
|
+
transform: {
|
|
6276
|
+
// X 를 Y 에 넣다 (patient, destination, verb-last)
|
|
6277
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6278
|
+
insertMarkers: true
|
|
6279
|
+
}
|
|
6280
|
+
},
|
|
6281
|
+
{
|
|
6282
|
+
name: "set-to",
|
|
6283
|
+
description: "Transform set X to Y to Korean verb-final order",
|
|
6284
|
+
priority: 90,
|
|
6285
|
+
match: {
|
|
6286
|
+
commands: ["set", "\uC124\uC815"],
|
|
6287
|
+
requiredRoles: ["action", "patient", "destination"],
|
|
6288
|
+
// Skip a set whose value swept up a trailing block terminator (`set X to Y
|
|
6289
|
+
// end` — the body of an inline `if … then set … end`): verb-final reorder
|
|
6290
|
+
// would push the verb past `end` and break the block. These parse fine
|
|
6291
|
+
// verb-medial (the default).
|
|
6292
|
+
predicate: (parsed) => !/(^|\s)end$/i.test((parsed.original ?? "").trim())
|
|
6293
|
+
},
|
|
6294
|
+
transform: {
|
|
6295
|
+
// X 를 Y 에 설정 — verb-final, matching the generated SOV set pattern.
|
|
6296
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6297
|
+
insertMarkers: true
|
|
6298
|
+
}
|
|
6299
|
+
},
|
|
6300
|
+
{
|
|
6301
|
+
name: "bind-to",
|
|
6302
|
+
description: "Transform bind $var to #el to Korean verb-final order",
|
|
6303
|
+
priority: 90,
|
|
6304
|
+
match: {
|
|
6305
|
+
commands: ["bind", "\uBC14\uC778\uB4DC"],
|
|
6306
|
+
requiredRoles: ["action", "patient", "destination"]
|
|
6307
|
+
},
|
|
6308
|
+
transform: {
|
|
6309
|
+
// $var 를 #el 에 바인드
|
|
6310
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6311
|
+
insertMarkers: true
|
|
6312
|
+
}
|
|
5962
6313
|
}
|
|
5963
6314
|
]
|
|
5964
6315
|
};
|
|
@@ -5994,18 +6345,23 @@ var chineseProfile = {
|
|
|
5994
6345
|
requiredRoles: ["event", "action"]
|
|
5995
6346
|
},
|
|
5996
6347
|
transform: {
|
|
5997
|
-
// 当
|
|
6348
|
+
// 当 EVENT 时 ACTION [patient] [destination] [source] [style] [method] ...
|
|
5998
6349
|
roleOrder: ["event", "action", "patient"],
|
|
5999
6350
|
insertMarkers: true,
|
|
6000
|
-
custom: (parsed,
|
|
6351
|
+
custom: (parsed, profile) => {
|
|
6001
6352
|
const event = parsed.roles.get("event");
|
|
6002
6353
|
const action = parsed.roles.get("action");
|
|
6003
|
-
const
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6354
|
+
const remaining = new Map(parsed.roles);
|
|
6355
|
+
remaining.delete("event");
|
|
6356
|
+
remaining.delete("action");
|
|
6357
|
+
const remainingOrder = (profile.canonicalOrder || []).filter(
|
|
6358
|
+
(r) => r !== "event" && r !== "action"
|
|
6359
|
+
);
|
|
6360
|
+
const reordered = reorderRoles(remaining, remainingOrder);
|
|
6361
|
+
const markedTokens = insertMarkers(reordered, profile.markers, profile.adpositionType);
|
|
6362
|
+
const parts = ["\u5F53", event?.translated || event?.value || "", "\u65F6"];
|
|
6363
|
+
if (action) parts.push(action.translated || action.value);
|
|
6364
|
+
parts.push(...markedTokens);
|
|
6009
6365
|
return parts.filter(Boolean).join(" ");
|
|
6010
6366
|
}
|
|
6011
6367
|
}
|
|
@@ -6023,6 +6379,30 @@ var chineseProfile = {
|
|
|
6023
6379
|
roleOrder: ["patient", "action", "destination"],
|
|
6024
6380
|
insertMarkers: true
|
|
6025
6381
|
}
|
|
6382
|
+
},
|
|
6383
|
+
{
|
|
6384
|
+
name: "bind-to",
|
|
6385
|
+
description: "Bind binds a variable to an element: \u7ED1\u5B9A X \u5230 Y (no \u628A)",
|
|
6386
|
+
priority: 90,
|
|
6387
|
+
match: {
|
|
6388
|
+
commands: ["bind", "\u7ED1\u5B9A"],
|
|
6389
|
+
requiredRoles: ["action", "patient", "destination"]
|
|
6390
|
+
},
|
|
6391
|
+
transform: {
|
|
6392
|
+
// Plain SVO without the 把 object-fronting: the bound variable is the
|
|
6393
|
+
// semantic destination (not a fronted patient), and `到` marks the
|
|
6394
|
+
// target element. Custom so the patient does not pick up 把.
|
|
6395
|
+
roleOrder: ["action", "patient", "destination"],
|
|
6396
|
+
custom: (parsed) => {
|
|
6397
|
+
const action = parsed.roles.get("action");
|
|
6398
|
+
const patient = parsed.roles.get("patient");
|
|
6399
|
+
const destination = parsed.roles.get("destination");
|
|
6400
|
+
const verb = action?.translated || action?.value || "";
|
|
6401
|
+
const v = patient?.translated || patient?.value || "";
|
|
6402
|
+
const d = destination?.translated || destination?.value || "";
|
|
6403
|
+
return [verb, v, "\u5230", d].filter(Boolean).join(" ");
|
|
6404
|
+
}
|
|
6405
|
+
}
|
|
6026
6406
|
}
|
|
6027
6407
|
]
|
|
6028
6408
|
};
|
|
@@ -6114,6 +6494,56 @@ var turkishProfile = {
|
|
|
6114
6494
|
roleOrder: ["patient", "event", "action"],
|
|
6115
6495
|
insertMarkers: true
|
|
6116
6496
|
}
|
|
6497
|
+
},
|
|
6498
|
+
{
|
|
6499
|
+
name: "put-into",
|
|
6500
|
+
description: "Transform put X into Y to Turkish verb-final order",
|
|
6501
|
+
priority: 90,
|
|
6502
|
+
match: {
|
|
6503
|
+
commands: ["put", "koy"],
|
|
6504
|
+
requiredRoles: ["action", "patient", "destination"],
|
|
6505
|
+
// Standalone put only (e.g. a then-chain clause): an event handler whose
|
|
6506
|
+
// action is `put` must keep the event mid-stream, so don't verb-final it.
|
|
6507
|
+
predicate: (parsed) => !parsed.roles.has("event")
|
|
6508
|
+
},
|
|
6509
|
+
transform: {
|
|
6510
|
+
// X i Y e koy (patient, destination, verb-last)
|
|
6511
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6512
|
+
insertMarkers: true
|
|
6513
|
+
}
|
|
6514
|
+
},
|
|
6515
|
+
{
|
|
6516
|
+
name: "set-to",
|
|
6517
|
+
description: "Transform set X to Y to Turkish verb-final order",
|
|
6518
|
+
priority: 90,
|
|
6519
|
+
match: {
|
|
6520
|
+
commands: ["set", "ayarla"],
|
|
6521
|
+
requiredRoles: ["action", "patient", "destination"],
|
|
6522
|
+
// Skip a set whose value swept up a trailing block terminator (`set X to Y
|
|
6523
|
+
// end` — the body of an inline `if … then set … end`): verb-final reorder
|
|
6524
|
+
// would push the verb past `end` and break the block. These parse fine
|
|
6525
|
+
// verb-medial (the default).
|
|
6526
|
+
predicate: (parsed) => !/(^|\s)end$/i.test((parsed.original ?? "").trim())
|
|
6527
|
+
},
|
|
6528
|
+
transform: {
|
|
6529
|
+
// X i Y e ayarla — verb-final, matching the generated SOV set pattern.
|
|
6530
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6531
|
+
insertMarkers: true
|
|
6532
|
+
}
|
|
6533
|
+
},
|
|
6534
|
+
{
|
|
6535
|
+
name: "bind-to",
|
|
6536
|
+
description: "Transform bind $var to #el to Turkish verb-final order",
|
|
6537
|
+
priority: 90,
|
|
6538
|
+
match: {
|
|
6539
|
+
commands: ["bind"],
|
|
6540
|
+
requiredRoles: ["action", "patient", "destination"]
|
|
6541
|
+
},
|
|
6542
|
+
transform: {
|
|
6543
|
+
// $var i #el e bağla
|
|
6544
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6545
|
+
insertMarkers: true
|
|
6546
|
+
}
|
|
6117
6547
|
}
|
|
6118
6548
|
]
|
|
6119
6549
|
};
|
|
@@ -6210,6 +6640,25 @@ var indonesianProfile = {
|
|
|
6210
6640
|
{ form: "sebagai", role: "method", position: "preposition", required: false }
|
|
6211
6641
|
]
|
|
6212
6642
|
};
|
|
6643
|
+
var malayProfile = {
|
|
6644
|
+
code: "ms",
|
|
6645
|
+
name: "Bahasa Melayu",
|
|
6646
|
+
wordOrder: "SVO",
|
|
6647
|
+
adpositionType: "preposition",
|
|
6648
|
+
morphology: "agglutinative",
|
|
6649
|
+
direction: "ltr",
|
|
6650
|
+
canonicalOrder: ["event", "action", "patient", "destination"],
|
|
6651
|
+
markers: [
|
|
6652
|
+
// ms marks the event clause with `apabila` ("when/on") — matching the semantic
|
|
6653
|
+
// ms event-handler pattern (`apabila {event} {body}`) and the ms dict's
|
|
6654
|
+
// `on: apabila`. (Indonesian uses `pada` here; the two diverge on the event head.)
|
|
6655
|
+
{ form: "apabila", role: "event", position: "preposition", required: true },
|
|
6656
|
+
{ form: "ke", role: "destination", position: "preposition", required: false },
|
|
6657
|
+
{ form: "dari", role: "source", position: "preposition", required: false },
|
|
6658
|
+
{ form: "dengan", role: "style", position: "preposition", required: false },
|
|
6659
|
+
{ form: "sebagai", role: "method", position: "preposition", required: false }
|
|
6660
|
+
]
|
|
6661
|
+
};
|
|
6213
6662
|
var quechuaProfile = {
|
|
6214
6663
|
code: "qu",
|
|
6215
6664
|
name: "Runasimi",
|
|
@@ -6245,8 +6694,11 @@ var swahiliProfile = {
|
|
|
6245
6694
|
{ form: "kwa", role: "destination", position: "preposition", required: false },
|
|
6246
6695
|
{ form: "kutoka", role: "source", position: "preposition", required: false },
|
|
6247
6696
|
{ form: "na", role: "style", position: "preposition", required: false },
|
|
6248
|
-
|
|
6249
|
-
// "as
|
|
6697
|
+
// `kuwa`, not `kama`: sw `kama` is the IF keyword — rendering the method
|
|
6698
|
+
// role ("as X") with it grew a phantom `if` at semantic parse time. See the
|
|
6699
|
+
// matching comment in dictionaries/sw.ts (modifiers.as).
|
|
6700
|
+
{ form: "kuwa", role: "method", position: "preposition", required: false }
|
|
6701
|
+
// "as/become"
|
|
6250
6702
|
]
|
|
6251
6703
|
};
|
|
6252
6704
|
var bengaliProfile = {
|
|
@@ -6283,6 +6735,56 @@ var bengaliProfile = {
|
|
|
6283
6735
|
roleOrder: ["patient", "event", "action"],
|
|
6284
6736
|
insertMarkers: true
|
|
6285
6737
|
}
|
|
6738
|
+
},
|
|
6739
|
+
{
|
|
6740
|
+
name: "put-into",
|
|
6741
|
+
description: "Transform put X into Y to Bengali verb-final order",
|
|
6742
|
+
priority: 90,
|
|
6743
|
+
match: {
|
|
6744
|
+
commands: ["put", "\u09B0\u09BE\u0996\u09C1\u09A8"],
|
|
6745
|
+
requiredRoles: ["action", "patient", "destination"],
|
|
6746
|
+
// Standalone put only (e.g. a then-chain clause): an event handler whose
|
|
6747
|
+
// action is `put` must keep the event mid-stream, so don't verb-final it.
|
|
6748
|
+
predicate: (parsed) => !parsed.roles.has("event")
|
|
6749
|
+
},
|
|
6750
|
+
transform: {
|
|
6751
|
+
// X কে Y তে রাখুন (patient, destination, verb-last)
|
|
6752
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6753
|
+
insertMarkers: true
|
|
6754
|
+
}
|
|
6755
|
+
},
|
|
6756
|
+
{
|
|
6757
|
+
name: "set-to",
|
|
6758
|
+
description: "Transform set X to Y to Bengali verb-final order",
|
|
6759
|
+
priority: 90,
|
|
6760
|
+
match: {
|
|
6761
|
+
commands: ["set", "\u09B8\u09C7\u099F"],
|
|
6762
|
+
requiredRoles: ["action", "patient", "destination"],
|
|
6763
|
+
// Skip a set whose value swept up a trailing block terminator (`set X to Y
|
|
6764
|
+
// end` — the body of an inline `if … then set … end`): verb-final reorder
|
|
6765
|
+
// would push the verb past `end` and break the block. These parse fine
|
|
6766
|
+
// verb-medial (the default).
|
|
6767
|
+
predicate: (parsed) => !/(^|\s)end$/i.test((parsed.original ?? "").trim())
|
|
6768
|
+
},
|
|
6769
|
+
transform: {
|
|
6770
|
+
// X কে Y তে সেট — verb-final, matching the generated SOV set pattern.
|
|
6771
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6772
|
+
insertMarkers: true
|
|
6773
|
+
}
|
|
6774
|
+
},
|
|
6775
|
+
{
|
|
6776
|
+
name: "bind-to",
|
|
6777
|
+
description: "Transform bind $var to #el to Bengali verb-final order",
|
|
6778
|
+
priority: 90,
|
|
6779
|
+
match: {
|
|
6780
|
+
commands: ["bind", "\u09AC\u09BE\u0987\u09A8\u09CD\u09A1"],
|
|
6781
|
+
requiredRoles: ["action", "patient", "destination"]
|
|
6782
|
+
},
|
|
6783
|
+
transform: {
|
|
6784
|
+
// $var কে #el তে বাইন্ড
|
|
6785
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6786
|
+
insertMarkers: true
|
|
6787
|
+
}
|
|
6286
6788
|
}
|
|
6287
6789
|
]
|
|
6288
6790
|
};
|
|
@@ -6400,6 +6902,61 @@ var hindiProfile = {
|
|
|
6400
6902
|
roleOrder: ["patient", "event", "action"],
|
|
6401
6903
|
insertMarkers: true
|
|
6402
6904
|
}
|
|
6905
|
+
},
|
|
6906
|
+
{
|
|
6907
|
+
name: "put-into",
|
|
6908
|
+
description: "Transform put X into Y to Hindi verb-final order",
|
|
6909
|
+
priority: 90,
|
|
6910
|
+
match: {
|
|
6911
|
+
commands: ["put", "\u0930\u0916\u0947\u0902"],
|
|
6912
|
+
requiredRoles: ["action", "patient", "destination"]
|
|
6913
|
+
},
|
|
6914
|
+
transform: {
|
|
6915
|
+
// "hi" को #out में रखें
|
|
6916
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6917
|
+
insertMarkers: true
|
|
6918
|
+
}
|
|
6919
|
+
},
|
|
6920
|
+
{
|
|
6921
|
+
name: "set-to",
|
|
6922
|
+
description: "Transform set X to Y to Hindi verb-final order",
|
|
6923
|
+
priority: 90,
|
|
6924
|
+
match: {
|
|
6925
|
+
commands: ["set", "\u0938\u0947\u091F"],
|
|
6926
|
+
requiredRoles: ["action", "patient", "destination"],
|
|
6927
|
+
// Skip a set whose value swept up a trailing block terminator (`set X to Y
|
|
6928
|
+
// end` — the body of an inline `if … then set … end`): verb-final reorder
|
|
6929
|
+
// would push the verb past `end` and break the block. These parse fine
|
|
6930
|
+
// verb-medial (the default).
|
|
6931
|
+
predicate: (parsed) => !/(^|\s)end$/i.test((parsed.original ?? "").trim())
|
|
6932
|
+
},
|
|
6933
|
+
transform: {
|
|
6934
|
+
// #x.innerText को इसका.name में सेट — verb-final, matching the generated
|
|
6935
|
+
// SOV set pattern (set schema markerOverride puts को on the destination /
|
|
6936
|
+
// में on the value). The default reorder emitted verb-MEDIAL
|
|
6937
|
+
// (`#x को सेट … में`), which no set pattern matched → bare-event fallback.
|
|
6938
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6939
|
+
insertMarkers: true
|
|
6940
|
+
}
|
|
6941
|
+
},
|
|
6942
|
+
{
|
|
6943
|
+
name: "bind-to",
|
|
6944
|
+
description: "Transform bind $var to #el to Hindi verb-final order",
|
|
6945
|
+
priority: 90,
|
|
6946
|
+
match: {
|
|
6947
|
+
commands: ["bind", "\u092C\u093E\u0907\u0902\u0921", "\u092C\u093E\u0902\u0927\u0947\u0902"],
|
|
6948
|
+
requiredRoles: ["action", "patient", "destination"]
|
|
6949
|
+
},
|
|
6950
|
+
transform: {
|
|
6951
|
+
// $greeting को #name-input में bind — verb-final, matching the generated SOV
|
|
6952
|
+
// bind pattern (`{destination} को {source} में bind`). The default reorder
|
|
6953
|
+
// emitted verb-MEDIAL (`$greeting को bind #name-input में`), which the
|
|
6954
|
+
// verb-final pattern never matched → the bare-event fallback mis-anchored
|
|
6955
|
+
// the fronted `$greeting` as a phantom `on` event (the rf=0.00 bind residue).
|
|
6956
|
+
// ja/ko/zh/tr/bn already carry this rule; hi was the only SOV gap.
|
|
6957
|
+
roleOrder: ["patient", "destination", "action"],
|
|
6958
|
+
insertMarkers: true
|
|
6959
|
+
}
|
|
6403
6960
|
}
|
|
6404
6961
|
]
|
|
6405
6962
|
};
|
|
@@ -6415,7 +6972,11 @@ var tagalogProfile = {
|
|
|
6415
6972
|
markers: [
|
|
6416
6973
|
{ form: "kapag", role: "event", position: "preposition", required: true },
|
|
6417
6974
|
{ form: "sa", role: "destination", position: "preposition", required: false },
|
|
6418
|
-
|
|
6975
|
+
// mula_sa (underscore) matches the tl dict and the semantic profile's
|
|
6976
|
+
// source marker — the spaced form emitted two tokens the generated
|
|
6977
|
+
// patterns' single mula_sa literal could never match, so `remove X
|
|
6978
|
+
// mula sa Y` lost its source and the schema default fabricated me.
|
|
6979
|
+
{ form: "mula_sa", role: "source", position: "preposition", required: false },
|
|
6419
6980
|
{ form: "nang", role: "style", position: "preposition", required: false },
|
|
6420
6981
|
{ form: "bilang", role: "method", position: "preposition", required: false }
|
|
6421
6982
|
],
|
|
@@ -6498,6 +7059,32 @@ var hebrewProfile = {
|
|
|
6498
7059
|
{ form: "\u05DE\u05DF", role: "source", position: "preposition", required: false },
|
|
6499
7060
|
{ form: "\u05E2\u05DD", role: "style", position: "preposition", required: false },
|
|
6500
7061
|
{ form: "\u05DB", role: "method", position: "preposition", required: false }
|
|
7062
|
+
],
|
|
7063
|
+
rules: [
|
|
7064
|
+
{
|
|
7065
|
+
name: "bind-to",
|
|
7066
|
+
description: "Bind binds a variable to an element: \u05E7\u05E9\u05D5\u05E8 X \u05DC Y",
|
|
7067
|
+
priority: 90,
|
|
7068
|
+
match: {
|
|
7069
|
+
commands: ["bind", "\u05E7\u05E9\u05D5\u05E8"],
|
|
7070
|
+
requiredRoles: ["action", "patient", "destination"]
|
|
7071
|
+
},
|
|
7072
|
+
transform: {
|
|
7073
|
+
// The bound variable is the semantic destination (kept bare, no את
|
|
7074
|
+
// object marker), and ל marks the target element. Custom so the
|
|
7075
|
+
// variable does not pick up את and the element uses ל (not על).
|
|
7076
|
+
roleOrder: ["action", "patient", "destination"],
|
|
7077
|
+
custom: (parsed) => {
|
|
7078
|
+
const action = parsed.roles.get("action");
|
|
7079
|
+
const patient = parsed.roles.get("patient");
|
|
7080
|
+
const destination = parsed.roles.get("destination");
|
|
7081
|
+
const verb = action?.translated || action?.value || "";
|
|
7082
|
+
const v = patient?.translated || patient?.value || "";
|
|
7083
|
+
const d = destination?.translated || destination?.value || "";
|
|
7084
|
+
return [verb, v, "\u05DC", d].filter(Boolean).join(" ");
|
|
7085
|
+
}
|
|
7086
|
+
}
|
|
7087
|
+
}
|
|
6501
7088
|
]
|
|
6502
7089
|
};
|
|
6503
7090
|
var profiles = {
|
|
@@ -6512,6 +7099,7 @@ var profiles = {
|
|
|
6512
7099
|
fr: frenchProfile,
|
|
6513
7100
|
pt: portugueseProfile,
|
|
6514
7101
|
id: indonesianProfile,
|
|
7102
|
+
ms: malayProfile,
|
|
6515
7103
|
qu: quechuaProfile,
|
|
6516
7104
|
sw: swahiliProfile,
|
|
6517
7105
|
bn: bengaliProfile,
|
|
@@ -6908,6 +7496,51 @@ function getCommandKeywordsForLocale(locale) {
|
|
|
6908
7496
|
}
|
|
6909
7497
|
return keywords;
|
|
6910
7498
|
}
|
|
7499
|
+
var EN_COPULAS = ["is", "are", "was", "were", "am", "be"];
|
|
7500
|
+
function getCopulasForLocale(locale) {
|
|
7501
|
+
const copulas = new Set(EN_COPULAS);
|
|
7502
|
+
if (locale !== "en") {
|
|
7503
|
+
for (const form of EN_COPULAS) {
|
|
7504
|
+
copulas.add(translateWord(form, "en", locale).toLowerCase());
|
|
7505
|
+
}
|
|
7506
|
+
}
|
|
7507
|
+
return copulas;
|
|
7508
|
+
}
|
|
7509
|
+
function isPredicateAdjectivePosition(tokens, i, copulas) {
|
|
7510
|
+
const prev = tokens[i - 1]?.toLowerCase();
|
|
7511
|
+
return !!prev && copulas.has(prev);
|
|
7512
|
+
}
|
|
7513
|
+
function getForLoopWordsForLocale(locale) {
|
|
7514
|
+
const forWords = /* @__PURE__ */ new Set(["for"]);
|
|
7515
|
+
const inWords = /* @__PURE__ */ new Set(["in"]);
|
|
7516
|
+
if (locale !== "en") {
|
|
7517
|
+
forWords.add(translateWord("for", "en", locale).toLowerCase());
|
|
7518
|
+
inWords.add(translateWord("in", "en", locale).toLowerCase());
|
|
7519
|
+
}
|
|
7520
|
+
return { forWords, inWords };
|
|
7521
|
+
}
|
|
7522
|
+
function isLoopHeadFor(tokens, i, inWords, commandKeywords) {
|
|
7523
|
+
for (let j = i + 1; j < tokens.length; j++) {
|
|
7524
|
+
const lt = tokens[j].toLowerCase();
|
|
7525
|
+
if (inWords.has(lt)) return true;
|
|
7526
|
+
if (commandKeywords.has(lt)) return false;
|
|
7527
|
+
}
|
|
7528
|
+
return false;
|
|
7529
|
+
}
|
|
7530
|
+
function repairHebrewFrontedAccusative(text) {
|
|
7531
|
+
const ACC = "\u05D0\u05EA";
|
|
7532
|
+
const verbs = getCommandKeywordsForLocale("he");
|
|
7533
|
+
const tokens = text.split(/\s+/);
|
|
7534
|
+
let changed = false;
|
|
7535
|
+
for (let i = 0; i + 1 < tokens.length; i++) {
|
|
7536
|
+
if (tokens[i] === ACC && verbs.has(tokens[i + 1].toLowerCase())) {
|
|
7537
|
+
[tokens[i], tokens[i + 1]] = [tokens[i + 1], tokens[i]];
|
|
7538
|
+
changed = true;
|
|
7539
|
+
i++;
|
|
7540
|
+
}
|
|
7541
|
+
}
|
|
7542
|
+
return changed ? tokens.join(" ") : text;
|
|
7543
|
+
}
|
|
6911
7544
|
function extractBlockStructure(input, sourceLocale) {
|
|
6912
7545
|
const tokens = input.split(/\s+/);
|
|
6913
7546
|
const head = tokens[0]?.toLowerCase();
|
|
@@ -6945,9 +7578,10 @@ function extractBlockStructure(input, sourceLocale) {
|
|
|
6945
7578
|
return null;
|
|
6946
7579
|
}
|
|
6947
7580
|
const commands = getCommandKeywordsForLocale(sourceLocale);
|
|
7581
|
+
const copulas = getCopulasForLocale(sourceLocale);
|
|
6948
7582
|
let bodyStart = -1;
|
|
6949
7583
|
for (let i = 0; i < inner.length; i++) {
|
|
6950
|
-
if (commands.has(inner[i].toLowerCase())) {
|
|
7584
|
+
if (commands.has(inner[i].toLowerCase()) && !isPredicateAdjectivePosition(inner, i, copulas)) {
|
|
6951
7585
|
bodyStart = i;
|
|
6952
7586
|
break;
|
|
6953
7587
|
}
|
|
@@ -7074,9 +7708,40 @@ var BOUNDARY_MODIFIERS = /* @__PURE__ */ new Set([
|
|
|
7074
7708
|
"of",
|
|
7075
7709
|
"over"
|
|
7076
7710
|
]);
|
|
7711
|
+
var boundaryModifiersCache = /* @__PURE__ */ new Map();
|
|
7712
|
+
function getBoundaryModifiersForLocale(locale) {
|
|
7713
|
+
const cached = boundaryModifiersCache.get(locale);
|
|
7714
|
+
if (cached) return cached;
|
|
7715
|
+
const modifiers = new Set(BOUNDARY_MODIFIERS);
|
|
7716
|
+
const profile = getProfile(locale);
|
|
7717
|
+
profile?.markers.forEach((marker) => {
|
|
7718
|
+
const form = marker.form.replace(/^-|-$/g, "").toLowerCase();
|
|
7719
|
+
if (form) modifiers.add(form);
|
|
7720
|
+
marker.alternatives?.forEach((alt) => {
|
|
7721
|
+
const altForm = alt.replace(/^-|-$/g, "").toLowerCase();
|
|
7722
|
+
if (altForm) modifiers.add(altForm);
|
|
7723
|
+
});
|
|
7724
|
+
});
|
|
7725
|
+
boundaryModifiersCache.set(locale, modifiers);
|
|
7726
|
+
return modifiers;
|
|
7727
|
+
}
|
|
7728
|
+
var ON_TARGET_COMMANDS = /* @__PURE__ */ new Set(["toggle", "add", "remove", "trigger", "send"]);
|
|
7729
|
+
function commandVerbOf(tokens, commandKeywords) {
|
|
7730
|
+
for (const token of tokens) {
|
|
7731
|
+
const lt = token.toLowerCase();
|
|
7732
|
+
if (commandKeywords.has(lt) && !BOUNDARY_MODIFIERS.has(lt) && !EVENT_KEYWORDS.has(lt)) {
|
|
7733
|
+
return lt;
|
|
7734
|
+
}
|
|
7735
|
+
}
|
|
7736
|
+
return null;
|
|
7737
|
+
}
|
|
7077
7738
|
var BLOCK_HEAD_KEYWORDS = /* @__PURE__ */ new Set(["live", "when", "unless"]);
|
|
7739
|
+
var BLOCK_BODY_KEYWORDS = /* @__PURE__ */ new Set(["if", "repeat", "unless", "while", "for"]);
|
|
7740
|
+
var UNLESS_GUARD_OBJECT_MARKING_LOCALES = /* @__PURE__ */ new Set(["he", "zh"]);
|
|
7078
7741
|
function splitOnCommandBoundaries(input, sourceLocale) {
|
|
7079
7742
|
const commandKeywords = getCommandKeywordsForLocale(sourceLocale);
|
|
7743
|
+
const boundaryModifiers = getBoundaryModifiersForLocale(sourceLocale);
|
|
7744
|
+
const { forWords, inWords } = getForLoopWordsForLocale(sourceLocale);
|
|
7080
7745
|
const tokens = input.split(/\s+/);
|
|
7081
7746
|
if (tokens.length === 0) return [input];
|
|
7082
7747
|
const parts = [];
|
|
@@ -7105,7 +7770,27 @@ function splitOnCommandBoundaries(input, sourceLocale) {
|
|
|
7105
7770
|
currentPart.push(token);
|
|
7106
7771
|
continue;
|
|
7107
7772
|
}
|
|
7108
|
-
if (
|
|
7773
|
+
if (forWords.has(lowerToken) && !isLoopHeadFor(tokens, i, inWords, commandKeywords)) {
|
|
7774
|
+
currentPart.push(token);
|
|
7775
|
+
continue;
|
|
7776
|
+
}
|
|
7777
|
+
if (BOUNDARY_MODIFIERS.has(lowerToken)) {
|
|
7778
|
+
const verb = commandVerbOf(currentPart, commandKeywords);
|
|
7779
|
+
if (verb && ON_TARGET_COMMANDS.has(verb)) {
|
|
7780
|
+
currentPart.push(token);
|
|
7781
|
+
continue;
|
|
7782
|
+
}
|
|
7783
|
+
if (lowerToken === "on" && verb === "set") {
|
|
7784
|
+
const nextTok = tokens[i + 1];
|
|
7785
|
+
const nextLower = nextTok?.toLowerCase();
|
|
7786
|
+
const scopeLike = !!nextTok && (/^[#.<@[]/.test(nextTok) || nextLower === "me" || nextLower === "it" || nextLower === "you");
|
|
7787
|
+
if (scopeLike) {
|
|
7788
|
+
currentPart.push(token);
|
|
7789
|
+
continue;
|
|
7790
|
+
}
|
|
7791
|
+
}
|
|
7792
|
+
}
|
|
7793
|
+
if (!boundaryModifiers.has(prevLower) && !commandKeywords.has(prevLower)) {
|
|
7109
7794
|
parts.push(currentPart.join(" "));
|
|
7110
7795
|
currentPart = [token];
|
|
7111
7796
|
continue;
|
|
@@ -7159,6 +7844,15 @@ function deriveEventKeywordsFromProfiles() {
|
|
|
7159
7844
|
return keywords;
|
|
7160
7845
|
}
|
|
7161
7846
|
var EVENT_KEYWORDS = deriveEventKeywordsFromProfiles();
|
|
7847
|
+
var EVENT_CONJUNCTIONS = /* @__PURE__ */ new Set(["or"]);
|
|
7848
|
+
var BODY_MODIFIER_KEYWORDS = /* @__PURE__ */ new Set([
|
|
7849
|
+
"async",
|
|
7850
|
+
"once",
|
|
7851
|
+
"debounced",
|
|
7852
|
+
"debounce",
|
|
7853
|
+
"throttled",
|
|
7854
|
+
"throttle"
|
|
7855
|
+
]);
|
|
7162
7856
|
function generateModifierMap(profile) {
|
|
7163
7857
|
const map = {};
|
|
7164
7858
|
profile.markers.forEach((marker) => {
|
|
@@ -7180,6 +7874,18 @@ function generateModifierMap(profile) {
|
|
|
7180
7874
|
}
|
|
7181
7875
|
return map;
|
|
7182
7876
|
}
|
|
7877
|
+
function buildArgumentModifierMap(profile, actionVerb) {
|
|
7878
|
+
const map = generateModifierMap(profile);
|
|
7879
|
+
const verb = actionVerb?.toLowerCase();
|
|
7880
|
+
if (profile.wordOrder !== "SVO" || !verb || !ON_TARGET_COMMANDS.has(verb)) {
|
|
7881
|
+
return map;
|
|
7882
|
+
}
|
|
7883
|
+
const remapped = {};
|
|
7884
|
+
for (const [form, role] of Object.entries(map)) {
|
|
7885
|
+
remapped[form] = role === "event" ? "destination" : role;
|
|
7886
|
+
}
|
|
7887
|
+
return remapped;
|
|
7888
|
+
}
|
|
7183
7889
|
function parseStatement(input, sourceLocale = "en") {
|
|
7184
7890
|
const profile = getProfile(sourceLocale);
|
|
7185
7891
|
if (!profile) return null;
|
|
@@ -7250,6 +7956,8 @@ function tokenize(input, profile) {
|
|
|
7250
7956
|
let current = "";
|
|
7251
7957
|
let inSelector = false;
|
|
7252
7958
|
let selectorDepth = 0;
|
|
7959
|
+
let bracketDepth = 0;
|
|
7960
|
+
let parenDepth = 0;
|
|
7253
7961
|
for (let i = 0; i < input.length; i++) {
|
|
7254
7962
|
const char = input[i];
|
|
7255
7963
|
if (char === "<") {
|
|
@@ -7259,7 +7967,17 @@ function tokenize(input, profile) {
|
|
|
7259
7967
|
selectorDepth--;
|
|
7260
7968
|
if (selectorDepth === 0) inSelector = false;
|
|
7261
7969
|
}
|
|
7262
|
-
if (
|
|
7970
|
+
if (char === "[") {
|
|
7971
|
+
bracketDepth++;
|
|
7972
|
+
} else if (char === "]" && bracketDepth > 0) {
|
|
7973
|
+
bracketDepth--;
|
|
7974
|
+
}
|
|
7975
|
+
if (char === "(") {
|
|
7976
|
+
parenDepth++;
|
|
7977
|
+
} else if (char === ")" && parenDepth > 0) {
|
|
7978
|
+
parenDepth--;
|
|
7979
|
+
}
|
|
7980
|
+
if (/\s/.test(char) && !inSelector && bracketDepth === 0 && parenDepth === 0) {
|
|
7263
7981
|
if (current) {
|
|
7264
7982
|
tokens.push(current);
|
|
7265
7983
|
current = "";
|
|
@@ -7292,11 +8010,16 @@ function parseEventHandler(tokens, profile) {
|
|
|
7292
8010
|
const roles = /* @__PURE__ */ new Map();
|
|
7293
8011
|
let startIndex = EVENT_KEYWORDS.has(tokens[0]?.toLowerCase()) ? 1 : 0;
|
|
7294
8012
|
if (tokens[startIndex]) {
|
|
8013
|
+
const eventTokens = [tokens[startIndex]];
|
|
8014
|
+
startIndex++;
|
|
8015
|
+
while (tokens[startIndex] && EVENT_CONJUNCTIONS.has(tokens[startIndex].toLowerCase()) && tokens[startIndex + 1]) {
|
|
8016
|
+
eventTokens.push(tokens[startIndex], tokens[startIndex + 1]);
|
|
8017
|
+
startIndex += 2;
|
|
8018
|
+
}
|
|
7295
8019
|
roles.set("event", {
|
|
7296
8020
|
role: "event",
|
|
7297
|
-
value:
|
|
8021
|
+
value: eventTokens.join(" ")
|
|
7298
8022
|
});
|
|
7299
|
-
startIndex++;
|
|
7300
8023
|
}
|
|
7301
8024
|
if (tokens[startIndex] && tokens[startIndex].toLowerCase() === "from" && tokens[startIndex + 1]) {
|
|
7302
8025
|
startIndex++;
|
|
@@ -7323,7 +8046,7 @@ function parseEventHandler(tokens, profile) {
|
|
|
7323
8046
|
startIndex++;
|
|
7324
8047
|
}
|
|
7325
8048
|
if (tokens[startIndex]) {
|
|
7326
|
-
const modifierMap =
|
|
8049
|
+
const modifierMap = buildArgumentModifierMap(profile, roles.get("action")?.value);
|
|
7327
8050
|
let currentRole = "patient";
|
|
7328
8051
|
let currentValue = [];
|
|
7329
8052
|
for (let i = startIndex; i < tokens.length; i++) {
|
|
@@ -7368,7 +8091,7 @@ function parseCommand(tokens, profile) {
|
|
|
7368
8091
|
role: "action",
|
|
7369
8092
|
value: tokens[0]
|
|
7370
8093
|
});
|
|
7371
|
-
const modifierMap =
|
|
8094
|
+
const modifierMap = buildArgumentModifierMap(profile, tokens[0]);
|
|
7372
8095
|
let currentRole = "patient";
|
|
7373
8096
|
let currentValue = [];
|
|
7374
8097
|
for (let i = 1; i < tokens.length; i++) {
|
|
@@ -7403,6 +8126,22 @@ function parseCommand(tokens, profile) {
|
|
|
7403
8126
|
original: tokens.join(" ")
|
|
7404
8127
|
};
|
|
7405
8128
|
}
|
|
8129
|
+
var LITERAL_PRIMARY_ROLES = /* @__PURE__ */ new Set([
|
|
8130
|
+
"duration",
|
|
8131
|
+
"quantity"
|
|
8132
|
+
]);
|
|
8133
|
+
function applyPrimaryRole(parsed, targetProfile) {
|
|
8134
|
+
if (parsed.type !== "command") return;
|
|
8135
|
+
const action = parsed.roles.get("action")?.value;
|
|
8136
|
+
if (!action) return;
|
|
8137
|
+
const primaryRole = COMMAND_PRIMARY_ROLES[action.toLowerCase()];
|
|
8138
|
+
if (!primaryRole || !LITERAL_PRIMARY_ROLES.has(primaryRole)) return;
|
|
8139
|
+
const patientEl = parsed.roles.get("patient");
|
|
8140
|
+
if (!patientEl || parsed.roles.has(primaryRole)) return;
|
|
8141
|
+
if (targetProfile.markers.some((m) => m.role === primaryRole)) return;
|
|
8142
|
+
parsed.roles.delete("patient");
|
|
8143
|
+
parsed.roles.set(primaryRole, { ...patientEl, role: primaryRole });
|
|
8144
|
+
}
|
|
7406
8145
|
function parseConditional(tokens, _profile) {
|
|
7407
8146
|
const roles = /* @__PURE__ */ new Map();
|
|
7408
8147
|
roles.set("action", {
|
|
@@ -7416,6 +8155,11 @@ function parseConditional(tokens, _profile) {
|
|
|
7416
8155
|
role: "condition",
|
|
7417
8156
|
value: conditionValue
|
|
7418
8157
|
});
|
|
8158
|
+
} else if (thenIndex === -1 && tokens.length > 1) {
|
|
8159
|
+
roles.set("condition", {
|
|
8160
|
+
role: "condition",
|
|
8161
|
+
value: tokens.slice(1).join(" ")
|
|
8162
|
+
});
|
|
7419
8163
|
}
|
|
7420
8164
|
return {
|
|
7421
8165
|
type: "conditional",
|
|
@@ -7430,6 +8174,15 @@ function translateWord(word, sourceLocale, targetLocale) {
|
|
|
7430
8174
|
if (/^\d+/.test(word)) {
|
|
7431
8175
|
return word;
|
|
7432
8176
|
}
|
|
8177
|
+
if (/\s/.test(word) && word.startsWith("(")) {
|
|
8178
|
+
return word.split(/\s+/).map((w) => translateWord(w, sourceLocale, targetLocale)).join(" ");
|
|
8179
|
+
}
|
|
8180
|
+
if (word.length > 1 && (word.startsWith("(") || word.endsWith(")"))) {
|
|
8181
|
+
const m = word.match(/^(\(*)([^()]+)(\)*)$/);
|
|
8182
|
+
if (m && (m[1] || m[3])) {
|
|
8183
|
+
return m[1] + translateWord(m[2], sourceLocale, targetLocale) + m[3];
|
|
8184
|
+
}
|
|
8185
|
+
}
|
|
7433
8186
|
const sourceDict = sourceLocale === "en" ? null : dictionaries[sourceLocale];
|
|
7434
8187
|
const targetDict = dictionaries[targetLocale];
|
|
7435
8188
|
if (!targetDict) return word;
|
|
@@ -7453,9 +8206,21 @@ var POSSESSIVE_MARKERS = {
|
|
|
7453
8206
|
ko: { type: "suffix", marker: "\uC758" },
|
|
7454
8207
|
zh: { type: "suffix", marker: "\u7684" },
|
|
7455
8208
|
ar: { type: "preposition", marker: "\u0644\u0640" },
|
|
7456
|
-
|
|
8209
|
+
// Spaced genitive particle (not the glued `'ın`), so the tokenizer can split
|
|
8210
|
+
// it off the selector — consistent with Turkish's other spaced case markers.
|
|
8211
|
+
tr: { type: "particle", marker: "\u0131n" },
|
|
7457
8212
|
id: { type: "preposition", marker: "dari" },
|
|
7458
|
-
|
|
8213
|
+
// Latin-script genitive: must be a *spaced* particle (`#picker pa`), since a
|
|
8214
|
+
// glued `#pickerpa` can't be split from the selector by the tokenizer the
|
|
8215
|
+
// way a non-Latin suffix (の/의/র) can.
|
|
8216
|
+
qu: { type: "particle", marker: "pa" },
|
|
8217
|
+
// Bengali SOV postposition genitive, like ja/ko — a spaced suffix the
|
|
8218
|
+
// tokenizer splits off as a particle. Previously absent, so it fell back to
|
|
8219
|
+
// the English `'s` marker and its possessive property paths never parsed.
|
|
8220
|
+
// (Hindi `का` is intentionally omitted: its `bind` lacks a verb-final
|
|
8221
|
+
// grammar rule, so fixing its possessive alone yields a wrong `on` parse —
|
|
8222
|
+
// tracked as separate follow-up.)
|
|
8223
|
+
bn: { type: "suffix", marker: "\u09B0" },
|
|
7459
8224
|
sw: { type: "preposition", marker: "ya" }
|
|
7460
8225
|
};
|
|
7461
8226
|
function translatePossessive(token, sourceLocale, targetLocale) {
|
|
@@ -7479,6 +8244,8 @@ function translatePossessive(token, sourceLocale, targetLocale) {
|
|
|
7479
8244
|
switch (targetMarker.type) {
|
|
7480
8245
|
case "suffix":
|
|
7481
8246
|
return `${translatedOwner}${targetMarker.marker}`;
|
|
8247
|
+
case "particle":
|
|
8248
|
+
return `${translatedOwner} ${targetMarker.marker}`;
|
|
7482
8249
|
case "preposition":
|
|
7483
8250
|
return `__POSS__${targetMarker.marker}__${translatedOwner}__POSS__`;
|
|
7484
8251
|
default:
|
|
@@ -7514,6 +8281,17 @@ function translatePossessiveDotNotation(value, sourceLocale, targetLocale) {
|
|
|
7514
8281
|
return null;
|
|
7515
8282
|
}
|
|
7516
8283
|
function translateMultiWordValue(value, sourceLocale, targetLocale) {
|
|
8284
|
+
if (value.includes("[")) {
|
|
8285
|
+
const guards = [];
|
|
8286
|
+
const masked = value.replace(/\[[^\]]*\]/g, (match) => {
|
|
8287
|
+
guards.push(match);
|
|
8288
|
+
return `\uE000${guards.length - 1}\uE001`;
|
|
8289
|
+
});
|
|
8290
|
+
if (guards.length > 0) {
|
|
8291
|
+
const translated2 = translateMultiWordValue(masked, sourceLocale, targetLocale);
|
|
8292
|
+
return translated2.replace(/(\d+)/g, (_, n) => guards[Number(n)]);
|
|
8293
|
+
}
|
|
8294
|
+
}
|
|
7517
8295
|
if (!value.includes(" ")) {
|
|
7518
8296
|
if (value.includes("'s")) {
|
|
7519
8297
|
return translatePossessive(value, sourceLocale, targetLocale);
|
|
@@ -7581,6 +8359,24 @@ function translateElements(parsed, sourceLocale, targetLocale) {
|
|
|
7581
8359
|
}
|
|
7582
8360
|
}
|
|
7583
8361
|
}
|
|
8362
|
+
var CARET_SCOPE_OPEN = "\uE000";
|
|
8363
|
+
var CARET_SCOPE_CLOSE = "\uE001";
|
|
8364
|
+
var CARET_SCOPE_RE = /(\^[A-Za-z_][\w-]*)(\s+on\s+(?:[#.][\w-]+|<[^>]*\/>|\[[^\]]+\]))/g;
|
|
8365
|
+
function maskCaretScopes(input) {
|
|
8366
|
+
const scopes = [];
|
|
8367
|
+
const masked = input.replace(CARET_SCOPE_RE, (_m, varTok, scope) => {
|
|
8368
|
+
const idx = scopes.length;
|
|
8369
|
+
scopes.push(scope);
|
|
8370
|
+
return `${varTok}${CARET_SCOPE_OPEN}${idx}${CARET_SCOPE_CLOSE}`;
|
|
8371
|
+
});
|
|
8372
|
+
return scopes.length > 0 ? { masked, scopes } : null;
|
|
8373
|
+
}
|
|
8374
|
+
function restoreCaretScopes(input, scopes) {
|
|
8375
|
+
return input.replace(
|
|
8376
|
+
new RegExp(`${CARET_SCOPE_OPEN}(\\d+)${CARET_SCOPE_CLOSE}`, "g"),
|
|
8377
|
+
(_m, n) => scopes[Number(n)] ?? ""
|
|
8378
|
+
);
|
|
8379
|
+
}
|
|
7584
8380
|
var GrammarTransformer = class {
|
|
7585
8381
|
constructor(sourceLocale = "en", targetLocale) {
|
|
7586
8382
|
const source = getProfile(sourceLocale);
|
|
@@ -7598,7 +8394,25 @@ var GrammarTransformer = class {
|
|
|
7598
8394
|
* For multi-line input, preserves line structure (indentation, blank lines).
|
|
7599
8395
|
*/
|
|
7600
8396
|
transform(input) {
|
|
8397
|
+
const out = this.transformInternal(input);
|
|
8398
|
+
return this.targetProfile.code === "he" ? repairHebrewFrontedAccusative(out) : out;
|
|
8399
|
+
}
|
|
8400
|
+
transformInternal(input) {
|
|
8401
|
+
const caret = maskCaretScopes(input);
|
|
8402
|
+
if (caret) {
|
|
8403
|
+
return restoreCaretScopes(this.transform(caret.masked), caret.scopes);
|
|
8404
|
+
}
|
|
7601
8405
|
const targetThen = getTargetThenKeyword(this.targetProfile.code);
|
|
8406
|
+
if (!input.includes("\n")) {
|
|
8407
|
+
const jsBlock = this.tryTransformJsBlock(input);
|
|
8408
|
+
if (jsBlock !== null) return jsBlock;
|
|
8409
|
+
const eventModifier = this.tryTransformEventWithModifierBody(input);
|
|
8410
|
+
if (eventModifier !== null) return eventModifier;
|
|
8411
|
+
const eventBlock = this.tryTransformEventWithBlockBody(input);
|
|
8412
|
+
if (eventBlock !== null) return eventBlock;
|
|
8413
|
+
const eventGuard = this.tryTransformEventWithUnlessGuard(input);
|
|
8414
|
+
if (eventGuard !== null) return eventGuard;
|
|
8415
|
+
}
|
|
7602
8416
|
const hasMultiLineStructure = input.includes("\n");
|
|
7603
8417
|
if (hasMultiLineStructure) {
|
|
7604
8418
|
const { parts: parts2, lineMetadata, partToLineIndex } = splitCompoundStatementWithMetadata(
|
|
@@ -7628,10 +8442,15 @@ var GrammarTransformer = class {
|
|
|
7628
8442
|
if (block) {
|
|
7629
8443
|
return this.transformBlock(block);
|
|
7630
8444
|
}
|
|
8445
|
+
const setScope = this.transformSetWithScope(input);
|
|
8446
|
+
if (setScope !== null) {
|
|
8447
|
+
return setScope;
|
|
8448
|
+
}
|
|
7631
8449
|
const parsed = parseStatement(input, this.sourceProfile.code);
|
|
7632
8450
|
if (!parsed) {
|
|
7633
8451
|
return input;
|
|
7634
8452
|
}
|
|
8453
|
+
applyPrimaryRole(parsed, this.targetProfile);
|
|
7635
8454
|
translateElements(parsed, this.sourceProfile.code, this.targetProfile.code);
|
|
7636
8455
|
const rule = this.findRule(parsed);
|
|
7637
8456
|
if (rule?.transform.custom) {
|
|
@@ -7650,6 +8469,306 @@ var GrammarTransformer = class {
|
|
|
7650
8469
|
}
|
|
7651
8470
|
return joinTokens(reordered.map((e) => e.translated || e.value));
|
|
7652
8471
|
}
|
|
8472
|
+
/**
|
|
8473
|
+
* Detect and transform an inline JS block (`[on <event>] js <raw js> end`).
|
|
8474
|
+
*
|
|
8475
|
+
* The `js ... end` body is raw JavaScript: it must not be tokenized,
|
|
8476
|
+
* translated, or word-order reordered. We mask the whole block with a single
|
|
8477
|
+
* opaque placeholder, run the surrounding statement (the event-handler head,
|
|
8478
|
+
* if any) through the normal reorder pipeline so the placeholder lands in the
|
|
8479
|
+
* correct action position, then substitute the translated `js`/`end` keywords
|
|
8480
|
+
* around the verbatim body.
|
|
8481
|
+
*
|
|
8482
|
+
* Returns `null` (fall through to the normal path) when there is no js block,
|
|
8483
|
+
* no matching `end`, or trailing content after `end` (kept tight on purpose).
|
|
8484
|
+
*/
|
|
8485
|
+
tryTransformJsBlock(input) {
|
|
8486
|
+
const src = this.sourceProfile.code;
|
|
8487
|
+
const dst = this.targetProfile.code;
|
|
8488
|
+
const sourceJs = translateWord("js", "en", src);
|
|
8489
|
+
const sourceEnd = translateWord("end", "en", src).toLowerCase();
|
|
8490
|
+
const tokens = input.split(/\s+/).filter((t) => t.length > 0);
|
|
8491
|
+
const escapedJs = sourceJs.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8492
|
+
const jsRe = new RegExp(`^${escapedJs}(\\(.*\\))?$`, "i");
|
|
8493
|
+
const jsIdx = tokens.findIndex((t) => jsRe.test(t));
|
|
8494
|
+
if (jsIdx === -1) return null;
|
|
8495
|
+
let endIdx = -1;
|
|
8496
|
+
for (let i = jsIdx + 1; i < tokens.length; i++) {
|
|
8497
|
+
if (tokens[i].toLowerCase() === sourceEnd) {
|
|
8498
|
+
endIdx = i;
|
|
8499
|
+
break;
|
|
8500
|
+
}
|
|
8501
|
+
}
|
|
8502
|
+
if (endIdx === -1) return null;
|
|
8503
|
+
if (endIdx !== tokens.length - 1) return null;
|
|
8504
|
+
const jsToken = tokens[jsIdx];
|
|
8505
|
+
const jsParen = jsToken.match(jsRe)?.[1] ?? "";
|
|
8506
|
+
const jsKeywordRaw = jsParen ? jsToken.slice(0, jsToken.length - jsParen.length) : jsToken;
|
|
8507
|
+
const body = tokens.slice(jsIdx + 1, endIdx).join(" ");
|
|
8508
|
+
const targetJs = translateWord(jsKeywordRaw, src, dst) + jsParen;
|
|
8509
|
+
const targetEnd = translateWord(tokens[endIdx], src, dst);
|
|
8510
|
+
const replacement = [targetJs, body, targetEnd].filter((s) => s.length > 0).join(" ");
|
|
8511
|
+
const before = tokens.slice(0, jsIdx);
|
|
8512
|
+
if (before.length === 0) return replacement;
|
|
8513
|
+
const placeholder = "JSBLOCKPLACEHOLDER";
|
|
8514
|
+
const reordered = this.transformSingle([...before, placeholder].join(" "));
|
|
8515
|
+
if (!reordered.includes(placeholder)) return null;
|
|
8516
|
+
return reordered.replace(placeholder, replacement);
|
|
8517
|
+
}
|
|
8518
|
+
/**
|
|
8519
|
+
* Transform an event handler whose body is a block command
|
|
8520
|
+
* (`on <event> [from <src>] {if|repeat|unless|while|for} … end`).
|
|
8521
|
+
*
|
|
8522
|
+
* `parseEventHandler` would treat the block keyword as the action and sweep the
|
|
8523
|
+
* condition/body into role values, then reorder them — shredding the block
|
|
8524
|
+
* (`if event.shiftKey call submitAndContinue() end` → scattered tokens). Instead
|
|
8525
|
+
* we mask the whole block as an opaque action placeholder, reorder the event
|
|
8526
|
+
* head normally, transform the block as a self-contained unit, and restitch.
|
|
8527
|
+
*
|
|
8528
|
+
* Returns `null` (fall through) when the input isn't an event handler, has no
|
|
8529
|
+
* block-keyword body, or has no closing `end`.
|
|
8530
|
+
*/
|
|
8531
|
+
tryTransformEventWithBlockBody(input) {
|
|
8532
|
+
const tokens = tokenize(input, this.sourceProfile);
|
|
8533
|
+
if (tokens.length === 0) return null;
|
|
8534
|
+
if (!EVENT_KEYWORDS.has(tokens[0]?.toLowerCase())) return null;
|
|
8535
|
+
let blockIdx = -1;
|
|
8536
|
+
for (let i = 1; i < tokens.length; i++) {
|
|
8537
|
+
if (BLOCK_BODY_KEYWORDS.has(tokens[i].toLowerCase())) {
|
|
8538
|
+
blockIdx = i;
|
|
8539
|
+
break;
|
|
8540
|
+
}
|
|
8541
|
+
}
|
|
8542
|
+
if (blockIdx <= 0) return null;
|
|
8543
|
+
if (tokens[tokens.length - 1].toLowerCase() !== "end") return null;
|
|
8544
|
+
const eventHead = tokens.slice(0, blockIdx);
|
|
8545
|
+
const blockTokens = tokens.slice(blockIdx);
|
|
8546
|
+
if (this.targetProfile.wordOrder === "VSO" && eventHead.some((t) => t.toLowerCase() === "from")) {
|
|
8547
|
+
return null;
|
|
8548
|
+
}
|
|
8549
|
+
const placeholder = "EVENTBLOCKPLACEHOLDER";
|
|
8550
|
+
const headOut = this.transformSingle([...eventHead, placeholder].join(" "));
|
|
8551
|
+
if (!headOut.includes(placeholder)) return null;
|
|
8552
|
+
const blockOut = this.transformBlockBody(blockTokens);
|
|
8553
|
+
const eventClause = headOut.replace(placeholder, "").replace(/\s+/g, " ").trim();
|
|
8554
|
+
return [eventClause, blockOut].filter((s) => s.length > 0).join(" ");
|
|
8555
|
+
}
|
|
8556
|
+
/**
|
|
8557
|
+
* Transform an event handler whose body is an inline `unless` guard with NO
|
|
8558
|
+
* `end` (`on <event> unless <cond> <body>` — the `unless-condition` shape).
|
|
8559
|
+
*
|
|
8560
|
+
* Object-marking SVO targets (he, zh). `parseEventHandler` reads `unless` as the
|
|
8561
|
+
* action and sweeps the whole `<cond> <body>` tail into a single `patient` blob;
|
|
8562
|
+
* the target then prefixes that blob with its object marker — Hebrew's accusative
|
|
8563
|
+
* את (`… אלא את I match .disabled מתג .selected`) or Chinese's BA particle 把
|
|
8564
|
+
* (`… 除非 把 I match .disabled 切换 .selected`) — and the inner toggle loses its
|
|
8565
|
+
* own marker. The semantic parser can't recover the guard from that: the marker
|
|
8566
|
+
* ahead of the condition blocks the `unless` pattern AND the now-markerless body
|
|
8567
|
+
* command fails its object-marked toggle pattern, so the body collapses (`unless`
|
|
8568
|
+
* dropped). Marker-less languages (de/it/ar/pl) tolerate the same role-blob and
|
|
8569
|
+
* stay faithful, so this is an object-marker artifact, not a general parse gap.
|
|
8570
|
+
*
|
|
8571
|
+
* The standalone `unless <cond> <body>` path already produces the correct shape
|
|
8572
|
+
* (`extractBlockStructure` → `transformBlock`: condition kept marker-free, body
|
|
8573
|
+
* command keeps its marker — he `אלא I match .disabled מתג את .selected`, zh
|
|
8574
|
+
* `除非 I match .disabled 切换 把 .selected`). So we split the event head off,
|
|
8575
|
+
* transform the guard through that path, and emit the event clause first (he and
|
|
8576
|
+
* zh are both SVO — event leads). Returns `null` (fall through) when the input
|
|
8577
|
+
* isn't an object-marking event handler with an un-terminated inline `unless`
|
|
8578
|
+
* guard.
|
|
8579
|
+
*/
|
|
8580
|
+
tryTransformEventWithUnlessGuard(input) {
|
|
8581
|
+
if (!UNLESS_GUARD_OBJECT_MARKING_LOCALES.has(this.targetProfile.code)) return null;
|
|
8582
|
+
const tokens = tokenize(input, this.sourceProfile);
|
|
8583
|
+
if (tokens.length === 0) return null;
|
|
8584
|
+
if (!EVENT_KEYWORDS.has(tokens[0]?.toLowerCase())) return null;
|
|
8585
|
+
let guardIdx = -1;
|
|
8586
|
+
for (let i = 1; i < tokens.length; i++) {
|
|
8587
|
+
if (tokens[i].toLowerCase() === "unless") {
|
|
8588
|
+
guardIdx = i;
|
|
8589
|
+
break;
|
|
8590
|
+
}
|
|
8591
|
+
}
|
|
8592
|
+
if (guardIdx <= 0) return null;
|
|
8593
|
+
if (tokens[tokens.length - 1].toLowerCase() === "end") return null;
|
|
8594
|
+
const eventHead = tokens.slice(0, guardIdx);
|
|
8595
|
+
const guard = tokens.slice(guardIdx).join(" ");
|
|
8596
|
+
const guardOut = this.transform(guard);
|
|
8597
|
+
if (!guardOut) return null;
|
|
8598
|
+
const placeholder = "EVENTGUARDPLACEHOLDER";
|
|
8599
|
+
const headOut = this.transformSingle([...eventHead, placeholder].join(" "));
|
|
8600
|
+
if (!headOut.includes(placeholder)) return null;
|
|
8601
|
+
const eventClause = headOut.replace(placeholder, "").replace(/\s+/g, " ").trim();
|
|
8602
|
+
return [eventClause, guardOut].filter((s) => s.length > 0).join(" ");
|
|
8603
|
+
}
|
|
8604
|
+
/**
|
|
8605
|
+
* Transform an event handler whose body leads with a command-modifier
|
|
8606
|
+
* (`on <event> [from <src>] {async|once|debounced [at N]|throttled [at N]} <body>`).
|
|
8607
|
+
*
|
|
8608
|
+
* `parseEventHandler` reads the first token after the event as the **action**, so
|
|
8609
|
+
* a leading modifier is mistaken for the verb and the real verb (`fetch`/`add`) is
|
|
8610
|
+
* swept into the patient. For SOV targets the reorder then surfaces that verb
|
|
8611
|
+
* **first** (`取得 /api/data を クリック …`), and the semantic parser matches the
|
|
8612
|
+
* leading `<verb> <patient>` with the low-priority `*-generated-verb-first`
|
|
8613
|
+
* command pattern — returning a bare command and discarding the event + the rest
|
|
8614
|
+
* of the body (degenerate parse).
|
|
8615
|
+
*
|
|
8616
|
+
* Instead, lift the modifier out, transform the modifier-free handler through the
|
|
8617
|
+
* normal path (which keeps the body in canonical patient-first SOV order so the
|
|
8618
|
+
* event sits mid-stream and the existing SOV event-extraction recovers it), then
|
|
8619
|
+
* re-emit the modifier as a **leading English literal**. The semantic parser
|
|
8620
|
+
* strips a leading `once`/`debounced`/`throttled` (`extractStandaloneModifiers`)
|
|
8621
|
+
* and an `async` anywhere (`stripAsyncModifier`) before parsing, so the modifier
|
|
8622
|
+
* is consumed as handler metadata rather than shadowing the body.
|
|
8623
|
+
*
|
|
8624
|
+
* Returns `null` (fall through) when the input isn't an event handler or the body
|
|
8625
|
+
* doesn't lead with a modifier — leaving simple/Mode-B handlers byte-identical.
|
|
8626
|
+
*/
|
|
8627
|
+
tryTransformEventWithModifierBody(input) {
|
|
8628
|
+
if (this.targetProfile.wordOrder !== "SOV") return null;
|
|
8629
|
+
const tokens = tokenize(input, this.sourceProfile);
|
|
8630
|
+
if (tokens.length === 0) return null;
|
|
8631
|
+
if (!EVENT_KEYWORDS.has(tokens[0]?.toLowerCase())) return null;
|
|
8632
|
+
let i = 1;
|
|
8633
|
+
if (!tokens[i]) return null;
|
|
8634
|
+
i++;
|
|
8635
|
+
while (tokens[i] && EVENT_CONJUNCTIONS.has(tokens[i].toLowerCase()) && tokens[i + 1]) {
|
|
8636
|
+
i += 2;
|
|
8637
|
+
}
|
|
8638
|
+
if (tokens[i]?.toLowerCase() === "from" && tokens[i + 1]) {
|
|
8639
|
+
i++;
|
|
8640
|
+
while (tokens[i] && !ENGLISH_COMMANDS.has(tokens[i].toLowerCase()) && !BODY_MODIFIER_KEYWORDS.has(tokens[i].toLowerCase())) {
|
|
8641
|
+
i++;
|
|
8642
|
+
}
|
|
8643
|
+
}
|
|
8644
|
+
const modWord = tokens[i]?.toLowerCase();
|
|
8645
|
+
if (!modWord || !BODY_MODIFIER_KEYWORDS.has(modWord)) return null;
|
|
8646
|
+
const modStart = i;
|
|
8647
|
+
let modEnd = i + 1;
|
|
8648
|
+
if (modWord !== "async" && modWord !== "once") {
|
|
8649
|
+
if (tokens[modEnd]?.toLowerCase() === "at") modEnd++;
|
|
8650
|
+
if (tokens[modEnd] && /^\d+(ms|s|m)?$/.test(tokens[modEnd])) modEnd++;
|
|
8651
|
+
}
|
|
8652
|
+
const modifierPhrase = tokens.slice(modStart, modEnd).join(" ");
|
|
8653
|
+
const rebuilt = [...tokens.slice(0, modStart), ...tokens.slice(modEnd)].join(" ");
|
|
8654
|
+
if (tokens.length - (modEnd - modStart) <= 2) return null;
|
|
8655
|
+
const bodyOut = this.transform(rebuilt);
|
|
8656
|
+
return [modifierPhrase, bodyOut].filter((s) => s.length > 0).join(" ");
|
|
8657
|
+
}
|
|
8658
|
+
/**
|
|
8659
|
+
* Transform a `set <stuff> on <scope>` clause (S1 tabs-aria). The trailing
|
|
8660
|
+
* `on <scope>` is the element(s) the attribute is set on — kept attached by
|
|
8661
|
+
* splitOnCommandBoundaries. The semantic parser captures it as a `scope` role
|
|
8662
|
+
* via the passthrough literal `on` (setSchema's scope markerOverride is `on`
|
|
8663
|
+
* in every language), so `on` is emitted verbatim and only the scope *value*
|
|
8664
|
+
* is translated (selectors pass through; `me`/`it`/`you` translate to the
|
|
8665
|
+
* native reference, which the parser also accepts).
|
|
8666
|
+
*
|
|
8667
|
+
* Positioning matches where the set patterns expect the scope: at the clause
|
|
8668
|
+
* end for verb-first orders (SVO/VSO), and immediately before the clause-final
|
|
8669
|
+
* verb for SOV (the generated SOV pattern is `{dest} {patient} on {scope}
|
|
8670
|
+
* {verb}`). Returns null (fall through) when there is no trailing `on <scope>`.
|
|
8671
|
+
*
|
|
8672
|
+
* Source is English in the sync-translations pipeline, so the `set` verb and
|
|
8673
|
+
* `on` marker are matched as English literals.
|
|
8674
|
+
*/
|
|
8675
|
+
transformSetWithScope(input) {
|
|
8676
|
+
const src = this.sourceProfile.code;
|
|
8677
|
+
const dst = this.targetProfile.code;
|
|
8678
|
+
const m = input.match(/^(.*\bset\b.*\S)\s+on\s+([#.<@[]\S*|me|it|you)\s*$/i);
|
|
8679
|
+
if (!m) return null;
|
|
8680
|
+
const head = m[1];
|
|
8681
|
+
const scopeRaw = m[2];
|
|
8682
|
+
const headOut = this.transformSingle(head);
|
|
8683
|
+
const scopeT = /^[#.<@[]/.test(scopeRaw) ? scopeRaw : translateWord(scopeRaw, src, dst);
|
|
8684
|
+
if (this.targetProfile.wordOrder === "SOV") {
|
|
8685
|
+
const verb = translateWord("set", "en", dst);
|
|
8686
|
+
const firstTok = input.trim().split(/\s+/)[0]?.toLowerCase();
|
|
8687
|
+
const isEventHandler = !!firstTok && EVENT_KEYWORDS.has(firstTok);
|
|
8688
|
+
const toks = headOut.split(/\s+/).filter(Boolean);
|
|
8689
|
+
if (!isEventHandler) {
|
|
8690
|
+
const vIdx = toks.indexOf(verb);
|
|
8691
|
+
if (vIdx >= 0) {
|
|
8692
|
+
toks.splice(vIdx, 1);
|
|
8693
|
+
toks.push("on", scopeT, verb);
|
|
8694
|
+
return toks.join(" ");
|
|
8695
|
+
}
|
|
8696
|
+
} else if (toks.length > 0 && toks[toks.length - 1] === verb) {
|
|
8697
|
+
toks.splice(toks.length - 1, 0, "on", scopeT);
|
|
8698
|
+
return toks.join(" ");
|
|
8699
|
+
}
|
|
8700
|
+
return `${headOut} on ${scopeT}`;
|
|
8701
|
+
}
|
|
8702
|
+
return `${headOut} on ${scopeT}`;
|
|
8703
|
+
}
|
|
8704
|
+
/**
|
|
8705
|
+
* Transform a self-contained block command (`{head} {clause?} {body} {end}`),
|
|
8706
|
+
* where head ∈ {if, repeat, unless, …}. The clause (condition / `until event …`)
|
|
8707
|
+
* runs up to the first command verb and is translated word-by-word; the body is
|
|
8708
|
+
* recursively transformed (so its inner commands reorder for the target); the
|
|
8709
|
+
* head/tail keywords are translated. The block is never word-order reordered as
|
|
8710
|
+
* a whole — delimiters stay at the edges regardless of target word order.
|
|
8711
|
+
*/
|
|
8712
|
+
transformBlockBody(blockTokens) {
|
|
8713
|
+
const src = this.sourceProfile.code;
|
|
8714
|
+
const dst = this.targetProfile.code;
|
|
8715
|
+
const head = blockTokens[0];
|
|
8716
|
+
const hasEnd = blockTokens[blockTokens.length - 1]?.toLowerCase() === "end";
|
|
8717
|
+
const tail = hasEnd ? blockTokens[blockTokens.length - 1] : "";
|
|
8718
|
+
const inner = blockTokens.slice(1, hasEnd ? -1 : void 0);
|
|
8719
|
+
const commands = getCommandKeywordsForLocale(src);
|
|
8720
|
+
const copulas = getCopulasForLocale(src);
|
|
8721
|
+
let bodyStart = inner.findIndex(
|
|
8722
|
+
(t, i) => commands.has(t.toLowerCase()) && !isPredicateAdjectivePosition(inner, i, copulas)
|
|
8723
|
+
);
|
|
8724
|
+
if (bodyStart < 0) bodyStart = inner.length;
|
|
8725
|
+
const clause = inner.slice(0, bodyStart).join(" ");
|
|
8726
|
+
const bodyTokens = inner.slice(bodyStart);
|
|
8727
|
+
const headT = translateWord(head, src, dst);
|
|
8728
|
+
const tailT = tail ? translateWord(tail, src, dst) : "";
|
|
8729
|
+
const clauseT = clause ? translateMultiWordValue(clause, src, dst) : "";
|
|
8730
|
+
const bodyT = this.transformConditionalBody(bodyTokens);
|
|
8731
|
+
return [headT, clauseT, bodyT, tailT].filter((s) => s.length > 0).join(" ");
|
|
8732
|
+
}
|
|
8733
|
+
/**
|
|
8734
|
+
* Transform an `if`/`unless` block body, splitting it at a top-level `else` into
|
|
8735
|
+
* a then-branch and an else-branch so each is reordered as a self-contained unit
|
|
8736
|
+
* and the `else` keyword itself is translated. Without this, the body is reordered
|
|
8737
|
+
* as one stream: `else` rides along glued to the preceding clause (and, when that
|
|
8738
|
+
* clause begins with a selector, is marked a selector and left *untranslated*),
|
|
8739
|
+
* and a spurious `then` is inserted around it — both of which break the target
|
|
8740
|
+
* text and the downstream parse. The split is depth-aware so an `else` belonging
|
|
8741
|
+
* to a nested block is not mistaken for this block's separator. Bodies without an
|
|
8742
|
+
* `else` transform exactly as before.
|
|
8743
|
+
*/
|
|
8744
|
+
transformConditionalBody(bodyTokens) {
|
|
8745
|
+
const src = this.sourceProfile.code;
|
|
8746
|
+
const dst = this.targetProfile.code;
|
|
8747
|
+
const sourceElse = translateWord("else", "en", src).toLowerCase();
|
|
8748
|
+
let depth = 0;
|
|
8749
|
+
let elseIdx = -1;
|
|
8750
|
+
for (let i = 0; i < bodyTokens.length; i++) {
|
|
8751
|
+
const t = bodyTokens[i].toLowerCase();
|
|
8752
|
+
if (BLOCK_BODY_KEYWORDS.has(t)) depth++;
|
|
8753
|
+
else if (t === "end" && depth > 0) depth--;
|
|
8754
|
+
else if (t === sourceElse && depth === 0) {
|
|
8755
|
+
elseIdx = i;
|
|
8756
|
+
break;
|
|
8757
|
+
}
|
|
8758
|
+
}
|
|
8759
|
+
if (elseIdx === -1) {
|
|
8760
|
+
const body = bodyTokens.join(" ");
|
|
8761
|
+
return body ? this.transform(body) : "";
|
|
8762
|
+
}
|
|
8763
|
+
const thenBranch = bodyTokens.slice(0, elseIdx).join(" ");
|
|
8764
|
+
const elseBranch = bodyTokens.slice(elseIdx + 1).join(" ");
|
|
8765
|
+
const elseT = translateWord(bodyTokens[elseIdx], src, dst);
|
|
8766
|
+
return [
|
|
8767
|
+
thenBranch ? this.transform(thenBranch) : "",
|
|
8768
|
+
elseT,
|
|
8769
|
+
elseBranch ? this.transform(elseBranch) : ""
|
|
8770
|
+
].filter((s) => s.length > 0).join(" ");
|
|
8771
|
+
}
|
|
7653
8772
|
/**
|
|
7654
8773
|
* Translate a reactive block by translating the head/tail/connector
|
|
7655
8774
|
* via the dictionary, recursively transforming the body through the
|
|
@@ -7835,6 +8954,7 @@ exports.ko = ko;
|
|
|
7835
8954
|
exports.koDictionary = ko;
|
|
7836
8955
|
exports.koKeywords = koKeywords;
|
|
7837
8956
|
exports.koreanProfile = koreanProfile;
|
|
8957
|
+
exports.malayProfile = malayProfile;
|
|
7838
8958
|
exports.ms = ms;
|
|
7839
8959
|
exports.msDictionary = ms;
|
|
7840
8960
|
exports.msKeywords = msKeywords;
|