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