@lokascript/i18n 2.7.2 → 2.8.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 (60) hide show
  1. package/README.md +1 -1
  2. package/dist/browser.cjs +649 -180
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.d.cts +2 -2
  5. package/dist/browser.d.ts +2 -2
  6. package/dist/browser.js +649 -180
  7. package/dist/browser.js.map +1 -1
  8. package/dist/dictionaries/index.cjs +370 -174
  9. package/dist/dictionaries/index.cjs.map +1 -1
  10. package/dist/dictionaries/index.js +370 -174
  11. package/dist/dictionaries/index.js.map +1 -1
  12. package/dist/index.cjs +649 -180
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +35 -35
  15. package/dist/index.d.ts +35 -35
  16. package/dist/index.js +649 -180
  17. package/dist/index.js.map +1 -1
  18. package/dist/lokascript-i18n.min.js +1 -1
  19. package/dist/lokascript-i18n.min.js.map +1 -1
  20. package/dist/lokascript-i18n.mjs +678 -175
  21. package/dist/lokascript-i18n.mjs.map +1 -1
  22. package/dist/plugins/vite.cjs +370 -174
  23. package/dist/plugins/vite.cjs.map +1 -1
  24. package/dist/plugins/vite.js +370 -174
  25. package/dist/plugins/vite.js.map +1 -1
  26. package/dist/plugins/webpack.cjs +370 -174
  27. package/dist/plugins/webpack.cjs.map +1 -1
  28. package/dist/plugins/webpack.js +370 -174
  29. package/dist/plugins/webpack.js.map +1 -1
  30. package/dist/{transformer-DM7iplCU.d.cts → transformer--W46PGaW.d.cts} +8 -0
  31. package/dist/{transformer-BA8YX9u1.d.ts → transformer-FU06J6kG.d.ts} +8 -0
  32. package/package.json +7 -9
  33. package/src/dictionaries/ar.ts +20 -15
  34. package/src/dictionaries/bn.ts +10 -5
  35. package/src/dictionaries/de.ts +20 -8
  36. package/src/dictionaries/es.ts +10 -5
  37. package/src/dictionaries/fr.ts +15 -6
  38. package/src/dictionaries/he.ts +4 -0
  39. package/src/dictionaries/hi.ts +3 -2
  40. package/src/dictionaries/id.ts +31 -16
  41. package/src/dictionaries/it.ts +11 -4
  42. package/src/dictionaries/ja.ts +23 -15
  43. package/src/dictionaries/ko.ts +10 -5
  44. package/src/dictionaries/ms.ts +4 -1
  45. package/src/dictionaries/pl.ts +12 -5
  46. package/src/dictionaries/pt.ts +10 -5
  47. package/src/dictionaries/qu.ts +30 -19
  48. package/src/dictionaries/ru.ts +5 -2
  49. package/src/dictionaries/sw.ts +29 -14
  50. package/src/dictionaries/th.ts +5 -2
  51. package/src/dictionaries/tl.ts +4 -1
  52. package/src/dictionaries/tr.ts +24 -16
  53. package/src/dictionaries/uk.ts +5 -2
  54. package/src/dictionaries/vi.ts +23 -17
  55. package/src/dictionaries/zh.ts +24 -9
  56. package/src/grammar/grammar.test.ts +152 -0
  57. package/src/grammar/profiles/index.ts +316 -1
  58. package/src/grammar/transformer.ts +64 -1
  59. package/src/new-languages.test.ts +9 -3
  60. package/src/positional-keyword-drift.test.ts +6 -19
package/dist/browser.js CHANGED
@@ -593,17 +593,20 @@ var es = {
593
593
  mouseup: "rat\xF3narriba",
594
594
  mouseenter: "rat\xF3nentrar",
595
595
  mouseleave: "rat\xF3nsalir",
596
- mouseover: "rat\xF3nencima",
597
- mouseout: "rat\xF3nfuera",
596
+ // V3 Batch 2: fused forms split to the S5b/tokenizer-known forms (the fused
597
+ // spellings captured event=expression:undefined — broken listeners)
598
+ mouseover: "rat\xF3n encima",
599
+ mouseout: "rat\xF3n fuera",
598
600
  mousemove: "rat\xF3nmover",
599
- keydown: "teclaabajo",
600
- keyup: "teclaarriba",
601
+ keydown: "tecla abajo",
602
+ keyup: "tecla arriba",
601
603
  keypress: "teclapresar",
602
604
  focus: "enfocar",
603
605
  blur: "desenfocar",
604
606
  change: "cambiar",
605
607
  input: "entrada",
606
- submit: "enviar",
608
+ submit: "env\xEDo",
609
+ // Batch 3: enviar is the send verb — on-submit listener captured event "send"
607
610
  reset: "reiniciar",
608
611
  load: "cargar",
609
612
  unload: "descargar",
@@ -683,6 +686,9 @@ var es = {
683
686
  properties: "propiedades"
684
687
  },
685
688
  expressions: {
689
+ characters: "caracteres",
690
+ inclusive: "inclusivo",
691
+ exclusive: "exclusivo",
686
692
  first: "primero",
687
693
  last: "\xFAltimo",
688
694
  next: "siguiente",
@@ -774,7 +780,8 @@ var ja = {
774
780
  clear: "\u30AF\u30EA\u30A2",
775
781
  close: "\u9589\u3058\u308B",
776
782
  open: "\u958B\u304F",
777
- select: "\u9078\u629E",
783
+ select: "\u9078\u3076",
784
+ // Batch 3: 選択 is the pick keyword — bare select rendered with it parses null
778
785
  clone: "\u8907\u88FD",
779
786
  prepend: "\u5148\u982D\u8FFD\u52A0",
780
787
  socket: "\u30BD\u30B1\u30C3\u30C8"
@@ -799,17 +806,22 @@ var ja = {
799
806
  },
800
807
  events: {
801
808
  click: "\u30AF\u30EA\u30C3\u30AF",
802
- dblclick: "\u30C0\u30D6\u30EB\u30AF\u30EA\u30C3\u30AF",
809
+ dblclick: "dblclick",
803
810
  mousedown: "\u30DE\u30A6\u30B9\u62BC\u4E0B",
804
811
  mouseup: "\u30DE\u30A6\u30B9\u89E3\u653E",
805
- mouseenter: "\u30DE\u30A6\u30B9\u5165\u308B",
806
- mouseleave: "\u30DE\u30A6\u30B9\u96E2\u308C\u308B",
807
- mouseover: "\u30DE\u30A6\u30B9\u4E0A",
808
- mouseout: "\u30DE\u30A6\u30B9\u5916",
809
- mousemove: "\u30DE\u30A6\u30B9\u79FB\u52D5",
810
- keydown: "\u30AD\u30FC\u62BC\u4E0B",
811
- keyup: "\u30AD\u30FC\u89E3\u653E",
812
- keypress: "\u30AD\u30FC\u62BC\u3059",
812
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
813
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
814
+ mouseenter: "mouseenter",
815
+ mouseleave: "mouseleave",
816
+ // V3 Batch 2: kanji compounds realigned to the S5b/tokenizer katakana
817
+ // loanwords (the standard JS event terms; the compounds captured
818
+ // event=expression:undefined — broken listeners)
819
+ mouseover: "\u30DE\u30A6\u30B9\u30AA\u30FC\u30D0\u30FC",
820
+ mouseout: "\u30DE\u30A6\u30B9\u30A2\u30A6\u30C8",
821
+ mousemove: "mousemove",
822
+ keydown: "\u30AD\u30FC\u30C0\u30A6\u30F3",
823
+ keyup: "\u30AD\u30FC\u30A2\u30C3\u30D7",
824
+ keypress: "\u30AD\u30FC\u30D7\u30EC\u30B9",
813
825
  focus: "\u30D5\u30A9\u30FC\u30AB\u30B9",
814
826
  blur: "\u307C\u304B\u3057",
815
827
  change: "\u5909\u66F4",
@@ -817,13 +829,13 @@ var ja = {
817
829
  submit: "\u9001\u4FE1",
818
830
  reset: "\u30EA\u30BB\u30C3\u30C8",
819
831
  load: "\u8AAD\u307F\u8FBC\u307F",
820
- unload: "\u8AAD\u307F\u8FBC\u307F\u89E3\u9664",
832
+ unload: "unload",
821
833
  resize: "\u30B5\u30A4\u30BA\u5909\u66F4",
822
834
  scroll: "\u30B9\u30AF\u30ED\u30FC\u30EB",
823
- touchstart: "\u30BF\u30C3\u30C1\u958B\u59CB",
824
- touchend: "\u30BF\u30C3\u30C1\u7D42\u4E86",
825
- touchmove: "\u30BF\u30C3\u30C1\u79FB\u52D5",
826
- touchcancel: "\u30BF\u30C3\u30C1\u30AD\u30E3\u30F3\u30BB\u30EB"
835
+ touchstart: "touchstart",
836
+ touchend: "touchend",
837
+ touchmove: "touchmove",
838
+ touchcancel: "touchcancel"
827
839
  },
828
840
  logical: {
829
841
  when: "\u6642",
@@ -895,6 +907,9 @@ var ja = {
895
907
  properties: "\u30D7\u30ED\u30D1\u30C6\u30A3\u7FA4"
896
908
  },
897
909
  expressions: {
910
+ characters: "\u6587\u5B57",
911
+ inclusive: "\u542B\u3080",
912
+ exclusive: "\u9664\u304F",
898
913
  first: "\u6700\u521D",
899
914
  last: "\u6700\u5F8C",
900
915
  next: "\u6B21",
@@ -1011,15 +1026,21 @@ var fr = {
1011
1026
  events: {
1012
1027
  click: "clic",
1013
1028
  dblclick: "doubleclic",
1014
- mousedown: "sourisappuy\xE9e",
1015
- 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",
1016
1035
  mouseenter: "sourisentrer",
1017
1036
  mouseleave: "sourissortir",
1018
- mouseover: "sourissur",
1019
- 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",
1020
1041
  mousemove: "sourisbouger",
1021
- keydown: "toucheappuy\xE9e",
1022
- keyup: "toucherel\xE2ch\xE9e",
1042
+ keydown: "touche bas",
1043
+ keyup: "touche haut",
1023
1044
  keypress: "touchepress\xE9e",
1024
1045
  focus: "focus",
1025
1046
  blur: "flou",
@@ -1105,6 +1126,9 @@ var fr = {
1105
1126
  properties: "propri\xE9t\xE9s"
1106
1127
  },
1107
1128
  expressions: {
1129
+ characters: "caract\xE8res",
1130
+ inclusive: "inclusif",
1131
+ exclusive: "exclusif",
1108
1132
  first: "premier",
1109
1133
  last: "dernier",
1110
1134
  next: "suivant",
@@ -1200,7 +1224,8 @@ var de = {
1200
1224
  // löschen is a remove alternative in the profile
1201
1225
  close: "schlie\xDFen",
1202
1226
  open: "\xF6ffnen",
1203
- select: "ausw\xE4hlen",
1227
+ select: "markieren",
1228
+ // Batch 3: auswählen is the pick keyword — bare select rendered with it parses null
1204
1229
  clone: "klonen",
1205
1230
  prepend: "voranstellen",
1206
1231
  focus: "fokussieren"
@@ -1226,18 +1251,27 @@ var de = {
1226
1251
  events: {
1227
1252
  click: "klick",
1228
1253
  dblclick: "doppelklick",
1229
- mousedown: "mausunten",
1230
- mouseup: "mausoben",
1254
+ // mousedown/mouseup: English passthrough — no native form round-trips on the
1255
+ // parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
1256
+ // shattered to their first word — live broken listeners in repeat-until-event).
1257
+ // The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
1258
+ mousedown: "mousedown",
1259
+ mouseup: "mouseup",
1231
1260
  mouseenter: "mauseintreten",
1232
1261
  mouseleave: "mausverlassen",
1233
- mouseover: "maus\xFCber",
1234
- mouseout: "maushinaus",
1262
+ // V3 Batch 2: fused/dead event words realigned to the de tokenizer's
1263
+ // registered forms (S5b's `maus über`/`taste runter` are aspirational — they
1264
+ // do not tokenize; `mausüber` etc. captured event=expression:undefined).
1265
+ mouseover: "maus dr\xFCber",
1266
+ mouseout: "maus weg",
1235
1267
  mousemove: "mausbewegen",
1236
- keydown: "tasteunten",
1237
- keyup: "tasteoben",
1268
+ keydown: "taste unten",
1269
+ keyup: "taste oben",
1238
1270
  keypress: "tastedr\xFCcken",
1239
1271
  focus: "fokus",
1240
- blur: "unscharf",
1272
+ // matches commands.blur (which shadows this at render time) and the live
1273
+ // corpus render; `unscharf` was dead vocab that captured no event
1274
+ blur: "defokussieren",
1241
1275
  change: "\xE4ndern",
1242
1276
  input: "eingabe",
1243
1277
  submit: "absenden",
@@ -1320,6 +1354,9 @@ var de = {
1320
1354
  properties: "eigenschaften"
1321
1355
  },
1322
1356
  expressions: {
1357
+ characters: "Zeichen",
1358
+ inclusive: "inklusiv",
1359
+ exclusive: "exklusiv",
1323
1360
  first: "erste",
1324
1361
  last: "letzte",
1325
1362
  next: "n\xE4chste",
@@ -1417,7 +1454,8 @@ var ar = {
1417
1454
  // امسح is a remove alternative in the profile
1418
1455
  close: "\u0623\u063A\u0644\u0642",
1419
1456
  open: "\u0627\u0641\u062A\u062D",
1420
- select: "\u0627\u062E\u062A\u0631",
1457
+ select: "\u0638\u0644\u0644",
1458
+ // Batch 3: اختر is the pick keyword — bare select rendered with it parses null
1421
1459
  clone: "\u0627\u0633\u062A\u0646\u0633\u062E",
1422
1460
  prepend: "\u0633\u0628\u0642",
1423
1461
  socket: "\u0645\u0642\u0628\u0633"
@@ -1442,31 +1480,33 @@ var ar = {
1442
1480
  },
1443
1481
  events: {
1444
1482
  click: "\u0646\u0642\u0631",
1445
- dblclick: "\u0646\u0642\u0631 \u0645\u0632\u062F\u0648\u062C",
1446
- mousedown: "\u0641\u0623\u0631\u0629 \u0623\u0633\u0641\u0644",
1447
- mouseup: "\u0641\u0623\u0631\u0629 \u0623\u0639\u0644\u0649",
1448
- mouseenter: "\u0641\u0623\u0631\u0629 \u062F\u062E\u0648\u0644",
1449
- mouseleave: "\u0641\u0623\u0631\u0629 \u062E\u0631\u0648\u062C",
1483
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
1484
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
1485
+ dblclick: "dblclick",
1486
+ mousedown: "mousedown",
1487
+ mouseup: "mouseup",
1488
+ mouseenter: "mouseenter",
1489
+ mouseleave: "mouseleave",
1450
1490
  mouseover: "\u0641\u0623\u0631\u0629 \u0641\u0648\u0642",
1451
- mouseout: "\u0641\u0623\u0631\u0629 \u062E\u0627\u0631\u062C",
1452
- mousemove: "\u0641\u0623\u0631\u0629 \u062A\u062D\u0631\u0643",
1491
+ mouseout: "mouseout",
1492
+ mousemove: "mousemove",
1453
1493
  keydown: "\u0645\u0641\u062A\u0627\u062D \u0623\u0633\u0641\u0644",
1454
1494
  keyup: "\u0645\u0641\u062A\u0627\u062D \u0623\u0639\u0644\u0649",
1455
- keypress: "\u0645\u0641\u062A\u0627\u062D \u0636\u063A\u0637",
1495
+ keypress: "keypress",
1456
1496
  focus: "\u062A\u0631\u0643\u064A\u0632",
1457
1497
  blur: "\u0636\u0628\u0627\u0628\u064A\u0629",
1458
1498
  change: "\u062A\u063A\u064A\u064A\u0631",
1459
1499
  input: "\u0625\u062F\u062E\u0627\u0644",
1460
1500
  submit: "\u0625\u0631\u0633\u0627\u0644",
1461
- reset: "\u0625\u0639\u0627\u062F\u0629 \u062A\u0639\u064A\u064A\u0646",
1501
+ reset: "reset",
1462
1502
  load: "\u062A\u062D\u0645\u064A\u0644",
1463
- unload: "\u0625\u0644\u063A\u0627\u0621 \u062A\u062D\u0645\u064A\u0644",
1503
+ unload: "unload",
1464
1504
  resize: "\u062A\u063A\u064A\u064A\u0631 \u062D\u062C\u0645",
1465
1505
  scroll: "\u062A\u0645\u0631\u064A\u0631",
1466
- touchstart: "\u0628\u062F\u0627\u064A\u0629 \u0644\u0645\u0633",
1467
- touchend: "\u0646\u0647\u0627\u064A\u0629 \u0644\u0645\u0633",
1468
- touchmove: "\u062A\u062D\u0631\u0643 \u0644\u0645\u0633",
1469
- touchcancel: "\u0625\u0644\u063A\u0627\u0621 \u0644\u0645\u0633"
1506
+ touchstart: "touchstart",
1507
+ touchend: "touchend",
1508
+ touchmove: "touchmove",
1509
+ touchcancel: "touchcancel"
1470
1510
  },
1471
1511
  logical: {
1472
1512
  when: "\u0639\u0646\u062F\u0645\u0627",
@@ -1538,6 +1578,9 @@ var ar = {
1538
1578
  properties: "\u062E\u0635\u0627\u0626\u0635"
1539
1579
  },
1540
1580
  expressions: {
1581
+ characters: "\u062D\u0631\u0648\u0641",
1582
+ inclusive: "\u0634\u0627\u0645\u0644",
1583
+ exclusive: "\u062D\u0635\u0631\u064A",
1541
1584
  first: "\u0623\u0648\u0644",
1542
1585
  last: "\u0622\u062E\u0631",
1543
1586
  next: "\u0627\u0644\u062A\u0627\u0644\u064A",
@@ -1630,7 +1673,8 @@ var ko = {
1630
1673
  clear: "\uC9C0\uC6B0\uAE30",
1631
1674
  close: "\uB2EB\uAE30",
1632
1675
  open: "\uC5F4\uAE30",
1633
- select: "\uC120\uD0DD",
1676
+ select: "\uACE0\uB974\uAE30",
1677
+ // Batch 3: 선택 is the pick keyword — bare select rendered with it parses null
1634
1678
  clone: "\uBCF5\uC81C",
1635
1679
  prepend: "\uC55E\uC5D0\uCD94\uAC00",
1636
1680
  socket: "\uC18C\uCF13"
@@ -1671,14 +1715,17 @@ var ko = {
1671
1715
  change: "\uBCC0\uACBD",
1672
1716
  input: "\uC785\uB825",
1673
1717
  submit: "\uC81C\uCD9C",
1674
- reset: "\uB9AC\uC14B",
1718
+ reset: "\uC7AC\uC124\uC815",
1719
+ // Batch 3: 리셋 captured on.event as expression (broken listener) — profile word round-trips
1675
1720
  load: "\uB85C\uB4DC",
1676
- unload: "\uC5B8\uB85C\uB4DC",
1721
+ unload: "unload",
1677
1722
  resize: "\uB9AC\uC0AC\uC774\uC988",
1678
1723
  scroll: "\uC2A4\uD06C\uB864",
1679
- touchstart: "\uD130\uCE58\uC2DC\uC791",
1724
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
1725
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
1726
+ touchstart: "touchstart",
1680
1727
  touchend: "\uD130\uCE58\uC885\uB8CC",
1681
- touchmove: "\uD130\uCE58\uC774\uB3D9",
1728
+ touchmove: "touchmove",
1682
1729
  touchcancel: "\uD130\uCE58\uCDE8\uC18C"
1683
1730
  },
1684
1731
  logical: {
@@ -1751,6 +1798,9 @@ var ko = {
1751
1798
  properties: "\uD504\uB85C\uD37C\uD2F0\uB4E4"
1752
1799
  },
1753
1800
  expressions: {
1801
+ characters: "\uBB38\uC790",
1802
+ inclusive: "\uD3EC\uD568",
1803
+ exclusive: "\uC81C\uC678",
1754
1804
  first: "\uCCAB\uBC88\uC9F8",
1755
1805
  last: "\uB9C8\uC9C0\uB9C9",
1756
1806
  next: "\uB2E4\uC74C",
@@ -1869,16 +1919,26 @@ var zh = {
1869
1919
  events: {
1870
1920
  click: "\u70B9\u51FB",
1871
1921
  dblclick: "\u53CC\u51FB",
1872
- mousedown: "\u9F20\u6807\u6309\u4E0B",
1873
- mouseup: "\u9F20\u6807\u62AC\u8D77",
1874
- mouseenter: "\u9F20\u6807\u8FDB\u5165",
1875
- mouseleave: "\u9F20\u6807\u79BB\u5F00",
1876
- mouseover: "\u9F20\u6807\u60AC\u505C",
1922
+ // mousedown/mouseup: English passthrough — no native form round-trips on the
1923
+ // parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
1924
+ // shattered to their first word — live broken listeners in repeat-until-event).
1925
+ // The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
1926
+ mousedown: "mousedown",
1927
+ mouseup: "mouseup",
1928
+ mouseenter: "mouseenter",
1929
+ mouseleave: "mouseleave",
1930
+ // V3 Batch 2: 鼠标悬停 captured no event (expression:undefined) — realigned
1931
+ // to the tokenizer-registered 鼠标移入 (also S5b-listed). 按键抬起
1932
+ // prefix-shattered to 按键 and captured `keydown` (a keyup handler firing
1933
+ // on keydown) → 松键, the S5b/tokenizer form. keydown keeps 按键按下
1934
+ // (captures keydown via the registered 按键 prefix; S5b-aliased) — fixing
1935
+ // it to bare 按键 would collide with keypress below.
1936
+ mouseover: "\u9F20\u6807\u79FB\u5165",
1877
1937
  mouseout: "\u9F20\u6807\u79FB\u51FA",
1878
1938
  mousemove: "\u9F20\u6807\u79FB\u52A8",
1879
1939
  keydown: "\u6309\u952E\u6309\u4E0B",
1880
- keyup: "\u6309\u952E\u62AC\u8D77",
1881
- keypress: "\u6309\u952E",
1940
+ keyup: "\u677E\u952E",
1941
+ keypress: "keypress",
1882
1942
  focus: "\u805A\u7126",
1883
1943
  blur: "\u5931\u7126",
1884
1944
  change: "\u6539\u53D8",
@@ -1890,9 +1950,11 @@ var zh = {
1890
1950
  resize: "\u8C03\u6574\u5927\u5C0F",
1891
1951
  scroll: "\u6EDA\u52A8",
1892
1952
  touchstart: "\u89E6\u6478\u5F00\u59CB",
1893
- touchend: "\u89E6\u6478\u7ED3\u675F",
1953
+ touchend: "touchend",
1894
1954
  touchmove: "\u89E6\u6478\u79FB\u52A8",
1895
- touchcancel: "\u89E6\u6478\u53D6\u6D88"
1955
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
1956
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
1957
+ touchcancel: "touchcancel"
1896
1958
  },
1897
1959
  logical: {
1898
1960
  when: "\u5F53",
@@ -1964,6 +2026,9 @@ var zh = {
1964
2026
  properties: "\u7279\u6027\u96C6"
1965
2027
  },
1966
2028
  expressions: {
2029
+ characters: "\u5B57\u7B26",
2030
+ inclusive: "\u5305\u542B",
2031
+ exclusive: "\u6392\u9664",
1967
2032
  first: "\u7B2C\u4E00\u4E2A",
1968
2033
  last: "\u6700\u540E\u4E00\u4E2A",
1969
2034
  next: "\u4E0B\u4E00\u4E2A",
@@ -2056,7 +2121,8 @@ var tr = {
2056
2121
  clear: "temizle",
2057
2122
  close: "kapat",
2058
2123
  open: "a\xE7",
2059
- select: "se\xE7",
2124
+ select: "vurgula",
2125
+ // Batch 3: seç is the pick keyword — bare select rendered with it parses null
2060
2126
  clone: "klonla",
2061
2127
  prepend: "ba\u015F\u0131naekle",
2062
2128
  socket: "soket"
@@ -2081,34 +2147,40 @@ var tr = {
2081
2147
  },
2082
2148
  events: {
2083
2149
  click: "t\u0131klama",
2084
- dblclick: "\xE7ift_t\u0131klama",
2150
+ dblclick: "dblclick",
2085
2151
  // Fused (no `_`): the semantic tokenizer splits on `_`, breaking event
2086
2152
  // recognition (mousedown → "bas" / mouseup mis-captured). Mirrors the #535
2087
2153
  // ru/uk fuse + #510 resize fix.
2088
2154
  mousedown: "farebas",
2089
2155
  mouseup: "fareb\u0131rak",
2090
- mouseenter: "fare_gir",
2091
- mouseleave: "fare_\xE7\u0131k",
2092
- mouseover: "fare_\xFCst\xFC",
2093
- mouseout: "fare_d\u0131\u015F\u0131",
2094
- mousemove: "fare_hareket",
2095
- keydown: "tu\u015F_bas",
2096
- keyup: "tu\u015F_b\u0131rak",
2097
- keypress: "tu\u015F_bas\u0131m",
2156
+ mouseenter: "mouseenter",
2157
+ mouseleave: "mouseleave",
2158
+ // V3 Batch 2: same `_`-split class (tuş_bas captured verbatim `bas` — a
2159
+ // listener for a DOM event named "bas") — realigned to the S5b/tokenizer
2160
+ // fused forms.
2161
+ mouseover: "farei\xE7inde",
2162
+ mouseout: "fared\u0131\u015F\u0131nda",
2163
+ mousemove: "mousemove",
2164
+ keydown: "tu\u015Fbasma",
2165
+ keyup: "tu\u015Fb\u0131rakma",
2166
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
2167
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
2168
+ keypress: "keypress",
2098
2169
  focus: "odak",
2099
2170
  blur: "bulan\u0131k",
2100
2171
  change: "de\u011Fi\u015Fim",
2101
2172
  input: "giri\u015F",
2102
- submit: "g\xF6nder",
2173
+ submit: "g\xF6nderme",
2174
+ // Batch 3: gönder is the send verb — on-submit listener captured event "send"
2103
2175
  reset: "s\u0131f\u0131rla",
2104
2176
  load: "y\xFCkle",
2105
- unload: "y\xFCkle_kald\u0131r",
2177
+ unload: "unload",
2106
2178
  resize: "boyutland\u0131rma",
2107
2179
  scroll: "kayd\u0131r",
2108
- touchstart: "dokunma_ba\u015Fla",
2109
- touchend: "dokunma_bitir",
2110
- touchmove: "dokunma_hareket",
2111
- touchcancel: "dokunma_iptal"
2180
+ touchstart: "touchstart",
2181
+ touchend: "touchend",
2182
+ touchmove: "touchmove",
2183
+ touchcancel: "touchcancel"
2112
2184
  },
2113
2185
  logical: {
2114
2186
  when: "iken",
@@ -2179,6 +2251,9 @@ var tr = {
2179
2251
  properties: "\xF6zellikler"
2180
2252
  },
2181
2253
  expressions: {
2254
+ characters: "karakterler",
2255
+ inclusive: "dahil",
2256
+ exclusive: "hari\xE7",
2182
2257
  first: "ilk",
2183
2258
  // 'son' is also the END keyword emission (block terminator), and the
2184
2259
  // parser's end-recognizers match it by value — so a positional `last`
@@ -2280,9 +2355,11 @@ var id = {
2280
2355
  breakpoint: "titik-henti",
2281
2356
  clear: "bersihkan",
2282
2357
  // hapus is the remove PRIMARY in the profile
2283
- close: "tutup",
2358
+ close: "tutupkan",
2359
+ // Batch 3: tutup is the hide keyword — rendered close parsed as action=hide
2284
2360
  open: "buka",
2285
- select: "pilih",
2361
+ select: "tandai",
2362
+ // Batch 3: pilih is the pick keyword — bare select rendered with it parses null
2286
2363
  clone: "klon",
2287
2364
  prepend: "awali"
2288
2365
  },
@@ -2306,17 +2383,27 @@ var id = {
2306
2383
  },
2307
2384
  events: {
2308
2385
  click: "klik",
2309
- dblclick: "klik_ganda",
2310
- mousedown: "tekan_mouse",
2311
- mouseup: "lepas_mouse",
2312
- mouseenter: "mouse_masuk",
2313
- mouseleave: "mouse_keluar",
2314
- mouseover: "mouse_atas",
2315
- mouseout: "mouse_luar",
2316
- mousemove: "gerak_mouse",
2386
+ dblclick: "dblclick",
2387
+ // mousedown/mouseup: English passthrough — no native form round-trips on the
2388
+ // parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
2389
+ // shattered to their first word — live broken listeners in repeat-until-event).
2390
+ // The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
2391
+ mousedown: "mousedown",
2392
+ mouseup: "mouseup",
2393
+ mouseenter: "mouseenter",
2394
+ mouseleave: "mouseleave",
2395
+ // V3 Batch 2: mouse_atas/mouse_luar captured no event (the S5b forms
2396
+ // `mouse masuk`/`mouse keluar` are aspirational — they don't tokenize
2397
+ // either) — realigned to the tokenizer-registered natives. keydown keeps
2398
+ // tekan_tombol (captures keydown via the registered `tekan`; S5b-aliased).
2399
+ // keyup has NO parseable native (lepas is unregistered) → English
2400
+ // passthrough, matching the blur/reset precedent below.
2401
+ mouseover: "arahkan",
2402
+ mouseout: "tinggalkan",
2403
+ mousemove: "mousemove",
2317
2404
  keydown: "tekan_tombol",
2318
- keyup: "lepas_tombol",
2319
- keypress: "pencet_tombol",
2405
+ keyup: "keyup",
2406
+ keypress: "keypress",
2320
2407
  focus: "fokus",
2321
2408
  blur: "blur",
2322
2409
  change: "ubah",
@@ -2327,10 +2414,12 @@ var id = {
2327
2414
  unload: "bongkar",
2328
2415
  resize: "ubah_ukuran",
2329
2416
  scroll: "gulir",
2330
- touchstart: "mulai_sentuh",
2331
- touchend: "akhir_sentuh",
2332
- touchmove: "gerak_sentuh",
2333
- touchcancel: "batal_sentuh"
2417
+ touchstart: "touchstart",
2418
+ touchend: "touchend",
2419
+ touchmove: "touchmove",
2420
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
2421
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
2422
+ touchcancel: "touchcancel"
2334
2423
  },
2335
2424
  logical: {
2336
2425
  when: "ketika",
@@ -2401,6 +2490,9 @@ var id = {
2401
2490
  properties: "properti_properti"
2402
2491
  },
2403
2492
  expressions: {
2493
+ characters: "karakter",
2494
+ inclusive: "inklusif",
2495
+ exclusive: "eksklusif",
2404
2496
  first: "pertama",
2405
2497
  last: "terakhir",
2406
2498
  next: "berikutnya",
@@ -2511,8 +2603,10 @@ var qu = {
2511
2603
  breakpoint: "sayachinay",
2512
2604
  clear: "pichay",
2513
2605
  close: "wichqay",
2514
- open: "kichay",
2515
- select: "akllay",
2606
+ open: "paskay",
2607
+ // Batch 3: kichay is the trigger keyword — rendered open parsed null
2608
+ select: "marcay",
2609
+ // Batch 3: akllay is the pick keyword — bare select rendered with it parses null
2516
2610
  clone: "kikinchay",
2517
2611
  prepend: "\xF1awpachiy",
2518
2612
  socket: "tinkina"
@@ -2537,33 +2631,42 @@ var qu = {
2537
2631
  },
2538
2632
  events: {
2539
2633
  click: "\xF1itiy",
2540
- dblclick: "iskay_\xF1itiy",
2634
+ dblclick: "dblclick",
2541
2635
  // Fused (no `_`): the semantic tokenizer splits on `_` — and `rat_ñitiy` then
2542
2636
  // mis-captured as the `click` event (ñitiy→click). Mirrors the #535 ru/uk fuse.
2543
2637
  mousedown: "rat\xF1itiy",
2544
2638
  mouseup: "rathuqariy",
2545
- mouseenter: "rat_yaykuy",
2546
- mouseleave: "rat_lluqsiy",
2547
- mouseover: "rat_hawapi",
2548
- mouseout: "rat_hawamanta",
2549
- mousemove: "rat_kuyuy",
2550
- keydown: "yupana_\xF1itiy",
2551
- keyup: "yupana_huqariy",
2552
- keypress: "yupana_\xF1itana",
2639
+ mouseenter: "mouseenter",
2640
+ mouseleave: "mouseleave",
2641
+ mouseover: "mouseover",
2642
+ mouseout: "mouseout",
2643
+ mousemove: "mousemove",
2644
+ // V3 Batch 2: `yupana_ñitiy` split at `_` and mis-captured as the `click`
2645
+ // event (ñitiy→click, the same mechanism as the mousedown fuse above);
2646
+ // `yupana_huqariy` captured verbatim `huqariy`. Realigned to the
2647
+ // S5b/tokenizer forms.
2648
+ keydown: "llave uray",
2649
+ keyup: "llave hawa",
2650
+ keypress: "keypress",
2553
2651
  focus: "qhaway",
2554
2652
  blur: "paqariy",
2555
- change: "tikray",
2653
+ change: "kambiay",
2654
+ // Batch 3: tikray is the toggle verb — on-change listener captured event "toggle"
2556
2655
  input: "yaykuchiy",
2557
- submit: "kachay",
2558
- reset: "qallariy",
2656
+ submit: "apaykachay",
2657
+ // Batch 3: kachay is the send verb — on-submit captured "send" in one corpus slot
2658
+ reset: "musuqchay",
2659
+ // Batch 3: qallariy is the init/start word — on-reset listener captured event "default"
2559
2660
  load: "apakuy",
2560
- unload: "urmay",
2661
+ unload: "unload",
2561
2662
  resize: "hatun_kay",
2562
2663
  scroll: "kunray",
2563
- touchstart: "llamiy_qallay",
2564
- touchend: "llamiy_tukuy",
2565
- touchmove: "llamiy_kuyuy",
2566
- touchcancel: "llamiy_hark_ay"
2664
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
2665
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
2666
+ touchstart: "touchstart",
2667
+ touchend: "touchend",
2668
+ touchmove: "touchmove",
2669
+ touchcancel: "touchcancel"
2567
2670
  },
2568
2671
  logical: {
2569
2672
  when: "maykama",
@@ -2638,6 +2741,11 @@ var qu = {
2638
2741
  properties: "kanaykuna"
2639
2742
  },
2640
2743
  expressions: {
2744
+ // Pick unit word (arc 3): native-first per qu convention — `sanampa`
2745
+ // ("sign/letter", the standard term for alphabet characters) over a
2746
+ // loanword. Paired with the QUECHUA_EXTRAS entry in the semantic
2747
+ // tokenizer; both surfaces must match verbatim.
2748
+ characters: "sanampa",
2641
2749
  first: "\xF1awpaq",
2642
2750
  last: "qhipa",
2643
2751
  next: "qhipantin",
@@ -2701,7 +2809,10 @@ var sw = {
2701
2809
  wait: "ngoja",
2702
2810
  fetch: "leta",
2703
2811
  call: "ita",
2704
- return: "rudi",
2812
+ // `rudisha` (transitive, "give back a value"), not `rudi` ("go back"): the
2813
+ // semantic profile reads `rudisha`/`rejea`, so emitting `rudi` produced sw code
2814
+ // the parser could not read back. Kept clear of `rudia` (= `repeat`).
2815
+ return: "rudisha",
2705
2816
  make: "tengeneza",
2706
2817
  // auditor: dict emitted a word the profile reads differently
2707
2818
  log: "andika",
@@ -2715,7 +2826,8 @@ var sw = {
2715
2826
  go: "nenda",
2716
2827
  pushUrl: "sukumaUrl",
2717
2828
  replaceUrl: "badilishaUrl",
2718
- copy: "nakili",
2829
+ copy: "nakala",
2830
+ // Batch 3: nakili is the clone keyword — rendered copy parsed as action=clone
2719
2831
  pick: "chagua",
2720
2832
  beep: "lia",
2721
2833
  js: "js",
@@ -2734,7 +2846,8 @@ var sw = {
2734
2846
  // futa is a remove alternative in the profile
2735
2847
  close: "funga",
2736
2848
  open: "fungua",
2737
- select: "chagua",
2849
+ select: "alama",
2850
+ // Batch 3: chagua is the pick keyword — bare select rendered with it parses null
2738
2851
  clone: "nakili",
2739
2852
  prepend: "tanguliza",
2740
2853
  focus: "lenga",
@@ -2767,31 +2880,42 @@ var sw = {
2767
2880
  },
2768
2881
  events: {
2769
2882
  click: "bonyeza",
2770
- dblclick: "bonyeza_mara_mbili",
2883
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
2884
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
2885
+ dblclick: "dblclick",
2771
2886
  mousedown: "panya_shuka",
2772
2887
  mouseup: "panya_juu",
2773
2888
  mouseenter: "panya_ingia",
2774
2889
  mouseleave: "panya_toka",
2775
- mouseover: "panya_juu",
2890
+ // V3 Batch 2: panya_juu is mouseup's form (shared here by mistake — the
2891
+ // tokenizer deliberately maps it to mouseup for the corpus row, so a
2892
+ // mouseover handler captured `mouseup`) — realigned to the
2893
+ // tokenizer-registered `sogeza juu`.
2894
+ mouseover: "sogeza juu",
2776
2895
  mouseout: "panya_nje",
2777
2896
  mousemove: "panya_sogea",
2778
2897
  keydown: "kitufe_shuka",
2779
2898
  keyup: "kitufe_juu",
2780
- keypress: "kitufe_bonyeza",
2781
- focus: "zingatia",
2782
- blur: "poteza_macho",
2783
- change: "badilisha",
2899
+ keypress: "keypress",
2900
+ // V3 Batch 2: zingatia captured no event → lenga (S5b/tokenizer form);
2901
+ // poteza_macho was a null parse → `blur` (the S5b identity form — matches
2902
+ // the live corpus render `kwenye blur`); badilisha is the toggle VERB
2903
+ // homonym (a change handler captured event=`toggle` — a listener for a DOM
2904
+ // event named "toggle") → kubadilisha (S5b/tokenizer form).
2905
+ focus: "lenga",
2906
+ blur: "blur",
2907
+ change: "kubadilisha",
2784
2908
  input: "ingizo",
2785
2909
  submit: "wasilisha",
2786
- reset: "weka_upya",
2910
+ reset: "reset",
2787
2911
  load: "pakia",
2788
2912
  unload: "shuka",
2789
2913
  resize: "badilisha_ukubwa",
2790
2914
  scroll: "sogeza",
2791
- touchstart: "gusa_anza",
2792
- touchend: "gusa_mwisho",
2793
- touchmove: "gusa_sogea",
2794
- touchcancel: "gusa_ghairi"
2915
+ touchstart: "touchstart",
2916
+ touchend: "touchend",
2917
+ touchmove: "touchmove",
2918
+ touchcancel: "touchcancel"
2795
2919
  },
2796
2920
  logical: {
2797
2921
  when: "wakati",
@@ -2862,6 +2986,7 @@ var sw = {
2862
2986
  properties: "mali"
2863
2987
  },
2864
2988
  expressions: {
2989
+ characters: "herufi",
2865
2990
  first: "kwanza",
2866
2991
  // 'mwisho' is the END keyword (block terminator) — the tokenizer's keyword
2867
2992
  // map is last-wins, so a positional `last` emission of 'mwisho' reads as
@@ -2996,18 +3121,21 @@ var pt = {
2996
3121
  mouseup: "mouseCima",
2997
3122
  mouseenter: "mouseEntrar",
2998
3123
  mouseleave: "mouseSair",
2999
- mouseover: "mouseSobre",
3000
- mouseout: "mouseFora",
3124
+ // V3 Batch 2: camelCase forms split to the S5b/tokenizer-known forms (the
3125
+ // fused spellings captured event=expression:undefined — broken listeners)
3126
+ mouseover: "mouse sobre",
3127
+ mouseout: "mouse fora",
3001
3128
  mousemove: "mouseMover",
3002
- keydown: "teclaBaixo",
3003
- keyup: "teclaCima",
3129
+ keydown: "tecla baixo",
3130
+ keyup: "tecla cima",
3004
3131
  keypress: "teclaPressionar",
3005
3132
  focus: "foco",
3006
3133
  blur: "desfoque",
3007
3134
  change: "mudan\xE7a",
3008
3135
  input: "entrada",
3009
3136
  submit: "envio",
3010
- reset: "reiniciar",
3137
+ reset: "redefinir",
3138
+ // Batch 3: reiniciar captured on.event as expression (broken listener) — profile word round-trips
3011
3139
  load: "carregar",
3012
3140
  unload: "descarregar",
3013
3141
  resize: "redimensionar",
@@ -3086,6 +3214,9 @@ var pt = {
3086
3214
  properties: "propriedades"
3087
3215
  },
3088
3216
  expressions: {
3217
+ characters: "caracteres",
3218
+ inclusive: "inclusivo",
3219
+ exclusive: "exclusivo",
3089
3220
  first: "primeiro",
3090
3221
  last: "\xFAltimo",
3091
3222
  next: "pr\xF3ximo",
@@ -3201,8 +3332,12 @@ var it = {
3201
3332
  events: {
3202
3333
  click: "clic",
3203
3334
  dblclick: "doppioclic",
3204
- mousedown: "mousegi\xF9",
3205
- mouseup: "mousesu",
3335
+ // mousedown/mouseup: English passthrough — no native form round-trips on the
3336
+ // parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
3337
+ // shattered to their first word — live broken listeners in repeat-until-event).
3338
+ // The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
3339
+ mousedown: "mousedown",
3340
+ mouseup: "mouseup",
3206
3341
  mouseenter: "mouseentra",
3207
3342
  mouseleave: "mouseesce",
3208
3343
  mouseover: "mousesopra",
@@ -3212,11 +3347,13 @@ var it = {
3212
3347
  keyup: "tastosu",
3213
3348
  keypress: "tastopremi",
3214
3349
  focus: "fuoco",
3215
- blur: "sfuocatura",
3350
+ blur: "sfuocare",
3351
+ // Batch 3: the noun form parsed the blur command with no patient; the verb round-trips both event and command slots
3216
3352
  change: "cambio",
3217
3353
  input: "input",
3218
3354
  submit: "invio",
3219
- reset: "reset",
3355
+ reset: "reimpostare",
3356
+ // Batch 3: English passthrough captured on.event as expression — profile verb round-trips
3220
3357
  load: "carica",
3221
3358
  unload: "scarica",
3222
3359
  resize: "ridimensiona",
@@ -3295,6 +3432,9 @@ var it = {
3295
3432
  properties: "propriet\xE0"
3296
3433
  },
3297
3434
  expressions: {
3435
+ characters: "caratteri",
3436
+ inclusive: "inclusivo",
3437
+ exclusive: "esclusivo",
3298
3438
  first: "primo",
3299
3439
  last: "ultimo",
3300
3440
  next: "prossimo",
@@ -3382,15 +3522,18 @@ var vi = {
3382
3522
  init: "kh\u1EDFi t\u1EA1o",
3383
3523
  behavior: "h\xE0nh vi",
3384
3524
  install: "c\xE0i \u0111\u1EB7t",
3385
- clone: "sao ch\xE9p",
3386
- prepend: "th\xEAm \u0111\u1EA7u",
3525
+ clone: "nh\xE2n b\u1EA3n",
3526
+ // Batch 3: 'sao chép' is the copy verb — rendered clone parsed as action=copy
3527
+ prepend: "th\xEAm v\xE0o \u0111\u1EA7u",
3528
+ // Batch 3: 'thêm đầu' shatters at 'thêm' (add) — parsed as action=add
3387
3529
  else: "kh\xF4ng th\xEC",
3388
3530
  breakpoint: "\u0111i\u1EC3m-d\u1EEBng",
3389
3531
  clear: "t\u1EA9y",
3390
3532
  // xóa is the remove PRIMARY in the profile
3391
3533
  close: "\u0111\xF3ng",
3392
3534
  open: "m\u1EDF",
3393
- select: "ch\u1ECDn"
3535
+ select: "\u0111\xE1nh-d\u1EA5u"
3536
+ // Batch 3: 'chọn' is the pick keyword — bare select rendered with it parses null
3394
3537
  },
3395
3538
  modifiers: {
3396
3539
  into: "v\xE0o",
@@ -3413,21 +3556,24 @@ var vi = {
3413
3556
  },
3414
3557
  events: {
3415
3558
  click: "nh\u1EA5p",
3416
- dblclick: "nh\u1EA5p \u0111\xFAp",
3559
+ dblclick: "dblclick",
3417
3560
  input: "nh\u1EADp",
3418
- change: "thay \u0111\u1ED5i",
3419
- submit: "g\u1EEDi",
3420
- keydown: "ph\xEDm xu\u1ED1ng",
3421
- keyup: "ph\xEDm l\xEAn",
3422
- keypress: "nh\u1EA5n ph\xEDm",
3423
- mouseover: "chu\u1ED9t v\xE0o",
3424
- mouseout: "chu\u1ED9t ra",
3425
- mouseenter: "chu\u1ED9t v\xE0o",
3426
- mouseleave: "chu\u1ED9t r\u1EDDi",
3427
- focus: "t\u1EADp trung",
3428
- blur: "m\u1EA5t t\u1EADp trung",
3429
- reset: "\u0111\u1EB7t-l\u1EA1i",
3430
- load: "t\u1EA3i",
3561
+ change: "change",
3562
+ submit: "n\u1ED9p",
3563
+ // Batch 3: 'gửi' is the send verb — on-submit listener captured event "send"
3564
+ keydown: "keydown",
3565
+ keyup: "keyup",
3566
+ keypress: "keypress",
3567
+ mouseover: "mouseover",
3568
+ mouseout: "mouseout",
3569
+ mouseenter: "mouseenter",
3570
+ mouseleave: "mouseleave",
3571
+ focus: "focus",
3572
+ blur: "blur",
3573
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
3574
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
3575
+ reset: "reset",
3576
+ load: "load",
3431
3577
  scroll: "cu\u1ED9n",
3432
3578
  resize: "\u0111\u1ED5i k\xEDch th\u01B0\u1EDBc"
3433
3579
  },
@@ -3503,6 +3649,10 @@ var vi = {
3503
3649
  selected: "\u0111\u01B0\u1EE3c ch\u1ECDn"
3504
3650
  },
3505
3651
  expressions: {
3652
+ random: "ng\u1EABu nhi\xEAn",
3653
+ characters: "k\xFD t\u1EF1",
3654
+ inclusive: "bao g\u1ED3m",
3655
+ exclusive: "lo\u1EA1i tr\u1EEB",
3506
3656
  me: "t\xF4i",
3507
3657
  my: "c\u1EE7a t\xF4i",
3508
3658
  it: "n\xF3",
@@ -3599,7 +3749,8 @@ var pl = {
3599
3749
  // wyczyść is a remove alternative in the profile
3600
3750
  close: "zamknij",
3601
3751
  open: "otw\xF3rz",
3602
- select: "wybierz",
3752
+ select: "zaznacz",
3753
+ // Batch 3: wybierz is the pick keyword — bare select rendered with it parses null
3603
3754
  clone: "sklonuj",
3604
3755
  prepend: "poprzed\u017A",
3605
3756
  focus: "skup"
@@ -3625,8 +3776,12 @@ var pl = {
3625
3776
  events: {
3626
3777
  click: "klikni\u0119cie",
3627
3778
  dblclick: "podw\xF3jneklikni\u0119cie",
3628
- mousedown: "myszd\xF3\u0142",
3629
- mouseup: "myszg\xF3ra",
3779
+ // mousedown/mouseup: English passthrough — no native form round-trips on the
3780
+ // parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
3781
+ // shattered to their first word — live broken listeners in repeat-until-event).
3782
+ // The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
3783
+ mousedown: "mousedown",
3784
+ mouseup: "mouseup",
3630
3785
  mouseenter: "myszwej\u015Bcie",
3631
3786
  mouseleave: "myszwyj\u015Bcie",
3632
3787
  mouseover: "mysznad",
@@ -3639,8 +3794,10 @@ var pl = {
3639
3794
  blur: "rozmycie",
3640
3795
  change: "zmiana",
3641
3796
  input: "wej\u015Bcie",
3642
- submit: "wy\u015Blij",
3643
- reset: "resetuj",
3797
+ submit: "wys\u0142aniu",
3798
+ // Batch 3: wyślij is the send verb — on-submit listener captured event "send"
3799
+ reset: "zresetuj",
3800
+ // Batch 3: resetuj captured on.event as expression (broken listener) — profile word round-trips
3644
3801
  load: "za\u0142aduj",
3645
3802
  unload: "wy\u0142aduj",
3646
3803
  resize: "zmie\u0144rozmiar",
@@ -3719,6 +3876,9 @@ var pl = {
3719
3876
  properties: "w\u0142a\u015Bciwo\u015Bci"
3720
3877
  },
3721
3878
  expressions: {
3879
+ characters: "znaki",
3880
+ inclusive: "w\u0142\u0105cznie",
3881
+ exclusive: "wy\u0142\u0105cznie",
3722
3882
  first: "pierwszy",
3723
3883
  last: "ostatni",
3724
3884
  next: "nast\u0119pny",
@@ -3819,7 +3979,8 @@ var russianDictionary = {
3819
3979
  clear: "\u043E\u0447\u0438\u0441\u0442\u0438\u0442\u044C",
3820
3980
  close: "\u0437\u0430\u043A\u0440\u044B\u0442\u044C",
3821
3981
  open: "\u043E\u0442\u043A\u0440\u044B\u0442\u044C",
3822
- select: "\u0432\u044B\u0431\u0440\u0430\u0442\u044C"
3982
+ select: "\u0432\u044B\u0434\u0435\u043B\u0438\u0442\u044C"
3983
+ // Batch 3: выбрать is the pick keyword — bare select rendered with it parses null
3823
3984
  },
3824
3985
  modifiers: {
3825
3986
  to: "\u043A",
@@ -3861,7 +4022,8 @@ var russianDictionary = {
3861
4022
  change: "\u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435",
3862
4023
  input: "\u0432\u0432\u043E\u0434",
3863
4024
  submit: "\u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0430",
3864
- reset: "\u0441\u0431\u0440\u043E\u0441",
4025
+ reset: "\u0441\u0431\u0440\u043E\u0441\u0438\u0442\u044C",
4026
+ // Batch 3: сброс captured on.event as expression (broken listener) — profile verb round-trips
3865
4027
  load: "\u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0430",
3866
4028
  unload: "\u0432\u044B\u0433\u0440\u0443\u0437\u043A\u0430",
3867
4029
  resize: "\u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435\u0440\u0430\u0437\u043C\u0435\u0440\u0430",
@@ -3961,6 +4123,9 @@ var russianDictionary = {
3961
4123
  html: "html"
3962
4124
  },
3963
4125
  expressions: {
4126
+ characters: "\u0441\u0438\u043C\u0432\u043E\u043B\u044B",
4127
+ inclusive: "\u0432\u043A\u043B\u044E\u0447\u0438\u0442\u0435\u043B\u044C\u043D\u043E",
4128
+ exclusive: "\u0438\u0441\u043A\u043B\u044E\u0447\u0438\u0442\u0435\u043B\u044C\u043D\u043E",
3964
4129
  first: "\u043F\u0435\u0440\u0432\u044B\u0439",
3965
4130
  last: "\u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0439",
3966
4131
  next: "\u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439",
@@ -4061,7 +4226,8 @@ var ukrainianDictionary = {
4061
4226
  clear: "\u043E\u0447\u0438\u0441\u0442\u0438\u0442\u0438",
4062
4227
  close: "\u0437\u0430\u043A\u0440\u0438\u0442\u0438",
4063
4228
  open: "\u0432\u0456\u0434\u043A\u0440\u0438\u0442\u0438",
4064
- select: "\u0432\u0438\u0431\u0440\u0430\u0442\u0438"
4229
+ select: "\u0432\u0438\u0434\u0456\u043B\u0438\u0442\u0438"
4230
+ // Batch 3: вибрати is the pick keyword — bare select rendered with it parses null
4065
4231
  },
4066
4232
  modifiers: {
4067
4233
  to: "\u0434\u043E",
@@ -4102,7 +4268,8 @@ var ukrainianDictionary = {
4102
4268
  change: "\u0437\u043C\u0456\u043D\u0430",
4103
4269
  input: "\u0432\u0432\u0435\u0434\u0435\u043D\u043D\u044F",
4104
4270
  submit: "\u043D\u0430\u0434\u0441\u0438\u043B\u0430\u043D\u043D\u044F",
4105
- reset: "\u0441\u043A\u0438\u0434\u0430\u043D\u043D\u044F",
4271
+ reset: "\u0441\u043A\u0438\u043D\u0443\u0442\u0438",
4272
+ // Batch 3: скидання captured on.event as expression (broken listener) — profile verb round-trips
4106
4273
  load: "\u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F",
4107
4274
  unload: "\u0432\u0438\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F",
4108
4275
  resize: "\u0437\u043C\u0456\u043D\u0430\u0440\u043E\u0437\u043C\u0456\u0440\u0443",
@@ -4202,6 +4369,9 @@ var ukrainianDictionary = {
4202
4369
  html: "html"
4203
4370
  },
4204
4371
  expressions: {
4372
+ characters: "\u0441\u0438\u043C\u0432\u043E\u043B\u0438",
4373
+ inclusive: "\u0432\u043A\u043B\u044E\u0447\u043D\u043E",
4374
+ exclusive: "\u0432\u0438\u043A\u043B\u044E\u0447\u043D\u043E",
4205
4375
  first: "\u043F\u0435\u0440\u0448\u0438\u0439",
4206
4376
  last: "\u043E\u0441\u0442\u0430\u043D\u043D\u0456\u0439",
4207
4377
  next: "\u043D\u0430\u0441\u0442\u0443\u043F\u043D\u0438\u0439",
@@ -4291,13 +4461,15 @@ var hindiDictionary = {
4291
4461
  behavior: "\u0935\u094D\u092F\u0935\u0939\u093E\u0930",
4292
4462
  focus: "\u092B\u094B\u0915\u0938",
4293
4463
  blur: "\u0927\u0941\u0902\u0927\u0932\u093E",
4294
- clone: "\u0915\u0949\u092A\u0940",
4464
+ clone: "\u0915\u094D\u0932\u094B\u0928",
4465
+ // Batch 3: कॉपी is the copy verb — rendered clone parsed as action=copy
4295
4466
  prepend: "\u091C\u094B\u0921\u093C\u0947\u0902_\u0936\u0941\u0930\u0942",
4296
4467
  breakpoint: "\u092C\u094D\u0930\u0947\u0915\u092A\u094D\u0935\u093E\u0907\u0902\u091F",
4297
4468
  clear: "\u0938\u093E\u092B\u093C-\u0915\u0930\u0947\u0902",
4298
4469
  close: "\u092C\u0902\u0926-\u0915\u0930\u0947\u0902",
4299
4470
  open: "\u0916\u094B\u0932\u0947\u0902",
4300
- select: "\u091A\u0941\u0928\u0947\u0902",
4471
+ select: "\u091A\u093F\u0939\u094D\u0928\u093F\u0924-\u0915\u0930\u0947\u0902",
4472
+ // Batch 3: चुनें is the pick keyword — bare select rendered with it parses null
4301
4473
  socket: "\u0938\u0949\u0915\u0947\u091F"
4302
4474
  },
4303
4475
  modifiers: {
@@ -4442,6 +4614,7 @@ var hindiDictionary = {
4442
4614
  html: "html"
4443
4615
  },
4444
4616
  expressions: {
4617
+ characters: "\u0905\u0915\u094D\u0937\u0930",
4445
4618
  first: "\u092A\u0939\u0932\u093E",
4446
4619
  last: "\u0905\u0902\u0924\u093F\u092E",
4447
4620
  next: "\u0905\u0917\u0932\u093E",
@@ -4516,7 +4689,8 @@ var bengaliDictionary = {
4516
4689
  init: "\u09B6\u09C1\u09B0\u09C1",
4517
4690
  behavior: "\u0986\u099A\u09B0\u09A3",
4518
4691
  install: "\u0987\u09A8\u09B8\u09CD\u099F\u09B2",
4519
- clone: "\u0995\u09AA\u09BF",
4692
+ clone: "\u0995\u09CD\u09B2\u09CB\u09A8",
4693
+ // Batch 3: কপি is the copy verb — rendered clone parsed as action=copy
4520
4694
  swap: "\u09AC\u09A6\u09B2",
4521
4695
  morph: "\u09B0\u09C2\u09AA\u09BE\u09A8\u09CD\u09A4\u09B0",
4522
4696
  beep: "\u09AC\u09C0\u09AA",
@@ -4563,10 +4737,12 @@ var bengaliDictionary = {
4563
4737
  focus: "\u09AB\u09CB\u0995\u09BE\u09B8",
4564
4738
  blur: "\u099D\u09BE\u09AA\u09B8\u09BE",
4565
4739
  reset: "\u09B0\u09BF\u09B8\u09C7\u099F",
4566
- keydown: "\u0995\u09BF-\u09A1\u09BE\u0989\u09A8",
4567
- keyup: "\u0995\u09BF-\u0986\u09AA",
4568
- mouseover: "\u09AE\u09BE\u0989\u09B8-\u0993\u09AD\u09BE\u09B0",
4569
- mouseout: "\u09AE\u09BE\u0989\u09B8-\u0986\u0989\u099F",
4740
+ keydown: "keydown",
4741
+ keyup: "keyup",
4742
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
4743
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
4744
+ mouseover: "mouseover",
4745
+ mouseout: "mouseout",
4570
4746
  scroll: "\u09B8\u09CD\u0995\u09CD\u09B0\u09CB\u09B2",
4571
4747
  resize: "\u09B0\u09BF\u09B8\u09BE\u0987\u099C",
4572
4748
  every: "\u09AA\u09CD\u09B0\u09A4\u09BF"
@@ -4628,6 +4804,9 @@ var bengaliDictionary = {
4628
4804
  checked: "\u099A\u09C7\u0995 \u0995\u09B0\u09BE"
4629
4805
  },
4630
4806
  expressions: {
4807
+ characters: "\u0985\u0995\u09CD\u09B7\u09B0",
4808
+ inclusive: "\u0985\u09A8\u09CD\u09A4\u09B0\u09CD\u09AD\u09C1\u0995\u09CD\u09A4",
4809
+ exclusive: "\u09AC\u09BE\u09A6",
4631
4810
  first: "\u09AA\u09CD\u09B0\u09A5\u09AE",
4632
4811
  last: "\u09B6\u09C7\u09B7",
4633
4812
  next: "\u09AA\u09B0\u09AC\u09B0\u09CD\u09A4\u09C0",
@@ -4702,7 +4881,8 @@ var thaiDictionary = {
4702
4881
  init: "\u0E40\u0E23\u0E34\u0E48\u0E21\u0E15\u0E49\u0E19",
4703
4882
  behavior: "\u0E1E\u0E24\u0E15\u0E34\u0E01\u0E23\u0E23\u0E21",
4704
4883
  install: "\u0E15\u0E34\u0E14\u0E15\u0E31\u0E49\u0E07",
4705
- clone: "\u0E04\u0E31\u0E14\u0E25\u0E2D\u0E01",
4884
+ clone: "\u0E42\u0E04\u0E25\u0E19",
4885
+ // Batch 3: คัดลอก is the copy verb — rendered clone parsed as action=copy
4706
4886
  swap: "\u0E2A\u0E25\u0E31\u0E1A\u0E17\u0E35\u0E48",
4707
4887
  morph: "\u0E41\u0E1B\u0E25\u0E07\u0E23\u0E48\u0E32\u0E07",
4708
4888
  beep: "\u0E1A\u0E35\u0E4A\u0E1A",
@@ -4717,7 +4897,8 @@ var thaiDictionary = {
4717
4897
  clear: "\u0E40\u0E04\u0E25\u0E35\u0E22\u0E23\u0E4C",
4718
4898
  close: "\u0E1B\u0E34\u0E14",
4719
4899
  open: "\u0E40\u0E1B\u0E34\u0E14",
4720
- select: "\u0E40\u0E25\u0E37\u0E2D\u0E01"
4900
+ select: "\u0E17\u0E33\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u0E2B\u0E21\u0E32\u0E22"
4901
+ // Batch 3: เลือก is the pick keyword — bare select rendered with it parses null
4721
4902
  },
4722
4903
  modifiers: {
4723
4904
  to: "\u0E44\u0E1B\u0E22\u0E31\u0E07",
@@ -4812,6 +4993,9 @@ var thaiDictionary = {
4812
4993
  checked: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E41\u0E25\u0E49\u0E27"
4813
4994
  },
4814
4995
  expressions: {
4996
+ characters: "\u0E2D\u0E31\u0E01\u0E02\u0E23\u0E30",
4997
+ inclusive: "\u0E23\u0E27\u0E21",
4998
+ exclusive: "\u0E22\u0E01\u0E40\u0E27\u0E49\u0E19",
4815
4999
  first: "\u0E41\u0E23\u0E01",
4816
5000
  last: "\u0E2A\u0E38\u0E14\u0E17\u0E49\u0E32\u0E22",
4817
5001
  next: "\u0E16\u0E31\u0E14\u0E44\u0E1B",
@@ -4904,7 +5088,8 @@ var malayDictionary = {
4904
5088
  // padam is a remove alternative in the profile
4905
5089
  close: "tutup",
4906
5090
  open: "buka",
4907
- select: "pilih",
5091
+ select: "tandai",
5092
+ // Batch 3: pilih is the pick keyword — bare select rendered with it parses null
4908
5093
  socket: "soket"
4909
5094
  // derived from the ms profile (socket.primary); see generate-i18n-dictionaries
4910
5095
  },
@@ -5044,6 +5229,9 @@ var malayDictionary = {
5044
5229
  checked: "ditanda"
5045
5230
  },
5046
5231
  expressions: {
5232
+ characters: "aksara",
5233
+ inclusive: "inklusif",
5234
+ exclusive: "eksklusif",
5047
5235
  first: "pertama",
5048
5236
  last: "terakhir",
5049
5237
  next: "seterusnya",
@@ -5142,7 +5330,8 @@ var tagalogDictionary = {
5142
5330
  install: "ikabit",
5143
5331
  behavior: "ugali",
5144
5332
  init: "simulan",
5145
- clone: "kopyahin",
5333
+ clone: "i-clone",
5334
+ // Batch 3: kopyahin is the copy verb — rendered clone parsed as action=copy
5146
5335
  breakpoint: "breakpoint",
5147
5336
  clear: "burahin",
5148
5337
  close: "isara",
@@ -5289,6 +5478,9 @@ var tagalogDictionary = {
5289
5478
  checked: "naka_tsek"
5290
5479
  },
5291
5480
  expressions: {
5481
+ characters: "karakter",
5482
+ inclusive: "kasama",
5483
+ exclusive: "bukod",
5292
5484
  first: "una",
5293
5485
  last: "huli",
5294
5486
  next: "susunod",
@@ -5417,6 +5609,10 @@ var he = {
5417
5609
  },
5418
5610
  attributes: {},
5419
5611
  expressions: {
5612
+ random: "\u05D0\u05E7\u05E8\u05D0\u05D9",
5613
+ characters: "\u05EA\u05D5\u05D5\u05D9\u05DD",
5614
+ inclusive: "\u05DB\u05D5\u05DC\u05DC",
5615
+ exclusive: "\u05D1\u05DC\u05E2\u05D3\u05D9",
5420
5616
  last: "\u05D0\u05D7\u05E8\u05D5\u05DF"
5421
5617
  }
5422
5618
  };
@@ -6124,6 +6320,91 @@ var englishProfile = {
6124
6320
  { form: "for", role: "duration", position: "preposition", required: false }
6125
6321
  ]
6126
6322
  };
6323
+ function sovHaltCallFusedRule(cfg) {
6324
+ return {
6325
+ name: "halt-call-fused-verb-final",
6326
+ description: "Split the swept `halt <operand> call <args>` blob; both verbs clause-final",
6327
+ priority: 95,
6328
+ match: {
6329
+ commands: ["halt"],
6330
+ requiredRoles: ["action", "event", "patient"],
6331
+ // Only the juxtaposed-call blob: a plain `halt`/`halt the event` handler
6332
+ // keeps its default render. The translated call verb must be present to
6333
+ // split on — if the dictionary emission drifts, the rule stands down
6334
+ // rather than emitting a mangled clause.
6335
+ predicate: (parsed) => {
6336
+ const p = parsed.roles.get("patient");
6337
+ return !!p && /\bcall\b/.test(p.value) && !!p.translated && p.translated.includes(cfg.callVerb);
6338
+ }
6339
+ },
6340
+ transform: {
6341
+ roleOrder: [],
6342
+ // unused — custom takes over
6343
+ custom: (parsed) => {
6344
+ const p = parsed.roles.get("patient");
6345
+ const ev = parsed.roles.get("event");
6346
+ const act = parsed.roles.get("action");
6347
+ let blob = (p.translated ?? p.value).trim();
6348
+ const PH = "EVENTBLOCKPLACEHOLDER";
6349
+ let tail = "";
6350
+ if (blob.endsWith(PH)) {
6351
+ blob = blob.slice(0, -PH.length).trim();
6352
+ tail = ` ${PH}`;
6353
+ }
6354
+ const at = blob.indexOf(cfg.callVerb);
6355
+ const haltOperand = blob.slice(0, at).trim();
6356
+ const callArgs = blob.slice(at + cfg.callVerb.length).trim();
6357
+ return [
6358
+ haltOperand,
6359
+ cfg.patientMarker,
6360
+ ev.translated ?? ev.value,
6361
+ cfg.eventMarker,
6362
+ act.translated ?? act.value,
6363
+ cfg.connective,
6364
+ callArgs,
6365
+ cfg.patientMarker,
6366
+ cfg.callVerb
6367
+ ].join(" ") + tail;
6368
+ }
6369
+ }
6370
+ };
6371
+ }
6372
+ function sovPickRangeRule(cfg) {
6373
+ return {
6374
+ name: "pick-range-verb-final",
6375
+ description: "Reassemble the pick range (unit + endpoints + root) adjacent, verb-final",
6376
+ priority: 95,
6377
+ match: {
6378
+ commands: ["pick"],
6379
+ requiredRoles: ["action", "patient", "destination"],
6380
+ predicate: (parsed) => {
6381
+ const p = parsed.roles.get("patient");
6382
+ const d = parsed.roles.get("destination");
6383
+ return !!p && !!d && /^\S+\s+\d+$/.test(p.value.trim()) && /^\d+\s+of\s+\S+$/.test(d.value.trim());
6384
+ }
6385
+ },
6386
+ transform: {
6387
+ roleOrder: [],
6388
+ // unused — custom takes over
6389
+ custom: (parsed) => {
6390
+ const p = parsed.roles.get("patient");
6391
+ const d = parsed.roles.get("destination");
6392
+ const act = parsed.roles.get("action");
6393
+ const ev = parsed.roles.get("event");
6394
+ const pParts = (p.translated ?? p.value).trim().split(/\s+/);
6395
+ const a = pParts[pParts.length - 1];
6396
+ const unit = pParts.slice(0, -1).join(" ");
6397
+ const dMatch = d.value.trim().match(/^(\d+)\s+of\s+(\S+)$/);
6398
+ const b = dMatch[1];
6399
+ const root = dMatch[2];
6400
+ const verb = act.translated ?? act.value;
6401
+ const head = [root, cfg.genitive, unit, a, cfg.rangeSep, b, cfg.patientMarker];
6402
+ const eventPart = ev ? [ev.translated ?? ev.value, cfg.eventMarker] : [];
6403
+ return [...head, ...eventPart, verb].join(" ");
6404
+ }
6405
+ }
6406
+ };
6407
+ }
6127
6408
  var japaneseProfile = {
6128
6409
  code: "ja",
6129
6410
  name: "\u65E5\u672C\u8A9E",
@@ -6208,7 +6489,21 @@ var japaneseProfile = {
6208
6489
  roleOrder: ["patient", "destination", "action"],
6209
6490
  insertMarkers: true
6210
6491
  }
6211
- }
6492
+ },
6493
+ // the イベント を 送信 で 停止 それから validateForm() を 呼び出し
6494
+ sovHaltCallFusedRule({
6495
+ callVerb: "\u547C\u3073\u51FA\u3057",
6496
+ patientMarker: "\u3092",
6497
+ eventMarker: "\u3067",
6498
+ connective: "\u305D\u308C\u304B\u3089"
6499
+ }),
6500
+ // #note の 文字 0 から 5 を クリック で 選択
6501
+ sovPickRangeRule({
6502
+ genitive: "\u306E",
6503
+ rangeSep: "\u304B\u3089",
6504
+ patientMarker: "\u3092",
6505
+ eventMarker: "\u3067"
6506
+ })
6212
6507
  ]
6213
6508
  };
6214
6509
  var koreanProfile = {
@@ -6308,7 +6603,21 @@ var koreanProfile = {
6308
6603
  roleOrder: ["patient", "destination", "action"],
6309
6604
  insertMarkers: true
6310
6605
  }
6311
- }
6606
+ },
6607
+ // the 이벤트 를 제출 할 때 정지 그러면 validateForm() 를 호출
6608
+ sovHaltCallFusedRule({
6609
+ callVerb: "\uD638\uCD9C",
6610
+ patientMarker: "\uB97C",
6611
+ eventMarker: "\uD560 \uB54C",
6612
+ connective: "\uADF8\uB7EC\uBA74"
6613
+ }),
6614
+ // #note 의 문자 0 부터 5 를 클릭 할 때 선택
6615
+ sovPickRangeRule({
6616
+ genitive: "\uC758",
6617
+ rangeSep: "\uBD80\uD130",
6618
+ patientMarker: "\uB97C",
6619
+ eventMarker: "\uD560 \uB54C"
6620
+ })
6312
6621
  ]
6313
6622
  };
6314
6623
  var chineseProfile = {
@@ -6449,6 +6758,12 @@ var turkishProfile = {
6449
6758
  adpositionType: "postposition",
6450
6759
  morphology: "agglutinative",
6451
6760
  direction: "ltr",
6761
+ // NOTE: roles absent from this order are safety-net-appended AFTER the verb
6762
+ // by reorderRoles. That stranding is what the semantic parser's generated
6763
+ // patterns + reclaim tolerances were built around, so extending this order
6764
+ // wholesale re-renders (and breaks) the whole tr corpus — fix individual
6765
+ // defective shapes with per-command `rules` below instead (see the
6766
+ // wait/repeat-until rules from the transformer-rendering arc).
6452
6767
  canonicalOrder: ["patient", "event", "action"],
6453
6768
  markers: [
6454
6769
  // Turkish case suffixes - using spaced form for tokenization
@@ -6542,7 +6857,59 @@ var turkishProfile = {
6542
6857
  roleOrder: ["patient", "destination", "action"],
6543
6858
  insertMarkers: true
6544
6859
  }
6545
- }
6860
+ },
6861
+ {
6862
+ name: "wait-oblique-verb-final",
6863
+ description: "Keep wait's from-phrase and or-run inside the clause, verb-final",
6864
+ priority: 90,
6865
+ match: {
6866
+ commands: ["wait", "bekle"],
6867
+ // Only the multi-argument form (`wait for X or Y from Z`) strands:
6868
+ // without this rule the safety-net appends duration+source AFTER the
6869
+ // verb (`bekle … belge den`), and the stranded from-phrase is captured
6870
+ // by the NEXT statement as a junk trigger event (behavior-sortable R3).
6871
+ requiredRoles: ["action", "duration", "source"],
6872
+ // Never reorder a fused single-line handler — its event must stay put.
6873
+ predicate: (parsed) => !parsed.roles.has("event")
6874
+ },
6875
+ transform: {
6876
+ // belge den pointermove(clientY) veya pointerup(clientY) bekle
6877
+ roleOrder: ["patient", "source", "duration", "action"],
6878
+ insertMarkers: true
6879
+ }
6880
+ },
6881
+ {
6882
+ name: "repeat-until-event-verb-final",
6883
+ description: "Keep repeat-until-event's from-phrase before the verb",
6884
+ priority: 90,
6885
+ match: {
6886
+ commands: ["repeat", "tekrarla"],
6887
+ requiredRoles: ["action", "patient", "source"],
6888
+ // Gate to the until-event head; `repeat for item in .items` also
6889
+ // carries patient+source and must keep its (parseable) default order.
6890
+ predicate: (parsed) => /^repeat\s+until\s+event\b/i.test((parsed.original ?? "").trim())
6891
+ },
6892
+ transform: {
6893
+ // kadar olay pointerup i belge den tekrarla — matched semantic-side by
6894
+ // repeat-tr-until-head-verb-final.
6895
+ roleOrder: ["patient", "source", "action"],
6896
+ insertMarkers: true
6897
+ }
6898
+ },
6899
+ // the olay i gönder de durdur ardından validateForm() i çağır
6900
+ sovHaltCallFusedRule({
6901
+ callVerb: "\xE7a\u011F\u0131r",
6902
+ patientMarker: "i",
6903
+ eventMarker: "de",
6904
+ connective: "ard\u0131ndan"
6905
+ }),
6906
+ // #note nin karakterler 0 ile 5 i tıklama de seç
6907
+ sovPickRangeRule({
6908
+ genitive: "nin",
6909
+ rangeSep: "ile",
6910
+ patientMarker: "i",
6911
+ eventMarker: "de"
6912
+ })
6546
6913
  ]
6547
6914
  };
6548
6915
  var spanishProfile = {
@@ -6665,6 +7032,8 @@ var quechuaProfile = {
6665
7032
  morphology: "agglutinative",
6666
7033
  // Actually polysynthetic
6667
7034
  direction: "ltr",
7035
+ // NOTE: roles absent from this order are safety-net-appended AFTER the verb
7036
+ // (see the Turkish profile note) — extend via per-command `rules`, not here.
6668
7037
  canonicalOrder: ["patient", "source", "destination", "event", "action"],
6669
7038
  markers: [
6670
7039
  // Quechua case suffixes - using spaced form for tokenization
@@ -6677,6 +7046,41 @@ var quechuaProfile = {
6677
7046
  { form: "wan", role: "style", position: "postposition", required: false },
6678
7047
  { form: "hina", role: "method", position: "postposition", required: false }
6679
7048
  // "as/like"
7049
+ ],
7050
+ rules: [
7051
+ {
7052
+ name: "wait-oblique-verb-final",
7053
+ description: "Keep wait's from-phrase and or-run inside the clause, verb-final",
7054
+ priority: 90,
7055
+ match: {
7056
+ commands: ["wait", "suyay"],
7057
+ // Only `wait for X or Y from Z` strands: duration is missing from
7058
+ // canonicalOrder, so the or-run lands AFTER the verb and the next
7059
+ // trigger glues it into its event (behavior-sortable R3). See the
7060
+ // matching Turkish rule.
7061
+ requiredRoles: ["action", "duration", "source"],
7062
+ predicate: (parsed) => !parsed.roles.has("event")
7063
+ },
7064
+ transform: {
7065
+ // qillqa manta pointermove(clientY) utaq pointerup(clientY) suyay
7066
+ roleOrder: ["patient", "source", "duration", "action"],
7067
+ insertMarkers: true
7068
+ }
7069
+ },
7070
+ // the ruway ta kachay pi sayay chayqa validateForm() ta qayay
7071
+ sovHaltCallFusedRule({
7072
+ callVerb: "qayay",
7073
+ patientMarker: "ta",
7074
+ eventMarker: "pi",
7075
+ connective: "chayqa"
7076
+ }),
7077
+ // #note pa sanampa 0 kama 5 ta ñitiy pi akllay
7078
+ sovPickRangeRule({
7079
+ genitive: "pa",
7080
+ rangeSep: "kama",
7081
+ patientMarker: "ta",
7082
+ eventMarker: "pi"
7083
+ })
6680
7084
  ]
6681
7085
  };
6682
7086
  var swahiliProfile = {
@@ -6708,6 +7112,8 @@ var bengaliProfile = {
6708
7112
  direction: "ltr",
6709
7113
  // Bengali: Object comes before verb, postpositions follow nouns
6710
7114
  // "on click increment #count" → "#count কে ক্লিক এ বৃদ্ধি"
7115
+ // NOTE: roles absent from this order are safety-net-appended AFTER the verb
7116
+ // (see the Turkish profile note) — extend via per-command `rules`, not here.
6711
7117
  canonicalOrder: ["patient", "event", "action"],
6712
7118
  markers: [
6713
7119
  // Postpositions
@@ -6783,7 +7189,21 @@ var bengaliProfile = {
6783
7189
  roleOrder: ["patient", "destination", "action"],
6784
7190
  insertMarkers: true
6785
7191
  }
6786
- }
7192
+ },
7193
+ // the ঘটনা কে জমা এ থামুন তারপর validateForm() কে কল
7194
+ sovHaltCallFusedRule({
7195
+ callVerb: "\u0995\u09B2",
7196
+ patientMarker: "\u0995\u09C7",
7197
+ eventMarker: "\u098F",
7198
+ connective: "\u09A4\u09BE\u09B0\u09AA\u09B0"
7199
+ }),
7200
+ // #note র অক্ষর 0 থেকে 5 কে ক্লিক এ বাছুন
7201
+ sovPickRangeRule({
7202
+ genitive: "\u09B0",
7203
+ rangeSep: "\u09A5\u09C7\u0995\u09C7",
7204
+ patientMarker: "\u0995\u09C7",
7205
+ eventMarker: "\u098F"
7206
+ })
6787
7207
  ]
6788
7208
  };
6789
7209
  var italianProfile = {
@@ -6955,7 +7375,21 @@ var hindiProfile = {
6955
7375
  roleOrder: ["patient", "destination", "action"],
6956
7376
  insertMarkers: true
6957
7377
  }
6958
- }
7378
+ },
7379
+ // the घटना को जमा पर रोकें फिर validateForm() को कॉल
7380
+ sovHaltCallFusedRule({
7381
+ callVerb: "\u0915\u0949\u0932",
7382
+ patientMarker: "\u0915\u094B",
7383
+ eventMarker: "\u092A\u0930",
7384
+ connective: "\u092B\u093F\u0930"
7385
+ }),
7386
+ // #note का अक्षर 0 से 5 को क्लिक पर चुनें
7387
+ sovPickRangeRule({
7388
+ genitive: "\u0915\u093E",
7389
+ rangeSep: "\u0938\u0947",
7390
+ patientMarker: "\u0915\u094B",
7391
+ eventMarker: "\u092A\u0930"
7392
+ })
6959
7393
  ]
6960
7394
  };
6961
7395
  var tagalogProfile = {
@@ -8440,6 +8874,10 @@ var GrammarTransformer = class {
8440
8874
  if (block) {
8441
8875
  return this.transformBlock(block);
8442
8876
  }
8877
+ const strippedEnd = this.transformWithTrailingEnd(input);
8878
+ if (strippedEnd !== null) {
8879
+ return strippedEnd;
8880
+ }
8443
8881
  const setScope = this.transformSetWithScope(input);
8444
8882
  if (setScope !== null) {
8445
8883
  return setScope;
@@ -8467,6 +8905,35 @@ var GrammarTransformer = class {
8467
8905
  }
8468
8906
  return joinTokens(reordered.map((e) => e.translated || e.value));
8469
8907
  }
8908
+ /**
8909
+ * `<command …> end` fragments: transform the command without its stranded
8910
+ * terminator, then re-append the translated terminator as a standalone
8911
+ * trailing token. Fragments that open a block of their own (`if … end`,
8912
+ * `repeat … end`, `js … end`) bail — their terminator belongs to them and
8913
+ * their dedicated paths handle it.
8914
+ */
8915
+ transformWithTrailingEnd(input) {
8916
+ const src = this.sourceProfile.code;
8917
+ const tokens = input.trim().split(/\s+/);
8918
+ if (tokens.length < 2) {
8919
+ return null;
8920
+ }
8921
+ const sourceEnd = translateWord("end", "en", src).toLowerCase();
8922
+ if (tokens[tokens.length - 1].toLowerCase() !== sourceEnd) {
8923
+ return null;
8924
+ }
8925
+ const openers = new Set(
8926
+ ["if", "repeat", "unless", "while", "when", "live", "js"].map(
8927
+ (k) => translateWord(k, "en", src).toLowerCase()
8928
+ )
8929
+ );
8930
+ if (tokens.slice(0, -1).some((t) => openers.has(t.toLowerCase()))) {
8931
+ return null;
8932
+ }
8933
+ const inner = this.transformSingle(tokens.slice(0, -1).join(" "));
8934
+ const endT = translateWord(tokens[tokens.length - 1], src, this.targetProfile.code);
8935
+ return `${inner} ${endT}`;
8936
+ }
8470
8937
  /**
8471
8938
  * Detect and transform an inline JS block (`[on <event>] js <raw js> end`).
8472
8939
  *
@@ -8726,7 +9193,9 @@ var GrammarTransformer = class {
8726
9193
  const tailT = tail ? translateWord(tail, src, dst) : "";
8727
9194
  const clauseT = clause ? translateMultiWordValue(clause, src, dst) : "";
8728
9195
  const bodyT = this.transformConditionalBody(bodyTokens);
8729
- return [headT, clauseT, bodyT, tailT].filter((s) => s.length > 0).join(" ");
9196
+ const POSITIONAL_BRANCH_HEADS = /* @__PURE__ */ new Set(["first", "last", "next", "previous", "closest"]);
9197
+ const thenT = this.targetProfile.wordOrder === "SOV" && clauseT && POSITIONAL_BRANCH_HEADS.has(bodyTokens[1]?.toLowerCase()) && inner[bodyStart - 1]?.toLowerCase() !== "then" ? translateWord("then", src, dst) : "";
9198
+ return [headT, clauseT, thenT, bodyT, tailT].filter((s) => s.length > 0).join(" ");
8730
9199
  }
8731
9200
  /**
8732
9201
  * Transform an `if`/`unless` block body, splitting it at a top-level `else` into