@lokascript/framework 7.0.0 → 7.1.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 (283) hide show
  1. package/CHANGELOG.md +65 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/languages/ar.cjs +7 -0
  6. package/dist/languages/ar.cjs.map +1 -0
  7. package/dist/languages/ar.d.ts +49 -0
  8. package/dist/languages/ar.d.ts.map +1 -0
  9. package/dist/languages/ar.js +7 -0
  10. package/dist/languages/ar.js.map +1 -0
  11. package/dist/languages/bn.cjs +7 -0
  12. package/dist/languages/bn.cjs.map +1 -0
  13. package/dist/languages/bn.d.ts +58 -0
  14. package/dist/languages/bn.d.ts.map +1 -0
  15. package/dist/languages/bn.js +7 -0
  16. package/dist/languages/bn.js.map +1 -0
  17. package/dist/languages/chunks/chunk-2Y3XXFQO.cjs +47 -0
  18. package/dist/languages/chunks/chunk-2Y3XXFQO.cjs.map +1 -0
  19. package/dist/languages/chunks/chunk-7JFC6YCG.cjs +38 -0
  20. package/dist/languages/chunks/chunk-7JFC6YCG.cjs.map +1 -0
  21. package/dist/languages/chunks/chunk-7M7D3AZV.js +36 -0
  22. package/dist/languages/chunks/chunk-7M7D3AZV.js.map +1 -0
  23. package/dist/languages/chunks/chunk-BLWOTGS4.cjs +33 -0
  24. package/dist/languages/chunks/chunk-BLWOTGS4.cjs.map +1 -0
  25. package/dist/languages/chunks/chunk-BNU64ZWY.cjs +33 -0
  26. package/dist/languages/chunks/chunk-BNU64ZWY.cjs.map +1 -0
  27. package/dist/languages/chunks/chunk-CCC73SLG.js +33 -0
  28. package/dist/languages/chunks/chunk-CCC73SLG.js.map +1 -0
  29. package/dist/languages/chunks/chunk-CEZSJJBE.js +35 -0
  30. package/dist/languages/chunks/chunk-CEZSJJBE.js.map +1 -0
  31. package/dist/languages/chunks/chunk-CJPWN3UM.cjs +33 -0
  32. package/dist/languages/chunks/chunk-CJPWN3UM.cjs.map +1 -0
  33. package/dist/languages/chunks/chunk-CZUFBVAP.cjs +36 -0
  34. package/dist/languages/chunks/chunk-CZUFBVAP.cjs.map +1 -0
  35. package/dist/languages/chunks/chunk-DFQ7CZ43.js +32 -0
  36. package/dist/languages/chunks/chunk-DFQ7CZ43.js.map +1 -0
  37. package/dist/languages/chunks/chunk-DZIG3L3C.js +33 -0
  38. package/dist/languages/chunks/chunk-DZIG3L3C.js.map +1 -0
  39. package/dist/languages/chunks/chunk-EEEJDKZH.cjs +41 -0
  40. package/dist/languages/chunks/chunk-EEEJDKZH.cjs.map +1 -0
  41. package/dist/languages/chunks/chunk-EH3CS6QF.cjs +39 -0
  42. package/dist/languages/chunks/chunk-EH3CS6QF.cjs.map +1 -0
  43. package/dist/languages/chunks/chunk-EQVZR5WU.js +36 -0
  44. package/dist/languages/chunks/chunk-EQVZR5WU.js.map +1 -0
  45. package/dist/languages/chunks/chunk-EY2I2PZI.cjs +42 -0
  46. package/dist/languages/chunks/chunk-EY2I2PZI.cjs.map +1 -0
  47. package/dist/languages/chunks/chunk-FDD6SCYE.js +38 -0
  48. package/dist/languages/chunks/chunk-FDD6SCYE.js.map +1 -0
  49. package/dist/languages/chunks/chunk-FDL3DCUR.cjs +38 -0
  50. package/dist/languages/chunks/chunk-FDL3DCUR.cjs.map +1 -0
  51. package/dist/languages/chunks/chunk-FQZEBNEC.js +32 -0
  52. package/dist/languages/chunks/chunk-FQZEBNEC.js.map +1 -0
  53. package/dist/languages/chunks/chunk-FXKGDEEF.js +32 -0
  54. package/dist/languages/chunks/chunk-FXKGDEEF.js.map +1 -0
  55. package/dist/languages/chunks/chunk-G727KC5F.js +34 -0
  56. package/dist/languages/chunks/chunk-G727KC5F.js.map +1 -0
  57. package/dist/languages/chunks/chunk-HRTBXKAS.js +34 -0
  58. package/dist/languages/chunks/chunk-HRTBXKAS.js.map +1 -0
  59. package/dist/languages/chunks/chunk-HTWLJAXE.cjs +34 -0
  60. package/dist/languages/chunks/chunk-HTWLJAXE.cjs.map +1 -0
  61. package/dist/languages/chunks/chunk-IG2BHTIU.js +50 -0
  62. package/dist/languages/chunks/chunk-IG2BHTIU.js.map +1 -0
  63. package/dist/languages/chunks/chunk-JJGECSB7.js +44 -0
  64. package/dist/languages/chunks/chunk-JJGECSB7.js.map +1 -0
  65. package/dist/languages/chunks/chunk-KPGJSWSP.js +32 -0
  66. package/dist/languages/chunks/chunk-KPGJSWSP.js.map +1 -0
  67. package/dist/languages/chunks/chunk-LGZCHKVL.cjs +50 -0
  68. package/dist/languages/chunks/chunk-LGZCHKVL.cjs.map +1 -0
  69. package/dist/languages/chunks/chunk-LMRNA2XQ.cjs +35 -0
  70. package/dist/languages/chunks/chunk-LMRNA2XQ.cjs.map +1 -0
  71. package/dist/languages/chunks/chunk-NS4L6RCJ.js +42 -0
  72. package/dist/languages/chunks/chunk-NS4L6RCJ.js.map +1 -0
  73. package/dist/languages/chunks/chunk-OGVDC4MV.js +33 -0
  74. package/dist/languages/chunks/chunk-OGVDC4MV.js.map +1 -0
  75. package/dist/languages/chunks/chunk-OOI6MH2H.js +47 -0
  76. package/dist/languages/chunks/chunk-OOI6MH2H.js.map +1 -0
  77. package/dist/languages/chunks/chunk-OSHTQPFA.js +35 -0
  78. package/dist/languages/chunks/chunk-OSHTQPFA.js.map +1 -0
  79. package/dist/languages/chunks/chunk-P2ONCOPE.js +33 -0
  80. package/dist/languages/chunks/chunk-P2ONCOPE.js.map +1 -0
  81. package/dist/languages/chunks/chunk-PC4BLDMN.js +41 -0
  82. package/dist/languages/chunks/chunk-PC4BLDMN.js.map +1 -0
  83. package/dist/languages/chunks/chunk-Q7Z57FEP.js +39 -0
  84. package/dist/languages/chunks/chunk-Q7Z57FEP.js.map +1 -0
  85. package/dist/languages/chunks/chunk-SFDLZDQC.cjs +36 -0
  86. package/dist/languages/chunks/chunk-SFDLZDQC.cjs.map +1 -0
  87. package/dist/languages/chunks/chunk-SLSZETLO.js +39 -0
  88. package/dist/languages/chunks/chunk-SLSZETLO.js.map +1 -0
  89. package/dist/languages/chunks/chunk-T5QEXBP6.cjs +39 -0
  90. package/dist/languages/chunks/chunk-T5QEXBP6.cjs.map +1 -0
  91. package/dist/languages/chunks/chunk-TM54B2L7.cjs +34 -0
  92. package/dist/languages/chunks/chunk-TM54B2L7.cjs.map +1 -0
  93. package/dist/languages/chunks/chunk-UYYD7BWL.cjs +32 -0
  94. package/dist/languages/chunks/chunk-UYYD7BWL.cjs.map +1 -0
  95. package/dist/languages/chunks/chunk-V3EPOWJS.cjs +32 -0
  96. package/dist/languages/chunks/chunk-V3EPOWJS.cjs.map +1 -0
  97. package/dist/languages/chunks/chunk-W4Y2BHDV.cjs +33 -0
  98. package/dist/languages/chunks/chunk-W4Y2BHDV.cjs.map +1 -0
  99. package/dist/languages/chunks/chunk-W7UIUU64.cjs +32 -0
  100. package/dist/languages/chunks/chunk-W7UIUU64.cjs.map +1 -0
  101. package/dist/languages/chunks/chunk-WOTY3GYE.cjs +44 -0
  102. package/dist/languages/chunks/chunk-WOTY3GYE.cjs.map +1 -0
  103. package/dist/languages/chunks/chunk-WYH4M6NK.js +78 -0
  104. package/dist/languages/chunks/chunk-WYH4M6NK.js.map +1 -0
  105. package/dist/languages/chunks/chunk-XFSNOEMB.cjs +32 -0
  106. package/dist/languages/chunks/chunk-XFSNOEMB.cjs.map +1 -0
  107. package/dist/languages/chunks/chunk-XHHTLZRZ.cjs +78 -0
  108. package/dist/languages/chunks/chunk-XHHTLZRZ.cjs.map +1 -0
  109. package/dist/languages/chunks/chunk-YTZILXWL.cjs +35 -0
  110. package/dist/languages/chunks/chunk-YTZILXWL.cjs.map +1 -0
  111. package/dist/languages/chunks/chunk-ZLMXABY7.js +38 -0
  112. package/dist/languages/chunks/chunk-ZLMXABY7.js.map +1 -0
  113. package/dist/languages/de.cjs +7 -0
  114. package/dist/languages/de.cjs.map +1 -0
  115. package/dist/languages/de.d.ts +47 -0
  116. package/dist/languages/de.d.ts.map +1 -0
  117. package/dist/languages/de.js +7 -0
  118. package/dist/languages/de.js.map +1 -0
  119. package/dist/languages/en.cjs +7 -0
  120. package/dist/languages/en.cjs.map +1 -0
  121. package/dist/languages/en.d.ts +54 -0
  122. package/dist/languages/en.d.ts.map +1 -0
  123. package/dist/languages/en.js +7 -0
  124. package/dist/languages/en.js.map +1 -0
  125. package/dist/languages/es.cjs +7 -0
  126. package/dist/languages/es.cjs.map +1 -0
  127. package/dist/languages/es.d.ts +47 -0
  128. package/dist/languages/es.d.ts.map +1 -0
  129. package/dist/languages/es.js +7 -0
  130. package/dist/languages/es.js.map +1 -0
  131. package/dist/languages/fr.cjs +7 -0
  132. package/dist/languages/fr.cjs.map +1 -0
  133. package/dist/languages/fr.d.ts +47 -0
  134. package/dist/languages/fr.d.ts.map +1 -0
  135. package/dist/languages/fr.js +7 -0
  136. package/dist/languages/fr.js.map +1 -0
  137. package/dist/languages/he.cjs +7 -0
  138. package/dist/languages/he.cjs.map +1 -0
  139. package/dist/languages/he.d.ts +51 -0
  140. package/dist/languages/he.d.ts.map +1 -0
  141. package/dist/languages/he.js +7 -0
  142. package/dist/languages/he.js.map +1 -0
  143. package/dist/languages/hi.cjs +7 -0
  144. package/dist/languages/hi.cjs.map +1 -0
  145. package/dist/languages/hi.d.ts +54 -0
  146. package/dist/languages/hi.d.ts.map +1 -0
  147. package/dist/languages/hi.js +7 -0
  148. package/dist/languages/hi.js.map +1 -0
  149. package/dist/languages/id.cjs +7 -0
  150. package/dist/languages/id.cjs.map +1 -0
  151. package/dist/languages/id.d.ts +45 -0
  152. package/dist/languages/id.d.ts.map +1 -0
  153. package/dist/languages/id.js +7 -0
  154. package/dist/languages/id.js.map +1 -0
  155. package/dist/languages/index.cjs +99 -0
  156. package/dist/languages/index.cjs.map +1 -0
  157. package/dist/languages/index.d.ts +30 -0
  158. package/dist/languages/index.d.ts.map +1 -0
  159. package/dist/languages/index.js +99 -0
  160. package/dist/languages/index.js.map +1 -0
  161. package/dist/languages/it.cjs +7 -0
  162. package/dist/languages/it.cjs.map +1 -0
  163. package/dist/languages/it.d.ts +48 -0
  164. package/dist/languages/it.d.ts.map +1 -0
  165. package/dist/languages/it.js +7 -0
  166. package/dist/languages/it.js.map +1 -0
  167. package/dist/languages/ja.cjs +7 -0
  168. package/dist/languages/ja.cjs.map +1 -0
  169. package/dist/languages/ja.d.ts +58 -0
  170. package/dist/languages/ja.d.ts.map +1 -0
  171. package/dist/languages/ja.js +7 -0
  172. package/dist/languages/ja.js.map +1 -0
  173. package/dist/languages/ko.cjs +7 -0
  174. package/dist/languages/ko.cjs.map +1 -0
  175. package/dist/languages/ko.d.ts +61 -0
  176. package/dist/languages/ko.d.ts.map +1 -0
  177. package/dist/languages/ko.js +7 -0
  178. package/dist/languages/ko.js.map +1 -0
  179. package/dist/languages/ms.cjs +7 -0
  180. package/dist/languages/ms.cjs.map +1 -0
  181. package/dist/languages/ms.d.ts +44 -0
  182. package/dist/languages/ms.d.ts.map +1 -0
  183. package/dist/languages/ms.js +7 -0
  184. package/dist/languages/ms.js.map +1 -0
  185. package/dist/languages/pl.cjs +7 -0
  186. package/dist/languages/pl.cjs.map +1 -0
  187. package/dist/languages/pl.d.ts +50 -0
  188. package/dist/languages/pl.d.ts.map +1 -0
  189. package/dist/languages/pl.js +7 -0
  190. package/dist/languages/pl.js.map +1 -0
  191. package/dist/languages/pt.cjs +7 -0
  192. package/dist/languages/pt.cjs.map +1 -0
  193. package/dist/languages/pt.d.ts +46 -0
  194. package/dist/languages/pt.d.ts.map +1 -0
  195. package/dist/languages/pt.js +7 -0
  196. package/dist/languages/pt.js.map +1 -0
  197. package/dist/languages/qu.cjs +7 -0
  198. package/dist/languages/qu.cjs.map +1 -0
  199. package/dist/languages/qu.d.ts +48 -0
  200. package/dist/languages/qu.d.ts.map +1 -0
  201. package/dist/languages/qu.js +7 -0
  202. package/dist/languages/qu.js.map +1 -0
  203. package/dist/languages/ru.cjs +7 -0
  204. package/dist/languages/ru.cjs.map +1 -0
  205. package/dist/languages/ru.d.ts +50 -0
  206. package/dist/languages/ru.d.ts.map +1 -0
  207. package/dist/languages/ru.js +7 -0
  208. package/dist/languages/ru.js.map +1 -0
  209. package/dist/languages/sw.cjs +7 -0
  210. package/dist/languages/sw.cjs.map +1 -0
  211. package/dist/languages/sw.d.ts +45 -0
  212. package/dist/languages/sw.d.ts.map +1 -0
  213. package/dist/languages/sw.js +7 -0
  214. package/dist/languages/sw.js.map +1 -0
  215. package/dist/languages/th.cjs +7 -0
  216. package/dist/languages/th.cjs.map +1 -0
  217. package/dist/languages/th.d.ts +48 -0
  218. package/dist/languages/th.d.ts.map +1 -0
  219. package/dist/languages/th.js +7 -0
  220. package/dist/languages/th.js.map +1 -0
  221. package/dist/languages/tl.cjs +7 -0
  222. package/dist/languages/tl.cjs.map +1 -0
  223. package/dist/languages/tl.d.ts +44 -0
  224. package/dist/languages/tl.d.ts.map +1 -0
  225. package/dist/languages/tl.js +7 -0
  226. package/dist/languages/tl.js.map +1 -0
  227. package/dist/languages/tr.cjs +7 -0
  228. package/dist/languages/tr.cjs.map +1 -0
  229. package/dist/languages/tr.d.ts +57 -0
  230. package/dist/languages/tr.d.ts.map +1 -0
  231. package/dist/languages/tr.js +7 -0
  232. package/dist/languages/tr.js.map +1 -0
  233. package/dist/languages/types.d.ts +137 -0
  234. package/dist/languages/types.d.ts.map +1 -0
  235. package/dist/languages/uk.cjs +7 -0
  236. package/dist/languages/uk.cjs.map +1 -0
  237. package/dist/languages/uk.d.ts +50 -0
  238. package/dist/languages/uk.d.ts.map +1 -0
  239. package/dist/languages/uk.js +7 -0
  240. package/dist/languages/uk.js.map +1 -0
  241. package/dist/languages/vi.cjs +7 -0
  242. package/dist/languages/vi.cjs.map +1 -0
  243. package/dist/languages/vi.d.ts +47 -0
  244. package/dist/languages/vi.d.ts.map +1 -0
  245. package/dist/languages/vi.js +7 -0
  246. package/dist/languages/vi.js.map +1 -0
  247. package/dist/languages/zh.cjs +7 -0
  248. package/dist/languages/zh.cjs.map +1 -0
  249. package/dist/languages/zh.d.ts +49 -0
  250. package/dist/languages/zh.d.ts.map +1 -0
  251. package/dist/languages/zh.js +7 -0
  252. package/dist/languages/zh.js.map +1 -0
  253. package/dist/testing/index.js +1416 -930
  254. package/dist/testing/index.js.map +1 -1
  255. package/package.json +130 -5
  256. package/src/index.ts +2 -0
  257. package/src/languages/ar.ts +41 -0
  258. package/src/languages/bn.ts +45 -0
  259. package/src/languages/de.ts +37 -0
  260. package/src/languages/en.ts +36 -0
  261. package/src/languages/es.ts +40 -0
  262. package/src/languages/fr.ts +36 -0
  263. package/src/languages/he.ts +38 -0
  264. package/src/languages/hi.ts +44 -0
  265. package/src/languages/id.ts +34 -0
  266. package/src/languages/index.ts +42 -0
  267. package/src/languages/it.ts +38 -0
  268. package/src/languages/ja.ts +49 -0
  269. package/src/languages/ko.ts +50 -0
  270. package/src/languages/languages.test.ts +57 -0
  271. package/src/languages/ms.ts +33 -0
  272. package/src/languages/pl.ts +39 -0
  273. package/src/languages/pt.ts +34 -0
  274. package/src/languages/qu.ts +34 -0
  275. package/src/languages/ru.ts +37 -0
  276. package/src/languages/sw.ts +34 -0
  277. package/src/languages/th.ts +44 -0
  278. package/src/languages/tl.ts +37 -0
  279. package/src/languages/tr.ts +76 -0
  280. package/src/languages/types.ts +145 -0
  281. package/src/languages/uk.ts +37 -0
  282. package/src/languages/vi.ts +36 -0
  283. package/src/languages/zh.ts +36 -0
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Korean Grammar
3
+ *
4
+ * SOV word order, particles (을/를, 에, 에서, etc.), space-separated between words.
5
+ * Agglutinative language with particles attaching to words.
6
+ */
7
+
8
+ import type { GrammarProfile } from './types';
9
+
10
+ export const koreanGrammar = {
11
+ code: 'ko',
12
+ name: 'Korean',
13
+ nativeName: '한국어',
14
+ direction: 'ltr',
15
+ script: 'hangul',
16
+ wordOrder: 'SOV',
17
+ markingStrategy: 'particle',
18
+ usesSpaces: true, // Korean uses spaces between words, but particles attach
19
+ verb: {
20
+ position: 'end',
21
+ suffixes: ['다', '요', '니다', '세요'],
22
+ subjectDrop: true,
23
+ },
24
+ possessive: {
25
+ marker: '의', // Possessive particle
26
+ markerPosition: 'between',
27
+ },
28
+ roleMarkers: {
29
+ patient: { primary: '을', alternatives: ['를'], position: 'after' },
30
+ // 에서 is deliberately NOT a destination alternative: it is the SOURCE
31
+ // primary ("at/from"), and listing it here let an unconsumed wait-line
32
+ // tail (`문서 에서` — from document) satisfy the next SOV clause's
33
+ // optional destination group (behavior-draggable's add captured
34
+ // destination=문서 instead of the schema `me` default). A real Korean
35
+ // destination renders 에/으로/로/의.
36
+ destination: { primary: '에', alternatives: ['으로', '로', '의'], position: 'after' },
37
+ source: { primary: '에서', alternatives: ['부터'], position: 'after' },
38
+ style: { primary: '로', alternatives: ['으로'], position: 'after' },
39
+ event: { primary: '을', alternatives: ['를'], position: 'after' }, // Event as object marker
40
+ },
41
+ tokenization: {
42
+ particles: ['을', '를', '이', '가', '은', '는', '에', '에서', '으로', '로', '와', '과', '도'],
43
+ boundaryStrategy: 'space',
44
+ },
45
+ // Korean writes a particle onto its noun (`#out에`, `나를`; M2 N5).
46
+ attachedMarkers: {
47
+ markers: ['을', '를', '에', '으로', '로', '의', '에서', '부터', '에게'],
48
+ afterWords: 'all',
49
+ },
50
+ } satisfies GrammarProfile;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * The language grammars: one data module per language, each reachable three
3
+ * ways that must agree — its file, the `languages` barrel, and a package
4
+ * export (`@lokascript/framework/languages/<code>`). tsup builds whatever the
5
+ * directory holds, so a module missing from package.json builds and ships
6
+ * unimportable; a barrel entry missing hides it from tooling.
7
+ */
8
+ import { describe, it, expect } from 'vitest';
9
+ import { readdirSync, readFileSync } from 'fs';
10
+ import { join } from 'path';
11
+ import * as languages from './index';
12
+ import type { GrammarProfile } from './types';
13
+ import type { GrammarProfileSlice } from '../multilingual';
14
+ import { buildLanguageConfig } from '../multilingual';
15
+
16
+ const DIR = __dirname;
17
+ const codes = readdirSync(DIR)
18
+ .filter(
19
+ f => f.endsWith('.ts') && !f.endsWith('.test.ts') && !['index.ts', 'types.ts'].includes(f)
20
+ )
21
+ .map(f => f.slice(0, -3))
22
+ .sort();
23
+ const grammars = Object.values(languages) as GrammarProfile[];
24
+
25
+ describe('language grammars', () => {
26
+ it('exports each module from the barrel, under its own code', () => {
27
+ expect(grammars.map(g => g.code).sort()).toEqual(codes);
28
+ });
29
+
30
+ it('exports each module from the package, and nothing else under ./languages/', () => {
31
+ const pkg = JSON.parse(readFileSync(join(DIR, '../../package.json'), 'utf8'));
32
+ const exported = Object.keys(pkg.exports)
33
+ .filter(k => k.startsWith('./languages/'))
34
+ .map(k => k.slice('./languages/'.length))
35
+ .sort();
36
+ expect(exported).toEqual(codes);
37
+ // `require` too: semantic's dist/index.cjs requires each module.
38
+ for (const key of ['./languages', ...exported.map(code => `./languages/${code}`)]) {
39
+ expect(Object.keys(pkg.exports[key]), key).toEqual(['types', 'import', 'require']);
40
+ }
41
+ });
42
+
43
+ it.each(codes)('%s: is data (no imports but types)', code => {
44
+ const source = readFileSync(join(DIR, `${code}.ts`), 'utf8');
45
+ const imports = source.match(/^import .*$/gm) ?? [];
46
+ expect(imports).toEqual(["import type { GrammarProfile } from './types';"]);
47
+ });
48
+
49
+ it('injects into the bridge as a slice', () => {
50
+ for (const grammar of grammars) {
51
+ const slice: GrammarProfileSlice = grammar;
52
+ const config = buildLanguageConfig(slice, { keywords: { go: { primary: 'go' } } });
53
+ expect(config.code).toBe(grammar.code);
54
+ expect(config.patternProfile.wordOrder).toBe(grammar.wordOrder);
55
+ }
56
+ });
57
+ });
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Malay Grammar
3
+ *
4
+ * SVO word order, prepositions, space-separated.
5
+ */
6
+
7
+ import type { GrammarProfile } from './types';
8
+
9
+ export const malayGrammar = {
10
+ code: 'ms',
11
+ name: 'Malay',
12
+ nativeName: 'Melayu',
13
+ direction: 'ltr',
14
+ script: 'latin',
15
+ wordOrder: 'SVO',
16
+ markingStrategy: 'preposition',
17
+ usesSpaces: true,
18
+ defaultVerbForm: 'base',
19
+ verb: {
20
+ position: 'start',
21
+ subjectDrop: true,
22
+ },
23
+ possessive: {
24
+ marker: '', // Malay often uses suffix or juxtaposition
25
+ markerPosition: 'after-object',
26
+ },
27
+ roleMarkers: {
28
+ destination: { primary: 'ke', alternatives: ['pada'], position: 'before' },
29
+ source: { primary: 'dari', position: 'before' },
30
+ patient: { primary: '', position: 'before' },
31
+ style: { primary: 'dengan', position: 'before' },
32
+ },
33
+ } satisfies GrammarProfile;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Polish Grammar
3
+ *
4
+ * SVO word order, prepositions, space-separated.
5
+ * Polish is a fusional language with rich verb conjugation.
6
+ * Unlike most languages, Polish software UI uses IMPERATIVE form.
7
+ */
8
+
9
+ import type { GrammarProfile } from './types';
10
+
11
+ export const polishGrammar = {
12
+ code: 'pl',
13
+ name: 'Polish',
14
+ nativeName: 'Polski',
15
+ direction: 'ltr',
16
+ script: 'latin',
17
+ wordOrder: 'SVO',
18
+ markingStrategy: 'preposition',
19
+ usesSpaces: true,
20
+ // Polish uses imperative form for commands in software UI
21
+ // (unlike most languages that use infinitive)
22
+ defaultVerbForm: 'imperative',
23
+ verb: {
24
+ position: 'start',
25
+ subjectDrop: true,
26
+ suffixes: ['ać', 'eć', 'ić', 'yć', 'ąć', 'ować'],
27
+ },
28
+ possessive: {
29
+ marker: '', // Polish uses genitive case, not a marker
30
+ markerPosition: 'after-object',
31
+ usePossessiveAdjectives: true,
32
+ },
33
+ roleMarkers: {
34
+ destination: { primary: 'do', alternatives: ['w', 'na', 'we'], position: 'before' },
35
+ source: { primary: 'z', alternatives: ['od', 'ze'], position: 'before' },
36
+ patient: { primary: '', position: 'before' },
37
+ style: { primary: 'z', alternatives: ['ze'], position: 'before' },
38
+ },
39
+ } satisfies GrammarProfile;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Portuguese Grammar
3
+ *
4
+ * SVO word order, prepositions, space-separated.
5
+ * Features rich verb conjugation with pro-drop (subject omission).
6
+ */
7
+
8
+ import type { GrammarProfile } from './types';
9
+
10
+ export const portugueseGrammar = {
11
+ code: 'pt',
12
+ name: 'Portuguese',
13
+ nativeName: 'Português',
14
+ direction: 'ltr',
15
+ script: 'latin',
16
+ wordOrder: 'SVO',
17
+ markingStrategy: 'preposition',
18
+ usesSpaces: true,
19
+ verb: {
20
+ position: 'start',
21
+ subjectDrop: true,
22
+ },
23
+ possessive: {
24
+ marker: 'de', // Uses "de" for general possession
25
+ markerPosition: 'before-property',
26
+ usePossessiveAdjectives: true,
27
+ },
28
+ roleMarkers: {
29
+ destination: { primary: 'em', alternatives: ['para', 'a'], position: 'before' },
30
+ source: { primary: 'de', alternatives: ['desde'], position: 'before' },
31
+ patient: { primary: '', position: 'before' },
32
+ style: { primary: 'com', position: 'before' },
33
+ },
34
+ } satisfies GrammarProfile;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Quechua Grammar
3
+ *
4
+ * SOV word order, postpositions (suffixes), polysynthetic/agglutinative.
5
+ * Indigenous language of the Andean region with rich morphology.
6
+ */
7
+
8
+ import type { GrammarProfile } from './types';
9
+
10
+ export const quechuaGrammar = {
11
+ code: 'qu',
12
+ name: 'Quechua',
13
+ nativeName: 'Runasimi',
14
+ direction: 'ltr',
15
+ script: 'latin',
16
+ wordOrder: 'SOV',
17
+ markingStrategy: 'postposition',
18
+ usesSpaces: true,
19
+ verb: {
20
+ position: 'end',
21
+ subjectDrop: true,
22
+ },
23
+ possessive: {
24
+ marker: '-pa', // Genitive suffix
25
+ markerPosition: 'after-object',
26
+ },
27
+ roleMarkers: {
28
+ patient: { primary: 'ta', position: 'after' },
29
+ destination: { primary: 'man', alternatives: ['pa'], position: 'after' },
30
+ source: { primary: 'manta', position: 'after' },
31
+ style: { primary: 'wan', position: 'after' },
32
+ event: { primary: 'pi', position: 'after' }, // Locative: event occurs "at" (pi)
33
+ },
34
+ } satisfies GrammarProfile;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Russian Grammar
3
+ *
4
+ * SVO word order, prepositions, space-separated.
5
+ * Russian is a fusional language with rich verb conjugation.
6
+ * Uses infinitive form in software UI (industry standard).
7
+ */
8
+
9
+ import type { GrammarProfile } from './types';
10
+
11
+ export const russianGrammar = {
12
+ code: 'ru',
13
+ name: 'Russian',
14
+ nativeName: 'Русский',
15
+ direction: 'ltr',
16
+ script: 'cyrillic',
17
+ wordOrder: 'SVO',
18
+ markingStrategy: 'preposition',
19
+ usesSpaces: true,
20
+ defaultVerbForm: 'infinitive',
21
+ verb: {
22
+ position: 'start',
23
+ subjectDrop: true,
24
+ suffixes: ['ть', 'ться', 'ить', 'иться', 'ать', 'аться', 'еть', 'еться'],
25
+ },
26
+ possessive: {
27
+ marker: '',
28
+ markerPosition: 'after-object',
29
+ usePossessiveAdjectives: true,
30
+ },
31
+ roleMarkers: {
32
+ destination: { primary: 'в', alternatives: ['на', 'к', 'во', 'ко'], position: 'before' },
33
+ source: { primary: 'из', alternatives: ['от', 'с'], position: 'before' },
34
+ patient: { primary: '', position: 'before' },
35
+ style: { primary: 'с', alternatives: ['со'], position: 'before' },
36
+ },
37
+ } satisfies GrammarProfile;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Swahili Grammar
3
+ *
4
+ * SVO word order, prepositions, space-separated, agglutinative.
5
+ * Features noun class system (18 classes) and verb agreement prefixes.
6
+ */
7
+
8
+ import type { GrammarProfile } from './types';
9
+
10
+ export const swahiliGrammar = {
11
+ code: 'sw',
12
+ name: 'Swahili',
13
+ nativeName: 'Kiswahili',
14
+ direction: 'ltr',
15
+ script: 'latin',
16
+ wordOrder: 'SVO',
17
+ markingStrategy: 'preposition',
18
+ usesSpaces: true,
19
+ verb: {
20
+ position: 'start',
21
+ subjectDrop: true,
22
+ },
23
+ possessive: {
24
+ marker: '', // Swahili uses possessive pronouns
25
+ markerPosition: 'after-object',
26
+ usePossessiveAdjectives: true,
27
+ },
28
+ roleMarkers: {
29
+ destination: { primary: 'kwenye', alternatives: ['kwa'], position: 'before' },
30
+ source: { primary: 'kutoka', position: 'before' },
31
+ patient: { primary: '', position: 'before' },
32
+ style: { primary: 'na', position: 'before' },
33
+ },
34
+ } satisfies GrammarProfile;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Thai Grammar
3
+ *
4
+ * SVO word order, prepositions, Thai script.
5
+ * Isolating language (like Chinese) with no inflection.
6
+ */
7
+
8
+ import type { GrammarProfile } from './types';
9
+
10
+ export const thaiGrammar = {
11
+ code: 'th',
12
+ name: 'Thai',
13
+ nativeName: 'ไทย',
14
+ direction: 'ltr',
15
+ script: 'thai',
16
+ wordOrder: 'SVO',
17
+ markingStrategy: 'preposition',
18
+ usesSpaces: false, // Thai doesn't use spaces between words
19
+ defaultVerbForm: 'base',
20
+ verb: {
21
+ position: 'second',
22
+ subjectDrop: true,
23
+ },
24
+ possessive: {
25
+ marker: 'ของ',
26
+ markerPosition: 'between',
27
+ },
28
+ roleMarkers: {
29
+ patient: { primary: '', position: 'before' }, // Thai is isolating - no case markers
30
+ destination: { primary: 'ใน', alternatives: ['ไปยัง'], position: 'before' },
31
+ source: { primary: 'จาก', position: 'before' },
32
+ style: { primary: 'ด้วย', position: 'before' },
33
+ // No `event` role marker: a command's event argument (`trigger foo` /
34
+ // `send foo`) is an UNMARKED object in Thai, like every other SVO profile
35
+ // (es/zh/id/…). `เมื่อ` is the temporal "when/on" marker and belongs only on
36
+ // the event-HANDLER head — which uses `eventHandler.eventMarker` (below),
37
+ // not this role marker. Carrying it here generated `ทริกเกอร์ เมื่อ {event}`,
38
+ // which never matched the transformer's `ทริกเกอร์ {event}` → trigger/send
39
+ // dropped (th behavior-draggable/removable/resizable/sortable lossy).
40
+ },
41
+ tokenization: {
42
+ boundaryStrategy: 'character', // Character-based like Chinese/Japanese
43
+ },
44
+ } satisfies GrammarProfile;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Tagalog Grammar
3
+ *
4
+ * VSO word order, prepositions, space-separated.
5
+ */
6
+
7
+ import type { GrammarProfile } from './types';
8
+
9
+ export const tagalogGrammar = {
10
+ code: 'tl',
11
+ name: 'Tagalog',
12
+ nativeName: 'Tagalog',
13
+ direction: 'ltr',
14
+ script: 'latin',
15
+ wordOrder: 'VSO',
16
+ markingStrategy: 'preposition',
17
+ usesSpaces: true,
18
+ defaultVerbForm: 'base',
19
+ verb: {
20
+ position: 'start',
21
+ subjectDrop: true,
22
+ },
23
+ possessive: {
24
+ marker: 'ng', // Linker used in possessive constructions
25
+ markerPosition: 'between',
26
+ },
27
+ roleMarkers: {
28
+ // `bago` (before) / `matapos` (after) are positional destination markers for
29
+ // `put X before/after Y`, mirroring how Arabic lists قبل/بعد as destination
30
+ // alternatives. Without them the generated put pattern can't match a
31
+ // before/after target.
32
+ destination: { primary: 'sa', alternatives: ['bago', 'matapos'], position: 'before' }, // "to/into"
33
+ source: { primary: 'mula_sa', position: 'before' }, // "from"
34
+ patient: { primary: '', position: 'before' },
35
+ style: { primary: 'nang', position: 'before' }, // manner marker
36
+ },
37
+ } satisfies GrammarProfile;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Turkish Grammar
3
+ *
4
+ * SOV word order, case suffixes (agglutinative), space-separated.
5
+ * Features vowel harmony and extensive suffixation.
6
+ */
7
+
8
+ import type { GrammarProfile } from './types';
9
+
10
+ export const turkishGrammar = {
11
+ code: 'tr',
12
+ name: 'Turkish',
13
+ nativeName: 'Türkçe',
14
+ direction: 'ltr',
15
+ script: 'latin',
16
+ wordOrder: 'SOV',
17
+ markingStrategy: 'case-suffix',
18
+ usesSpaces: true,
19
+ verb: {
20
+ position: 'end',
21
+ suffixes: ['mek', 'mak', 'yor', 'di', 'miş'],
22
+ subjectDrop: true,
23
+ },
24
+ // The locative written onto a Turkish word, in the form its harmony gives
25
+ // (`tıklamada`, `değişiklikte`; M2 N4). Code keeps its suffix apart
26
+ // (`keyup da`) until a reviewer picks a code word's harmony (FUSED_FORMS.md
27
+ // Q2); the other case suffixes stay apart on code for the same reason.
28
+ attachedMarkers: { markers: ['da', 'de', 'ta', 'te'] },
29
+ possessive: {
30
+ // Genitive suffix, spaced for tokenization like Turkish's other case
31
+ // markers (i/e/de). i18n renders `#picker ın değer`; the parser matches
32
+ // `ın` as the possessive marker. Vowel-harmony variants (in/un/ün) are not
33
+ // distinguished — the generator emits the `ın` form for all owners.
34
+ marker: 'ın',
35
+ markerPosition: 'after-object',
36
+ usePossessiveAdjectives: true,
37
+ },
38
+ roleMarkers: {
39
+ patient: {
40
+ primary: 'i',
41
+ alternatives: ['ı', 'u', 'ü', 'yi', 'yı', 'yu', 'yü', 'ni', 'nı', 'nu', 'nü'],
42
+ position: 'after',
43
+ }, // Accusative (with buffer consonants y/n)
44
+ destination: {
45
+ primary: 'e',
46
+ // Include both dative (e/a) and genitive (ın/in/un/ün) for possessive patterns
47
+ // Genitive is used in "X's Y" patterns: #button ın .active = "#button's .active"
48
+ alternatives: [
49
+ 'a',
50
+ 'ye',
51
+ 'ya',
52
+ 'ne',
53
+ 'na',
54
+ 'de',
55
+ 'da',
56
+ 'te',
57
+ 'ta',
58
+ 'ın',
59
+ 'in',
60
+ 'un',
61
+ 'ün',
62
+ 'nın',
63
+ 'nin',
64
+ 'nun',
65
+ 'nün',
66
+ ],
67
+ position: 'after',
68
+ }, // Dative/Locative + Genitive (with buffer consonants)
69
+ source: { primary: 'den', alternatives: ['dan', 'ten', 'tan'], position: 'after' }, // Ablative
70
+ // `ile` is the free-standing instrumental the transformer actually emits
71
+ // for with-phrases (`getir method:"POST" body:form ile`); the suffix
72
+ // forms cover hand-written agglutinated variants.
73
+ style: { primary: 'le', alternatives: ['la', 'yle', 'yla', 'ile'], position: 'after' }, // Instrumental
74
+ event: { primary: 'i', alternatives: ['ı', 'u', 'ü'], position: 'after' }, // Event as accusative
75
+ },
76
+ } satisfies GrammarProfile;
@@ -0,0 +1,145 @@
1
+ /**
2
+ * A language's grammar: the facts that hold for it whatever a DSL says in it.
3
+ *
4
+ * `@lokascript/semantic`'s `LanguageProfile` spreads one of these and adds
5
+ * hyperscript's vocabulary (keywords, references, event-handler words); a
6
+ * domain injects one into the bridge builders (`./multilingual`) with its own
7
+ * vocabulary. Each `languages/<code>` module exports one, as data: no
8
+ * registration, no side effects.
9
+ */
10
+
11
+ /**
12
+ * Word order in a language (for declarative statements).
13
+ */
14
+ export type WordOrder = 'SVO' | 'SOV' | 'VSO' | 'VOS' | 'OSV' | 'OVS';
15
+
16
+ /**
17
+ * How grammatical relationships are marked.
18
+ */
19
+ export type MarkingStrategy = 'preposition' | 'postposition' | 'particle' | 'case-suffix';
20
+
21
+ /**
22
+ * Writing system used by a language.
23
+ * Non-latin scripts require AsciiIdentifierExtractor in their tokenizer
24
+ * to handle mixed-script input (e.g., Arabic verb + CSS property name).
25
+ */
26
+ export type ScriptType =
27
+ 'latin' | 'cyrillic' | 'arabic' | 'cjk' | 'devanagari' | 'hangul' | 'bengali' | 'thai' | 'hebrew';
28
+
29
+ /**
30
+ * A grammatical marker (preposition, particle, etc.) for a semantic role.
31
+ */
32
+ export interface RoleMarker {
33
+ /** Primary marker for this role */
34
+ readonly primary: string;
35
+ /** Alternative markers that also work */
36
+ readonly alternatives?: string[];
37
+ /** Position relative to the role value */
38
+ readonly position: 'before' | 'after';
39
+ }
40
+
41
+ /**
42
+ * Verb form configuration for a language.
43
+ */
44
+ export interface VerbConfig {
45
+ /** Position of verb in the sentence */
46
+ readonly position: 'start' | 'end' | 'second';
47
+ /** Common verb suffixes/conjugations to recognize */
48
+ readonly suffixes?: string[];
49
+ /** Whether the language commonly drops subjects */
50
+ readonly subjectDrop?: boolean;
51
+ }
52
+
53
+ /**
54
+ * Verb form used for command keywords.
55
+ *
56
+ * Based on software localization research:
57
+ * - 'infinitive': Standard for most languages (Spanish, French, German, Russian)
58
+ * Example: "Guardar", "Enregistrer", "Speichern"
59
+ * - 'imperative': Used by some languages (Polish)
60
+ * Example: "Zapisz", "Otwórz"
61
+ * - 'base': For languages where forms are identical (English, Japanese, Korean)
62
+ * or where the distinction doesn't apply
63
+ */
64
+ export type VerbForm = 'infinitive' | 'imperative' | 'base';
65
+
66
+ /**
67
+ * Special tokenization configuration.
68
+ */
69
+ export interface TokenizationConfig {
70
+ /** Particles to recognize (for particle languages) */
71
+ readonly particles?: string[];
72
+ /** Prefixes to recognize (for prefixing languages) */
73
+ readonly prefixes?: string[];
74
+ /** Word boundary detection strategy */
75
+ readonly boundaryStrategy?: 'space' | 'particle' | 'character';
76
+ }
77
+
78
+ /**
79
+ * How "X's Y" is built in a language. The possessive WORDS (my, your, its)
80
+ * are vocabulary, and stay with the DSL that names the references.
81
+ */
82
+ export interface PossessiveGrammar {
83
+ /** Possessive marker (e.g., "'s" in English, "の" in Japanese) */
84
+ readonly marker: string;
85
+ /** Position of marker: 'after-object' (X's Y), 'between' (X の Y), 'before-property' */
86
+ readonly markerPosition: 'after-object' | 'between' | 'before-property';
87
+ /** Whether to use possessive adjectives instead of marker (e.g., Spanish mi/tu/su) */
88
+ readonly usePossessiveAdjectives?: boolean;
89
+ }
90
+
91
+ /**
92
+ * Role markers written onto the word before them, as the language writes its
93
+ * case particles (M2 N5): ko `#out에`, ja `#outに`, bn `#outকে`. `markers`
94
+ * attach after code (a selector, a variable, a string); `afterWords` also
95
+ * after a word of the language, where its spelling does not change the
96
+ * marker (`'all'`; bn lists `কে`, and its locative takes the word's form by
97
+ * its own rule: `ক্লিকে`, `জমাতে`). ko picks each particle's form by the
98
+ * word's final consonant (`나를`).
99
+ */
100
+ export interface AttachedMarkers {
101
+ readonly markers: readonly string[];
102
+ readonly afterWords?: 'all' | readonly string[];
103
+ }
104
+
105
+ /**
106
+ * One language's grammar. A structural superset of the bridge's
107
+ * `GrammarProfileSlice`, so it injects into the builders as is.
108
+ */
109
+ export interface GrammarProfile {
110
+ /** ISO 639-1 or BCP 47 language code (e.g., 'es' or 'en-US') */
111
+ readonly code: string;
112
+ /** Human-readable language name */
113
+ readonly name: string;
114
+ /** Native name */
115
+ readonly nativeName: string;
116
+ /** Text direction */
117
+ readonly direction: 'ltr' | 'rtl';
118
+ /** Writing system — non-latin scripts require AsciiIdentifierExtractor in their tokenizer */
119
+ readonly script: ScriptType;
120
+ /** Primary word order */
121
+ readonly wordOrder: WordOrder;
122
+ /** How this language marks grammatical roles */
123
+ readonly markingStrategy: MarkingStrategy;
124
+ /** Whether the language uses spaces between words */
125
+ readonly usesSpaces: boolean;
126
+ /** Markers for each semantic role */
127
+ readonly roleMarkers: { readonly [role: string]: RoleMarker | undefined };
128
+ /** Verb configuration */
129
+ readonly verb: VerbConfig;
130
+ /** Special tokenization notes */
131
+ readonly tokenization?: TokenizationConfig;
132
+ /**
133
+ * Default verb form for command keywords. Defaults to 'infinitive'.
134
+ *
135
+ * Based on software UI localization research:
136
+ * - 'infinitive': Spanish, French, German, Portuguese, Russian (industry standard)
137
+ * - 'imperative': Polish
138
+ * - 'base': English, Japanese, Korean (no distinction or same form)
139
+ */
140
+ readonly defaultVerbForm?: VerbForm;
141
+ /** Role markers the language writes onto the word before them */
142
+ readonly attachedMarkers?: AttachedMarkers;
143
+ /** How the language builds "X's Y" */
144
+ readonly possessive?: PossessiveGrammar;
145
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Ukrainian Grammar
3
+ *
4
+ * SVO word order, prepositions, space-separated.
5
+ * Ukrainian is a fusional language with rich verb conjugation.
6
+ * Uses infinitive form in software UI (industry standard).
7
+ */
8
+
9
+ import type { GrammarProfile } from './types';
10
+
11
+ export const ukrainianGrammar = {
12
+ code: 'uk',
13
+ name: 'Ukrainian',
14
+ nativeName: 'Українська',
15
+ direction: 'ltr',
16
+ script: 'cyrillic',
17
+ wordOrder: 'SVO',
18
+ markingStrategy: 'preposition',
19
+ usesSpaces: true,
20
+ defaultVerbForm: 'infinitive',
21
+ verb: {
22
+ position: 'start',
23
+ subjectDrop: true,
24
+ suffixes: ['ти', 'тися', 'ити', 'итися', 'ати', 'атися', 'іти', 'ітися'],
25
+ },
26
+ possessive: {
27
+ marker: '',
28
+ markerPosition: 'after-object',
29
+ usePossessiveAdjectives: true,
30
+ },
31
+ roleMarkers: {
32
+ destination: { primary: 'в', alternatives: ['на', 'до'], position: 'before' },
33
+ source: { primary: 'з', alternatives: ['від', 'із'], position: 'before' },
34
+ patient: { primary: '', position: 'before' },
35
+ style: { primary: 'з', alternatives: ['із'], position: 'before' },
36
+ },
37
+ } satisfies GrammarProfile;