@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.
- package/README.md +1 -1
- package/dist/browser.cjs +649 -180
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +2 -2
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +649 -180
- package/dist/browser.js.map +1 -1
- package/dist/dictionaries/index.cjs +370 -174
- package/dist/dictionaries/index.cjs.map +1 -1
- package/dist/dictionaries/index.js +370 -174
- package/dist/dictionaries/index.js.map +1 -1
- package/dist/index.cjs +649 -180
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -35
- package/dist/index.d.ts +35 -35
- package/dist/index.js +649 -180
- package/dist/index.js.map +1 -1
- package/dist/lokascript-i18n.min.js +1 -1
- package/dist/lokascript-i18n.min.js.map +1 -1
- package/dist/lokascript-i18n.mjs +678 -175
- package/dist/lokascript-i18n.mjs.map +1 -1
- package/dist/plugins/vite.cjs +370 -174
- package/dist/plugins/vite.cjs.map +1 -1
- package/dist/plugins/vite.js +370 -174
- package/dist/plugins/vite.js.map +1 -1
- package/dist/plugins/webpack.cjs +370 -174
- package/dist/plugins/webpack.cjs.map +1 -1
- package/dist/plugins/webpack.js +370 -174
- package/dist/plugins/webpack.js.map +1 -1
- package/dist/{transformer-DM7iplCU.d.cts → transformer--W46PGaW.d.cts} +8 -0
- package/dist/{transformer-BA8YX9u1.d.ts → transformer-FU06J6kG.d.ts} +8 -0
- package/package.json +7 -9
- package/src/dictionaries/ar.ts +20 -15
- package/src/dictionaries/bn.ts +10 -5
- package/src/dictionaries/de.ts +20 -8
- package/src/dictionaries/es.ts +10 -5
- package/src/dictionaries/fr.ts +15 -6
- package/src/dictionaries/he.ts +4 -0
- package/src/dictionaries/hi.ts +3 -2
- package/src/dictionaries/id.ts +31 -16
- package/src/dictionaries/it.ts +11 -4
- package/src/dictionaries/ja.ts +23 -15
- package/src/dictionaries/ko.ts +10 -5
- package/src/dictionaries/ms.ts +4 -1
- package/src/dictionaries/pl.ts +12 -5
- package/src/dictionaries/pt.ts +10 -5
- package/src/dictionaries/qu.ts +30 -19
- package/src/dictionaries/ru.ts +5 -2
- package/src/dictionaries/sw.ts +29 -14
- package/src/dictionaries/th.ts +5 -2
- package/src/dictionaries/tl.ts +4 -1
- package/src/dictionaries/tr.ts +24 -16
- package/src/dictionaries/uk.ts +5 -2
- package/src/dictionaries/vi.ts +23 -17
- package/src/dictionaries/zh.ts +24 -9
- package/src/grammar/grammar.test.ts +152 -0
- package/src/grammar/profiles/index.ts +316 -1
- package/src/grammar/transformer.ts +64 -1
- package/src/new-languages.test.ts +9 -3
- package/src/positional-keyword-drift.test.ts +6 -19
package/dist/lokascript-i18n.mjs
CHANGED
|
@@ -708,17 +708,19 @@ const es$1 = {
|
|
|
708
708
|
mouseup: 'ratónarriba',
|
|
709
709
|
mouseenter: 'ratónentrar',
|
|
710
710
|
mouseleave: 'ratónsalir',
|
|
711
|
-
|
|
712
|
-
|
|
711
|
+
// V3 Batch 2: fused forms split to the S5b/tokenizer-known forms (the fused
|
|
712
|
+
// spellings captured event=expression:undefined — broken listeners)
|
|
713
|
+
mouseover: 'ratón encima',
|
|
714
|
+
mouseout: 'ratón fuera',
|
|
713
715
|
mousemove: 'ratónmover',
|
|
714
|
-
keydown: '
|
|
715
|
-
keyup: '
|
|
716
|
+
keydown: 'tecla abajo',
|
|
717
|
+
keyup: 'tecla arriba',
|
|
716
718
|
keypress: 'teclapresar',
|
|
717
719
|
focus: 'enfocar',
|
|
718
720
|
blur: 'desenfocar',
|
|
719
721
|
change: 'cambiar',
|
|
720
722
|
input: 'entrada',
|
|
721
|
-
submit: '
|
|
723
|
+
submit: 'envío', // Batch 3: enviar is the send verb — on-submit listener captured event "send"
|
|
722
724
|
reset: 'reiniciar',
|
|
723
725
|
load: 'cargar',
|
|
724
726
|
unload: 'descargar',
|
|
@@ -798,6 +800,9 @@ const es$1 = {
|
|
|
798
800
|
properties: 'propiedades',
|
|
799
801
|
},
|
|
800
802
|
expressions: {
|
|
803
|
+
characters: 'caracteres',
|
|
804
|
+
inclusive: 'inclusivo',
|
|
805
|
+
exclusive: 'exclusivo',
|
|
801
806
|
first: 'primero',
|
|
802
807
|
last: 'último',
|
|
803
808
|
next: 'siguiente',
|
|
@@ -908,7 +913,7 @@ const ja$1 = {
|
|
|
908
913
|
clear: 'クリア',
|
|
909
914
|
close: '閉じる',
|
|
910
915
|
open: '開く',
|
|
911
|
-
select: '
|
|
916
|
+
select: '選ぶ', // Batch 3: 選択 is the pick keyword — bare select rendered with it parses null
|
|
912
917
|
clone: '複製',
|
|
913
918
|
prepend: '先頭追加',
|
|
914
919
|
socket: 'ソケット',
|
|
@@ -933,17 +938,22 @@ const ja$1 = {
|
|
|
933
938
|
},
|
|
934
939
|
events: {
|
|
935
940
|
click: 'クリック',
|
|
936
|
-
dblclick: '
|
|
941
|
+
dblclick: 'dblclick',
|
|
937
942
|
mousedown: 'マウス押下',
|
|
938
943
|
mouseup: 'マウス解放',
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
944
|
+
// V3c burn-down (2026-07-14): English passthrough — no native form round-trips
|
|
945
|
+
// on the parse side (probe: split forms shatter, fused forms capture verbatim).
|
|
946
|
+
mouseenter: 'mouseenter',
|
|
947
|
+
mouseleave: 'mouseleave',
|
|
948
|
+
// V3 Batch 2: kanji compounds realigned to the S5b/tokenizer katakana
|
|
949
|
+
// loanwords (the standard JS event terms; the compounds captured
|
|
950
|
+
// event=expression:undefined — broken listeners)
|
|
951
|
+
mouseover: 'マウスオーバー',
|
|
952
|
+
mouseout: 'マウスアウト',
|
|
953
|
+
mousemove: 'mousemove',
|
|
954
|
+
keydown: 'キーダウン',
|
|
955
|
+
keyup: 'キーアップ',
|
|
956
|
+
keypress: 'キープレス',
|
|
947
957
|
focus: 'フォーカス',
|
|
948
958
|
blur: 'ぼかし',
|
|
949
959
|
change: '変更',
|
|
@@ -951,13 +961,13 @@ const ja$1 = {
|
|
|
951
961
|
submit: '送信',
|
|
952
962
|
reset: 'リセット',
|
|
953
963
|
load: '読み込み',
|
|
954
|
-
unload: '
|
|
964
|
+
unload: 'unload',
|
|
955
965
|
resize: 'サイズ変更',
|
|
956
966
|
scroll: 'スクロール',
|
|
957
|
-
touchstart: '
|
|
958
|
-
touchend: '
|
|
959
|
-
touchmove: '
|
|
960
|
-
touchcancel: '
|
|
967
|
+
touchstart: 'touchstart',
|
|
968
|
+
touchend: 'touchend',
|
|
969
|
+
touchmove: 'touchmove',
|
|
970
|
+
touchcancel: 'touchcancel',
|
|
961
971
|
},
|
|
962
972
|
logical: {
|
|
963
973
|
when: '時',
|
|
@@ -1029,6 +1039,9 @@ const ja$1 = {
|
|
|
1029
1039
|
properties: 'プロパティ群',
|
|
1030
1040
|
},
|
|
1031
1041
|
expressions: {
|
|
1042
|
+
characters: '文字',
|
|
1043
|
+
inclusive: '含む',
|
|
1044
|
+
exclusive: '除く',
|
|
1032
1045
|
first: '最初',
|
|
1033
1046
|
last: '最後',
|
|
1034
1047
|
next: '次',
|
|
@@ -1169,15 +1182,21 @@ const fr$1 = {
|
|
|
1169
1182
|
events: {
|
|
1170
1183
|
click: 'clic',
|
|
1171
1184
|
dblclick: 'doubleclic',
|
|
1172
|
-
mousedown:
|
|
1173
|
-
|
|
1185
|
+
// mousedown/mouseup: English passthrough — no native form round-trips on the
|
|
1186
|
+
// parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
|
|
1187
|
+
// shattered to their first word — live broken listeners in repeat-until-event).
|
|
1188
|
+
// The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
|
|
1189
|
+
mousedown: 'mousedown',
|
|
1190
|
+
mouseup: 'mouseup',
|
|
1174
1191
|
mouseenter: 'sourisentrer',
|
|
1175
1192
|
mouseleave: 'sourissortir',
|
|
1176
|
-
|
|
1177
|
-
|
|
1193
|
+
// V3 Batch 2: fused forms split to the S5b/tokenizer-known forms (the fused
|
|
1194
|
+
// spellings captured event=expression:undefined — broken listeners)
|
|
1195
|
+
mouseover: 'souris dessus',
|
|
1196
|
+
mouseout: 'souris dehors',
|
|
1178
1197
|
mousemove: 'sourisbouger',
|
|
1179
|
-
keydown: '
|
|
1180
|
-
keyup: '
|
|
1198
|
+
keydown: 'touche bas',
|
|
1199
|
+
keyup: 'touche haut',
|
|
1181
1200
|
keypress: 'touchepressée',
|
|
1182
1201
|
focus: 'focus',
|
|
1183
1202
|
blur: 'flou',
|
|
@@ -1263,6 +1282,9 @@ const fr$1 = {
|
|
|
1263
1282
|
properties: 'propriétés',
|
|
1264
1283
|
},
|
|
1265
1284
|
expressions: {
|
|
1285
|
+
characters: 'caractères',
|
|
1286
|
+
inclusive: 'inclusif',
|
|
1287
|
+
exclusive: 'exclusif',
|
|
1266
1288
|
first: 'premier',
|
|
1267
1289
|
last: 'dernier',
|
|
1268
1290
|
next: 'suivant',
|
|
@@ -1377,7 +1399,7 @@ const de$1 = {
|
|
|
1377
1399
|
clear: 'bereinigen', // löschen is a remove alternative in the profile
|
|
1378
1400
|
close: 'schließen',
|
|
1379
1401
|
open: 'öffnen',
|
|
1380
|
-
select: '
|
|
1402
|
+
select: 'markieren', // Batch 3: auswählen is the pick keyword — bare select rendered with it parses null
|
|
1381
1403
|
clone: 'klonen',
|
|
1382
1404
|
prepend: 'voranstellen',
|
|
1383
1405
|
focus: 'fokussieren',
|
|
@@ -1403,18 +1425,27 @@ const de$1 = {
|
|
|
1403
1425
|
events: {
|
|
1404
1426
|
click: 'klick',
|
|
1405
1427
|
dblclick: 'doppelklick',
|
|
1406
|
-
mousedown:
|
|
1407
|
-
|
|
1428
|
+
// mousedown/mouseup: English passthrough — no native form round-trips on the
|
|
1429
|
+
// parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
|
|
1430
|
+
// shattered to their first word — live broken listeners in repeat-until-event).
|
|
1431
|
+
// The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
|
|
1432
|
+
mousedown: 'mousedown',
|
|
1433
|
+
mouseup: 'mouseup',
|
|
1408
1434
|
mouseenter: 'mauseintreten',
|
|
1409
1435
|
mouseleave: 'mausverlassen',
|
|
1410
|
-
|
|
1411
|
-
|
|
1436
|
+
// V3 Batch 2: fused/dead event words realigned to the de tokenizer's
|
|
1437
|
+
// registered forms (S5b's `maus über`/`taste runter` are aspirational — they
|
|
1438
|
+
// do not tokenize; `mausüber` etc. captured event=expression:undefined).
|
|
1439
|
+
mouseover: 'maus drüber',
|
|
1440
|
+
mouseout: 'maus weg',
|
|
1412
1441
|
mousemove: 'mausbewegen',
|
|
1413
|
-
keydown: '
|
|
1414
|
-
keyup: '
|
|
1442
|
+
keydown: 'taste unten',
|
|
1443
|
+
keyup: 'taste oben',
|
|
1415
1444
|
keypress: 'tastedrücken',
|
|
1416
1445
|
focus: 'fokus',
|
|
1417
|
-
blur
|
|
1446
|
+
// matches commands.blur (which shadows this at render time) and the live
|
|
1447
|
+
// corpus render; `unscharf` was dead vocab that captured no event
|
|
1448
|
+
blur: 'defokussieren',
|
|
1418
1449
|
change: 'ändern',
|
|
1419
1450
|
input: 'eingabe',
|
|
1420
1451
|
submit: 'absenden',
|
|
@@ -1497,6 +1528,9 @@ const de$1 = {
|
|
|
1497
1528
|
properties: 'eigenschaften',
|
|
1498
1529
|
},
|
|
1499
1530
|
expressions: {
|
|
1531
|
+
characters: 'Zeichen',
|
|
1532
|
+
inclusive: 'inklusiv',
|
|
1533
|
+
exclusive: 'exklusiv',
|
|
1500
1534
|
first: 'erste',
|
|
1501
1535
|
last: 'letzte',
|
|
1502
1536
|
next: 'nächste',
|
|
@@ -1617,7 +1651,7 @@ const ar$1 = {
|
|
|
1617
1651
|
clear: 'نظّف', // امسح is a remove alternative in the profile
|
|
1618
1652
|
close: 'أغلق',
|
|
1619
1653
|
open: 'افتح',
|
|
1620
|
-
select: '
|
|
1654
|
+
select: 'ظلل', // Batch 3: اختر is the pick keyword — bare select rendered with it parses null
|
|
1621
1655
|
clone: 'استنسخ',
|
|
1622
1656
|
prepend: 'سبق',
|
|
1623
1657
|
socket: 'مقبس',
|
|
@@ -1642,31 +1676,33 @@ const ar$1 = {
|
|
|
1642
1676
|
},
|
|
1643
1677
|
events: {
|
|
1644
1678
|
click: 'نقر',
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1679
|
+
// V3c burn-down (2026-07-14): English passthrough — no native form round-trips
|
|
1680
|
+
// on the parse side (probe: split forms shatter, fused forms capture verbatim).
|
|
1681
|
+
dblclick: 'dblclick',
|
|
1682
|
+
mousedown: 'mousedown',
|
|
1683
|
+
mouseup: 'mouseup',
|
|
1684
|
+
mouseenter: 'mouseenter',
|
|
1685
|
+
mouseleave: 'mouseleave',
|
|
1650
1686
|
mouseover: 'فأرة فوق',
|
|
1651
|
-
mouseout: '
|
|
1652
|
-
mousemove: '
|
|
1687
|
+
mouseout: 'mouseout',
|
|
1688
|
+
mousemove: 'mousemove',
|
|
1653
1689
|
keydown: 'مفتاح أسفل',
|
|
1654
1690
|
keyup: 'مفتاح أعلى',
|
|
1655
|
-
keypress: '
|
|
1691
|
+
keypress: 'keypress',
|
|
1656
1692
|
focus: 'تركيز',
|
|
1657
1693
|
blur: 'ضبابية',
|
|
1658
1694
|
change: 'تغيير',
|
|
1659
1695
|
input: 'إدخال',
|
|
1660
1696
|
submit: 'إرسال',
|
|
1661
|
-
reset: '
|
|
1697
|
+
reset: 'reset',
|
|
1662
1698
|
load: 'تحميل',
|
|
1663
|
-
unload: '
|
|
1699
|
+
unload: 'unload',
|
|
1664
1700
|
resize: 'تغيير حجم',
|
|
1665
1701
|
scroll: 'تمرير',
|
|
1666
|
-
touchstart: '
|
|
1667
|
-
touchend: '
|
|
1668
|
-
touchmove: '
|
|
1669
|
-
touchcancel: '
|
|
1702
|
+
touchstart: 'touchstart',
|
|
1703
|
+
touchend: 'touchend',
|
|
1704
|
+
touchmove: 'touchmove',
|
|
1705
|
+
touchcancel: 'touchcancel',
|
|
1670
1706
|
},
|
|
1671
1707
|
logical: {
|
|
1672
1708
|
when: 'عندما',
|
|
@@ -1738,6 +1774,9 @@ const ar$1 = {
|
|
|
1738
1774
|
properties: 'خصائص',
|
|
1739
1775
|
},
|
|
1740
1776
|
expressions: {
|
|
1777
|
+
characters: 'حروف',
|
|
1778
|
+
inclusive: 'شامل',
|
|
1779
|
+
exclusive: 'حصري',
|
|
1741
1780
|
first: 'أول',
|
|
1742
1781
|
last: 'آخر',
|
|
1743
1782
|
next: 'التالي',
|
|
@@ -1856,7 +1895,7 @@ const ko$1 = {
|
|
|
1856
1895
|
clear: '지우기',
|
|
1857
1896
|
close: '닫기',
|
|
1858
1897
|
open: '열기',
|
|
1859
|
-
select: '
|
|
1898
|
+
select: '고르기', // Batch 3: 선택 is the pick keyword — bare select rendered with it parses null
|
|
1860
1899
|
clone: '복제',
|
|
1861
1900
|
prepend: '앞에추가',
|
|
1862
1901
|
socket: '소켓',
|
|
@@ -1897,14 +1936,16 @@ const ko$1 = {
|
|
|
1897
1936
|
change: '변경',
|
|
1898
1937
|
input: '입력',
|
|
1899
1938
|
submit: '제출',
|
|
1900
|
-
reset: '
|
|
1939
|
+
reset: '재설정', // Batch 3: 리셋 captured on.event as expression (broken listener) — profile word round-trips
|
|
1901
1940
|
load: '로드',
|
|
1902
|
-
unload: '
|
|
1941
|
+
unload: 'unload',
|
|
1903
1942
|
resize: '리사이즈',
|
|
1904
1943
|
scroll: '스크롤',
|
|
1905
|
-
|
|
1944
|
+
// V3c burn-down (2026-07-14): English passthrough — no native form round-trips
|
|
1945
|
+
// on the parse side (probe: split forms shatter, fused forms capture verbatim).
|
|
1946
|
+
touchstart: 'touchstart',
|
|
1906
1947
|
touchend: '터치종료',
|
|
1907
|
-
touchmove: '
|
|
1948
|
+
touchmove: 'touchmove',
|
|
1908
1949
|
touchcancel: '터치취소',
|
|
1909
1950
|
},
|
|
1910
1951
|
logical: {
|
|
@@ -1977,6 +2018,9 @@ const ko$1 = {
|
|
|
1977
2018
|
properties: '프로퍼티들',
|
|
1978
2019
|
},
|
|
1979
2020
|
expressions: {
|
|
2021
|
+
characters: '문자',
|
|
2022
|
+
inclusive: '포함',
|
|
2023
|
+
exclusive: '제외',
|
|
1980
2024
|
first: '첫번째',
|
|
1981
2025
|
last: '마지막',
|
|
1982
2026
|
next: '다음',
|
|
@@ -2121,16 +2165,26 @@ const zh$1 = {
|
|
|
2121
2165
|
events: {
|
|
2122
2166
|
click: '点击',
|
|
2123
2167
|
dblclick: '双击',
|
|
2124
|
-
mousedown:
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2168
|
+
// mousedown/mouseup: English passthrough — no native form round-trips on the
|
|
2169
|
+
// parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
|
|
2170
|
+
// shattered to their first word — live broken listeners in repeat-until-event).
|
|
2171
|
+
// The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
|
|
2172
|
+
mousedown: 'mousedown',
|
|
2173
|
+
mouseup: 'mouseup',
|
|
2174
|
+
mouseenter: 'mouseenter',
|
|
2175
|
+
mouseleave: 'mouseleave',
|
|
2176
|
+
// V3 Batch 2: 鼠标悬停 captured no event (expression:undefined) — realigned
|
|
2177
|
+
// to the tokenizer-registered 鼠标移入 (also S5b-listed). 按键抬起
|
|
2178
|
+
// prefix-shattered to 按键 and captured `keydown` (a keyup handler firing
|
|
2179
|
+
// on keydown) → 松键, the S5b/tokenizer form. keydown keeps 按键按下
|
|
2180
|
+
// (captures keydown via the registered 按键 prefix; S5b-aliased) — fixing
|
|
2181
|
+
// it to bare 按键 would collide with keypress below.
|
|
2182
|
+
mouseover: '鼠标移入',
|
|
2129
2183
|
mouseout: '鼠标移出',
|
|
2130
2184
|
mousemove: '鼠标移动',
|
|
2131
2185
|
keydown: '按键按下',
|
|
2132
|
-
keyup: '
|
|
2133
|
-
keypress: '
|
|
2186
|
+
keyup: '松键',
|
|
2187
|
+
keypress: 'keypress',
|
|
2134
2188
|
focus: '聚焦',
|
|
2135
2189
|
blur: '失焦',
|
|
2136
2190
|
change: '改变',
|
|
@@ -2142,9 +2196,11 @@ const zh$1 = {
|
|
|
2142
2196
|
resize: '调整大小',
|
|
2143
2197
|
scroll: '滚动',
|
|
2144
2198
|
touchstart: '触摸开始',
|
|
2145
|
-
touchend: '
|
|
2199
|
+
touchend: 'touchend',
|
|
2146
2200
|
touchmove: '触摸移动',
|
|
2147
|
-
|
|
2201
|
+
// V3c burn-down (2026-07-14): English passthrough — no native form round-trips
|
|
2202
|
+
// on the parse side (probe: split forms shatter, fused forms capture verbatim).
|
|
2203
|
+
touchcancel: 'touchcancel',
|
|
2148
2204
|
},
|
|
2149
2205
|
logical: {
|
|
2150
2206
|
when: '当',
|
|
@@ -2216,6 +2272,9 @@ const zh$1 = {
|
|
|
2216
2272
|
properties: '特性集',
|
|
2217
2273
|
},
|
|
2218
2274
|
expressions: {
|
|
2275
|
+
characters: '字符',
|
|
2276
|
+
inclusive: '包含',
|
|
2277
|
+
exclusive: '排除',
|
|
2219
2278
|
first: '第一个',
|
|
2220
2279
|
last: '最后一个',
|
|
2221
2280
|
next: '下一个',
|
|
@@ -2333,7 +2392,7 @@ const tr$1 = {
|
|
|
2333
2392
|
clear: 'temizle',
|
|
2334
2393
|
close: 'kapat',
|
|
2335
2394
|
open: 'aç',
|
|
2336
|
-
select: '
|
|
2395
|
+
select: 'vurgula', // Batch 3: seç is the pick keyword — bare select rendered with it parses null
|
|
2337
2396
|
clone: 'klonla',
|
|
2338
2397
|
prepend: 'başınaekle',
|
|
2339
2398
|
socket: 'soket',
|
|
@@ -2358,34 +2417,39 @@ const tr$1 = {
|
|
|
2358
2417
|
},
|
|
2359
2418
|
events: {
|
|
2360
2419
|
click: 'tıklama',
|
|
2361
|
-
dblclick: '
|
|
2420
|
+
dblclick: 'dblclick',
|
|
2362
2421
|
// Fused (no `_`): the semantic tokenizer splits on `_`, breaking event
|
|
2363
2422
|
// recognition (mousedown → "bas" / mouseup mis-captured). Mirrors the #535
|
|
2364
2423
|
// ru/uk fuse + #510 resize fix.
|
|
2365
2424
|
mousedown: 'farebas',
|
|
2366
2425
|
mouseup: 'farebırak',
|
|
2367
|
-
mouseenter: '
|
|
2368
|
-
mouseleave: '
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2426
|
+
mouseenter: 'mouseenter',
|
|
2427
|
+
mouseleave: 'mouseleave',
|
|
2428
|
+
// V3 Batch 2: same `_`-split class (tuş_bas captured verbatim `bas` — a
|
|
2429
|
+
// listener for a DOM event named "bas") — realigned to the S5b/tokenizer
|
|
2430
|
+
// fused forms.
|
|
2431
|
+
mouseover: 'fareiçinde',
|
|
2432
|
+
mouseout: 'faredışında',
|
|
2433
|
+
mousemove: 'mousemove',
|
|
2434
|
+
keydown: 'tuşbasma',
|
|
2435
|
+
keyup: 'tuşbırakma',
|
|
2436
|
+
// V3c burn-down (2026-07-14): English passthrough — no native form round-trips
|
|
2437
|
+
// on the parse side (probe: split forms shatter, fused forms capture verbatim).
|
|
2438
|
+
keypress: 'keypress',
|
|
2375
2439
|
focus: 'odak',
|
|
2376
2440
|
blur: 'bulanık',
|
|
2377
2441
|
change: 'değişim',
|
|
2378
2442
|
input: 'giriş',
|
|
2379
|
-
submit: '
|
|
2443
|
+
submit: 'gönderme', // Batch 3: gönder is the send verb — on-submit listener captured event "send"
|
|
2380
2444
|
reset: 'sıfırla',
|
|
2381
2445
|
load: 'yükle',
|
|
2382
|
-
unload: '
|
|
2446
|
+
unload: 'unload',
|
|
2383
2447
|
resize: 'boyutlandırma',
|
|
2384
2448
|
scroll: 'kaydır',
|
|
2385
|
-
touchstart: '
|
|
2386
|
-
touchend: '
|
|
2387
|
-
touchmove: '
|
|
2388
|
-
touchcancel: '
|
|
2449
|
+
touchstart: 'touchstart',
|
|
2450
|
+
touchend: 'touchend',
|
|
2451
|
+
touchmove: 'touchmove',
|
|
2452
|
+
touchcancel: 'touchcancel',
|
|
2389
2453
|
},
|
|
2390
2454
|
logical: {
|
|
2391
2455
|
when: 'iken',
|
|
@@ -2456,6 +2520,9 @@ const tr$1 = {
|
|
|
2456
2520
|
properties: 'özellikler',
|
|
2457
2521
|
},
|
|
2458
2522
|
expressions: {
|
|
2523
|
+
characters: 'karakterler',
|
|
2524
|
+
inclusive: 'dahil',
|
|
2525
|
+
exclusive: 'hariç',
|
|
2459
2526
|
first: 'ilk',
|
|
2460
2527
|
// 'son' is also the END keyword emission (block terminator), and the
|
|
2461
2528
|
// parser's end-recognizers match it by value — so a positional `last`
|
|
@@ -2579,9 +2646,9 @@ const id$1 = {
|
|
|
2579
2646
|
install: 'pasang',
|
|
2580
2647
|
breakpoint: 'titik-henti',
|
|
2581
2648
|
clear: 'bersihkan', // hapus is the remove PRIMARY in the profile
|
|
2582
|
-
close: '
|
|
2649
|
+
close: 'tutupkan', // Batch 3: tutup is the hide keyword — rendered close parsed as action=hide
|
|
2583
2650
|
open: 'buka',
|
|
2584
|
-
select: '
|
|
2651
|
+
select: 'tandai', // Batch 3: pilih is the pick keyword — bare select rendered with it parses null
|
|
2585
2652
|
clone: 'klon',
|
|
2586
2653
|
prepend: 'awali',
|
|
2587
2654
|
},
|
|
@@ -2605,17 +2672,27 @@ const id$1 = {
|
|
|
2605
2672
|
},
|
|
2606
2673
|
events: {
|
|
2607
2674
|
click: 'klik',
|
|
2608
|
-
dblclick: '
|
|
2609
|
-
mousedown:
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2675
|
+
dblclick: 'dblclick',
|
|
2676
|
+
// mousedown/mouseup: English passthrough — no native form round-trips on the
|
|
2677
|
+
// parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
|
|
2678
|
+
// shattered to their first word — live broken listeners in repeat-until-event).
|
|
2679
|
+
// The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
|
|
2680
|
+
mousedown: 'mousedown',
|
|
2681
|
+
mouseup: 'mouseup',
|
|
2682
|
+
mouseenter: 'mouseenter',
|
|
2683
|
+
mouseleave: 'mouseleave',
|
|
2684
|
+
// V3 Batch 2: mouse_atas/mouse_luar captured no event (the S5b forms
|
|
2685
|
+
// `mouse masuk`/`mouse keluar` are aspirational — they don't tokenize
|
|
2686
|
+
// either) — realigned to the tokenizer-registered natives. keydown keeps
|
|
2687
|
+
// tekan_tombol (captures keydown via the registered `tekan`; S5b-aliased).
|
|
2688
|
+
// keyup has NO parseable native (lepas is unregistered) → English
|
|
2689
|
+
// passthrough, matching the blur/reset precedent below.
|
|
2690
|
+
mouseover: 'arahkan',
|
|
2691
|
+
mouseout: 'tinggalkan',
|
|
2692
|
+
mousemove: 'mousemove',
|
|
2616
2693
|
keydown: 'tekan_tombol',
|
|
2617
|
-
keyup: '
|
|
2618
|
-
keypress: '
|
|
2694
|
+
keyup: 'keyup',
|
|
2695
|
+
keypress: 'keypress',
|
|
2619
2696
|
focus: 'fokus',
|
|
2620
2697
|
blur: 'blur',
|
|
2621
2698
|
change: 'ubah',
|
|
@@ -2626,10 +2703,12 @@ const id$1 = {
|
|
|
2626
2703
|
unload: 'bongkar',
|
|
2627
2704
|
resize: 'ubah_ukuran',
|
|
2628
2705
|
scroll: 'gulir',
|
|
2629
|
-
touchstart: '
|
|
2630
|
-
touchend: '
|
|
2631
|
-
touchmove: '
|
|
2632
|
-
|
|
2706
|
+
touchstart: 'touchstart',
|
|
2707
|
+
touchend: 'touchend',
|
|
2708
|
+
touchmove: 'touchmove',
|
|
2709
|
+
// V3c burn-down (2026-07-14): English passthrough — no native form round-trips
|
|
2710
|
+
// on the parse side (probe: split forms shatter, fused forms capture verbatim).
|
|
2711
|
+
touchcancel: 'touchcancel',
|
|
2633
2712
|
},
|
|
2634
2713
|
logical: {
|
|
2635
2714
|
when: 'ketika',
|
|
@@ -2700,6 +2779,9 @@ const id$1 = {
|
|
|
2700
2779
|
properties: 'properti_properti',
|
|
2701
2780
|
},
|
|
2702
2781
|
expressions: {
|
|
2782
|
+
characters: 'karakter',
|
|
2783
|
+
inclusive: 'inklusif',
|
|
2784
|
+
exclusive: 'eksklusif',
|
|
2703
2785
|
first: 'pertama',
|
|
2704
2786
|
last: 'terakhir',
|
|
2705
2787
|
next: 'berikutnya',
|
|
@@ -2825,8 +2907,8 @@ const qu$1 = {
|
|
|
2825
2907
|
breakpoint: 'sayachinay',
|
|
2826
2908
|
clear: 'pichay',
|
|
2827
2909
|
close: 'wichqay',
|
|
2828
|
-
open: '
|
|
2829
|
-
select: '
|
|
2910
|
+
open: 'paskay', // Batch 3: kichay is the trigger keyword — rendered open parsed null
|
|
2911
|
+
select: 'marcay', // Batch 3: akllay is the pick keyword — bare select rendered with it parses null
|
|
2830
2912
|
clone: 'kikinchay',
|
|
2831
2913
|
prepend: 'ñawpachiy',
|
|
2832
2914
|
socket: 'tinkina',
|
|
@@ -2851,33 +2933,39 @@ const qu$1 = {
|
|
|
2851
2933
|
},
|
|
2852
2934
|
events: {
|
|
2853
2935
|
click: 'ñitiy',
|
|
2854
|
-
dblclick: '
|
|
2936
|
+
dblclick: 'dblclick',
|
|
2855
2937
|
// Fused (no `_`): the semantic tokenizer splits on `_` — and `rat_ñitiy` then
|
|
2856
2938
|
// mis-captured as the `click` event (ñitiy→click). Mirrors the #535 ru/uk fuse.
|
|
2857
2939
|
mousedown: 'ratñitiy',
|
|
2858
2940
|
mouseup: 'rathuqariy',
|
|
2859
|
-
mouseenter: '
|
|
2860
|
-
mouseleave: '
|
|
2861
|
-
mouseover: '
|
|
2862
|
-
mouseout: '
|
|
2863
|
-
mousemove: '
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2941
|
+
mouseenter: 'mouseenter',
|
|
2942
|
+
mouseleave: 'mouseleave',
|
|
2943
|
+
mouseover: 'mouseover',
|
|
2944
|
+
mouseout: 'mouseout',
|
|
2945
|
+
mousemove: 'mousemove',
|
|
2946
|
+
// V3 Batch 2: `yupana_ñitiy` split at `_` and mis-captured as the `click`
|
|
2947
|
+
// event (ñitiy→click, the same mechanism as the mousedown fuse above);
|
|
2948
|
+
// `yupana_huqariy` captured verbatim `huqariy`. Realigned to the
|
|
2949
|
+
// S5b/tokenizer forms.
|
|
2950
|
+
keydown: 'llave uray',
|
|
2951
|
+
keyup: 'llave hawa',
|
|
2952
|
+
keypress: 'keypress',
|
|
2867
2953
|
focus: 'qhaway',
|
|
2868
2954
|
blur: 'paqariy',
|
|
2869
|
-
change: '
|
|
2955
|
+
change: 'kambiay', // Batch 3: tikray is the toggle verb — on-change listener captured event "toggle"
|
|
2870
2956
|
input: 'yaykuchiy',
|
|
2871
|
-
submit: '
|
|
2872
|
-
reset: '
|
|
2957
|
+
submit: 'apaykachay', // Batch 3: kachay is the send verb — on-submit captured "send" in one corpus slot
|
|
2958
|
+
reset: 'musuqchay', // Batch 3: qallariy is the init/start word — on-reset listener captured event "default"
|
|
2873
2959
|
load: 'apakuy',
|
|
2874
|
-
unload: '
|
|
2960
|
+
unload: 'unload',
|
|
2875
2961
|
resize: 'hatun_kay',
|
|
2876
2962
|
scroll: 'kunray',
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2963
|
+
// V3c burn-down (2026-07-14): English passthrough — no native form round-trips
|
|
2964
|
+
// on the parse side (probe: split forms shatter, fused forms capture verbatim).
|
|
2965
|
+
touchstart: 'touchstart',
|
|
2966
|
+
touchend: 'touchend',
|
|
2967
|
+
touchmove: 'touchmove',
|
|
2968
|
+
touchcancel: 'touchcancel',
|
|
2881
2969
|
},
|
|
2882
2970
|
logical: {
|
|
2883
2971
|
when: 'maykama',
|
|
@@ -2952,6 +3040,11 @@ const qu$1 = {
|
|
|
2952
3040
|
properties: 'kanaykuna',
|
|
2953
3041
|
},
|
|
2954
3042
|
expressions: {
|
|
3043
|
+
// Pick unit word (arc 3): native-first per qu convention — `sanampa`
|
|
3044
|
+
// ("sign/letter", the standard term for alphabet characters) over a
|
|
3045
|
+
// loanword. Paired with the QUECHUA_EXTRAS entry in the semantic
|
|
3046
|
+
// tokenizer; both surfaces must match verbatim.
|
|
3047
|
+
characters: 'sanampa',
|
|
2955
3048
|
first: 'ñawpaq',
|
|
2956
3049
|
last: 'qhipa',
|
|
2957
3050
|
next: 'qhipantin',
|
|
@@ -3041,7 +3134,10 @@ const sw$1 = {
|
|
|
3041
3134
|
wait: 'ngoja',
|
|
3042
3135
|
fetch: 'leta',
|
|
3043
3136
|
call: 'ita',
|
|
3044
|
-
|
|
3137
|
+
// `rudisha` (transitive, "give back a value"), not `rudi` ("go back"): the
|
|
3138
|
+
// semantic profile reads `rudisha`/`rejea`, so emitting `rudi` produced sw code
|
|
3139
|
+
// the parser could not read back. Kept clear of `rudia` (= `repeat`).
|
|
3140
|
+
return: 'rudisha',
|
|
3045
3141
|
make: 'tengeneza', // auditor: dict emitted a word the profile reads differently
|
|
3046
3142
|
log: 'andika',
|
|
3047
3143
|
throw: 'tupa',
|
|
@@ -3054,7 +3150,7 @@ const sw$1 = {
|
|
|
3054
3150
|
go: 'nenda',
|
|
3055
3151
|
pushUrl: 'sukumaUrl',
|
|
3056
3152
|
replaceUrl: 'badilishaUrl',
|
|
3057
|
-
copy: '
|
|
3153
|
+
copy: 'nakala', // Batch 3: nakili is the clone keyword — rendered copy parsed as action=clone
|
|
3058
3154
|
pick: 'chagua',
|
|
3059
3155
|
beep: 'lia',
|
|
3060
3156
|
js: 'js',
|
|
@@ -3070,7 +3166,7 @@ const sw$1 = {
|
|
|
3070
3166
|
clear: 'safisha', // futa is a remove alternative in the profile
|
|
3071
3167
|
close: 'funga',
|
|
3072
3168
|
open: 'fungua',
|
|
3073
|
-
select: '
|
|
3169
|
+
select: 'alama', // Batch 3: chagua is the pick keyword — bare select rendered with it parses null
|
|
3074
3170
|
clone: 'nakili',
|
|
3075
3171
|
prepend: 'tanguliza',
|
|
3076
3172
|
focus: 'lenga',
|
|
@@ -3103,31 +3199,42 @@ const sw$1 = {
|
|
|
3103
3199
|
},
|
|
3104
3200
|
events: {
|
|
3105
3201
|
click: 'bonyeza',
|
|
3106
|
-
|
|
3202
|
+
// V3c burn-down (2026-07-14): English passthrough — no native form round-trips
|
|
3203
|
+
// on the parse side (probe: split forms shatter, fused forms capture verbatim).
|
|
3204
|
+
dblclick: 'dblclick',
|
|
3107
3205
|
mousedown: 'panya_shuka',
|
|
3108
3206
|
mouseup: 'panya_juu',
|
|
3109
3207
|
mouseenter: 'panya_ingia',
|
|
3110
3208
|
mouseleave: 'panya_toka',
|
|
3111
|
-
|
|
3209
|
+
// V3 Batch 2: panya_juu is mouseup's form (shared here by mistake — the
|
|
3210
|
+
// tokenizer deliberately maps it to mouseup for the corpus row, so a
|
|
3211
|
+
// mouseover handler captured `mouseup`) — realigned to the
|
|
3212
|
+
// tokenizer-registered `sogeza juu`.
|
|
3213
|
+
mouseover: 'sogeza juu',
|
|
3112
3214
|
mouseout: 'panya_nje',
|
|
3113
3215
|
mousemove: 'panya_sogea',
|
|
3114
3216
|
keydown: 'kitufe_shuka',
|
|
3115
3217
|
keyup: 'kitufe_juu',
|
|
3116
|
-
keypress: '
|
|
3117
|
-
|
|
3118
|
-
blur
|
|
3119
|
-
|
|
3218
|
+
keypress: 'keypress',
|
|
3219
|
+
// V3 Batch 2: zingatia captured no event → lenga (S5b/tokenizer form);
|
|
3220
|
+
// poteza_macho was a null parse → `blur` (the S5b identity form — matches
|
|
3221
|
+
// the live corpus render `kwenye blur`); badilisha is the toggle VERB
|
|
3222
|
+
// homonym (a change handler captured event=`toggle` — a listener for a DOM
|
|
3223
|
+
// event named "toggle") → kubadilisha (S5b/tokenizer form).
|
|
3224
|
+
focus: 'lenga',
|
|
3225
|
+
blur: 'blur',
|
|
3226
|
+
change: 'kubadilisha',
|
|
3120
3227
|
input: 'ingizo',
|
|
3121
3228
|
submit: 'wasilisha',
|
|
3122
|
-
reset: '
|
|
3229
|
+
reset: 'reset',
|
|
3123
3230
|
load: 'pakia',
|
|
3124
3231
|
unload: 'shuka',
|
|
3125
3232
|
resize: 'badilisha_ukubwa',
|
|
3126
3233
|
scroll: 'sogeza',
|
|
3127
|
-
touchstart: '
|
|
3128
|
-
touchend: '
|
|
3129
|
-
touchmove: '
|
|
3130
|
-
touchcancel: '
|
|
3234
|
+
touchstart: 'touchstart',
|
|
3235
|
+
touchend: 'touchend',
|
|
3236
|
+
touchmove: 'touchmove',
|
|
3237
|
+
touchcancel: 'touchcancel',
|
|
3131
3238
|
},
|
|
3132
3239
|
logical: {
|
|
3133
3240
|
when: 'wakati',
|
|
@@ -3198,6 +3305,7 @@ const sw$1 = {
|
|
|
3198
3305
|
properties: 'mali',
|
|
3199
3306
|
},
|
|
3200
3307
|
expressions: {
|
|
3308
|
+
characters: 'herufi',
|
|
3201
3309
|
first: 'kwanza',
|
|
3202
3310
|
// 'mwisho' is the END keyword (block terminator) — the tokenizer's keyword
|
|
3203
3311
|
// map is last-wins, so a positional `last` emission of 'mwisho' reads as
|
|
@@ -3357,18 +3465,20 @@ const pt$1 = {
|
|
|
3357
3465
|
mouseup: 'mouseCima',
|
|
3358
3466
|
mouseenter: 'mouseEntrar',
|
|
3359
3467
|
mouseleave: 'mouseSair',
|
|
3360
|
-
|
|
3361
|
-
|
|
3468
|
+
// V3 Batch 2: camelCase forms split to the S5b/tokenizer-known forms (the
|
|
3469
|
+
// fused spellings captured event=expression:undefined — broken listeners)
|
|
3470
|
+
mouseover: 'mouse sobre',
|
|
3471
|
+
mouseout: 'mouse fora',
|
|
3362
3472
|
mousemove: 'mouseMover',
|
|
3363
|
-
keydown: '
|
|
3364
|
-
keyup: '
|
|
3473
|
+
keydown: 'tecla baixo',
|
|
3474
|
+
keyup: 'tecla cima',
|
|
3365
3475
|
keypress: 'teclaPressionar',
|
|
3366
3476
|
focus: 'foco',
|
|
3367
3477
|
blur: 'desfoque',
|
|
3368
3478
|
change: 'mudança',
|
|
3369
3479
|
input: 'entrada',
|
|
3370
3480
|
submit: 'envio',
|
|
3371
|
-
reset: '
|
|
3481
|
+
reset: 'redefinir', // Batch 3: reiniciar captured on.event as expression (broken listener) — profile word round-trips
|
|
3372
3482
|
load: 'carregar',
|
|
3373
3483
|
unload: 'descarregar',
|
|
3374
3484
|
resize: 'redimensionar',
|
|
@@ -3447,6 +3557,9 @@ const pt$1 = {
|
|
|
3447
3557
|
properties: 'propriedades',
|
|
3448
3558
|
},
|
|
3449
3559
|
expressions: {
|
|
3560
|
+
characters: 'caracteres',
|
|
3561
|
+
inclusive: 'inclusivo',
|
|
3562
|
+
exclusive: 'exclusivo',
|
|
3450
3563
|
first: 'primeiro',
|
|
3451
3564
|
last: 'último',
|
|
3452
3565
|
next: 'próximo',
|
|
@@ -3587,8 +3700,12 @@ const it$1 = {
|
|
|
3587
3700
|
events: {
|
|
3588
3701
|
click: 'clic',
|
|
3589
3702
|
dblclick: 'doppioclic',
|
|
3590
|
-
mousedown:
|
|
3591
|
-
|
|
3703
|
+
// mousedown/mouseup: English passthrough — no native form round-trips on the
|
|
3704
|
+
// parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
|
|
3705
|
+
// shattered to their first word — live broken listeners in repeat-until-event).
|
|
3706
|
+
// The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
|
|
3707
|
+
mousedown: 'mousedown',
|
|
3708
|
+
mouseup: 'mouseup',
|
|
3592
3709
|
mouseenter: 'mouseentra',
|
|
3593
3710
|
mouseleave: 'mouseesce',
|
|
3594
3711
|
mouseover: 'mousesopra',
|
|
@@ -3598,11 +3715,11 @@ const it$1 = {
|
|
|
3598
3715
|
keyup: 'tastosu',
|
|
3599
3716
|
keypress: 'tastopremi',
|
|
3600
3717
|
focus: 'fuoco',
|
|
3601
|
-
blur: '
|
|
3718
|
+
blur: 'sfuocare', // Batch 3: the noun form parsed the blur command with no patient; the verb round-trips both event and command slots
|
|
3602
3719
|
change: 'cambio',
|
|
3603
3720
|
input: 'input',
|
|
3604
3721
|
submit: 'invio',
|
|
3605
|
-
reset: '
|
|
3722
|
+
reset: 'reimpostare', // Batch 3: English passthrough captured on.event as expression — profile verb round-trips
|
|
3606
3723
|
load: 'carica',
|
|
3607
3724
|
unload: 'scarica',
|
|
3608
3725
|
resize: 'ridimensiona',
|
|
@@ -3681,6 +3798,9 @@ const it$1 = {
|
|
|
3681
3798
|
properties: 'proprietà',
|
|
3682
3799
|
},
|
|
3683
3800
|
expressions: {
|
|
3801
|
+
characters: 'caratteri',
|
|
3802
|
+
inclusive: 'inclusivo',
|
|
3803
|
+
exclusive: 'esclusivo',
|
|
3684
3804
|
first: 'primo',
|
|
3685
3805
|
last: 'ultimo',
|
|
3686
3806
|
next: 'prossimo',
|
|
@@ -3767,14 +3887,14 @@ const vi$1 = {
|
|
|
3767
3887
|
init: 'khởi tạo',
|
|
3768
3888
|
behavior: 'hành vi',
|
|
3769
3889
|
install: 'cài đặt',
|
|
3770
|
-
clone: 'sao chép'
|
|
3771
|
-
prepend: 'thêm đầu',
|
|
3890
|
+
clone: 'nhân bản', // Batch 3: 'sao chép' is the copy verb — rendered clone parsed as action=copy
|
|
3891
|
+
prepend: 'thêm vào đầu', // Batch 3: 'thêm đầu' shatters at 'thêm' (add) — parsed as action=add
|
|
3772
3892
|
else: 'không thì',
|
|
3773
3893
|
breakpoint: 'điểm-dừng',
|
|
3774
3894
|
clear: 'tẩy', // xóa is the remove PRIMARY in the profile
|
|
3775
3895
|
close: 'đóng',
|
|
3776
3896
|
open: 'mở',
|
|
3777
|
-
select: 'chọn'
|
|
3897
|
+
select: 'đánh-dấu', // Batch 3: 'chọn' is the pick keyword — bare select rendered with it parses null
|
|
3778
3898
|
},
|
|
3779
3899
|
modifiers: {
|
|
3780
3900
|
into: 'vào',
|
|
@@ -3797,21 +3917,23 @@ const vi$1 = {
|
|
|
3797
3917
|
},
|
|
3798
3918
|
events: {
|
|
3799
3919
|
click: 'nhấp',
|
|
3800
|
-
dblclick: '
|
|
3920
|
+
dblclick: 'dblclick',
|
|
3801
3921
|
input: 'nhập',
|
|
3802
|
-
change: '
|
|
3803
|
-
submit: 'gửi'
|
|
3804
|
-
keydown: '
|
|
3805
|
-
keyup: '
|
|
3806
|
-
keypress: '
|
|
3807
|
-
mouseover: '
|
|
3808
|
-
mouseout: '
|
|
3809
|
-
mouseenter: '
|
|
3810
|
-
mouseleave: '
|
|
3811
|
-
focus: '
|
|
3812
|
-
blur: '
|
|
3813
|
-
|
|
3814
|
-
|
|
3922
|
+
change: 'change',
|
|
3923
|
+
submit: 'nộp', // Batch 3: 'gửi' is the send verb — on-submit listener captured event "send"
|
|
3924
|
+
keydown: 'keydown',
|
|
3925
|
+
keyup: 'keyup',
|
|
3926
|
+
keypress: 'keypress',
|
|
3927
|
+
mouseover: 'mouseover',
|
|
3928
|
+
mouseout: 'mouseout',
|
|
3929
|
+
mouseenter: 'mouseenter',
|
|
3930
|
+
mouseleave: 'mouseleave',
|
|
3931
|
+
focus: 'focus',
|
|
3932
|
+
blur: 'blur',
|
|
3933
|
+
// V3c burn-down (2026-07-14): English passthrough — no native form round-trips
|
|
3934
|
+
// on the parse side (probe: split forms shatter, fused forms capture verbatim).
|
|
3935
|
+
reset: 'reset',
|
|
3936
|
+
load: 'load',
|
|
3815
3937
|
scroll: 'cuộn',
|
|
3816
3938
|
resize: 'đổi kích thước',
|
|
3817
3939
|
},
|
|
@@ -3887,6 +4009,10 @@ const vi$1 = {
|
|
|
3887
4009
|
selected: 'được chọn',
|
|
3888
4010
|
},
|
|
3889
4011
|
expressions: {
|
|
4012
|
+
random: 'ngẫu nhiên',
|
|
4013
|
+
characters: 'ký tự',
|
|
4014
|
+
inclusive: 'bao gồm',
|
|
4015
|
+
exclusive: 'loại trừ',
|
|
3890
4016
|
me: 'tôi',
|
|
3891
4017
|
my: 'của tôi',
|
|
3892
4018
|
it: 'nó',
|
|
@@ -3981,7 +4107,7 @@ const pl$1 = {
|
|
|
3981
4107
|
clear: 'zeruj', // wyczyść is a remove alternative in the profile
|
|
3982
4108
|
close: 'zamknij',
|
|
3983
4109
|
open: 'otwórz',
|
|
3984
|
-
select: '
|
|
4110
|
+
select: 'zaznacz', // Batch 3: wybierz is the pick keyword — bare select rendered with it parses null
|
|
3985
4111
|
clone: 'sklonuj',
|
|
3986
4112
|
prepend: 'poprzedź',
|
|
3987
4113
|
focus: 'skup',
|
|
@@ -4007,8 +4133,12 @@ const pl$1 = {
|
|
|
4007
4133
|
events: {
|
|
4008
4134
|
click: 'kliknięcie',
|
|
4009
4135
|
dblclick: 'podwójnekliknięcie',
|
|
4010
|
-
mousedown:
|
|
4011
|
-
|
|
4136
|
+
// mousedown/mouseup: English passthrough — no native form round-trips on the
|
|
4137
|
+
// parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
|
|
4138
|
+
// shattered to their first word — live broken listeners in repeat-until-event).
|
|
4139
|
+
// The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
|
|
4140
|
+
mousedown: 'mousedown',
|
|
4141
|
+
mouseup: 'mouseup',
|
|
4012
4142
|
mouseenter: 'myszwejście',
|
|
4013
4143
|
mouseleave: 'myszwyjście',
|
|
4014
4144
|
mouseover: 'mysznad',
|
|
@@ -4021,8 +4151,8 @@ const pl$1 = {
|
|
|
4021
4151
|
blur: 'rozmycie',
|
|
4022
4152
|
change: 'zmiana',
|
|
4023
4153
|
input: 'wejście',
|
|
4024
|
-
submit: '
|
|
4025
|
-
reset: '
|
|
4154
|
+
submit: 'wysłaniu', // Batch 3: wyślij is the send verb — on-submit listener captured event "send"
|
|
4155
|
+
reset: 'zresetuj', // Batch 3: resetuj captured on.event as expression (broken listener) — profile word round-trips
|
|
4026
4156
|
load: 'załaduj',
|
|
4027
4157
|
unload: 'wyładuj',
|
|
4028
4158
|
resize: 'zmieńrozmiar',
|
|
@@ -4101,6 +4231,9 @@ const pl$1 = {
|
|
|
4101
4231
|
properties: 'właściwości',
|
|
4102
4232
|
},
|
|
4103
4233
|
expressions: {
|
|
4234
|
+
characters: 'znaki',
|
|
4235
|
+
inclusive: 'włącznie',
|
|
4236
|
+
exclusive: 'wyłącznie',
|
|
4104
4237
|
first: 'pierwszy',
|
|
4105
4238
|
last: 'ostatni',
|
|
4106
4239
|
next: 'następny',
|
|
@@ -4198,7 +4331,7 @@ const russianDictionary = {
|
|
|
4198
4331
|
clear: 'очистить',
|
|
4199
4332
|
close: 'закрыть',
|
|
4200
4333
|
open: 'открыть',
|
|
4201
|
-
select: '
|
|
4334
|
+
select: 'выделить', // Batch 3: выбрать is the pick keyword — bare select rendered with it parses null
|
|
4202
4335
|
},
|
|
4203
4336
|
modifiers: {
|
|
4204
4337
|
to: 'к',
|
|
@@ -4240,7 +4373,7 @@ const russianDictionary = {
|
|
|
4240
4373
|
change: 'изменение',
|
|
4241
4374
|
input: 'ввод',
|
|
4242
4375
|
submit: 'отправка',
|
|
4243
|
-
reset: '
|
|
4376
|
+
reset: 'сбросить', // Batch 3: сброс captured on.event as expression (broken listener) — profile verb round-trips
|
|
4244
4377
|
load: 'загрузка',
|
|
4245
4378
|
unload: 'выгрузка',
|
|
4246
4379
|
resize: 'изменениеразмера', // fused (no `_`) — see mousedown note above
|
|
@@ -4339,6 +4472,9 @@ const russianDictionary = {
|
|
|
4339
4472
|
html: 'html',
|
|
4340
4473
|
},
|
|
4341
4474
|
expressions: {
|
|
4475
|
+
characters: 'символы',
|
|
4476
|
+
inclusive: 'включительно',
|
|
4477
|
+
exclusive: 'исключительно',
|
|
4342
4478
|
first: 'первый',
|
|
4343
4479
|
last: 'последний',
|
|
4344
4480
|
next: 'следующий',
|
|
@@ -4436,7 +4572,7 @@ const ukrainianDictionary = {
|
|
|
4436
4572
|
clear: 'очистити',
|
|
4437
4573
|
close: 'закрити',
|
|
4438
4574
|
open: 'відкрити',
|
|
4439
|
-
select: '
|
|
4575
|
+
select: 'виділити', // Batch 3: вибрати is the pick keyword — bare select rendered with it parses null
|
|
4440
4576
|
},
|
|
4441
4577
|
modifiers: {
|
|
4442
4578
|
to: 'до',
|
|
@@ -4477,7 +4613,7 @@ const ukrainianDictionary = {
|
|
|
4477
4613
|
change: 'зміна',
|
|
4478
4614
|
input: 'введення',
|
|
4479
4615
|
submit: 'надсилання',
|
|
4480
|
-
reset: '
|
|
4616
|
+
reset: 'скинути', // Batch 3: скидання captured on.event as expression (broken listener) — profile verb round-trips
|
|
4481
4617
|
load: 'завантаження',
|
|
4482
4618
|
unload: 'вивантаження',
|
|
4483
4619
|
resize: 'змінарозміру', // fused (no `_`) — see mousedown note above
|
|
@@ -4576,6 +4712,9 @@ const ukrainianDictionary = {
|
|
|
4576
4712
|
html: 'html',
|
|
4577
4713
|
},
|
|
4578
4714
|
expressions: {
|
|
4715
|
+
characters: 'символи',
|
|
4716
|
+
inclusive: 'включно',
|
|
4717
|
+
exclusive: 'виключно',
|
|
4579
4718
|
first: 'перший',
|
|
4580
4719
|
last: 'останній',
|
|
4581
4720
|
next: 'наступний',
|
|
@@ -4663,13 +4802,13 @@ const hindiDictionary = {
|
|
|
4663
4802
|
behavior: 'व्यवहार',
|
|
4664
4803
|
focus: 'फोकस',
|
|
4665
4804
|
blur: 'धुंधला',
|
|
4666
|
-
clone: '
|
|
4805
|
+
clone: 'क्लोन', // Batch 3: कॉपी is the copy verb — rendered clone parsed as action=copy
|
|
4667
4806
|
prepend: 'जोड़ें_शुरू',
|
|
4668
4807
|
breakpoint: 'ब्रेकप्वाइंट',
|
|
4669
4808
|
clear: 'साफ़-करें',
|
|
4670
4809
|
close: 'बंद-करें',
|
|
4671
4810
|
open: 'खोलें',
|
|
4672
|
-
select: '
|
|
4811
|
+
select: 'चिह्नित-करें', // Batch 3: चुनें is the pick keyword — bare select rendered with it parses null
|
|
4673
4812
|
socket: 'सॉकेट',
|
|
4674
4813
|
},
|
|
4675
4814
|
modifiers: {
|
|
@@ -4814,6 +4953,7 @@ const hindiDictionary = {
|
|
|
4814
4953
|
html: 'html',
|
|
4815
4954
|
},
|
|
4816
4955
|
expressions: {
|
|
4956
|
+
characters: 'अक्षर',
|
|
4817
4957
|
first: 'पहला',
|
|
4818
4958
|
last: 'अंतिम',
|
|
4819
4959
|
next: 'अगला',
|
|
@@ -4888,7 +5028,7 @@ const bengaliDictionary = {
|
|
|
4888
5028
|
init: 'শুরু',
|
|
4889
5029
|
behavior: 'আচরণ',
|
|
4890
5030
|
install: 'ইনস্টল',
|
|
4891
|
-
clone: '
|
|
5031
|
+
clone: 'ক্লোন', // Batch 3: কপি is the copy verb — rendered clone parsed as action=copy
|
|
4892
5032
|
swap: 'বদল',
|
|
4893
5033
|
morph: 'রূপান্তর',
|
|
4894
5034
|
beep: 'বীপ',
|
|
@@ -4935,10 +5075,12 @@ const bengaliDictionary = {
|
|
|
4935
5075
|
focus: 'ফোকাস',
|
|
4936
5076
|
blur: 'ঝাপসা',
|
|
4937
5077
|
reset: 'রিসেট',
|
|
4938
|
-
keydown: '
|
|
4939
|
-
keyup: '
|
|
4940
|
-
|
|
4941
|
-
|
|
5078
|
+
keydown: 'keydown',
|
|
5079
|
+
keyup: 'keyup',
|
|
5080
|
+
// V3c burn-down (2026-07-14): English passthrough — no native form round-trips
|
|
5081
|
+
// on the parse side (probe: split forms shatter, fused forms capture verbatim).
|
|
5082
|
+
mouseover: 'mouseover',
|
|
5083
|
+
mouseout: 'mouseout',
|
|
4942
5084
|
scroll: 'স্ক্রোল',
|
|
4943
5085
|
resize: 'রিসাইজ',
|
|
4944
5086
|
every: 'প্রতি',
|
|
@@ -5000,6 +5142,9 @@ const bengaliDictionary = {
|
|
|
5000
5142
|
checked: 'চেক করা',
|
|
5001
5143
|
},
|
|
5002
5144
|
expressions: {
|
|
5145
|
+
characters: 'অক্ষর',
|
|
5146
|
+
inclusive: 'অন্তর্ভুক্ত',
|
|
5147
|
+
exclusive: 'বাদ',
|
|
5003
5148
|
first: 'প্রথম',
|
|
5004
5149
|
last: 'শেষ',
|
|
5005
5150
|
next: 'পরবর্তী',
|
|
@@ -5074,7 +5219,7 @@ const thaiDictionary = {
|
|
|
5074
5219
|
init: 'เริ่มต้น',
|
|
5075
5220
|
behavior: 'พฤติกรรม',
|
|
5076
5221
|
install: 'ติดตั้ง',
|
|
5077
|
-
clone: '
|
|
5222
|
+
clone: 'โคลน', // Batch 3: คัดลอก is the copy verb — rendered clone parsed as action=copy
|
|
5078
5223
|
swap: 'สลับที่',
|
|
5079
5224
|
morph: 'แปลงร่าง',
|
|
5080
5225
|
beep: 'บี๊บ',
|
|
@@ -5089,7 +5234,7 @@ const thaiDictionary = {
|
|
|
5089
5234
|
clear: 'เคลียร์',
|
|
5090
5235
|
close: 'ปิด',
|
|
5091
5236
|
open: 'เปิด',
|
|
5092
|
-
select: '
|
|
5237
|
+
select: 'ทำเครื่องหมาย', // Batch 3: เลือก is the pick keyword — bare select rendered with it parses null
|
|
5093
5238
|
},
|
|
5094
5239
|
modifiers: {
|
|
5095
5240
|
to: 'ไปยัง',
|
|
@@ -5184,6 +5329,9 @@ const thaiDictionary = {
|
|
|
5184
5329
|
checked: 'เลือกแล้ว',
|
|
5185
5330
|
},
|
|
5186
5331
|
expressions: {
|
|
5332
|
+
characters: 'อักขระ',
|
|
5333
|
+
inclusive: 'รวม',
|
|
5334
|
+
exclusive: 'ยกเว้น',
|
|
5187
5335
|
first: 'แรก',
|
|
5188
5336
|
last: 'สุดท้าย',
|
|
5189
5337
|
next: 'ถัดไป',
|
|
@@ -5275,7 +5423,7 @@ const malayDictionary = {
|
|
|
5275
5423
|
clear: 'bersihkan', // padam is a remove alternative in the profile
|
|
5276
5424
|
close: 'tutup',
|
|
5277
5425
|
open: 'buka',
|
|
5278
|
-
select: '
|
|
5426
|
+
select: 'tandai', // Batch 3: pilih is the pick keyword — bare select rendered with it parses null
|
|
5279
5427
|
socket: 'soket', // derived from the ms profile (socket.primary); see generate-i18n-dictionaries
|
|
5280
5428
|
},
|
|
5281
5429
|
modifiers: {
|
|
@@ -5414,6 +5562,9 @@ const malayDictionary = {
|
|
|
5414
5562
|
checked: 'ditanda',
|
|
5415
5563
|
},
|
|
5416
5564
|
expressions: {
|
|
5565
|
+
characters: 'aksara',
|
|
5566
|
+
inclusive: 'inklusif',
|
|
5567
|
+
exclusive: 'eksklusif',
|
|
5417
5568
|
first: 'pertama',
|
|
5418
5569
|
last: 'terakhir',
|
|
5419
5570
|
next: 'seterusnya',
|
|
@@ -5508,7 +5659,7 @@ const tagalogDictionary = {
|
|
|
5508
5659
|
install: 'ikabit',
|
|
5509
5660
|
behavior: 'ugali',
|
|
5510
5661
|
init: 'simulan',
|
|
5511
|
-
clone: '
|
|
5662
|
+
clone: 'i-clone', // Batch 3: kopyahin is the copy verb — rendered clone parsed as action=copy
|
|
5512
5663
|
breakpoint: 'breakpoint',
|
|
5513
5664
|
clear: 'burahin',
|
|
5514
5665
|
close: 'isara',
|
|
@@ -5655,6 +5806,9 @@ const tagalogDictionary = {
|
|
|
5655
5806
|
checked: 'naka_tsek',
|
|
5656
5807
|
},
|
|
5657
5808
|
expressions: {
|
|
5809
|
+
characters: 'karakter',
|
|
5810
|
+
inclusive: 'kasama',
|
|
5811
|
+
exclusive: 'bukod',
|
|
5658
5812
|
first: 'una',
|
|
5659
5813
|
last: 'huli',
|
|
5660
5814
|
next: 'susunod',
|
|
@@ -5782,6 +5936,10 @@ const he$1 = {
|
|
|
5782
5936
|
},
|
|
5783
5937
|
attributes: {},
|
|
5784
5938
|
expressions: {
|
|
5939
|
+
random: 'אקראי',
|
|
5940
|
+
characters: 'תווים',
|
|
5941
|
+
inclusive: 'כולל',
|
|
5942
|
+
exclusive: 'בלעדי',
|
|
5785
5943
|
last: 'אחרון',
|
|
5786
5944
|
},
|
|
5787
5945
|
};
|
|
@@ -6648,6 +6806,143 @@ const englishProfile = {
|
|
|
6648
6806
|
],
|
|
6649
6807
|
};
|
|
6650
6808
|
// =============================================================================
|
|
6809
|
+
// Shared SOV rule factory — fused `halt the event call fn()` heads (Family H,
|
|
6810
|
+
// docs-internal/HANDOFF_r1-deferred-tail.md)
|
|
6811
|
+
// =============================================================================
|
|
6812
|
+
/**
|
|
6813
|
+
* The form-submit-prevent head fuses TWO juxtaposed commands (`on submit halt
|
|
6814
|
+
* the event call validateForm()`): parseEventHandler reads `halt` as the
|
|
6815
|
+
* action and sweeps `the event call validateForm()` into ONE patient blob, so
|
|
6816
|
+
* the SOV patient-first reorder fronts the whole blob — halt's operand lands
|
|
6817
|
+
* clause-initial far from its verb, and call's operand rides inside the blob
|
|
6818
|
+
* (tr bound validateForm() to halt and the event to call). No roleOrder can
|
|
6819
|
+
* fix a single-blob patient; this custom render splits the blob at the
|
|
6820
|
+
* language's call verb and emits both commands verb-final, joined by the
|
|
6821
|
+
* then-connective (the boundary the semantic compound-splitter already
|
|
6822
|
+
* respects — the event-debounce geometry):
|
|
6823
|
+
*
|
|
6824
|
+
* `<halt-operand> <pm> <event> <em> <halt-verb> <conn> <call-args> <pm> <call-verb>`
|
|
6825
|
+
*
|
|
6826
|
+
* The trailing EVENTBLOCKPLACEHOLDER (tryTransformEventWithBlockBody's mask
|
|
6827
|
+
* for an `if … end` tail) is re-emitted clause-final so the caller's
|
|
6828
|
+
* strip-and-append keeps working.
|
|
6829
|
+
*/
|
|
6830
|
+
function sovHaltCallFusedRule(cfg) {
|
|
6831
|
+
return {
|
|
6832
|
+
name: 'halt-call-fused-verb-final',
|
|
6833
|
+
description: 'Split the swept `halt <operand> call <args>` blob; both verbs clause-final',
|
|
6834
|
+
priority: 95,
|
|
6835
|
+
match: {
|
|
6836
|
+
commands: ['halt'],
|
|
6837
|
+
requiredRoles: ['action', 'event', 'patient'],
|
|
6838
|
+
// Only the juxtaposed-call blob: a plain `halt`/`halt the event` handler
|
|
6839
|
+
// keeps its default render. The translated call verb must be present to
|
|
6840
|
+
// split on — if the dictionary emission drifts, the rule stands down
|
|
6841
|
+
// rather than emitting a mangled clause.
|
|
6842
|
+
predicate: parsed => {
|
|
6843
|
+
const p = parsed.roles.get('patient');
|
|
6844
|
+
return (!!p && /\bcall\b/.test(p.value) && !!p.translated && p.translated.includes(cfg.callVerb));
|
|
6845
|
+
},
|
|
6846
|
+
},
|
|
6847
|
+
transform: {
|
|
6848
|
+
roleOrder: [], // unused — custom takes over
|
|
6849
|
+
custom: parsed => {
|
|
6850
|
+
const p = parsed.roles.get('patient');
|
|
6851
|
+
const ev = parsed.roles.get('event');
|
|
6852
|
+
const act = parsed.roles.get('action');
|
|
6853
|
+
let blob = (p.translated ?? p.value).trim();
|
|
6854
|
+
const PH = 'EVENTBLOCKPLACEHOLDER';
|
|
6855
|
+
let tail = '';
|
|
6856
|
+
if (blob.endsWith(PH)) {
|
|
6857
|
+
blob = blob.slice(0, -PH.length).trim();
|
|
6858
|
+
tail = ` ${PH}`;
|
|
6859
|
+
}
|
|
6860
|
+
const at = blob.indexOf(cfg.callVerb);
|
|
6861
|
+
const haltOperand = blob.slice(0, at).trim();
|
|
6862
|
+
const callArgs = blob.slice(at + cfg.callVerb.length).trim();
|
|
6863
|
+
return ([
|
|
6864
|
+
haltOperand,
|
|
6865
|
+
cfg.patientMarker,
|
|
6866
|
+
ev.translated ?? ev.value,
|
|
6867
|
+
cfg.eventMarker,
|
|
6868
|
+
act.translated ?? act.value,
|
|
6869
|
+
cfg.connective,
|
|
6870
|
+
callArgs,
|
|
6871
|
+
cfg.patientMarker,
|
|
6872
|
+
cfg.callVerb,
|
|
6873
|
+
].join(' ') + tail);
|
|
6874
|
+
},
|
|
6875
|
+
},
|
|
6876
|
+
};
|
|
6877
|
+
}
|
|
6878
|
+
// =============================================================================
|
|
6879
|
+
// Shared SOV rule factory — pick range rows (`pick characters 0 to 5 of #note`,
|
|
6880
|
+
// docs-internal/HANDOFF_pick-text-range-arc3.md)
|
|
6881
|
+
// =============================================================================
|
|
6882
|
+
/**
|
|
6883
|
+
* The canonical pick range row decomposes in parseStatement/parseEventHandler as
|
|
6884
|
+
* patient=`characters 0` + destination=`5 of #note` (the range's `to` reads as a
|
|
6885
|
+
* destination marker), so the default SOV reorder scatters the range across the
|
|
6886
|
+
* clause — ja emitted `文字 0 を クリック で 選択 5 の #note に` with the `5`
|
|
6887
|
+
* stranded after the verb, unparseable in every SOV language. No roleOrder can
|
|
6888
|
+
* reunite a range split across two roles; this custom render reassembles the
|
|
6889
|
+
* canonical surface and emits the SOV convention shape (big patient phrase
|
|
6890
|
+
* first, verb final):
|
|
6891
|
+
*
|
|
6892
|
+
* `<root> <gen> <unit> <a> <sep> <b> <pm> [<event> <em>] <verb>`
|
|
6893
|
+
*
|
|
6894
|
+
* e.g. ja `#note の 文字 0 から 5 を クリック で 選択`. The paired semantic
|
|
6895
|
+
* pick pattern (patterns/pick.ts VERB_FINAL_SPECS) parses exactly this shape
|
|
6896
|
+
* back, with the range fold normalizing `<a> <sep> <b>` to English `a to b` —
|
|
6897
|
+
* the two sides co-evolve per the i18n-renders-semantic-patterns-coevolve
|
|
6898
|
+
* lesson; change one and you must re-probe the other.
|
|
6899
|
+
*
|
|
6900
|
+
* Gated tight to the numeric-endpoint corpus shape (`<unit> <int>` patient +
|
|
6901
|
+
* `<int> of <root>` destination); word endpoints (`start`/`end`), modes
|
|
6902
|
+
* (`inclusive`) and anything else fall through to the default render unchanged.
|
|
6903
|
+
*/
|
|
6904
|
+
function sovPickRangeRule(cfg) {
|
|
6905
|
+
return {
|
|
6906
|
+
name: 'pick-range-verb-final',
|
|
6907
|
+
description: 'Reassemble the pick range (unit + endpoints + root) adjacent, verb-final',
|
|
6908
|
+
priority: 95,
|
|
6909
|
+
match: {
|
|
6910
|
+
commands: ['pick'],
|
|
6911
|
+
requiredRoles: ['action', 'patient', 'destination'],
|
|
6912
|
+
predicate: parsed => {
|
|
6913
|
+
const p = parsed.roles.get('patient');
|
|
6914
|
+
const d = parsed.roles.get('destination');
|
|
6915
|
+
return (!!p &&
|
|
6916
|
+
!!d &&
|
|
6917
|
+
/^\S+\s+\d+$/.test(p.value.trim()) &&
|
|
6918
|
+
/^\d+\s+of\s+\S+$/.test(d.value.trim()));
|
|
6919
|
+
},
|
|
6920
|
+
},
|
|
6921
|
+
transform: {
|
|
6922
|
+
roleOrder: [], // unused — custom takes over
|
|
6923
|
+
custom: parsed => {
|
|
6924
|
+
const p = parsed.roles.get('patient');
|
|
6925
|
+
const d = parsed.roles.get('destination');
|
|
6926
|
+
const act = parsed.roles.get('action');
|
|
6927
|
+
const ev = parsed.roles.get('event');
|
|
6928
|
+
// Unit word from the TRANSLATED patient (`文字 0` → `文字`); endpoints
|
|
6929
|
+
// and root from the UNTRANSLATED values — integers and selectors are
|
|
6930
|
+
// language-invariant by construction (the R3 rule).
|
|
6931
|
+
const pParts = (p.translated ?? p.value).trim().split(/\s+/);
|
|
6932
|
+
const a = pParts[pParts.length - 1];
|
|
6933
|
+
const unit = pParts.slice(0, -1).join(' ');
|
|
6934
|
+
const dMatch = d.value.trim().match(/^(\d+)\s+of\s+(\S+)$/);
|
|
6935
|
+
const b = dMatch[1];
|
|
6936
|
+
const root = dMatch[2];
|
|
6937
|
+
const verb = act.translated ?? act.value;
|
|
6938
|
+
const head = [root, cfg.genitive, unit, a, cfg.rangeSep, b, cfg.patientMarker];
|
|
6939
|
+
const eventPart = ev ? [ev.translated ?? ev.value, cfg.eventMarker] : [];
|
|
6940
|
+
return [...head, ...eventPart, verb].join(' ');
|
|
6941
|
+
},
|
|
6942
|
+
},
|
|
6943
|
+
};
|
|
6944
|
+
}
|
|
6945
|
+
// =============================================================================
|
|
6651
6946
|
// Japanese (SOV, Postpositions)
|
|
6652
6947
|
// =============================================================================
|
|
6653
6948
|
const japaneseProfile = {
|
|
@@ -6735,6 +7030,20 @@ const japaneseProfile = {
|
|
|
6735
7030
|
insertMarkers: true,
|
|
6736
7031
|
},
|
|
6737
7032
|
},
|
|
7033
|
+
// the イベント を 送信 で 停止 それから validateForm() を 呼び出し
|
|
7034
|
+
sovHaltCallFusedRule({
|
|
7035
|
+
callVerb: '呼び出し',
|
|
7036
|
+
patientMarker: 'を',
|
|
7037
|
+
eventMarker: 'で',
|
|
7038
|
+
connective: 'それから',
|
|
7039
|
+
}),
|
|
7040
|
+
// #note の 文字 0 から 5 を クリック で 選択
|
|
7041
|
+
sovPickRangeRule({
|
|
7042
|
+
genitive: 'の',
|
|
7043
|
+
rangeSep: 'から',
|
|
7044
|
+
patientMarker: 'を',
|
|
7045
|
+
eventMarker: 'で',
|
|
7046
|
+
}),
|
|
6738
7047
|
],
|
|
6739
7048
|
};
|
|
6740
7049
|
// =============================================================================
|
|
@@ -6837,6 +7146,20 @@ const koreanProfile = {
|
|
|
6837
7146
|
insertMarkers: true,
|
|
6838
7147
|
},
|
|
6839
7148
|
},
|
|
7149
|
+
// the 이벤트 를 제출 할 때 정지 그러면 validateForm() 를 호출
|
|
7150
|
+
sovHaltCallFusedRule({
|
|
7151
|
+
callVerb: '호출',
|
|
7152
|
+
patientMarker: '를',
|
|
7153
|
+
eventMarker: '할 때',
|
|
7154
|
+
connective: '그러면',
|
|
7155
|
+
}),
|
|
7156
|
+
// #note 의 문자 0 부터 5 를 클릭 할 때 선택
|
|
7157
|
+
sovPickRangeRule({
|
|
7158
|
+
genitive: '의',
|
|
7159
|
+
rangeSep: '부터',
|
|
7160
|
+
patientMarker: '를',
|
|
7161
|
+
eventMarker: '할 때',
|
|
7162
|
+
}),
|
|
6840
7163
|
],
|
|
6841
7164
|
};
|
|
6842
7165
|
// =============================================================================
|
|
@@ -6988,6 +7311,12 @@ const turkishProfile = {
|
|
|
6988
7311
|
adpositionType: 'postposition',
|
|
6989
7312
|
morphology: 'agglutinative',
|
|
6990
7313
|
direction: 'ltr',
|
|
7314
|
+
// NOTE: roles absent from this order are safety-net-appended AFTER the verb
|
|
7315
|
+
// by reorderRoles. That stranding is what the semantic parser's generated
|
|
7316
|
+
// patterns + reclaim tolerances were built around, so extending this order
|
|
7317
|
+
// wholesale re-renders (and breaks) the whole tr corpus — fix individual
|
|
7318
|
+
// defective shapes with per-command `rules` below instead (see the
|
|
7319
|
+
// wait/repeat-until rules from the transformer-rendering arc).
|
|
6991
7320
|
canonicalOrder: ['patient', 'event', 'action'],
|
|
6992
7321
|
markers: [
|
|
6993
7322
|
// Turkish case suffixes - using spaced form for tokenization
|
|
@@ -7082,6 +7411,58 @@ const turkishProfile = {
|
|
|
7082
7411
|
insertMarkers: true,
|
|
7083
7412
|
},
|
|
7084
7413
|
},
|
|
7414
|
+
{
|
|
7415
|
+
name: 'wait-oblique-verb-final',
|
|
7416
|
+
description: "Keep wait's from-phrase and or-run inside the clause, verb-final",
|
|
7417
|
+
priority: 90,
|
|
7418
|
+
match: {
|
|
7419
|
+
commands: ['wait', 'bekle'],
|
|
7420
|
+
// Only the multi-argument form (`wait for X or Y from Z`) strands:
|
|
7421
|
+
// without this rule the safety-net appends duration+source AFTER the
|
|
7422
|
+
// verb (`bekle … belge den`), and the stranded from-phrase is captured
|
|
7423
|
+
// by the NEXT statement as a junk trigger event (behavior-sortable R3).
|
|
7424
|
+
requiredRoles: ['action', 'duration', 'source'],
|
|
7425
|
+
// Never reorder a fused single-line handler — its event must stay put.
|
|
7426
|
+
predicate: parsed => !parsed.roles.has('event'),
|
|
7427
|
+
},
|
|
7428
|
+
transform: {
|
|
7429
|
+
// belge den pointermove(clientY) veya pointerup(clientY) bekle
|
|
7430
|
+
roleOrder: ['patient', 'source', 'duration', 'action'],
|
|
7431
|
+
insertMarkers: true,
|
|
7432
|
+
},
|
|
7433
|
+
},
|
|
7434
|
+
{
|
|
7435
|
+
name: 'repeat-until-event-verb-final',
|
|
7436
|
+
description: "Keep repeat-until-event's from-phrase before the verb",
|
|
7437
|
+
priority: 90,
|
|
7438
|
+
match: {
|
|
7439
|
+
commands: ['repeat', 'tekrarla'],
|
|
7440
|
+
requiredRoles: ['action', 'patient', 'source'],
|
|
7441
|
+
// Gate to the until-event head; `repeat for item in .items` also
|
|
7442
|
+
// carries patient+source and must keep its (parseable) default order.
|
|
7443
|
+
predicate: parsed => /^repeat\s+until\s+event\b/i.test((parsed.original ?? '').trim()),
|
|
7444
|
+
},
|
|
7445
|
+
transform: {
|
|
7446
|
+
// kadar olay pointerup i belge den tekrarla — matched semantic-side by
|
|
7447
|
+
// repeat-tr-until-head-verb-final.
|
|
7448
|
+
roleOrder: ['patient', 'source', 'action'],
|
|
7449
|
+
insertMarkers: true,
|
|
7450
|
+
},
|
|
7451
|
+
},
|
|
7452
|
+
// the olay i gönder de durdur ardından validateForm() i çağır
|
|
7453
|
+
sovHaltCallFusedRule({
|
|
7454
|
+
callVerb: 'çağır',
|
|
7455
|
+
patientMarker: 'i',
|
|
7456
|
+
eventMarker: 'de',
|
|
7457
|
+
connective: 'ardından',
|
|
7458
|
+
}),
|
|
7459
|
+
// #note nin karakterler 0 ile 5 i tıklama de seç
|
|
7460
|
+
sovPickRangeRule({
|
|
7461
|
+
genitive: 'nin',
|
|
7462
|
+
rangeSep: 'ile',
|
|
7463
|
+
patientMarker: 'i',
|
|
7464
|
+
eventMarker: 'de',
|
|
7465
|
+
}),
|
|
7085
7466
|
],
|
|
7086
7467
|
};
|
|
7087
7468
|
// =============================================================================
|
|
@@ -7224,6 +7605,8 @@ const quechuaProfile = {
|
|
|
7224
7605
|
adpositionType: 'postposition',
|
|
7225
7606
|
morphology: 'agglutinative', // Actually polysynthetic
|
|
7226
7607
|
direction: 'ltr',
|
|
7608
|
+
// NOTE: roles absent from this order are safety-net-appended AFTER the verb
|
|
7609
|
+
// (see the Turkish profile note) — extend via per-command `rules`, not here.
|
|
7227
7610
|
canonicalOrder: ['patient', 'source', 'destination', 'event', 'action'],
|
|
7228
7611
|
markers: [
|
|
7229
7612
|
// Quechua case suffixes - using spaced form for tokenization
|
|
@@ -7236,6 +7619,41 @@ const quechuaProfile = {
|
|
|
7236
7619
|
{ form: 'wan', role: 'style', position: 'postposition', required: false },
|
|
7237
7620
|
{ form: 'hina', role: 'method', position: 'postposition', required: false }, // "as/like"
|
|
7238
7621
|
],
|
|
7622
|
+
rules: [
|
|
7623
|
+
{
|
|
7624
|
+
name: 'wait-oblique-verb-final',
|
|
7625
|
+
description: "Keep wait's from-phrase and or-run inside the clause, verb-final",
|
|
7626
|
+
priority: 90,
|
|
7627
|
+
match: {
|
|
7628
|
+
commands: ['wait', 'suyay'],
|
|
7629
|
+
// Only `wait for X or Y from Z` strands: duration is missing from
|
|
7630
|
+
// canonicalOrder, so the or-run lands AFTER the verb and the next
|
|
7631
|
+
// trigger glues it into its event (behavior-sortable R3). See the
|
|
7632
|
+
// matching Turkish rule.
|
|
7633
|
+
requiredRoles: ['action', 'duration', 'source'],
|
|
7634
|
+
predicate: parsed => !parsed.roles.has('event'),
|
|
7635
|
+
},
|
|
7636
|
+
transform: {
|
|
7637
|
+
// qillqa manta pointermove(clientY) utaq pointerup(clientY) suyay
|
|
7638
|
+
roleOrder: ['patient', 'source', 'duration', 'action'],
|
|
7639
|
+
insertMarkers: true,
|
|
7640
|
+
},
|
|
7641
|
+
},
|
|
7642
|
+
// the ruway ta kachay pi sayay chayqa validateForm() ta qayay
|
|
7643
|
+
sovHaltCallFusedRule({
|
|
7644
|
+
callVerb: 'qayay',
|
|
7645
|
+
patientMarker: 'ta',
|
|
7646
|
+
eventMarker: 'pi',
|
|
7647
|
+
connective: 'chayqa',
|
|
7648
|
+
}),
|
|
7649
|
+
// #note pa sanampa 0 kama 5 ta ñitiy pi akllay
|
|
7650
|
+
sovPickRangeRule({
|
|
7651
|
+
genitive: 'pa',
|
|
7652
|
+
rangeSep: 'kama',
|
|
7653
|
+
patientMarker: 'ta',
|
|
7654
|
+
eventMarker: 'pi',
|
|
7655
|
+
}),
|
|
7656
|
+
],
|
|
7239
7657
|
};
|
|
7240
7658
|
// =============================================================================
|
|
7241
7659
|
// Swahili (SVO, Bantu)
|
|
@@ -7271,6 +7689,8 @@ const bengaliProfile = {
|
|
|
7271
7689
|
direction: 'ltr',
|
|
7272
7690
|
// Bengali: Object comes before verb, postpositions follow nouns
|
|
7273
7691
|
// "on click increment #count" → "#count কে ক্লিক এ বৃদ্ধি"
|
|
7692
|
+
// NOTE: roles absent from this order are safety-net-appended AFTER the verb
|
|
7693
|
+
// (see the Turkish profile note) — extend via per-command `rules`, not here.
|
|
7274
7694
|
canonicalOrder: ['patient', 'event', 'action'],
|
|
7275
7695
|
markers: [
|
|
7276
7696
|
// Postpositions
|
|
@@ -7347,6 +7767,20 @@ const bengaliProfile = {
|
|
|
7347
7767
|
insertMarkers: true,
|
|
7348
7768
|
},
|
|
7349
7769
|
},
|
|
7770
|
+
// the ঘটনা কে জমা এ থামুন তারপর validateForm() কে কল
|
|
7771
|
+
sovHaltCallFusedRule({
|
|
7772
|
+
callVerb: 'কল',
|
|
7773
|
+
patientMarker: 'কে',
|
|
7774
|
+
eventMarker: 'এ',
|
|
7775
|
+
connective: 'তারপর',
|
|
7776
|
+
}),
|
|
7777
|
+
// #note র অক্ষর 0 থেকে 5 কে ক্লিক এ বাছুন
|
|
7778
|
+
sovPickRangeRule({
|
|
7779
|
+
genitive: 'র',
|
|
7780
|
+
rangeSep: 'থেকে',
|
|
7781
|
+
patientMarker: 'কে',
|
|
7782
|
+
eventMarker: 'এ',
|
|
7783
|
+
}),
|
|
7350
7784
|
],
|
|
7351
7785
|
};
|
|
7352
7786
|
// =============================================================================
|
|
@@ -7534,6 +7968,20 @@ const hindiProfile = {
|
|
|
7534
7968
|
insertMarkers: true,
|
|
7535
7969
|
},
|
|
7536
7970
|
},
|
|
7971
|
+
// the घटना को जमा पर रोकें फिर validateForm() को कॉल
|
|
7972
|
+
sovHaltCallFusedRule({
|
|
7973
|
+
callVerb: 'कॉल',
|
|
7974
|
+
patientMarker: 'को',
|
|
7975
|
+
eventMarker: 'पर',
|
|
7976
|
+
connective: 'फिर',
|
|
7977
|
+
}),
|
|
7978
|
+
// #note का अक्षर 0 से 5 को क्लिक पर चुनें
|
|
7979
|
+
sovPickRangeRule({
|
|
7980
|
+
genitive: 'का',
|
|
7981
|
+
rangeSep: 'से',
|
|
7982
|
+
patientMarker: 'को',
|
|
7983
|
+
eventMarker: 'पर',
|
|
7984
|
+
}),
|
|
7537
7985
|
],
|
|
7538
7986
|
};
|
|
7539
7987
|
// =============================================================================
|
|
@@ -9749,6 +10197,17 @@ class GrammarTransformer {
|
|
|
9749
10197
|
if (block) {
|
|
9750
10198
|
return this.transformBlock(block);
|
|
9751
10199
|
}
|
|
10200
|
+
// 0a. Fragment carrying a stranded trailing block terminator (`wait 200ms
|
|
10201
|
+
// end`, `set x to y end` — what the `then`-splitter leaves from
|
|
10202
|
+
// `if … then <cmd> end`). `end` is not a marker, so left in place it is
|
|
10203
|
+
// swept into the open role's VALUE and rendered inside that phrase
|
|
10204
|
+
// (bn `200ms শেষ কে অপেক্ষা`). Strip it, transform the clause alone, and
|
|
10205
|
+
// re-append the translated terminator after the verb — the same tail
|
|
10206
|
+
// position transformBlockBody emits for event-headed blocks.
|
|
10207
|
+
const strippedEnd = this.transformWithTrailingEnd(input);
|
|
10208
|
+
if (strippedEnd !== null) {
|
|
10209
|
+
return strippedEnd;
|
|
10210
|
+
}
|
|
9752
10211
|
// 0b. `set @attr to V on <scope>` (S1 tabs-aria): strip the trailing
|
|
9753
10212
|
// `on <scope>`, transform the scope-less set normally, then re-insert
|
|
9754
10213
|
// `on <scope>` where the semantic set patterns expect it.
|
|
@@ -9786,6 +10245,31 @@ class GrammarTransformer {
|
|
|
9786
10245
|
// 7. Join without markers (still use joinTokens for consistency)
|
|
9787
10246
|
return joinTokens(reordered.map(e => e.translated || e.value));
|
|
9788
10247
|
}
|
|
10248
|
+
/**
|
|
10249
|
+
* `<command …> end` fragments: transform the command without its stranded
|
|
10250
|
+
* terminator, then re-append the translated terminator as a standalone
|
|
10251
|
+
* trailing token. Fragments that open a block of their own (`if … end`,
|
|
10252
|
+
* `repeat … end`, `js … end`) bail — their terminator belongs to them and
|
|
10253
|
+
* their dedicated paths handle it.
|
|
10254
|
+
*/
|
|
10255
|
+
transformWithTrailingEnd(input) {
|
|
10256
|
+
const src = this.sourceProfile.code;
|
|
10257
|
+
const tokens = input.trim().split(/\s+/);
|
|
10258
|
+
if (tokens.length < 2) {
|
|
10259
|
+
return null;
|
|
10260
|
+
}
|
|
10261
|
+
const sourceEnd = translateWord('end', 'en', src).toLowerCase();
|
|
10262
|
+
if (tokens[tokens.length - 1].toLowerCase() !== sourceEnd) {
|
|
10263
|
+
return null;
|
|
10264
|
+
}
|
|
10265
|
+
const openers = new Set(['if', 'repeat', 'unless', 'while', 'when', 'live', 'js'].map(k => translateWord(k, 'en', src).toLowerCase()));
|
|
10266
|
+
if (tokens.slice(0, -1).some(t => openers.has(t.toLowerCase()))) {
|
|
10267
|
+
return null;
|
|
10268
|
+
}
|
|
10269
|
+
const inner = this.transformSingle(tokens.slice(0, -1).join(' '));
|
|
10270
|
+
const endT = translateWord(tokens[tokens.length - 1], src, this.targetProfile.code);
|
|
10271
|
+
return `${inner} ${endT}`;
|
|
10272
|
+
}
|
|
9789
10273
|
/**
|
|
9790
10274
|
* Detect and transform an inline JS block (`[on <event>] js <raw js> end`).
|
|
9791
10275
|
*
|
|
@@ -10146,7 +10630,26 @@ class GrammarTransformer {
|
|
|
10146
10630
|
const tailT = tail ? translateWord(tail, src, dst) : '';
|
|
10147
10631
|
const clauseT = clause ? translateMultiWordValue(clause, src, dst) : '';
|
|
10148
10632
|
const bodyT = this.transformConditionalBody(bodyTokens);
|
|
10149
|
-
|
|
10633
|
+
// SOV condition/branch boundary (R1 deferred-tail Family G): the SOV body
|
|
10634
|
+
// renders its first command operand-first (`最初 <button/> の中 .modal を
|
|
10635
|
+
// フォーカス`), so nothing marks where the condition ends and the branch
|
|
10636
|
+
// operand begins — the semantic fold's command-start detection needs a
|
|
10637
|
+
// `{value}{particle}` run followed by a verb, which a POSITIONAL-headed
|
|
10638
|
+
// operand (`first <button/> …`) never forms, and the condition scan
|
|
10639
|
+
// swallows the operand's head (focus-trap: ja focus.patient fell to the
|
|
10640
|
+
// `me` default, ko/qu to the `.modal` tail). Emit the target's
|
|
10641
|
+
// then-connective at the seam — the boundary the fold already respects
|
|
10642
|
+
// (isThenKeyword) — gated to exactly the blind shape: SOV target, a
|
|
10643
|
+
// positional keyword right after the branch's command verb, and no `then`
|
|
10644
|
+
// already ending the condition.
|
|
10645
|
+
const POSITIONAL_BRANCH_HEADS = new Set(['first', 'last', 'next', 'previous', 'closest']);
|
|
10646
|
+
const thenT = this.targetProfile.wordOrder === 'SOV' &&
|
|
10647
|
+
clauseT &&
|
|
10648
|
+
POSITIONAL_BRANCH_HEADS.has(bodyTokens[1]?.toLowerCase()) &&
|
|
10649
|
+
inner[bodyStart - 1]?.toLowerCase() !== 'then'
|
|
10650
|
+
? translateWord('then', src, dst)
|
|
10651
|
+
: '';
|
|
10652
|
+
return [headT, clauseT, thenT, bodyT, tailT].filter(s => s.length > 0).join(' ');
|
|
10150
10653
|
}
|
|
10151
10654
|
/**
|
|
10152
10655
|
* Transform an `if`/`unless` block body, splitting it at a top-level `else` into
|