@lokascript/i18n 2.7.2 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +1 -1
  3. package/dist/browser.cjs +649 -180
  4. package/dist/browser.cjs.map +1 -1
  5. package/dist/browser.d.cts +2 -2
  6. package/dist/browser.d.ts +2 -2
  7. package/dist/browser.js +649 -180
  8. package/dist/browser.js.map +1 -1
  9. package/dist/dictionaries/index.cjs +370 -174
  10. package/dist/dictionaries/index.cjs.map +1 -1
  11. package/dist/dictionaries/index.js +370 -174
  12. package/dist/dictionaries/index.js.map +1 -1
  13. package/dist/index.cjs +649 -180
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +1 -1
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +649 -180
  18. package/dist/index.js.map +1 -1
  19. package/dist/lokascript-i18n.min.js +1 -1
  20. package/dist/lokascript-i18n.min.js.map +1 -1
  21. package/dist/lokascript-i18n.mjs +678 -175
  22. package/dist/lokascript-i18n.mjs.map +1 -1
  23. package/dist/plugins/vite.cjs +370 -174
  24. package/dist/plugins/vite.cjs.map +1 -1
  25. package/dist/plugins/vite.js +370 -174
  26. package/dist/plugins/vite.js.map +1 -1
  27. package/dist/plugins/webpack.cjs +370 -174
  28. package/dist/plugins/webpack.cjs.map +1 -1
  29. package/dist/plugins/webpack.js +370 -174
  30. package/dist/plugins/webpack.js.map +1 -1
  31. package/dist/{transformer-DM7iplCU.d.cts → transformer--W46PGaW.d.cts} +8 -0
  32. package/dist/{transformer-BA8YX9u1.d.ts → transformer-FU06J6kG.d.ts} +8 -0
  33. package/package.json +9 -10
  34. package/src/dictionaries/ar.ts +20 -15
  35. package/src/dictionaries/bn.ts +10 -5
  36. package/src/dictionaries/de.ts +20 -8
  37. package/src/dictionaries/es.ts +10 -5
  38. package/src/dictionaries/fr.ts +15 -6
  39. package/src/dictionaries/he.ts +4 -0
  40. package/src/dictionaries/hi.ts +3 -2
  41. package/src/dictionaries/id.ts +31 -16
  42. package/src/dictionaries/it.ts +11 -4
  43. package/src/dictionaries/ja.ts +23 -15
  44. package/src/dictionaries/ko.ts +10 -5
  45. package/src/dictionaries/ms.ts +4 -1
  46. package/src/dictionaries/pl.ts +12 -5
  47. package/src/dictionaries/pt.ts +10 -5
  48. package/src/dictionaries/qu.ts +30 -19
  49. package/src/dictionaries/ru.ts +5 -2
  50. package/src/dictionaries/sw.ts +29 -14
  51. package/src/dictionaries/th.ts +5 -2
  52. package/src/dictionaries/tl.ts +4 -1
  53. package/src/dictionaries/tr.ts +24 -16
  54. package/src/dictionaries/uk.ts +5 -2
  55. package/src/dictionaries/vi.ts +23 -17
  56. package/src/dictionaries/zh.ts +24 -9
  57. package/src/grammar/grammar.test.ts +152 -0
  58. package/src/grammar/profiles/index.ts +316 -1
  59. package/src/grammar/transformer.ts +64 -1
  60. package/src/new-languages.test.ts +9 -3
  61. package/src/positional-keyword-drift.test.ts +6 -19
package/dist/index.cjs CHANGED
@@ -383,17 +383,20 @@ var es = {
383
383
  mouseup: "rat\xF3narriba",
384
384
  mouseenter: "rat\xF3nentrar",
385
385
  mouseleave: "rat\xF3nsalir",
386
- mouseover: "rat\xF3nencima",
387
- mouseout: "rat\xF3nfuera",
386
+ // V3 Batch 2: fused forms split to the S5b/tokenizer-known forms (the fused
387
+ // spellings captured event=expression:undefined — broken listeners)
388
+ mouseover: "rat\xF3n encima",
389
+ mouseout: "rat\xF3n fuera",
388
390
  mousemove: "rat\xF3nmover",
389
- keydown: "teclaabajo",
390
- keyup: "teclaarriba",
391
+ keydown: "tecla abajo",
392
+ keyup: "tecla arriba",
391
393
  keypress: "teclapresar",
392
394
  focus: "enfocar",
393
395
  blur: "desenfocar",
394
396
  change: "cambiar",
395
397
  input: "entrada",
396
- submit: "enviar",
398
+ submit: "env\xEDo",
399
+ // Batch 3: enviar is the send verb — on-submit listener captured event "send"
397
400
  reset: "reiniciar",
398
401
  load: "cargar",
399
402
  unload: "descargar",
@@ -473,6 +476,9 @@ var es = {
473
476
  properties: "propiedades"
474
477
  },
475
478
  expressions: {
479
+ characters: "caracteres",
480
+ inclusive: "inclusivo",
481
+ exclusive: "exclusivo",
476
482
  first: "primero",
477
483
  last: "\xFAltimo",
478
484
  next: "siguiente",
@@ -560,7 +566,8 @@ var ko = {
560
566
  clear: "\uC9C0\uC6B0\uAE30",
561
567
  close: "\uB2EB\uAE30",
562
568
  open: "\uC5F4\uAE30",
563
- select: "\uC120\uD0DD",
569
+ select: "\uACE0\uB974\uAE30",
570
+ // Batch 3: 선택 is the pick keyword — bare select rendered with it parses null
564
571
  clone: "\uBCF5\uC81C",
565
572
  prepend: "\uC55E\uC5D0\uCD94\uAC00",
566
573
  socket: "\uC18C\uCF13"
@@ -601,14 +608,17 @@ var ko = {
601
608
  change: "\uBCC0\uACBD",
602
609
  input: "\uC785\uB825",
603
610
  submit: "\uC81C\uCD9C",
604
- reset: "\uB9AC\uC14B",
611
+ reset: "\uC7AC\uC124\uC815",
612
+ // Batch 3: 리셋 captured on.event as expression (broken listener) — profile word round-trips
605
613
  load: "\uB85C\uB4DC",
606
- unload: "\uC5B8\uB85C\uB4DC",
614
+ unload: "unload",
607
615
  resize: "\uB9AC\uC0AC\uC774\uC988",
608
616
  scroll: "\uC2A4\uD06C\uB864",
609
- touchstart: "\uD130\uCE58\uC2DC\uC791",
617
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
618
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
619
+ touchstart: "touchstart",
610
620
  touchend: "\uD130\uCE58\uC885\uB8CC",
611
- touchmove: "\uD130\uCE58\uC774\uB3D9",
621
+ touchmove: "touchmove",
612
622
  touchcancel: "\uD130\uCE58\uCDE8\uC18C"
613
623
  },
614
624
  logical: {
@@ -681,6 +691,9 @@ var ko = {
681
691
  properties: "\uD504\uB85C\uD37C\uD2F0\uB4E4"
682
692
  },
683
693
  expressions: {
694
+ characters: "\uBB38\uC790",
695
+ inclusive: "\uD3EC\uD568",
696
+ exclusive: "\uC81C\uC678",
684
697
  first: "\uCCAB\uBC88\uC9F8",
685
698
  last: "\uB9C8\uC9C0\uB9C9",
686
699
  next: "\uB2E4\uC74C",
@@ -794,16 +807,26 @@ var zh = {
794
807
  events: {
795
808
  click: "\u70B9\u51FB",
796
809
  dblclick: "\u53CC\u51FB",
797
- mousedown: "\u9F20\u6807\u6309\u4E0B",
798
- mouseup: "\u9F20\u6807\u62AC\u8D77",
799
- mouseenter: "\u9F20\u6807\u8FDB\u5165",
800
- mouseleave: "\u9F20\u6807\u79BB\u5F00",
801
- mouseover: "\u9F20\u6807\u60AC\u505C",
810
+ // mousedown/mouseup: English passthrough — no native form round-trips on the
811
+ // parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
812
+ // shattered to their first word — live broken listeners in repeat-until-event).
813
+ // The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
814
+ mousedown: "mousedown",
815
+ mouseup: "mouseup",
816
+ mouseenter: "mouseenter",
817
+ mouseleave: "mouseleave",
818
+ // V3 Batch 2: 鼠标悬停 captured no event (expression:undefined) — realigned
819
+ // to the tokenizer-registered 鼠标移入 (also S5b-listed). 按键抬起
820
+ // prefix-shattered to 按键 and captured `keydown` (a keyup handler firing
821
+ // on keydown) → 松键, the S5b/tokenizer form. keydown keeps 按键按下
822
+ // (captures keydown via the registered 按键 prefix; S5b-aliased) — fixing
823
+ // it to bare 按键 would collide with keypress below.
824
+ mouseover: "\u9F20\u6807\u79FB\u5165",
802
825
  mouseout: "\u9F20\u6807\u79FB\u51FA",
803
826
  mousemove: "\u9F20\u6807\u79FB\u52A8",
804
827
  keydown: "\u6309\u952E\u6309\u4E0B",
805
- keyup: "\u6309\u952E\u62AC\u8D77",
806
- keypress: "\u6309\u952E",
828
+ keyup: "\u677E\u952E",
829
+ keypress: "keypress",
807
830
  focus: "\u805A\u7126",
808
831
  blur: "\u5931\u7126",
809
832
  change: "\u6539\u53D8",
@@ -815,9 +838,11 @@ var zh = {
815
838
  resize: "\u8C03\u6574\u5927\u5C0F",
816
839
  scroll: "\u6EDA\u52A8",
817
840
  touchstart: "\u89E6\u6478\u5F00\u59CB",
818
- touchend: "\u89E6\u6478\u7ED3\u675F",
841
+ touchend: "touchend",
819
842
  touchmove: "\u89E6\u6478\u79FB\u52A8",
820
- touchcancel: "\u89E6\u6478\u53D6\u6D88"
843
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
844
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
845
+ touchcancel: "touchcancel"
821
846
  },
822
847
  logical: {
823
848
  when: "\u5F53",
@@ -889,6 +914,9 @@ var zh = {
889
914
  properties: "\u7279\u6027\u96C6"
890
915
  },
891
916
  expressions: {
917
+ characters: "\u5B57\u7B26",
918
+ inclusive: "\u5305\u542B",
919
+ exclusive: "\u6392\u9664",
892
920
  first: "\u7B2C\u4E00\u4E2A",
893
921
  last: "\u6700\u540E\u4E00\u4E2A",
894
922
  next: "\u4E0B\u4E00\u4E2A",
@@ -1000,15 +1028,21 @@ var fr = {
1000
1028
  events: {
1001
1029
  click: "clic",
1002
1030
  dblclick: "doubleclic",
1003
- mousedown: "sourisappuy\xE9e",
1004
- mouseup: "sourisrel\xE2ch\xE9e",
1031
+ // mousedown/mouseup: English passthrough — no native form round-trips on the
1032
+ // parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
1033
+ // shattered to their first word — live broken listeners in repeat-until-event).
1034
+ // The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
1035
+ mousedown: "mousedown",
1036
+ mouseup: "mouseup",
1005
1037
  mouseenter: "sourisentrer",
1006
1038
  mouseleave: "sourissortir",
1007
- mouseover: "sourissur",
1008
- mouseout: "sourisdehors",
1039
+ // V3 Batch 2: fused forms split to the S5b/tokenizer-known forms (the fused
1040
+ // spellings captured event=expression:undefined — broken listeners)
1041
+ mouseover: "souris dessus",
1042
+ mouseout: "souris dehors",
1009
1043
  mousemove: "sourisbouger",
1010
- keydown: "toucheappuy\xE9e",
1011
- keyup: "toucherel\xE2ch\xE9e",
1044
+ keydown: "touche bas",
1045
+ keyup: "touche haut",
1012
1046
  keypress: "touchepress\xE9e",
1013
1047
  focus: "focus",
1014
1048
  blur: "flou",
@@ -1094,6 +1128,9 @@ var fr = {
1094
1128
  properties: "propri\xE9t\xE9s"
1095
1129
  },
1096
1130
  expressions: {
1131
+ characters: "caract\xE8res",
1132
+ inclusive: "inclusif",
1133
+ exclusive: "exclusif",
1097
1134
  first: "premier",
1098
1135
  last: "dernier",
1099
1136
  next: "suivant",
@@ -1184,7 +1221,8 @@ var de = {
1184
1221
  // löschen is a remove alternative in the profile
1185
1222
  close: "schlie\xDFen",
1186
1223
  open: "\xF6ffnen",
1187
- select: "ausw\xE4hlen",
1224
+ select: "markieren",
1225
+ // Batch 3: auswählen is the pick keyword — bare select rendered with it parses null
1188
1226
  clone: "klonen",
1189
1227
  prepend: "voranstellen",
1190
1228
  focus: "fokussieren"
@@ -1210,18 +1248,27 @@ var de = {
1210
1248
  events: {
1211
1249
  click: "klick",
1212
1250
  dblclick: "doppelklick",
1213
- mousedown: "mausunten",
1214
- mouseup: "mausoben",
1251
+ // mousedown/mouseup: English passthrough — no native form round-trips on the
1252
+ // parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
1253
+ // shattered to their first word — live broken listeners in repeat-until-event).
1254
+ // The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
1255
+ mousedown: "mousedown",
1256
+ mouseup: "mouseup",
1215
1257
  mouseenter: "mauseintreten",
1216
1258
  mouseleave: "mausverlassen",
1217
- mouseover: "maus\xFCber",
1218
- mouseout: "maushinaus",
1259
+ // V3 Batch 2: fused/dead event words realigned to the de tokenizer's
1260
+ // registered forms (S5b's `maus über`/`taste runter` are aspirational — they
1261
+ // do not tokenize; `mausüber` etc. captured event=expression:undefined).
1262
+ mouseover: "maus dr\xFCber",
1263
+ mouseout: "maus weg",
1219
1264
  mousemove: "mausbewegen",
1220
- keydown: "tasteunten",
1221
- keyup: "tasteoben",
1265
+ keydown: "taste unten",
1266
+ keyup: "taste oben",
1222
1267
  keypress: "tastedr\xFCcken",
1223
1268
  focus: "fokus",
1224
- blur: "unscharf",
1269
+ // matches commands.blur (which shadows this at render time) and the live
1270
+ // corpus render; `unscharf` was dead vocab that captured no event
1271
+ blur: "defokussieren",
1225
1272
  change: "\xE4ndern",
1226
1273
  input: "eingabe",
1227
1274
  submit: "absenden",
@@ -1304,6 +1351,9 @@ var de = {
1304
1351
  properties: "eigenschaften"
1305
1352
  },
1306
1353
  expressions: {
1354
+ characters: "Zeichen",
1355
+ inclusive: "inklusiv",
1356
+ exclusive: "exklusiv",
1307
1357
  first: "erste",
1308
1358
  last: "letzte",
1309
1359
  next: "n\xE4chste",
@@ -1396,7 +1446,8 @@ var ja = {
1396
1446
  clear: "\u30AF\u30EA\u30A2",
1397
1447
  close: "\u9589\u3058\u308B",
1398
1448
  open: "\u958B\u304F",
1399
- select: "\u9078\u629E",
1449
+ select: "\u9078\u3076",
1450
+ // Batch 3: 選択 is the pick keyword — bare select rendered with it parses null
1400
1451
  clone: "\u8907\u88FD",
1401
1452
  prepend: "\u5148\u982D\u8FFD\u52A0",
1402
1453
  socket: "\u30BD\u30B1\u30C3\u30C8"
@@ -1421,17 +1472,22 @@ var ja = {
1421
1472
  },
1422
1473
  events: {
1423
1474
  click: "\u30AF\u30EA\u30C3\u30AF",
1424
- dblclick: "\u30C0\u30D6\u30EB\u30AF\u30EA\u30C3\u30AF",
1475
+ dblclick: "dblclick",
1425
1476
  mousedown: "\u30DE\u30A6\u30B9\u62BC\u4E0B",
1426
1477
  mouseup: "\u30DE\u30A6\u30B9\u89E3\u653E",
1427
- mouseenter: "\u30DE\u30A6\u30B9\u5165\u308B",
1428
- mouseleave: "\u30DE\u30A6\u30B9\u96E2\u308C\u308B",
1429
- mouseover: "\u30DE\u30A6\u30B9\u4E0A",
1430
- mouseout: "\u30DE\u30A6\u30B9\u5916",
1431
- mousemove: "\u30DE\u30A6\u30B9\u79FB\u52D5",
1432
- keydown: "\u30AD\u30FC\u62BC\u4E0B",
1433
- keyup: "\u30AD\u30FC\u89E3\u653E",
1434
- keypress: "\u30AD\u30FC\u62BC\u3059",
1478
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
1479
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
1480
+ mouseenter: "mouseenter",
1481
+ mouseleave: "mouseleave",
1482
+ // V3 Batch 2: kanji compounds realigned to the S5b/tokenizer katakana
1483
+ // loanwords (the standard JS event terms; the compounds captured
1484
+ // event=expression:undefined — broken listeners)
1485
+ mouseover: "\u30DE\u30A6\u30B9\u30AA\u30FC\u30D0\u30FC",
1486
+ mouseout: "\u30DE\u30A6\u30B9\u30A2\u30A6\u30C8",
1487
+ mousemove: "mousemove",
1488
+ keydown: "\u30AD\u30FC\u30C0\u30A6\u30F3",
1489
+ keyup: "\u30AD\u30FC\u30A2\u30C3\u30D7",
1490
+ keypress: "\u30AD\u30FC\u30D7\u30EC\u30B9",
1435
1491
  focus: "\u30D5\u30A9\u30FC\u30AB\u30B9",
1436
1492
  blur: "\u307C\u304B\u3057",
1437
1493
  change: "\u5909\u66F4",
@@ -1439,13 +1495,13 @@ var ja = {
1439
1495
  submit: "\u9001\u4FE1",
1440
1496
  reset: "\u30EA\u30BB\u30C3\u30C8",
1441
1497
  load: "\u8AAD\u307F\u8FBC\u307F",
1442
- unload: "\u8AAD\u307F\u8FBC\u307F\u89E3\u9664",
1498
+ unload: "unload",
1443
1499
  resize: "\u30B5\u30A4\u30BA\u5909\u66F4",
1444
1500
  scroll: "\u30B9\u30AF\u30ED\u30FC\u30EB",
1445
- touchstart: "\u30BF\u30C3\u30C1\u958B\u59CB",
1446
- touchend: "\u30BF\u30C3\u30C1\u7D42\u4E86",
1447
- touchmove: "\u30BF\u30C3\u30C1\u79FB\u52D5",
1448
- touchcancel: "\u30BF\u30C3\u30C1\u30AD\u30E3\u30F3\u30BB\u30EB"
1501
+ touchstart: "touchstart",
1502
+ touchend: "touchend",
1503
+ touchmove: "touchmove",
1504
+ touchcancel: "touchcancel"
1449
1505
  },
1450
1506
  logical: {
1451
1507
  when: "\u6642",
@@ -1517,6 +1573,9 @@ var ja = {
1517
1573
  properties: "\u30D7\u30ED\u30D1\u30C6\u30A3\u7FA4"
1518
1574
  },
1519
1575
  expressions: {
1576
+ characters: "\u6587\u5B57",
1577
+ inclusive: "\u542B\u3080",
1578
+ exclusive: "\u9664\u304F",
1520
1579
  first: "\u6700\u521D",
1521
1580
  last: "\u6700\u5F8C",
1522
1581
  next: "\u6B21",
@@ -1603,7 +1662,8 @@ var ar = {
1603
1662
  // امسح is a remove alternative in the profile
1604
1663
  close: "\u0623\u063A\u0644\u0642",
1605
1664
  open: "\u0627\u0641\u062A\u062D",
1606
- select: "\u0627\u062E\u062A\u0631",
1665
+ select: "\u0638\u0644\u0644",
1666
+ // Batch 3: اختر is the pick keyword — bare select rendered with it parses null
1607
1667
  clone: "\u0627\u0633\u062A\u0646\u0633\u062E",
1608
1668
  prepend: "\u0633\u0628\u0642",
1609
1669
  socket: "\u0645\u0642\u0628\u0633"
@@ -1628,31 +1688,33 @@ var ar = {
1628
1688
  },
1629
1689
  events: {
1630
1690
  click: "\u0646\u0642\u0631",
1631
- dblclick: "\u0646\u0642\u0631 \u0645\u0632\u062F\u0648\u062C",
1632
- mousedown: "\u0641\u0623\u0631\u0629 \u0623\u0633\u0641\u0644",
1633
- mouseup: "\u0641\u0623\u0631\u0629 \u0623\u0639\u0644\u0649",
1634
- mouseenter: "\u0641\u0623\u0631\u0629 \u062F\u062E\u0648\u0644",
1635
- mouseleave: "\u0641\u0623\u0631\u0629 \u062E\u0631\u0648\u062C",
1691
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
1692
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
1693
+ dblclick: "dblclick",
1694
+ mousedown: "mousedown",
1695
+ mouseup: "mouseup",
1696
+ mouseenter: "mouseenter",
1697
+ mouseleave: "mouseleave",
1636
1698
  mouseover: "\u0641\u0623\u0631\u0629 \u0641\u0648\u0642",
1637
- mouseout: "\u0641\u0623\u0631\u0629 \u062E\u0627\u0631\u062C",
1638
- mousemove: "\u0641\u0623\u0631\u0629 \u062A\u062D\u0631\u0643",
1699
+ mouseout: "mouseout",
1700
+ mousemove: "mousemove",
1639
1701
  keydown: "\u0645\u0641\u062A\u0627\u062D \u0623\u0633\u0641\u0644",
1640
1702
  keyup: "\u0645\u0641\u062A\u0627\u062D \u0623\u0639\u0644\u0649",
1641
- keypress: "\u0645\u0641\u062A\u0627\u062D \u0636\u063A\u0637",
1703
+ keypress: "keypress",
1642
1704
  focus: "\u062A\u0631\u0643\u064A\u0632",
1643
1705
  blur: "\u0636\u0628\u0627\u0628\u064A\u0629",
1644
1706
  change: "\u062A\u063A\u064A\u064A\u0631",
1645
1707
  input: "\u0625\u062F\u062E\u0627\u0644",
1646
1708
  submit: "\u0625\u0631\u0633\u0627\u0644",
1647
- reset: "\u0625\u0639\u0627\u062F\u0629 \u062A\u0639\u064A\u064A\u0646",
1709
+ reset: "reset",
1648
1710
  load: "\u062A\u062D\u0645\u064A\u0644",
1649
- unload: "\u0625\u0644\u063A\u0627\u0621 \u062A\u062D\u0645\u064A\u0644",
1711
+ unload: "unload",
1650
1712
  resize: "\u062A\u063A\u064A\u064A\u0631 \u062D\u062C\u0645",
1651
1713
  scroll: "\u062A\u0645\u0631\u064A\u0631",
1652
- touchstart: "\u0628\u062F\u0627\u064A\u0629 \u0644\u0645\u0633",
1653
- touchend: "\u0646\u0647\u0627\u064A\u0629 \u0644\u0645\u0633",
1654
- touchmove: "\u062A\u062D\u0631\u0643 \u0644\u0645\u0633",
1655
- touchcancel: "\u0625\u0644\u063A\u0627\u0621 \u0644\u0645\u0633"
1714
+ touchstart: "touchstart",
1715
+ touchend: "touchend",
1716
+ touchmove: "touchmove",
1717
+ touchcancel: "touchcancel"
1656
1718
  },
1657
1719
  logical: {
1658
1720
  when: "\u0639\u0646\u062F\u0645\u0627",
@@ -1724,6 +1786,9 @@ var ar = {
1724
1786
  properties: "\u062E\u0635\u0627\u0626\u0635"
1725
1787
  },
1726
1788
  expressions: {
1789
+ characters: "\u062D\u0631\u0648\u0641",
1790
+ inclusive: "\u0634\u0627\u0645\u0644",
1791
+ exclusive: "\u062D\u0635\u0631\u064A",
1727
1792
  first: "\u0623\u0648\u0644",
1728
1793
  last: "\u0622\u062E\u0631",
1729
1794
  next: "\u0627\u0644\u062A\u0627\u0644\u064A",
@@ -1811,7 +1876,8 @@ var tr = {
1811
1876
  clear: "temizle",
1812
1877
  close: "kapat",
1813
1878
  open: "a\xE7",
1814
- select: "se\xE7",
1879
+ select: "vurgula",
1880
+ // Batch 3: seç is the pick keyword — bare select rendered with it parses null
1815
1881
  clone: "klonla",
1816
1882
  prepend: "ba\u015F\u0131naekle",
1817
1883
  socket: "soket"
@@ -1836,34 +1902,40 @@ var tr = {
1836
1902
  },
1837
1903
  events: {
1838
1904
  click: "t\u0131klama",
1839
- dblclick: "\xE7ift_t\u0131klama",
1905
+ dblclick: "dblclick",
1840
1906
  // Fused (no `_`): the semantic tokenizer splits on `_`, breaking event
1841
1907
  // recognition (mousedown → "bas" / mouseup mis-captured). Mirrors the #535
1842
1908
  // ru/uk fuse + #510 resize fix.
1843
1909
  mousedown: "farebas",
1844
1910
  mouseup: "fareb\u0131rak",
1845
- mouseenter: "fare_gir",
1846
- mouseleave: "fare_\xE7\u0131k",
1847
- mouseover: "fare_\xFCst\xFC",
1848
- mouseout: "fare_d\u0131\u015F\u0131",
1849
- mousemove: "fare_hareket",
1850
- keydown: "tu\u015F_bas",
1851
- keyup: "tu\u015F_b\u0131rak",
1852
- keypress: "tu\u015F_bas\u0131m",
1911
+ mouseenter: "mouseenter",
1912
+ mouseleave: "mouseleave",
1913
+ // V3 Batch 2: same `_`-split class (tuş_bas captured verbatim `bas` — a
1914
+ // listener for a DOM event named "bas") — realigned to the S5b/tokenizer
1915
+ // fused forms.
1916
+ mouseover: "farei\xE7inde",
1917
+ mouseout: "fared\u0131\u015F\u0131nda",
1918
+ mousemove: "mousemove",
1919
+ keydown: "tu\u015Fbasma",
1920
+ keyup: "tu\u015Fb\u0131rakma",
1921
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
1922
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
1923
+ keypress: "keypress",
1853
1924
  focus: "odak",
1854
1925
  blur: "bulan\u0131k",
1855
1926
  change: "de\u011Fi\u015Fim",
1856
1927
  input: "giri\u015F",
1857
- submit: "g\xF6nder",
1928
+ submit: "g\xF6nderme",
1929
+ // Batch 3: gönder is the send verb — on-submit listener captured event "send"
1858
1930
  reset: "s\u0131f\u0131rla",
1859
1931
  load: "y\xFCkle",
1860
- unload: "y\xFCkle_kald\u0131r",
1932
+ unload: "unload",
1861
1933
  resize: "boyutland\u0131rma",
1862
1934
  scroll: "kayd\u0131r",
1863
- touchstart: "dokunma_ba\u015Fla",
1864
- touchend: "dokunma_bitir",
1865
- touchmove: "dokunma_hareket",
1866
- touchcancel: "dokunma_iptal"
1935
+ touchstart: "touchstart",
1936
+ touchend: "touchend",
1937
+ touchmove: "touchmove",
1938
+ touchcancel: "touchcancel"
1867
1939
  },
1868
1940
  logical: {
1869
1941
  when: "iken",
@@ -1934,6 +2006,9 @@ var tr = {
1934
2006
  properties: "\xF6zellikler"
1935
2007
  },
1936
2008
  expressions: {
2009
+ characters: "karakterler",
2010
+ inclusive: "dahil",
2011
+ exclusive: "hari\xE7",
1937
2012
  first: "ilk",
1938
2013
  // 'son' is also the END keyword emission (block terminator), and the
1939
2014
  // parser's end-recognizers match it by value — so a positional `last`
@@ -2030,9 +2105,11 @@ var id = {
2030
2105
  breakpoint: "titik-henti",
2031
2106
  clear: "bersihkan",
2032
2107
  // hapus is the remove PRIMARY in the profile
2033
- close: "tutup",
2108
+ close: "tutupkan",
2109
+ // Batch 3: tutup is the hide keyword — rendered close parsed as action=hide
2034
2110
  open: "buka",
2035
- select: "pilih",
2111
+ select: "tandai",
2112
+ // Batch 3: pilih is the pick keyword — bare select rendered with it parses null
2036
2113
  clone: "klon",
2037
2114
  prepend: "awali"
2038
2115
  },
@@ -2056,17 +2133,27 @@ var id = {
2056
2133
  },
2057
2134
  events: {
2058
2135
  click: "klik",
2059
- dblclick: "klik_ganda",
2060
- mousedown: "tekan_mouse",
2061
- mouseup: "lepas_mouse",
2062
- mouseenter: "mouse_masuk",
2063
- mouseleave: "mouse_keluar",
2064
- mouseover: "mouse_atas",
2065
- mouseout: "mouse_luar",
2066
- mousemove: "gerak_mouse",
2136
+ dblclick: "dblclick",
2137
+ // mousedown/mouseup: English passthrough — no native form round-trips on the
2138
+ // parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
2139
+ // shattered to their first word — live broken listeners in repeat-until-event).
2140
+ // The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
2141
+ mousedown: "mousedown",
2142
+ mouseup: "mouseup",
2143
+ mouseenter: "mouseenter",
2144
+ mouseleave: "mouseleave",
2145
+ // V3 Batch 2: mouse_atas/mouse_luar captured no event (the S5b forms
2146
+ // `mouse masuk`/`mouse keluar` are aspirational — they don't tokenize
2147
+ // either) — realigned to the tokenizer-registered natives. keydown keeps
2148
+ // tekan_tombol (captures keydown via the registered `tekan`; S5b-aliased).
2149
+ // keyup has NO parseable native (lepas is unregistered) → English
2150
+ // passthrough, matching the blur/reset precedent below.
2151
+ mouseover: "arahkan",
2152
+ mouseout: "tinggalkan",
2153
+ mousemove: "mousemove",
2067
2154
  keydown: "tekan_tombol",
2068
- keyup: "lepas_tombol",
2069
- keypress: "pencet_tombol",
2155
+ keyup: "keyup",
2156
+ keypress: "keypress",
2070
2157
  focus: "fokus",
2071
2158
  blur: "blur",
2072
2159
  change: "ubah",
@@ -2077,10 +2164,12 @@ var id = {
2077
2164
  unload: "bongkar",
2078
2165
  resize: "ubah_ukuran",
2079
2166
  scroll: "gulir",
2080
- touchstart: "mulai_sentuh",
2081
- touchend: "akhir_sentuh",
2082
- touchmove: "gerak_sentuh",
2083
- touchcancel: "batal_sentuh"
2167
+ touchstart: "touchstart",
2168
+ touchend: "touchend",
2169
+ touchmove: "touchmove",
2170
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
2171
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
2172
+ touchcancel: "touchcancel"
2084
2173
  },
2085
2174
  logical: {
2086
2175
  when: "ketika",
@@ -2151,6 +2240,9 @@ var id = {
2151
2240
  properties: "properti_properti"
2152
2241
  },
2153
2242
  expressions: {
2243
+ characters: "karakter",
2244
+ inclusive: "inklusif",
2245
+ exclusive: "eksklusif",
2154
2246
  first: "pertama",
2155
2247
  last: "terakhir",
2156
2248
  next: "berikutnya",
@@ -2256,8 +2348,10 @@ var qu = {
2256
2348
  breakpoint: "sayachinay",
2257
2349
  clear: "pichay",
2258
2350
  close: "wichqay",
2259
- open: "kichay",
2260
- select: "akllay",
2351
+ open: "paskay",
2352
+ // Batch 3: kichay is the trigger keyword — rendered open parsed null
2353
+ select: "marcay",
2354
+ // Batch 3: akllay is the pick keyword — bare select rendered with it parses null
2261
2355
  clone: "kikinchay",
2262
2356
  prepend: "\xF1awpachiy",
2263
2357
  socket: "tinkina"
@@ -2282,33 +2376,42 @@ var qu = {
2282
2376
  },
2283
2377
  events: {
2284
2378
  click: "\xF1itiy",
2285
- dblclick: "iskay_\xF1itiy",
2379
+ dblclick: "dblclick",
2286
2380
  // Fused (no `_`): the semantic tokenizer splits on `_` — and `rat_ñitiy` then
2287
2381
  // mis-captured as the `click` event (ñitiy→click). Mirrors the #535 ru/uk fuse.
2288
2382
  mousedown: "rat\xF1itiy",
2289
2383
  mouseup: "rathuqariy",
2290
- mouseenter: "rat_yaykuy",
2291
- mouseleave: "rat_lluqsiy",
2292
- mouseover: "rat_hawapi",
2293
- mouseout: "rat_hawamanta",
2294
- mousemove: "rat_kuyuy",
2295
- keydown: "yupana_\xF1itiy",
2296
- keyup: "yupana_huqariy",
2297
- keypress: "yupana_\xF1itana",
2384
+ mouseenter: "mouseenter",
2385
+ mouseleave: "mouseleave",
2386
+ mouseover: "mouseover",
2387
+ mouseout: "mouseout",
2388
+ mousemove: "mousemove",
2389
+ // V3 Batch 2: `yupana_ñitiy` split at `_` and mis-captured as the `click`
2390
+ // event (ñitiy→click, the same mechanism as the mousedown fuse above);
2391
+ // `yupana_huqariy` captured verbatim `huqariy`. Realigned to the
2392
+ // S5b/tokenizer forms.
2393
+ keydown: "llave uray",
2394
+ keyup: "llave hawa",
2395
+ keypress: "keypress",
2298
2396
  focus: "qhaway",
2299
2397
  blur: "paqariy",
2300
- change: "tikray",
2398
+ change: "kambiay",
2399
+ // Batch 3: tikray is the toggle verb — on-change listener captured event "toggle"
2301
2400
  input: "yaykuchiy",
2302
- submit: "kachay",
2303
- reset: "qallariy",
2401
+ submit: "apaykachay",
2402
+ // Batch 3: kachay is the send verb — on-submit captured "send" in one corpus slot
2403
+ reset: "musuqchay",
2404
+ // Batch 3: qallariy is the init/start word — on-reset listener captured event "default"
2304
2405
  load: "apakuy",
2305
- unload: "urmay",
2406
+ unload: "unload",
2306
2407
  resize: "hatun_kay",
2307
2408
  scroll: "kunray",
2308
- touchstart: "llamiy_qallay",
2309
- touchend: "llamiy_tukuy",
2310
- touchmove: "llamiy_kuyuy",
2311
- touchcancel: "llamiy_hark_ay"
2409
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
2410
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
2411
+ touchstart: "touchstart",
2412
+ touchend: "touchend",
2413
+ touchmove: "touchmove",
2414
+ touchcancel: "touchcancel"
2312
2415
  },
2313
2416
  logical: {
2314
2417
  when: "maykama",
@@ -2383,6 +2486,11 @@ var qu = {
2383
2486
  properties: "kanaykuna"
2384
2487
  },
2385
2488
  expressions: {
2489
+ // Pick unit word (arc 3): native-first per qu convention — `sanampa`
2490
+ // ("sign/letter", the standard term for alphabet characters) over a
2491
+ // loanword. Paired with the QUECHUA_EXTRAS entry in the semantic
2492
+ // tokenizer; both surfaces must match verbatim.
2493
+ characters: "sanampa",
2386
2494
  first: "\xF1awpaq",
2387
2495
  last: "qhipa",
2388
2496
  next: "qhipantin",
@@ -2441,7 +2549,10 @@ var sw = {
2441
2549
  wait: "ngoja",
2442
2550
  fetch: "leta",
2443
2551
  call: "ita",
2444
- return: "rudi",
2552
+ // `rudisha` (transitive, "give back a value"), not `rudi` ("go back"): the
2553
+ // semantic profile reads `rudisha`/`rejea`, so emitting `rudi` produced sw code
2554
+ // the parser could not read back. Kept clear of `rudia` (= `repeat`).
2555
+ return: "rudisha",
2445
2556
  make: "tengeneza",
2446
2557
  // auditor: dict emitted a word the profile reads differently
2447
2558
  log: "andika",
@@ -2455,7 +2566,8 @@ var sw = {
2455
2566
  go: "nenda",
2456
2567
  pushUrl: "sukumaUrl",
2457
2568
  replaceUrl: "badilishaUrl",
2458
- copy: "nakili",
2569
+ copy: "nakala",
2570
+ // Batch 3: nakili is the clone keyword — rendered copy parsed as action=clone
2459
2571
  pick: "chagua",
2460
2572
  beep: "lia",
2461
2573
  js: "js",
@@ -2474,7 +2586,8 @@ var sw = {
2474
2586
  // futa is a remove alternative in the profile
2475
2587
  close: "funga",
2476
2588
  open: "fungua",
2477
- select: "chagua",
2589
+ select: "alama",
2590
+ // Batch 3: chagua is the pick keyword — bare select rendered with it parses null
2478
2591
  clone: "nakili",
2479
2592
  prepend: "tanguliza",
2480
2593
  focus: "lenga",
@@ -2507,31 +2620,42 @@ var sw = {
2507
2620
  },
2508
2621
  events: {
2509
2622
  click: "bonyeza",
2510
- dblclick: "bonyeza_mara_mbili",
2623
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
2624
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
2625
+ dblclick: "dblclick",
2511
2626
  mousedown: "panya_shuka",
2512
2627
  mouseup: "panya_juu",
2513
2628
  mouseenter: "panya_ingia",
2514
2629
  mouseleave: "panya_toka",
2515
- mouseover: "panya_juu",
2630
+ // V3 Batch 2: panya_juu is mouseup's form (shared here by mistake — the
2631
+ // tokenizer deliberately maps it to mouseup for the corpus row, so a
2632
+ // mouseover handler captured `mouseup`) — realigned to the
2633
+ // tokenizer-registered `sogeza juu`.
2634
+ mouseover: "sogeza juu",
2516
2635
  mouseout: "panya_nje",
2517
2636
  mousemove: "panya_sogea",
2518
2637
  keydown: "kitufe_shuka",
2519
2638
  keyup: "kitufe_juu",
2520
- keypress: "kitufe_bonyeza",
2521
- focus: "zingatia",
2522
- blur: "poteza_macho",
2523
- change: "badilisha",
2639
+ keypress: "keypress",
2640
+ // V3 Batch 2: zingatia captured no event → lenga (S5b/tokenizer form);
2641
+ // poteza_macho was a null parse → `blur` (the S5b identity form — matches
2642
+ // the live corpus render `kwenye blur`); badilisha is the toggle VERB
2643
+ // homonym (a change handler captured event=`toggle` — a listener for a DOM
2644
+ // event named "toggle") → kubadilisha (S5b/tokenizer form).
2645
+ focus: "lenga",
2646
+ blur: "blur",
2647
+ change: "kubadilisha",
2524
2648
  input: "ingizo",
2525
2649
  submit: "wasilisha",
2526
- reset: "weka_upya",
2650
+ reset: "reset",
2527
2651
  load: "pakia",
2528
2652
  unload: "shuka",
2529
2653
  resize: "badilisha_ukubwa",
2530
2654
  scroll: "sogeza",
2531
- touchstart: "gusa_anza",
2532
- touchend: "gusa_mwisho",
2533
- touchmove: "gusa_sogea",
2534
- touchcancel: "gusa_ghairi"
2655
+ touchstart: "touchstart",
2656
+ touchend: "touchend",
2657
+ touchmove: "touchmove",
2658
+ touchcancel: "touchcancel"
2535
2659
  },
2536
2660
  logical: {
2537
2661
  when: "wakati",
@@ -2602,6 +2726,7 @@ var sw = {
2602
2726
  properties: "mali"
2603
2727
  },
2604
2728
  expressions: {
2729
+ characters: "herufi",
2605
2730
  first: "kwanza",
2606
2731
  // 'mwisho' is the END keyword (block terminator) — the tokenizer's keyword
2607
2732
  // map is last-wins, so a positional `last` emission of 'mwisho' reads as
@@ -2731,18 +2856,21 @@ var pt = {
2731
2856
  mouseup: "mouseCima",
2732
2857
  mouseenter: "mouseEntrar",
2733
2858
  mouseleave: "mouseSair",
2734
- mouseover: "mouseSobre",
2735
- mouseout: "mouseFora",
2859
+ // V3 Batch 2: camelCase forms split to the S5b/tokenizer-known forms (the
2860
+ // fused spellings captured event=expression:undefined — broken listeners)
2861
+ mouseover: "mouse sobre",
2862
+ mouseout: "mouse fora",
2736
2863
  mousemove: "mouseMover",
2737
- keydown: "teclaBaixo",
2738
- keyup: "teclaCima",
2864
+ keydown: "tecla baixo",
2865
+ keyup: "tecla cima",
2739
2866
  keypress: "teclaPressionar",
2740
2867
  focus: "foco",
2741
2868
  blur: "desfoque",
2742
2869
  change: "mudan\xE7a",
2743
2870
  input: "entrada",
2744
2871
  submit: "envio",
2745
- reset: "reiniciar",
2872
+ reset: "redefinir",
2873
+ // Batch 3: reiniciar captured on.event as expression (broken listener) — profile word round-trips
2746
2874
  load: "carregar",
2747
2875
  unload: "descarregar",
2748
2876
  resize: "redimensionar",
@@ -2821,6 +2949,9 @@ var pt = {
2821
2949
  properties: "propriedades"
2822
2950
  },
2823
2951
  expressions: {
2952
+ characters: "caracteres",
2953
+ inclusive: "inclusivo",
2954
+ exclusive: "exclusivo",
2824
2955
  first: "primeiro",
2825
2956
  last: "\xFAltimo",
2826
2957
  next: "pr\xF3ximo",
@@ -2931,8 +3062,12 @@ var it = {
2931
3062
  events: {
2932
3063
  click: "clic",
2933
3064
  dblclick: "doppioclic",
2934
- mousedown: "mousegi\xF9",
2935
- mouseup: "mousesu",
3065
+ // mousedown/mouseup: English passthrough — no native form round-trips on the
3066
+ // parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
3067
+ // shattered to their first word — live broken listeners in repeat-until-event).
3068
+ // The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
3069
+ mousedown: "mousedown",
3070
+ mouseup: "mouseup",
2936
3071
  mouseenter: "mouseentra",
2937
3072
  mouseleave: "mouseesce",
2938
3073
  mouseover: "mousesopra",
@@ -2942,11 +3077,13 @@ var it = {
2942
3077
  keyup: "tastosu",
2943
3078
  keypress: "tastopremi",
2944
3079
  focus: "fuoco",
2945
- blur: "sfuocatura",
3080
+ blur: "sfuocare",
3081
+ // Batch 3: the noun form parsed the blur command with no patient; the verb round-trips both event and command slots
2946
3082
  change: "cambio",
2947
3083
  input: "input",
2948
3084
  submit: "invio",
2949
- reset: "reset",
3085
+ reset: "reimpostare",
3086
+ // Batch 3: English passthrough captured on.event as expression — profile verb round-trips
2950
3087
  load: "carica",
2951
3088
  unload: "scarica",
2952
3089
  resize: "ridimensiona",
@@ -3025,6 +3162,9 @@ var it = {
3025
3162
  properties: "propriet\xE0"
3026
3163
  },
3027
3164
  expressions: {
3165
+ characters: "caratteri",
3166
+ inclusive: "inclusivo",
3167
+ exclusive: "esclusivo",
3028
3168
  first: "primo",
3029
3169
  last: "ultimo",
3030
3170
  next: "prossimo",
@@ -3107,15 +3247,18 @@ var vi = {
3107
3247
  init: "kh\u1EDFi t\u1EA1o",
3108
3248
  behavior: "h\xE0nh vi",
3109
3249
  install: "c\xE0i \u0111\u1EB7t",
3110
- clone: "sao ch\xE9p",
3111
- prepend: "th\xEAm \u0111\u1EA7u",
3250
+ clone: "nh\xE2n b\u1EA3n",
3251
+ // Batch 3: 'sao chép' is the copy verb — rendered clone parsed as action=copy
3252
+ prepend: "th\xEAm v\xE0o \u0111\u1EA7u",
3253
+ // Batch 3: 'thêm đầu' shatters at 'thêm' (add) — parsed as action=add
3112
3254
  else: "kh\xF4ng th\xEC",
3113
3255
  breakpoint: "\u0111i\u1EC3m-d\u1EEBng",
3114
3256
  clear: "t\u1EA9y",
3115
3257
  // xóa is the remove PRIMARY in the profile
3116
3258
  close: "\u0111\xF3ng",
3117
3259
  open: "m\u1EDF",
3118
- select: "ch\u1ECDn"
3260
+ select: "\u0111\xE1nh-d\u1EA5u"
3261
+ // Batch 3: 'chọn' is the pick keyword — bare select rendered with it parses null
3119
3262
  },
3120
3263
  modifiers: {
3121
3264
  into: "v\xE0o",
@@ -3138,21 +3281,24 @@ var vi = {
3138
3281
  },
3139
3282
  events: {
3140
3283
  click: "nh\u1EA5p",
3141
- dblclick: "nh\u1EA5p \u0111\xFAp",
3284
+ dblclick: "dblclick",
3142
3285
  input: "nh\u1EADp",
3143
- change: "thay \u0111\u1ED5i",
3144
- submit: "g\u1EEDi",
3145
- keydown: "ph\xEDm xu\u1ED1ng",
3146
- keyup: "ph\xEDm l\xEAn",
3147
- keypress: "nh\u1EA5n ph\xEDm",
3148
- mouseover: "chu\u1ED9t v\xE0o",
3149
- mouseout: "chu\u1ED9t ra",
3150
- mouseenter: "chu\u1ED9t v\xE0o",
3151
- mouseleave: "chu\u1ED9t r\u1EDDi",
3152
- focus: "t\u1EADp trung",
3153
- blur: "m\u1EA5t t\u1EADp trung",
3154
- reset: "\u0111\u1EB7t-l\u1EA1i",
3155
- load: "t\u1EA3i",
3286
+ change: "change",
3287
+ submit: "n\u1ED9p",
3288
+ // Batch 3: 'gửi' is the send verb — on-submit listener captured event "send"
3289
+ keydown: "keydown",
3290
+ keyup: "keyup",
3291
+ keypress: "keypress",
3292
+ mouseover: "mouseover",
3293
+ mouseout: "mouseout",
3294
+ mouseenter: "mouseenter",
3295
+ mouseleave: "mouseleave",
3296
+ focus: "focus",
3297
+ blur: "blur",
3298
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
3299
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
3300
+ reset: "reset",
3301
+ load: "load",
3156
3302
  scroll: "cu\u1ED9n",
3157
3303
  resize: "\u0111\u1ED5i k\xEDch th\u01B0\u1EDBc"
3158
3304
  },
@@ -3228,6 +3374,10 @@ var vi = {
3228
3374
  selected: "\u0111\u01B0\u1EE3c ch\u1ECDn"
3229
3375
  },
3230
3376
  expressions: {
3377
+ random: "ng\u1EABu nhi\xEAn",
3378
+ characters: "k\xFD t\u1EF1",
3379
+ inclusive: "bao g\u1ED3m",
3380
+ exclusive: "lo\u1EA1i tr\u1EEB",
3231
3381
  me: "t\xF4i",
3232
3382
  my: "c\u1EE7a t\xF4i",
3233
3383
  it: "n\xF3",
@@ -3319,7 +3469,8 @@ var pl = {
3319
3469
  // wyczyść is a remove alternative in the profile
3320
3470
  close: "zamknij",
3321
3471
  open: "otw\xF3rz",
3322
- select: "wybierz",
3472
+ select: "zaznacz",
3473
+ // Batch 3: wybierz is the pick keyword — bare select rendered with it parses null
3323
3474
  clone: "sklonuj",
3324
3475
  prepend: "poprzed\u017A",
3325
3476
  focus: "skup"
@@ -3345,8 +3496,12 @@ var pl = {
3345
3496
  events: {
3346
3497
  click: "klikni\u0119cie",
3347
3498
  dblclick: "podw\xF3jneklikni\u0119cie",
3348
- mousedown: "myszd\xF3\u0142",
3349
- mouseup: "myszg\xF3ra",
3499
+ // mousedown/mouseup: English passthrough — no native form round-trips on the
3500
+ // parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
3501
+ // shattered to their first word — live broken listeners in repeat-until-event).
3502
+ // The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
3503
+ mousedown: "mousedown",
3504
+ mouseup: "mouseup",
3350
3505
  mouseenter: "myszwej\u015Bcie",
3351
3506
  mouseleave: "myszwyj\u015Bcie",
3352
3507
  mouseover: "mysznad",
@@ -3359,8 +3514,10 @@ var pl = {
3359
3514
  blur: "rozmycie",
3360
3515
  change: "zmiana",
3361
3516
  input: "wej\u015Bcie",
3362
- submit: "wy\u015Blij",
3363
- reset: "resetuj",
3517
+ submit: "wys\u0142aniu",
3518
+ // Batch 3: wyślij is the send verb — on-submit listener captured event "send"
3519
+ reset: "zresetuj",
3520
+ // Batch 3: resetuj captured on.event as expression (broken listener) — profile word round-trips
3364
3521
  load: "za\u0142aduj",
3365
3522
  unload: "wy\u0142aduj",
3366
3523
  resize: "zmie\u0144rozmiar",
@@ -3439,6 +3596,9 @@ var pl = {
3439
3596
  properties: "w\u0142a\u015Bciwo\u015Bci"
3440
3597
  },
3441
3598
  expressions: {
3599
+ characters: "znaki",
3600
+ inclusive: "w\u0142\u0105cznie",
3601
+ exclusive: "wy\u0142\u0105cznie",
3442
3602
  first: "pierwszy",
3443
3603
  last: "ostatni",
3444
3604
  next: "nast\u0119pny",
@@ -3534,7 +3694,8 @@ var russianDictionary = {
3534
3694
  clear: "\u043E\u0447\u0438\u0441\u0442\u0438\u0442\u044C",
3535
3695
  close: "\u0437\u0430\u043A\u0440\u044B\u0442\u044C",
3536
3696
  open: "\u043E\u0442\u043A\u0440\u044B\u0442\u044C",
3537
- select: "\u0432\u044B\u0431\u0440\u0430\u0442\u044C"
3697
+ select: "\u0432\u044B\u0434\u0435\u043B\u0438\u0442\u044C"
3698
+ // Batch 3: выбрать is the pick keyword — bare select rendered with it parses null
3538
3699
  },
3539
3700
  modifiers: {
3540
3701
  to: "\u043A",
@@ -3576,7 +3737,8 @@ var russianDictionary = {
3576
3737
  change: "\u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435",
3577
3738
  input: "\u0432\u0432\u043E\u0434",
3578
3739
  submit: "\u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0430",
3579
- reset: "\u0441\u0431\u0440\u043E\u0441",
3740
+ reset: "\u0441\u0431\u0440\u043E\u0441\u0438\u0442\u044C",
3741
+ // Batch 3: сброс captured on.event as expression (broken listener) — profile verb round-trips
3580
3742
  load: "\u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0430",
3581
3743
  unload: "\u0432\u044B\u0433\u0440\u0443\u0437\u043A\u0430",
3582
3744
  resize: "\u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435\u0440\u0430\u0437\u043C\u0435\u0440\u0430",
@@ -3676,6 +3838,9 @@ var russianDictionary = {
3676
3838
  html: "html"
3677
3839
  },
3678
3840
  expressions: {
3841
+ characters: "\u0441\u0438\u043C\u0432\u043E\u043B\u044B",
3842
+ inclusive: "\u0432\u043A\u043B\u044E\u0447\u0438\u0442\u0435\u043B\u044C\u043D\u043E",
3843
+ exclusive: "\u0438\u0441\u043A\u043B\u044E\u0447\u0438\u0442\u0435\u043B\u044C\u043D\u043E",
3679
3844
  first: "\u043F\u0435\u0440\u0432\u044B\u0439",
3680
3845
  last: "\u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0439",
3681
3846
  next: "\u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439",
@@ -3771,7 +3936,8 @@ var ukrainianDictionary = {
3771
3936
  clear: "\u043E\u0447\u0438\u0441\u0442\u0438\u0442\u0438",
3772
3937
  close: "\u0437\u0430\u043A\u0440\u0438\u0442\u0438",
3773
3938
  open: "\u0432\u0456\u0434\u043A\u0440\u0438\u0442\u0438",
3774
- select: "\u0432\u0438\u0431\u0440\u0430\u0442\u0438"
3939
+ select: "\u0432\u0438\u0434\u0456\u043B\u0438\u0442\u0438"
3940
+ // Batch 3: вибрати is the pick keyword — bare select rendered with it parses null
3775
3941
  },
3776
3942
  modifiers: {
3777
3943
  to: "\u0434\u043E",
@@ -3812,7 +3978,8 @@ var ukrainianDictionary = {
3812
3978
  change: "\u0437\u043C\u0456\u043D\u0430",
3813
3979
  input: "\u0432\u0432\u0435\u0434\u0435\u043D\u043D\u044F",
3814
3980
  submit: "\u043D\u0430\u0434\u0441\u0438\u043B\u0430\u043D\u043D\u044F",
3815
- reset: "\u0441\u043A\u0438\u0434\u0430\u043D\u043D\u044F",
3981
+ reset: "\u0441\u043A\u0438\u043D\u0443\u0442\u0438",
3982
+ // Batch 3: скидання captured on.event as expression (broken listener) — profile verb round-trips
3816
3983
  load: "\u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F",
3817
3984
  unload: "\u0432\u0438\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F",
3818
3985
  resize: "\u0437\u043C\u0456\u043D\u0430\u0440\u043E\u0437\u043C\u0456\u0440\u0443",
@@ -3912,6 +4079,9 @@ var ukrainianDictionary = {
3912
4079
  html: "html"
3913
4080
  },
3914
4081
  expressions: {
4082
+ characters: "\u0441\u0438\u043C\u0432\u043E\u043B\u0438",
4083
+ inclusive: "\u0432\u043A\u043B\u044E\u0447\u043D\u043E",
4084
+ exclusive: "\u0432\u0438\u043A\u043B\u044E\u0447\u043D\u043E",
3915
4085
  first: "\u043F\u0435\u0440\u0448\u0438\u0439",
3916
4086
  last: "\u043E\u0441\u0442\u0430\u043D\u043D\u0456\u0439",
3917
4087
  next: "\u043D\u0430\u0441\u0442\u0443\u043F\u043D\u0438\u0439",
@@ -3996,13 +4166,15 @@ var hindiDictionary = {
3996
4166
  behavior: "\u0935\u094D\u092F\u0935\u0939\u093E\u0930",
3997
4167
  focus: "\u092B\u094B\u0915\u0938",
3998
4168
  blur: "\u0927\u0941\u0902\u0927\u0932\u093E",
3999
- clone: "\u0915\u0949\u092A\u0940",
4169
+ clone: "\u0915\u094D\u0932\u094B\u0928",
4170
+ // Batch 3: कॉपी is the copy verb — rendered clone parsed as action=copy
4000
4171
  prepend: "\u091C\u094B\u0921\u093C\u0947\u0902_\u0936\u0941\u0930\u0942",
4001
4172
  breakpoint: "\u092C\u094D\u0930\u0947\u0915\u092A\u094D\u0935\u093E\u0907\u0902\u091F",
4002
4173
  clear: "\u0938\u093E\u092B\u093C-\u0915\u0930\u0947\u0902",
4003
4174
  close: "\u092C\u0902\u0926-\u0915\u0930\u0947\u0902",
4004
4175
  open: "\u0916\u094B\u0932\u0947\u0902",
4005
- select: "\u091A\u0941\u0928\u0947\u0902",
4176
+ select: "\u091A\u093F\u0939\u094D\u0928\u093F\u0924-\u0915\u0930\u0947\u0902",
4177
+ // Batch 3: चुनें is the pick keyword — bare select rendered with it parses null
4006
4178
  socket: "\u0938\u0949\u0915\u0947\u091F"
4007
4179
  },
4008
4180
  modifiers: {
@@ -4147,6 +4319,7 @@ var hindiDictionary = {
4147
4319
  html: "html"
4148
4320
  },
4149
4321
  expressions: {
4322
+ characters: "\u0905\u0915\u094D\u0937\u0930",
4150
4323
  first: "\u092A\u0939\u0932\u093E",
4151
4324
  last: "\u0905\u0902\u0924\u093F\u092E",
4152
4325
  next: "\u0905\u0917\u0932\u093E",
@@ -4216,7 +4389,8 @@ var bengaliDictionary = {
4216
4389
  init: "\u09B6\u09C1\u09B0\u09C1",
4217
4390
  behavior: "\u0986\u099A\u09B0\u09A3",
4218
4391
  install: "\u0987\u09A8\u09B8\u09CD\u099F\u09B2",
4219
- clone: "\u0995\u09AA\u09BF",
4392
+ clone: "\u0995\u09CD\u09B2\u09CB\u09A8",
4393
+ // Batch 3: কপি is the copy verb — rendered clone parsed as action=copy
4220
4394
  swap: "\u09AC\u09A6\u09B2",
4221
4395
  morph: "\u09B0\u09C2\u09AA\u09BE\u09A8\u09CD\u09A4\u09B0",
4222
4396
  beep: "\u09AC\u09C0\u09AA",
@@ -4263,10 +4437,12 @@ var bengaliDictionary = {
4263
4437
  focus: "\u09AB\u09CB\u0995\u09BE\u09B8",
4264
4438
  blur: "\u099D\u09BE\u09AA\u09B8\u09BE",
4265
4439
  reset: "\u09B0\u09BF\u09B8\u09C7\u099F",
4266
- keydown: "\u0995\u09BF-\u09A1\u09BE\u0989\u09A8",
4267
- keyup: "\u0995\u09BF-\u0986\u09AA",
4268
- mouseover: "\u09AE\u09BE\u0989\u09B8-\u0993\u09AD\u09BE\u09B0",
4269
- mouseout: "\u09AE\u09BE\u0989\u09B8-\u0986\u0989\u099F",
4440
+ keydown: "keydown",
4441
+ keyup: "keyup",
4442
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
4443
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
4444
+ mouseover: "mouseover",
4445
+ mouseout: "mouseout",
4270
4446
  scroll: "\u09B8\u09CD\u0995\u09CD\u09B0\u09CB\u09B2",
4271
4447
  resize: "\u09B0\u09BF\u09B8\u09BE\u0987\u099C",
4272
4448
  every: "\u09AA\u09CD\u09B0\u09A4\u09BF"
@@ -4328,6 +4504,9 @@ var bengaliDictionary = {
4328
4504
  checked: "\u099A\u09C7\u0995 \u0995\u09B0\u09BE"
4329
4505
  },
4330
4506
  expressions: {
4507
+ characters: "\u0985\u0995\u09CD\u09B7\u09B0",
4508
+ inclusive: "\u0985\u09A8\u09CD\u09A4\u09B0\u09CD\u09AD\u09C1\u0995\u09CD\u09A4",
4509
+ exclusive: "\u09AC\u09BE\u09A6",
4331
4510
  first: "\u09AA\u09CD\u09B0\u09A5\u09AE",
4332
4511
  last: "\u09B6\u09C7\u09B7",
4333
4512
  next: "\u09AA\u09B0\u09AC\u09B0\u09CD\u09A4\u09C0",
@@ -4397,7 +4576,8 @@ var thaiDictionary = {
4397
4576
  init: "\u0E40\u0E23\u0E34\u0E48\u0E21\u0E15\u0E49\u0E19",
4398
4577
  behavior: "\u0E1E\u0E24\u0E15\u0E34\u0E01\u0E23\u0E23\u0E21",
4399
4578
  install: "\u0E15\u0E34\u0E14\u0E15\u0E31\u0E49\u0E07",
4400
- clone: "\u0E04\u0E31\u0E14\u0E25\u0E2D\u0E01",
4579
+ clone: "\u0E42\u0E04\u0E25\u0E19",
4580
+ // Batch 3: คัดลอก is the copy verb — rendered clone parsed as action=copy
4401
4581
  swap: "\u0E2A\u0E25\u0E31\u0E1A\u0E17\u0E35\u0E48",
4402
4582
  morph: "\u0E41\u0E1B\u0E25\u0E07\u0E23\u0E48\u0E32\u0E07",
4403
4583
  beep: "\u0E1A\u0E35\u0E4A\u0E1A",
@@ -4412,7 +4592,8 @@ var thaiDictionary = {
4412
4592
  clear: "\u0E40\u0E04\u0E25\u0E35\u0E22\u0E23\u0E4C",
4413
4593
  close: "\u0E1B\u0E34\u0E14",
4414
4594
  open: "\u0E40\u0E1B\u0E34\u0E14",
4415
- select: "\u0E40\u0E25\u0E37\u0E2D\u0E01"
4595
+ select: "\u0E17\u0E33\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u0E2B\u0E21\u0E32\u0E22"
4596
+ // Batch 3: เลือก is the pick keyword — bare select rendered with it parses null
4416
4597
  },
4417
4598
  modifiers: {
4418
4599
  to: "\u0E44\u0E1B\u0E22\u0E31\u0E07",
@@ -4507,6 +4688,9 @@ var thaiDictionary = {
4507
4688
  checked: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E41\u0E25\u0E49\u0E27"
4508
4689
  },
4509
4690
  expressions: {
4691
+ characters: "\u0E2D\u0E31\u0E01\u0E02\u0E23\u0E30",
4692
+ inclusive: "\u0E23\u0E27\u0E21",
4693
+ exclusive: "\u0E22\u0E01\u0E40\u0E27\u0E49\u0E19",
4510
4694
  first: "\u0E41\u0E23\u0E01",
4511
4695
  last: "\u0E2A\u0E38\u0E14\u0E17\u0E49\u0E32\u0E22",
4512
4696
  next: "\u0E16\u0E31\u0E14\u0E44\u0E1B",
@@ -4594,7 +4778,8 @@ var malayDictionary = {
4594
4778
  // padam is a remove alternative in the profile
4595
4779
  close: "tutup",
4596
4780
  open: "buka",
4597
- select: "pilih",
4781
+ select: "tandai",
4782
+ // Batch 3: pilih is the pick keyword — bare select rendered with it parses null
4598
4783
  socket: "soket"
4599
4784
  // derived from the ms profile (socket.primary); see generate-i18n-dictionaries
4600
4785
  },
@@ -4734,6 +4919,9 @@ var malayDictionary = {
4734
4919
  checked: "ditanda"
4735
4920
  },
4736
4921
  expressions: {
4922
+ characters: "aksara",
4923
+ inclusive: "inklusif",
4924
+ exclusive: "eksklusif",
4737
4925
  first: "pertama",
4738
4926
  last: "terakhir",
4739
4927
  next: "seterusnya",
@@ -4827,7 +5015,8 @@ var tagalogDictionary = {
4827
5015
  install: "ikabit",
4828
5016
  behavior: "ugali",
4829
5017
  init: "simulan",
4830
- clone: "kopyahin",
5018
+ clone: "i-clone",
5019
+ // Batch 3: kopyahin is the copy verb — rendered clone parsed as action=copy
4831
5020
  breakpoint: "breakpoint",
4832
5021
  clear: "burahin",
4833
5022
  close: "isara",
@@ -4974,6 +5163,9 @@ var tagalogDictionary = {
4974
5163
  checked: "naka_tsek"
4975
5164
  },
4976
5165
  expressions: {
5166
+ characters: "karakter",
5167
+ inclusive: "kasama",
5168
+ exclusive: "bukod",
4977
5169
  first: "una",
4978
5170
  last: "huli",
4979
5171
  next: "susunod",
@@ -5097,6 +5289,10 @@ var he = {
5097
5289
  },
5098
5290
  attributes: {},
5099
5291
  expressions: {
5292
+ random: "\u05D0\u05E7\u05E8\u05D0\u05D9",
5293
+ characters: "\u05EA\u05D5\u05D5\u05D9\u05DD",
5294
+ inclusive: "\u05DB\u05D5\u05DC\u05DC",
5295
+ exclusive: "\u05D1\u05DC\u05E2\u05D3\u05D9",
5100
5296
  last: "\u05D0\u05D7\u05E8\u05D5\u05DF"
5101
5297
  }
5102
5298
  };
@@ -5494,6 +5690,91 @@ var englishProfile = {
5494
5690
  { form: "for", role: "duration", position: "preposition", required: false }
5495
5691
  ]
5496
5692
  };
5693
+ function sovHaltCallFusedRule(cfg) {
5694
+ return {
5695
+ name: "halt-call-fused-verb-final",
5696
+ description: "Split the swept `halt <operand> call <args>` blob; both verbs clause-final",
5697
+ priority: 95,
5698
+ match: {
5699
+ commands: ["halt"],
5700
+ requiredRoles: ["action", "event", "patient"],
5701
+ // Only the juxtaposed-call blob: a plain `halt`/`halt the event` handler
5702
+ // keeps its default render. The translated call verb must be present to
5703
+ // split on — if the dictionary emission drifts, the rule stands down
5704
+ // rather than emitting a mangled clause.
5705
+ predicate: (parsed) => {
5706
+ const p = parsed.roles.get("patient");
5707
+ return !!p && /\bcall\b/.test(p.value) && !!p.translated && p.translated.includes(cfg.callVerb);
5708
+ }
5709
+ },
5710
+ transform: {
5711
+ roleOrder: [],
5712
+ // unused — custom takes over
5713
+ custom: (parsed) => {
5714
+ const p = parsed.roles.get("patient");
5715
+ const ev = parsed.roles.get("event");
5716
+ const act = parsed.roles.get("action");
5717
+ let blob = (p.translated ?? p.value).trim();
5718
+ const PH = "EVENTBLOCKPLACEHOLDER";
5719
+ let tail = "";
5720
+ if (blob.endsWith(PH)) {
5721
+ blob = blob.slice(0, -PH.length).trim();
5722
+ tail = ` ${PH}`;
5723
+ }
5724
+ const at = blob.indexOf(cfg.callVerb);
5725
+ const haltOperand = blob.slice(0, at).trim();
5726
+ const callArgs = blob.slice(at + cfg.callVerb.length).trim();
5727
+ return [
5728
+ haltOperand,
5729
+ cfg.patientMarker,
5730
+ ev.translated ?? ev.value,
5731
+ cfg.eventMarker,
5732
+ act.translated ?? act.value,
5733
+ cfg.connective,
5734
+ callArgs,
5735
+ cfg.patientMarker,
5736
+ cfg.callVerb
5737
+ ].join(" ") + tail;
5738
+ }
5739
+ }
5740
+ };
5741
+ }
5742
+ function sovPickRangeRule(cfg) {
5743
+ return {
5744
+ name: "pick-range-verb-final",
5745
+ description: "Reassemble the pick range (unit + endpoints + root) adjacent, verb-final",
5746
+ priority: 95,
5747
+ match: {
5748
+ commands: ["pick"],
5749
+ requiredRoles: ["action", "patient", "destination"],
5750
+ predicate: (parsed) => {
5751
+ const p = parsed.roles.get("patient");
5752
+ const d = parsed.roles.get("destination");
5753
+ return !!p && !!d && /^\S+\s+\d+$/.test(p.value.trim()) && /^\d+\s+of\s+\S+$/.test(d.value.trim());
5754
+ }
5755
+ },
5756
+ transform: {
5757
+ roleOrder: [],
5758
+ // unused — custom takes over
5759
+ custom: (parsed) => {
5760
+ const p = parsed.roles.get("patient");
5761
+ const d = parsed.roles.get("destination");
5762
+ const act = parsed.roles.get("action");
5763
+ const ev = parsed.roles.get("event");
5764
+ const pParts = (p.translated ?? p.value).trim().split(/\s+/);
5765
+ const a = pParts[pParts.length - 1];
5766
+ const unit = pParts.slice(0, -1).join(" ");
5767
+ const dMatch = d.value.trim().match(/^(\d+)\s+of\s+(\S+)$/);
5768
+ const b = dMatch[1];
5769
+ const root = dMatch[2];
5770
+ const verb = act.translated ?? act.value;
5771
+ const head = [root, cfg.genitive, unit, a, cfg.rangeSep, b, cfg.patientMarker];
5772
+ const eventPart = ev ? [ev.translated ?? ev.value, cfg.eventMarker] : [];
5773
+ return [...head, ...eventPart, verb].join(" ");
5774
+ }
5775
+ }
5776
+ };
5777
+ }
5497
5778
  var japaneseProfile = {
5498
5779
  code: "ja",
5499
5780
  name: "\u65E5\u672C\u8A9E",
@@ -5578,7 +5859,21 @@ var japaneseProfile = {
5578
5859
  roleOrder: ["patient", "destination", "action"],
5579
5860
  insertMarkers: true
5580
5861
  }
5581
- }
5862
+ },
5863
+ // the イベント を 送信 で 停止 それから validateForm() を 呼び出し
5864
+ sovHaltCallFusedRule({
5865
+ callVerb: "\u547C\u3073\u51FA\u3057",
5866
+ patientMarker: "\u3092",
5867
+ eventMarker: "\u3067",
5868
+ connective: "\u305D\u308C\u304B\u3089"
5869
+ }),
5870
+ // #note の 文字 0 から 5 を クリック で 選択
5871
+ sovPickRangeRule({
5872
+ genitive: "\u306E",
5873
+ rangeSep: "\u304B\u3089",
5874
+ patientMarker: "\u3092",
5875
+ eventMarker: "\u3067"
5876
+ })
5582
5877
  ]
5583
5878
  };
5584
5879
  var koreanProfile = {
@@ -5678,7 +5973,21 @@ var koreanProfile = {
5678
5973
  roleOrder: ["patient", "destination", "action"],
5679
5974
  insertMarkers: true
5680
5975
  }
5681
- }
5976
+ },
5977
+ // the 이벤트 를 제출 할 때 정지 그러면 validateForm() 를 호출
5978
+ sovHaltCallFusedRule({
5979
+ callVerb: "\uD638\uCD9C",
5980
+ patientMarker: "\uB97C",
5981
+ eventMarker: "\uD560 \uB54C",
5982
+ connective: "\uADF8\uB7EC\uBA74"
5983
+ }),
5984
+ // #note 의 문자 0 부터 5 를 클릭 할 때 선택
5985
+ sovPickRangeRule({
5986
+ genitive: "\uC758",
5987
+ rangeSep: "\uBD80\uD130",
5988
+ patientMarker: "\uB97C",
5989
+ eventMarker: "\uD560 \uB54C"
5990
+ })
5682
5991
  ]
5683
5992
  };
5684
5993
  var chineseProfile = {
@@ -5819,6 +6128,12 @@ var turkishProfile = {
5819
6128
  adpositionType: "postposition",
5820
6129
  morphology: "agglutinative",
5821
6130
  direction: "ltr",
6131
+ // NOTE: roles absent from this order are safety-net-appended AFTER the verb
6132
+ // by reorderRoles. That stranding is what the semantic parser's generated
6133
+ // patterns + reclaim tolerances were built around, so extending this order
6134
+ // wholesale re-renders (and breaks) the whole tr corpus — fix individual
6135
+ // defective shapes with per-command `rules` below instead (see the
6136
+ // wait/repeat-until rules from the transformer-rendering arc).
5822
6137
  canonicalOrder: ["patient", "event", "action"],
5823
6138
  markers: [
5824
6139
  // Turkish case suffixes - using spaced form for tokenization
@@ -5912,7 +6227,59 @@ var turkishProfile = {
5912
6227
  roleOrder: ["patient", "destination", "action"],
5913
6228
  insertMarkers: true
5914
6229
  }
5915
- }
6230
+ },
6231
+ {
6232
+ name: "wait-oblique-verb-final",
6233
+ description: "Keep wait's from-phrase and or-run inside the clause, verb-final",
6234
+ priority: 90,
6235
+ match: {
6236
+ commands: ["wait", "bekle"],
6237
+ // Only the multi-argument form (`wait for X or Y from Z`) strands:
6238
+ // without this rule the safety-net appends duration+source AFTER the
6239
+ // verb (`bekle … belge den`), and the stranded from-phrase is captured
6240
+ // by the NEXT statement as a junk trigger event (behavior-sortable R3).
6241
+ requiredRoles: ["action", "duration", "source"],
6242
+ // Never reorder a fused single-line handler — its event must stay put.
6243
+ predicate: (parsed) => !parsed.roles.has("event")
6244
+ },
6245
+ transform: {
6246
+ // belge den pointermove(clientY) veya pointerup(clientY) bekle
6247
+ roleOrder: ["patient", "source", "duration", "action"],
6248
+ insertMarkers: true
6249
+ }
6250
+ },
6251
+ {
6252
+ name: "repeat-until-event-verb-final",
6253
+ description: "Keep repeat-until-event's from-phrase before the verb",
6254
+ priority: 90,
6255
+ match: {
6256
+ commands: ["repeat", "tekrarla"],
6257
+ requiredRoles: ["action", "patient", "source"],
6258
+ // Gate to the until-event head; `repeat for item in .items` also
6259
+ // carries patient+source and must keep its (parseable) default order.
6260
+ predicate: (parsed) => /^repeat\s+until\s+event\b/i.test((parsed.original ?? "").trim())
6261
+ },
6262
+ transform: {
6263
+ // kadar olay pointerup i belge den tekrarla — matched semantic-side by
6264
+ // repeat-tr-until-head-verb-final.
6265
+ roleOrder: ["patient", "source", "action"],
6266
+ insertMarkers: true
6267
+ }
6268
+ },
6269
+ // the olay i gönder de durdur ardından validateForm() i çağır
6270
+ sovHaltCallFusedRule({
6271
+ callVerb: "\xE7a\u011F\u0131r",
6272
+ patientMarker: "i",
6273
+ eventMarker: "de",
6274
+ connective: "ard\u0131ndan"
6275
+ }),
6276
+ // #note nin karakterler 0 ile 5 i tıklama de seç
6277
+ sovPickRangeRule({
6278
+ genitive: "nin",
6279
+ rangeSep: "ile",
6280
+ patientMarker: "i",
6281
+ eventMarker: "de"
6282
+ })
5916
6283
  ]
5917
6284
  };
5918
6285
  var spanishProfile = {
@@ -6035,6 +6402,8 @@ var quechuaProfile = {
6035
6402
  morphology: "agglutinative",
6036
6403
  // Actually polysynthetic
6037
6404
  direction: "ltr",
6405
+ // NOTE: roles absent from this order are safety-net-appended AFTER the verb
6406
+ // (see the Turkish profile note) — extend via per-command `rules`, not here.
6038
6407
  canonicalOrder: ["patient", "source", "destination", "event", "action"],
6039
6408
  markers: [
6040
6409
  // Quechua case suffixes - using spaced form for tokenization
@@ -6047,6 +6416,41 @@ var quechuaProfile = {
6047
6416
  { form: "wan", role: "style", position: "postposition", required: false },
6048
6417
  { form: "hina", role: "method", position: "postposition", required: false }
6049
6418
  // "as/like"
6419
+ ],
6420
+ rules: [
6421
+ {
6422
+ name: "wait-oblique-verb-final",
6423
+ description: "Keep wait's from-phrase and or-run inside the clause, verb-final",
6424
+ priority: 90,
6425
+ match: {
6426
+ commands: ["wait", "suyay"],
6427
+ // Only `wait for X or Y from Z` strands: duration is missing from
6428
+ // canonicalOrder, so the or-run lands AFTER the verb and the next
6429
+ // trigger glues it into its event (behavior-sortable R3). See the
6430
+ // matching Turkish rule.
6431
+ requiredRoles: ["action", "duration", "source"],
6432
+ predicate: (parsed) => !parsed.roles.has("event")
6433
+ },
6434
+ transform: {
6435
+ // qillqa manta pointermove(clientY) utaq pointerup(clientY) suyay
6436
+ roleOrder: ["patient", "source", "duration", "action"],
6437
+ insertMarkers: true
6438
+ }
6439
+ },
6440
+ // the ruway ta kachay pi sayay chayqa validateForm() ta qayay
6441
+ sovHaltCallFusedRule({
6442
+ callVerb: "qayay",
6443
+ patientMarker: "ta",
6444
+ eventMarker: "pi",
6445
+ connective: "chayqa"
6446
+ }),
6447
+ // #note pa sanampa 0 kama 5 ta ñitiy pi akllay
6448
+ sovPickRangeRule({
6449
+ genitive: "pa",
6450
+ rangeSep: "kama",
6451
+ patientMarker: "ta",
6452
+ eventMarker: "pi"
6453
+ })
6050
6454
  ]
6051
6455
  };
6052
6456
  var swahiliProfile = {
@@ -6078,6 +6482,8 @@ var bengaliProfile = {
6078
6482
  direction: "ltr",
6079
6483
  // Bengali: Object comes before verb, postpositions follow nouns
6080
6484
  // "on click increment #count" → "#count কে ক্লিক এ বৃদ্ধি"
6485
+ // NOTE: roles absent from this order are safety-net-appended AFTER the verb
6486
+ // (see the Turkish profile note) — extend via per-command `rules`, not here.
6081
6487
  canonicalOrder: ["patient", "event", "action"],
6082
6488
  markers: [
6083
6489
  // Postpositions
@@ -6153,7 +6559,21 @@ var bengaliProfile = {
6153
6559
  roleOrder: ["patient", "destination", "action"],
6154
6560
  insertMarkers: true
6155
6561
  }
6156
- }
6562
+ },
6563
+ // the ঘটনা কে জমা এ থামুন তারপর validateForm() কে কল
6564
+ sovHaltCallFusedRule({
6565
+ callVerb: "\u0995\u09B2",
6566
+ patientMarker: "\u0995\u09C7",
6567
+ eventMarker: "\u098F",
6568
+ connective: "\u09A4\u09BE\u09B0\u09AA\u09B0"
6569
+ }),
6570
+ // #note র অক্ষর 0 থেকে 5 কে ক্লিক এ বাছুন
6571
+ sovPickRangeRule({
6572
+ genitive: "\u09B0",
6573
+ rangeSep: "\u09A5\u09C7\u0995\u09C7",
6574
+ patientMarker: "\u0995\u09C7",
6575
+ eventMarker: "\u098F"
6576
+ })
6157
6577
  ]
6158
6578
  };
6159
6579
  var italianProfile = {
@@ -6325,7 +6745,21 @@ var hindiProfile = {
6325
6745
  roleOrder: ["patient", "destination", "action"],
6326
6746
  insertMarkers: true
6327
6747
  }
6328
- }
6748
+ },
6749
+ // the घटना को जमा पर रोकें फिर validateForm() को कॉल
6750
+ sovHaltCallFusedRule({
6751
+ callVerb: "\u0915\u0949\u0932",
6752
+ patientMarker: "\u0915\u094B",
6753
+ eventMarker: "\u092A\u0930",
6754
+ connective: "\u092B\u093F\u0930"
6755
+ }),
6756
+ // #note का अक्षर 0 से 5 को क्लिक पर चुनें
6757
+ sovPickRangeRule({
6758
+ genitive: "\u0915\u093E",
6759
+ rangeSep: "\u0938\u0947",
6760
+ patientMarker: "\u0915\u094B",
6761
+ eventMarker: "\u092A\u0930"
6762
+ })
6329
6763
  ]
6330
6764
  };
6331
6765
  var tagalogProfile = {
@@ -14954,6 +15388,10 @@ var GrammarTransformer = class {
14954
15388
  if (block) {
14955
15389
  return this.transformBlock(block);
14956
15390
  }
15391
+ const strippedEnd = this.transformWithTrailingEnd(input);
15392
+ if (strippedEnd !== null) {
15393
+ return strippedEnd;
15394
+ }
14957
15395
  const setScope = this.transformSetWithScope(input);
14958
15396
  if (setScope !== null) {
14959
15397
  return setScope;
@@ -14981,6 +15419,35 @@ var GrammarTransformer = class {
14981
15419
  }
14982
15420
  return joinTokens(reordered.map((e) => e.translated || e.value));
14983
15421
  }
15422
+ /**
15423
+ * `<command …> end` fragments: transform the command without its stranded
15424
+ * terminator, then re-append the translated terminator as a standalone
15425
+ * trailing token. Fragments that open a block of their own (`if … end`,
15426
+ * `repeat … end`, `js … end`) bail — their terminator belongs to them and
15427
+ * their dedicated paths handle it.
15428
+ */
15429
+ transformWithTrailingEnd(input) {
15430
+ const src = this.sourceProfile.code;
15431
+ const tokens = input.trim().split(/\s+/);
15432
+ if (tokens.length < 2) {
15433
+ return null;
15434
+ }
15435
+ const sourceEnd = translateWord("end", "en", src).toLowerCase();
15436
+ if (tokens[tokens.length - 1].toLowerCase() !== sourceEnd) {
15437
+ return null;
15438
+ }
15439
+ const openers = new Set(
15440
+ ["if", "repeat", "unless", "while", "when", "live", "js"].map(
15441
+ (k) => translateWord(k, "en", src).toLowerCase()
15442
+ )
15443
+ );
15444
+ if (tokens.slice(0, -1).some((t) => openers.has(t.toLowerCase()))) {
15445
+ return null;
15446
+ }
15447
+ const inner = this.transformSingle(tokens.slice(0, -1).join(" "));
15448
+ const endT = translateWord(tokens[tokens.length - 1], src, this.targetProfile.code);
15449
+ return `${inner} ${endT}`;
15450
+ }
14984
15451
  /**
14985
15452
  * Detect and transform an inline JS block (`[on <event>] js <raw js> end`).
14986
15453
  *
@@ -15240,7 +15707,9 @@ var GrammarTransformer = class {
15240
15707
  const tailT = tail ? translateWord(tail, src, dst) : "";
15241
15708
  const clauseT = clause ? translateMultiWordValue(clause, src, dst) : "";
15242
15709
  const bodyT = this.transformConditionalBody(bodyTokens);
15243
- return [headT, clauseT, bodyT, tailT].filter((s) => s.length > 0).join(" ");
15710
+ const POSITIONAL_BRANCH_HEADS = /* @__PURE__ */ new Set(["first", "last", "next", "previous", "closest"]);
15711
+ const thenT = this.targetProfile.wordOrder === "SOV" && clauseT && POSITIONAL_BRANCH_HEADS.has(bodyTokens[1]?.toLowerCase()) && inner[bodyStart - 1]?.toLowerCase() !== "then" ? translateWord("then", src, dst) : "";
15712
+ return [headT, clauseT, thenT, bodyT, tailT].filter((s) => s.length > 0).join(" ");
15244
15713
  }
15245
15714
  /**
15246
15715
  * Transform an `if`/`unless` block body, splitting it at a top-level `else` into