@lokascript/i18n 2.7.2 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +1 -1
  3. package/dist/browser.cjs +649 -180
  4. package/dist/browser.cjs.map +1 -1
  5. package/dist/browser.d.cts +2 -2
  6. package/dist/browser.d.ts +2 -2
  7. package/dist/browser.js +649 -180
  8. package/dist/browser.js.map +1 -1
  9. package/dist/dictionaries/index.cjs +370 -174
  10. package/dist/dictionaries/index.cjs.map +1 -1
  11. package/dist/dictionaries/index.js +370 -174
  12. package/dist/dictionaries/index.js.map +1 -1
  13. package/dist/index.cjs +649 -180
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +1 -1
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +649 -180
  18. package/dist/index.js.map +1 -1
  19. package/dist/lokascript-i18n.min.js +1 -1
  20. package/dist/lokascript-i18n.min.js.map +1 -1
  21. package/dist/lokascript-i18n.mjs +678 -175
  22. package/dist/lokascript-i18n.mjs.map +1 -1
  23. package/dist/plugins/vite.cjs +370 -174
  24. package/dist/plugins/vite.cjs.map +1 -1
  25. package/dist/plugins/vite.js +370 -174
  26. package/dist/plugins/vite.js.map +1 -1
  27. package/dist/plugins/webpack.cjs +370 -174
  28. package/dist/plugins/webpack.cjs.map +1 -1
  29. package/dist/plugins/webpack.js +370 -174
  30. package/dist/plugins/webpack.js.map +1 -1
  31. package/dist/{transformer-DM7iplCU.d.cts → transformer--W46PGaW.d.cts} +8 -0
  32. package/dist/{transformer-BA8YX9u1.d.ts → transformer-FU06J6kG.d.ts} +8 -0
  33. package/package.json +9 -10
  34. package/src/dictionaries/ar.ts +20 -15
  35. package/src/dictionaries/bn.ts +10 -5
  36. package/src/dictionaries/de.ts +20 -8
  37. package/src/dictionaries/es.ts +10 -5
  38. package/src/dictionaries/fr.ts +15 -6
  39. package/src/dictionaries/he.ts +4 -0
  40. package/src/dictionaries/hi.ts +3 -2
  41. package/src/dictionaries/id.ts +31 -16
  42. package/src/dictionaries/it.ts +11 -4
  43. package/src/dictionaries/ja.ts +23 -15
  44. package/src/dictionaries/ko.ts +10 -5
  45. package/src/dictionaries/ms.ts +4 -1
  46. package/src/dictionaries/pl.ts +12 -5
  47. package/src/dictionaries/pt.ts +10 -5
  48. package/src/dictionaries/qu.ts +30 -19
  49. package/src/dictionaries/ru.ts +5 -2
  50. package/src/dictionaries/sw.ts +29 -14
  51. package/src/dictionaries/th.ts +5 -2
  52. package/src/dictionaries/tl.ts +4 -1
  53. package/src/dictionaries/tr.ts +24 -16
  54. package/src/dictionaries/uk.ts +5 -2
  55. package/src/dictionaries/vi.ts +23 -17
  56. package/src/dictionaries/zh.ts +24 -9
  57. package/src/grammar/grammar.test.ts +152 -0
  58. package/src/grammar/profiles/index.ts +316 -1
  59. package/src/grammar/transformer.ts +64 -1
  60. package/src/new-languages.test.ts +9 -3
  61. package/src/positional-keyword-drift.test.ts +6 -19
@@ -96,18 +96,20 @@ export const pt: Dictionary = {
96
96
  mouseup: 'mouseCima',
97
97
  mouseenter: 'mouseEntrar',
98
98
  mouseleave: 'mouseSair',
99
- mouseover: 'mouseSobre',
100
- mouseout: 'mouseFora',
99
+ // V3 Batch 2: camelCase forms split to the S5b/tokenizer-known forms (the
100
+ // fused spellings captured event=expression:undefined — broken listeners)
101
+ mouseover: 'mouse sobre',
102
+ mouseout: 'mouse fora',
101
103
  mousemove: 'mouseMover',
102
- keydown: 'teclaBaixo',
103
- keyup: 'teclaCima',
104
+ keydown: 'tecla baixo',
105
+ keyup: 'tecla cima',
104
106
  keypress: 'teclaPressionar',
105
107
  focus: 'foco',
106
108
  blur: 'desfoque',
107
109
  change: 'mudança',
108
110
  input: 'entrada',
109
111
  submit: 'envio',
110
- reset: 'reiniciar',
112
+ reset: 'redefinir', // Batch 3: reiniciar captured on.event as expression (broken listener) — profile word round-trips
111
113
  load: 'carregar',
112
114
  unload: 'descarregar',
113
115
  resize: 'redimensionar',
@@ -191,6 +193,9 @@ export const pt: Dictionary = {
191
193
  },
192
194
 
193
195
  expressions: {
196
+ characters: 'caracteres',
197
+ inclusive: 'inclusivo',
198
+ exclusive: 'exclusivo',
194
199
  first: 'primeiro',
195
200
  last: 'último',
196
201
  next: 'próximo',
@@ -75,8 +75,8 @@ export const qu: Dictionary = {
75
75
  breakpoint: 'sayachinay',
76
76
  clear: 'pichay',
77
77
  close: 'wichqay',
78
- open: 'kichay',
79
- select: 'akllay',
78
+ open: 'paskay', // Batch 3: kichay is the trigger keyword — rendered open parsed null
79
+ select: 'marcay', // Batch 3: akllay is the pick keyword — bare select rendered with it parses null
80
80
  clone: 'kikinchay',
81
81
  prepend: 'ñawpachiy',
82
82
  socket: 'tinkina',
@@ -103,33 +103,39 @@ export const qu: Dictionary = {
103
103
 
104
104
  events: {
105
105
  click: 'ñitiy',
106
- dblclick: 'iskay_ñitiy',
106
+ dblclick: 'dblclick',
107
107
  // Fused (no `_`): the semantic tokenizer splits on `_` — and `rat_ñitiy` then
108
108
  // mis-captured as the `click` event (ñitiy→click). Mirrors the #535 ru/uk fuse.
109
109
  mousedown: 'ratñitiy',
110
110
  mouseup: 'rathuqariy',
111
- mouseenter: 'rat_yaykuy',
112
- mouseleave: 'rat_lluqsiy',
113
- mouseover: 'rat_hawapi',
114
- mouseout: 'rat_hawamanta',
115
- mousemove: 'rat_kuyuy',
116
- keydown: 'yupana_ñitiy',
117
- keyup: 'yupana_huqariy',
118
- keypress: 'yupana_ñitana',
111
+ mouseenter: 'mouseenter',
112
+ mouseleave: 'mouseleave',
113
+ mouseover: 'mouseover',
114
+ mouseout: 'mouseout',
115
+ mousemove: 'mousemove',
116
+ // V3 Batch 2: `yupana_ñitiy` split at `_` and mis-captured as the `click`
117
+ // event (ñitiy→click, the same mechanism as the mousedown fuse above);
118
+ // `yupana_huqariy` captured verbatim `huqariy`. Realigned to the
119
+ // S5b/tokenizer forms.
120
+ keydown: 'llave uray',
121
+ keyup: 'llave hawa',
122
+ keypress: 'keypress',
119
123
  focus: 'qhaway',
120
124
  blur: 'paqariy',
121
- change: 'tikray',
125
+ change: 'kambiay', // Batch 3: tikray is the toggle verb — on-change listener captured event "toggle"
122
126
  input: 'yaykuchiy',
123
- submit: 'kachay',
124
- reset: 'qallariy',
127
+ submit: 'apaykachay', // Batch 3: kachay is the send verb — on-submit captured "send" in one corpus slot
128
+ reset: 'musuqchay', // Batch 3: qallariy is the init/start word — on-reset listener captured event "default"
125
129
  load: 'apakuy',
126
- unload: 'urmay',
130
+ unload: 'unload',
127
131
  resize: 'hatun_kay',
128
132
  scroll: 'kunray',
129
- touchstart: 'llamiy_qallay',
130
- touchend: 'llamiy_tukuy',
131
- touchmove: 'llamiy_kuyuy',
132
- touchcancel: 'llamiy_hark_ay',
133
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
134
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
135
+ touchstart: 'touchstart',
136
+ touchend: 'touchend',
137
+ touchmove: 'touchmove',
138
+ touchcancel: 'touchcancel',
133
139
  },
134
140
 
135
141
  logical: {
@@ -209,6 +215,11 @@ export const qu: Dictionary = {
209
215
  },
210
216
 
211
217
  expressions: {
218
+ // Pick unit word (arc 3): native-first per qu convention — `sanampa`
219
+ // ("sign/letter", the standard term for alphabet characters) over a
220
+ // loanword. Paired with the QUECHUA_EXTRAS entry in the semantic
221
+ // tokenizer; both surfaces must match verbatim.
222
+ characters: 'sanampa',
212
223
  first: 'ñawpaq',
213
224
  last: 'qhipa',
214
225
  next: 'qhipantin',
@@ -70,7 +70,7 @@ export const russianDictionary: Dictionary = {
70
70
  clear: 'очистить',
71
71
  close: 'закрыть',
72
72
  open: 'открыть',
73
- select: 'выбрать',
73
+ select: 'выделить', // Batch 3: выбрать is the pick keyword — bare select rendered with it parses null
74
74
  },
75
75
 
76
76
  modifiers: {
@@ -114,7 +114,7 @@ export const russianDictionary: Dictionary = {
114
114
  change: 'изменение',
115
115
  input: 'ввод',
116
116
  submit: 'отправка',
117
- reset: 'сброс',
117
+ reset: 'сбросить', // Batch 3: сброс captured on.event as expression (broken listener) — profile verb round-trips
118
118
  load: 'загрузка',
119
119
  unload: 'выгрузка',
120
120
  resize: 'изменениеразмера', // fused (no `_`) — see mousedown note above
@@ -218,6 +218,9 @@ export const russianDictionary: Dictionary = {
218
218
  },
219
219
 
220
220
  expressions: {
221
+ characters: 'символы',
222
+ inclusive: 'включительно',
223
+ exclusive: 'исключительно',
221
224
  first: 'первый',
222
225
  last: 'последний',
223
226
  next: 'следующий',
@@ -36,7 +36,10 @@ export const sw: Dictionary = {
36
36
  wait: 'ngoja',
37
37
  fetch: 'leta',
38
38
  call: 'ita',
39
- return: 'rudi',
39
+ // `rudisha` (transitive, "give back a value"), not `rudi` ("go back"): the
40
+ // semantic profile reads `rudisha`/`rejea`, so emitting `rudi` produced sw code
41
+ // the parser could not read back. Kept clear of `rudia` (= `repeat`).
42
+ return: 'rudisha',
40
43
  make: 'tengeneza', // auditor: dict emitted a word the profile reads differently
41
44
  log: 'andika',
42
45
  throw: 'tupa',
@@ -49,7 +52,7 @@ export const sw: Dictionary = {
49
52
  go: 'nenda',
50
53
  pushUrl: 'sukumaUrl',
51
54
  replaceUrl: 'badilishaUrl',
52
- copy: 'nakili',
55
+ copy: 'nakala', // Batch 3: nakili is the clone keyword — rendered copy parsed as action=clone
53
56
  pick: 'chagua',
54
57
  beep: 'lia',
55
58
  js: 'js',
@@ -65,7 +68,7 @@ export const sw: Dictionary = {
65
68
  clear: 'safisha', // futa is a remove alternative in the profile
66
69
  close: 'funga',
67
70
  open: 'fungua',
68
- select: 'chagua',
71
+ select: 'alama', // Batch 3: chagua is the pick keyword — bare select rendered with it parses null
69
72
  clone: 'nakili',
70
73
  prepend: 'tanguliza',
71
74
  focus: 'lenga',
@@ -100,31 +103,42 @@ export const sw: Dictionary = {
100
103
 
101
104
  events: {
102
105
  click: 'bonyeza',
103
- dblclick: 'bonyeza_mara_mbili',
106
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
107
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
108
+ dblclick: 'dblclick',
104
109
  mousedown: 'panya_shuka',
105
110
  mouseup: 'panya_juu',
106
111
  mouseenter: 'panya_ingia',
107
112
  mouseleave: 'panya_toka',
108
- mouseover: 'panya_juu',
113
+ // V3 Batch 2: panya_juu is mouseup's form (shared here by mistake — the
114
+ // tokenizer deliberately maps it to mouseup for the corpus row, so a
115
+ // mouseover handler captured `mouseup`) — realigned to the
116
+ // tokenizer-registered `sogeza juu`.
117
+ mouseover: 'sogeza juu',
109
118
  mouseout: 'panya_nje',
110
119
  mousemove: 'panya_sogea',
111
120
  keydown: 'kitufe_shuka',
112
121
  keyup: 'kitufe_juu',
113
- keypress: 'kitufe_bonyeza',
114
- focus: 'zingatia',
115
- blur: 'poteza_macho',
116
- change: 'badilisha',
122
+ keypress: 'keypress',
123
+ // V3 Batch 2: zingatia captured no event → lenga (S5b/tokenizer form);
124
+ // poteza_macho was a null parse → `blur` (the S5b identity form — matches
125
+ // the live corpus render `kwenye blur`); badilisha is the toggle VERB
126
+ // homonym (a change handler captured event=`toggle` — a listener for a DOM
127
+ // event named "toggle") → kubadilisha (S5b/tokenizer form).
128
+ focus: 'lenga',
129
+ blur: 'blur',
130
+ change: 'kubadilisha',
117
131
  input: 'ingizo',
118
132
  submit: 'wasilisha',
119
- reset: 'weka_upya',
133
+ reset: 'reset',
120
134
  load: 'pakia',
121
135
  unload: 'shuka',
122
136
  resize: 'badilisha_ukubwa',
123
137
  scroll: 'sogeza',
124
- touchstart: 'gusa_anza',
125
- touchend: 'gusa_mwisho',
126
- touchmove: 'gusa_sogea',
127
- touchcancel: 'gusa_ghairi',
138
+ touchstart: 'touchstart',
139
+ touchend: 'touchend',
140
+ touchmove: 'touchmove',
141
+ touchcancel: 'touchcancel',
128
142
  },
129
143
 
130
144
  logical: {
@@ -200,6 +214,7 @@ export const sw: Dictionary = {
200
214
  },
201
215
 
202
216
  expressions: {
217
+ characters: 'herufi',
203
218
  first: 'kwanza',
204
219
  // 'mwisho' is the END keyword (block terminator) — the tokenizer's keyword
205
220
  // map is last-wins, so a positional `last` emission of 'mwisho' reads as
@@ -49,7 +49,7 @@ export const thaiDictionary: Dictionary = {
49
49
  init: 'เริ่มต้น',
50
50
  behavior: 'พฤติกรรม',
51
51
  install: 'ติดตั้ง',
52
- clone: 'คัดลอก',
52
+ clone: 'โคลน', // Batch 3: คัดลอก is the copy verb — rendered clone parsed as action=copy
53
53
  swap: 'สลับที่',
54
54
  morph: 'แปลงร่าง',
55
55
  beep: 'บี๊บ',
@@ -64,7 +64,7 @@ export const thaiDictionary: Dictionary = {
64
64
  clear: 'เคลียร์',
65
65
  close: 'ปิด',
66
66
  open: 'เปิด',
67
- select: 'เลือก',
67
+ select: 'ทำเครื่องหมาย', // Batch 3: เลือก is the pick keyword — bare select rendered with it parses null
68
68
  },
69
69
 
70
70
  modifiers: {
@@ -166,6 +166,9 @@ export const thaiDictionary: Dictionary = {
166
166
  },
167
167
 
168
168
  expressions: {
169
+ characters: 'อักขระ',
170
+ inclusive: 'รวม',
171
+ exclusive: 'ยกเว้น',
169
172
  first: 'แรก',
170
173
  last: 'สุดท้าย',
171
174
  next: 'ถัดไป',
@@ -64,7 +64,7 @@ export const tagalogDictionary: Dictionary = {
64
64
  install: 'ikabit',
65
65
  behavior: 'ugali',
66
66
  init: 'simulan',
67
- clone: 'kopyahin',
67
+ clone: 'i-clone', // Batch 3: kopyahin is the copy verb — rendered clone parsed as action=copy
68
68
  breakpoint: 'breakpoint',
69
69
  clear: 'burahin',
70
70
  close: 'isara',
@@ -218,6 +218,9 @@ export const tagalogDictionary: Dictionary = {
218
218
  },
219
219
 
220
220
  expressions: {
221
+ characters: 'karakter',
222
+ inclusive: 'kasama',
223
+ exclusive: 'bukod',
221
224
  first: 'una',
222
225
  last: 'huli',
223
226
  next: 'susunod',
@@ -63,7 +63,7 @@ export const tr: Dictionary = {
63
63
  clear: 'temizle',
64
64
  close: 'kapat',
65
65
  open: 'aç',
66
- select: 'seç',
66
+ select: 'vurgula', // Batch 3: seç is the pick keyword — bare select rendered with it parses null
67
67
  clone: 'klonla',
68
68
  prepend: 'başınaekle',
69
69
  socket: 'soket',
@@ -90,34 +90,39 @@ export const tr: Dictionary = {
90
90
 
91
91
  events: {
92
92
  click: 'tıklama',
93
- dblclick: 'çift_tıklama',
93
+ dblclick: 'dblclick',
94
94
  // Fused (no `_`): the semantic tokenizer splits on `_`, breaking event
95
95
  // recognition (mousedown → "bas" / mouseup mis-captured). Mirrors the #535
96
96
  // ru/uk fuse + #510 resize fix.
97
97
  mousedown: 'farebas',
98
98
  mouseup: 'farebırak',
99
- mouseenter: 'fare_gir',
100
- mouseleave: 'fare_çık',
101
- mouseover: 'fare_üstü',
102
- mouseout: 'fare_dışı',
103
- mousemove: 'fare_hareket',
104
- keydown: 'tuş_bas',
105
- keyup: 'tuş_bırak',
106
- keypress: 'tuş_basım',
99
+ mouseenter: 'mouseenter',
100
+ mouseleave: 'mouseleave',
101
+ // V3 Batch 2: same `_`-split class (tuş_bas captured verbatim `bas` — a
102
+ // listener for a DOM event named "bas") — realigned to the S5b/tokenizer
103
+ // fused forms.
104
+ mouseover: 'fareiçinde',
105
+ mouseout: 'faredışında',
106
+ mousemove: 'mousemove',
107
+ keydown: 'tuşbasma',
108
+ keyup: 'tuşbırakma',
109
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
110
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
111
+ keypress: 'keypress',
107
112
  focus: 'odak',
108
113
  blur: 'bulanık',
109
114
  change: 'değişim',
110
115
  input: 'giriş',
111
- submit: 'gönder',
116
+ submit: 'gönderme', // Batch 3: gönder is the send verb — on-submit listener captured event "send"
112
117
  reset: 'sıfırla',
113
118
  load: 'yükle',
114
- unload: 'yükle_kaldır',
119
+ unload: 'unload',
115
120
  resize: 'boyutlandırma',
116
121
  scroll: 'kaydır',
117
- touchstart: 'dokunma_başla',
118
- touchend: 'dokunma_bitir',
119
- touchmove: 'dokunma_hareket',
120
- touchcancel: 'dokunma_iptal',
122
+ touchstart: 'touchstart',
123
+ touchend: 'touchend',
124
+ touchmove: 'touchmove',
125
+ touchcancel: 'touchcancel',
121
126
  },
122
127
 
123
128
  logical: {
@@ -193,6 +198,9 @@ export const tr: Dictionary = {
193
198
  },
194
199
 
195
200
  expressions: {
201
+ characters: 'karakterler',
202
+ inclusive: 'dahil',
203
+ exclusive: 'hariç',
196
204
  first: 'ilk',
197
205
  // 'son' is also the END keyword emission (block terminator), and the
198
206
  // parser's end-recognizers match it by value — so a positional `last`
@@ -70,7 +70,7 @@ export const ukrainianDictionary: Dictionary = {
70
70
  clear: 'очистити',
71
71
  close: 'закрити',
72
72
  open: 'відкрити',
73
- select: 'вибрати',
73
+ select: 'виділити', // Batch 3: вибрати is the pick keyword — bare select rendered with it parses null
74
74
  },
75
75
 
76
76
  modifiers: {
@@ -113,7 +113,7 @@ export const ukrainianDictionary: Dictionary = {
113
113
  change: 'зміна',
114
114
  input: 'введення',
115
115
  submit: 'надсилання',
116
- reset: 'скидання',
116
+ reset: 'скинути', // Batch 3: скидання captured on.event as expression (broken listener) — profile verb round-trips
117
117
  load: 'завантаження',
118
118
  unload: 'вивантаження',
119
119
  resize: 'змінарозміру', // fused (no `_`) — see mousedown note above
@@ -217,6 +217,9 @@ export const ukrainianDictionary: Dictionary = {
217
217
  },
218
218
 
219
219
  expressions: {
220
+ characters: 'символи',
221
+ inclusive: 'включно',
222
+ exclusive: 'виключно',
220
223
  first: 'перший',
221
224
  last: 'останній',
222
225
  next: 'наступний',
@@ -59,14 +59,14 @@ export const vi: Dictionary = {
59
59
  init: 'khởi tạo',
60
60
  behavior: 'hành vi',
61
61
  install: 'cài đặt',
62
- clone: 'sao chép',
63
- prepend: 'thêm đầu',
62
+ clone: 'nhân bản', // Batch 3: 'sao chép' is the copy verb — rendered clone parsed as action=copy
63
+ prepend: 'thêm vào đầu', // Batch 3: 'thêm đầu' shatters at 'thêm' (add) — parsed as action=add
64
64
  else: 'không thì',
65
65
  breakpoint: 'điểm-dừng',
66
66
  clear: 'tẩy', // xóa is the remove PRIMARY in the profile
67
67
  close: 'đóng',
68
68
  open: 'mở',
69
- select: 'chọn',
69
+ select: 'đánh-dấu', // Batch 3: 'chọn' is the pick keyword — bare select rendered with it parses null
70
70
  },
71
71
 
72
72
  modifiers: {
@@ -91,21 +91,23 @@ export const vi: Dictionary = {
91
91
 
92
92
  events: {
93
93
  click: 'nhấp',
94
- dblclick: 'nhấp đúp',
94
+ dblclick: 'dblclick',
95
95
  input: 'nhập',
96
- change: 'thay đổi',
97
- submit: 'gửi',
98
- keydown: 'phím xuống',
99
- keyup: 'phím lên',
100
- keypress: 'nhấn phím',
101
- mouseover: 'chuột vào',
102
- mouseout: 'chuột ra',
103
- mouseenter: 'chuột vào',
104
- mouseleave: 'chuột rời',
105
- focus: 'tập trung',
106
- blur: 'mất tập trung',
107
- reset: 'đặt-lại',
108
- load: 'tải',
96
+ change: 'change',
97
+ submit: 'nộp', // Batch 3: 'gửi' is the send verb — on-submit listener captured event "send"
98
+ keydown: 'keydown',
99
+ keyup: 'keyup',
100
+ keypress: 'keypress',
101
+ mouseover: 'mouseover',
102
+ mouseout: 'mouseout',
103
+ mouseenter: 'mouseenter',
104
+ mouseleave: 'mouseleave',
105
+ focus: 'focus',
106
+ blur: 'blur',
107
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
108
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
109
+ reset: 'reset',
110
+ load: 'load',
109
111
  scroll: 'cuộn',
110
112
  resize: 'đổi kích thước',
111
113
  },
@@ -186,6 +188,10 @@ export const vi: Dictionary = {
186
188
  },
187
189
 
188
190
  expressions: {
191
+ random: 'ngẫu nhiên',
192
+ characters: 'ký tự',
193
+ inclusive: 'bao gồm',
194
+ exclusive: 'loại trừ',
189
195
  me: 'tôi',
190
196
  my: 'của tôi',
191
197
  it: 'nó',
@@ -93,16 +93,26 @@ export const zh: Dictionary = {
93
93
  events: {
94
94
  click: '点击',
95
95
  dblclick: '双击',
96
- mousedown: '鼠标按下',
97
- mouseup: '鼠标抬起',
98
- mouseenter: '鼠标进入',
99
- mouseleave: '鼠标离开',
100
- mouseover: '鼠标悬停',
96
+ // mousedown/mouseup: English passthrough — no native form round-trips on the
97
+ // parse side (V3c probe 2026-07-14: fused forms captured verbatim, split forms
98
+ // shattered to their first word — live broken listeners in repeat-until-event).
99
+ // The Batch-2 id-keyup precedent; revisit if S5b + tokenizer gain native entries.
100
+ mousedown: 'mousedown',
101
+ mouseup: 'mouseup',
102
+ mouseenter: 'mouseenter',
103
+ mouseleave: 'mouseleave',
104
+ // V3 Batch 2: 鼠标悬停 captured no event (expression:undefined) — realigned
105
+ // to the tokenizer-registered 鼠标移入 (also S5b-listed). 按键抬起
106
+ // prefix-shattered to 按键 and captured `keydown` (a keyup handler firing
107
+ // on keydown) → 松键, the S5b/tokenizer form. keydown keeps 按键按下
108
+ // (captures keydown via the registered 按键 prefix; S5b-aliased) — fixing
109
+ // it to bare 按键 would collide with keypress below.
110
+ mouseover: '鼠标移入',
101
111
  mouseout: '鼠标移出',
102
112
  mousemove: '鼠标移动',
103
113
  keydown: '按键按下',
104
- keyup: '按键抬起',
105
- keypress: '按键',
114
+ keyup: '松键',
115
+ keypress: 'keypress',
106
116
  focus: '聚焦',
107
117
  blur: '失焦',
108
118
  change: '改变',
@@ -114,9 +124,11 @@ export const zh: Dictionary = {
114
124
  resize: '调整大小',
115
125
  scroll: '滚动',
116
126
  touchstart: '触摸开始',
117
- touchend: '触摸结束',
127
+ touchend: 'touchend',
118
128
  touchmove: '触摸移动',
119
- touchcancel: '触摸取消',
129
+ // V3c burn-down (2026-07-14): English passthrough — no native form round-trips
130
+ // on the parse side (probe: split forms shatter, fused forms capture verbatim).
131
+ touchcancel: 'touchcancel',
120
132
  },
121
133
 
122
134
  logical: {
@@ -193,6 +205,9 @@ export const zh: Dictionary = {
193
205
  },
194
206
 
195
207
  expressions: {
208
+ characters: '字符',
209
+ inclusive: '包含',
210
+ exclusive: '排除',
196
211
  first: '第一个',
197
212
  last: '最后一个',
198
213
  next: '下一个',