@lokascript/i18n 3.1.1 → 3.2.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 (49) hide show
  1. package/README.md +35 -45
  2. package/dist/browser.cjs +52 -29
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.js +52 -29
  5. package/dist/browser.js.map +1 -1
  6. package/dist/dictionaries/index.cjs +52 -29
  7. package/dist/dictionaries/index.cjs.map +1 -1
  8. package/dist/dictionaries/index.js +52 -29
  9. package/dist/dictionaries/index.js.map +1 -1
  10. package/dist/index.cjs +52 -29
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +30 -30
  13. package/dist/index.d.ts +30 -30
  14. package/dist/index.js +52 -29
  15. package/dist/index.js.map +1 -1
  16. package/dist/lokascript-i18n.min.js +1 -1
  17. package/dist/lokascript-i18n.min.js.map +1 -1
  18. package/dist/lokascript-i18n.mjs +35 -12
  19. package/dist/lokascript-i18n.mjs.map +1 -1
  20. package/dist/plugins/vite.cjs +52 -29
  21. package/dist/plugins/vite.cjs.map +1 -1
  22. package/dist/plugins/vite.js +52 -29
  23. package/dist/plugins/vite.js.map +1 -1
  24. package/dist/plugins/webpack.cjs +52 -29
  25. package/dist/plugins/webpack.cjs.map +1 -1
  26. package/dist/plugins/webpack.js +52 -29
  27. package/dist/plugins/webpack.js.map +1 -1
  28. package/package.json +10 -10
  29. package/src/dictionaries/ar.ts +2 -1
  30. package/src/dictionaries/de.ts +1 -0
  31. package/src/dictionaries/es.ts +1 -0
  32. package/src/dictionaries/fr.ts +1 -0
  33. package/src/dictionaries/he.ts +3 -1
  34. package/src/dictionaries/hi.ts +3 -2
  35. package/src/dictionaries/id.ts +2 -1
  36. package/src/dictionaries/it.ts +1 -0
  37. package/src/dictionaries/ja.ts +1 -0
  38. package/src/dictionaries/ko.ts +1 -0
  39. package/src/dictionaries/pl.ts +1 -0
  40. package/src/dictionaries/pt.ts +1 -0
  41. package/src/dictionaries/qu.ts +3 -2
  42. package/src/dictionaries/ru.ts +1 -0
  43. package/src/dictionaries/sw.ts +2 -1
  44. package/src/dictionaries/th.ts +1 -1
  45. package/src/dictionaries/tl.ts +3 -1
  46. package/src/dictionaries/tr.ts +5 -2
  47. package/src/dictionaries/uk.ts +1 -0
  48. package/src/dictionaries/zh.ts +1 -0
  49. package/src/new-languages.test.ts +1 -1
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Comprehensive internationalization (i18n) support for LokaScript and \_hyperscript applications.
4
4
 
5
+ > **This package no longer translates code.** Its grammar transformer was retired on 2026-08-28 (#1001). To translate hyperscript between languages, use [`@lokascript/semantic`](https://www.npmjs.com/package/@lokascript/semantic): `translate(code, from, to)` or `render(parse(code, from), to)`. `@lokascript/i18n` provides the per-language vocabulary — dictionaries, keyword providers, locale utilities and word-order profiles.
6
+
5
7
  ## Installation
6
8
 
7
9
  ```bash
@@ -15,7 +17,7 @@ npm install @lokascript/i18n
15
17
  - **⚡ SSR Integration**: Server-side rendering with locale detection, SEO optimization, and hydration support
16
18
  - **📊 Pluralization**: CLDR-compliant pluralization rules for complex languages (Russian, Arabic, etc.)
17
19
  - **💰 Formatting**: Locale-aware number, date, currency, and unit formatting with fallbacks
18
- - **🛠️ Build Tool Integration**: Vite and Webpack plugins for build-time translation
20
+ - **🛠️ Build Tool Integration**: Vite and Webpack plugins for build-time keyword substitution
19
21
  - **🔍 Language Detection**: Automatically detect the language of hyperscript code from content
20
22
  - **✅ Validation**: Comprehensive dictionary validation with coverage reports and warnings
21
23
  - **🎯 Type Safety**: Full TypeScript support with comprehensive type definitions
@@ -26,42 +28,44 @@ npm install @lokascript/i18n
26
28
 
27
29
  LokaScript has two packages for multilingual support with different purposes:
28
30
 
29
- | Package | Purpose | Use Case |
30
- | ------------------------ | -------------------------------------------- | ---------------------------------------------------- |
31
- | **@lokascript/semantic** | Parse code written in any language → execute | Users **write** hyperscript in their native language |
32
- | **@lokascript/i18n** | Transform code between languages | **Translate** code examples for docs/teaching |
31
+ | Package | Purpose | Use Case |
32
+ | ------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------------------------ |
33
+ | **@lokascript/semantic** | Parse code written in any language → execute; translate it | Users **write** hyperscript in their native language; **translate** code |
34
+ | **@lokascript/i18n** | Per-language vocabulary: dictionaries, keyword providers, profiles | Tools and runtimes that need the **words** of each language |
33
35
 
34
36
  **Use @lokascript/semantic** when your users will write hyperscript in their native language. It parses multilingual input directly into executable AST nodes with native idiom support (e.g., Japanese conditionals like `クリックしたら`).
35
37
 
36
- **Use @lokascript/i18n** (this package) when you need to translate code examples between languages for documentation, tutorials, or teaching materials. It transforms existing code for display purposes—showing learners how the same logic looks in different languages.
38
+ **Use @lokascript/semantic** too when you need to translate code examples between languages for documentation, tutorials, or teaching materials. It parses the code and renders it in the target language's own word order.
37
39
 
38
40
  Example workflow for documentation:
39
41
 
40
42
  ```typescript
43
+ import { translate } from '@lokascript/semantic';
44
+
41
45
  // You have English examples in your docs
42
- const english = 'on click toggle .active';
46
+ const english = 'toggle .active';
43
47
 
44
48
  // Translate to show Japanese readers the equivalent
45
- const japanese = translator.translate(english, { from: 'en', to: 'ja' });
46
- // → "クリック で .active を 切り替え"
49
+ const japanese = translate(english, 'en', 'ja');
50
+ // → ".active を 切り替え"
47
51
  ```
48
52
 
53
+ **Use @lokascript/i18n** (this package) for the vocabulary itself: keyword dictionaries, keyword providers for parsers and editors, locale detection and formatting, and the word-order profiles.
54
+
49
55
  ## Quick Start
50
56
 
51
- ### Basic Translation
57
+ ### Keyword Substitution
58
+
59
+ `HyperscriptTranslator` (and the ready-made `defaultTranslator`) swaps keywords word-for-word using the dictionaries. It does not parse the code or reorder words, so its output is not a faithful translation — for that, use `@lokascript/semantic`'s `translate`.
52
60
 
53
61
  ```typescript
54
62
  import { HyperscriptTranslator } from '@lokascript/i18n';
55
63
 
56
- const translator = new HyperscriptTranslator({ locale: 'es' });
57
-
58
- // Translate from Spanish to English
59
- const english = translator.translate('en clic alternar .activo', { to: 'en' });
60
- // Result: "on click toggle .activo"
64
+ const translator = new HyperscriptTranslator({ locale: 'en' });
61
65
 
62
- // Translate from English to Korean
66
+ // Swap English keywords for Korean ones, in place
63
67
  const korean = translator.translate('on click toggle .active', { from: 'en', to: 'ko' });
64
- // Result: "클릭 토글 .active"
68
+ // Result: "에 클릭 토글 .active" (keywords substituted; English word order kept)
65
69
  ```
66
70
 
67
71
  ### Language Detection
@@ -73,6 +77,8 @@ const detectedLocale = translator.detectLanguage('si verdadero entonces registra
73
77
 
74
78
  ### Build Tool Integration
75
79
 
80
+ Both plugins run `HyperscriptTranslator` over hyperscript attributes at build time, so they substitute keywords; they do not translate.
81
+
76
82
  #### Vite
77
83
 
78
84
  ```typescript
@@ -123,6 +129,17 @@ module.exports = {
123
129
  | Indonesian | `id` | ✅ Complete | SVO | Agglutinative support |
124
130
  | Quechua | `qu` | ✅ Complete | SOV | Agglutinative support |
125
131
  | Swahili | `sw` | ✅ Complete | SVO | Noun class system |
132
+ | Bengali | `bn` | ✅ Complete | SOV | — |
133
+ | Hebrew | `he` | ✅ Complete | SVO | RTL support |
134
+ | Hindi | `hi` | ✅ Complete | SOV | — |
135
+ | Italian | `it` | ✅ Complete | SVO | Pluralization |
136
+ | Malay | `ms` | ✅ Complete | SVO | — |
137
+ | Polish | `pl` | ✅ Complete | SVO | Pluralization |
138
+ | Russian | `ru` | ✅ Complete | SVO | Pluralization |
139
+ | Tagalog | `tl` | ✅ Complete | VSO | — |
140
+ | Thai | `th` | ✅ Complete | SVO | — |
141
+ | Ukrainian | `uk` | ✅ Complete | SVO | — |
142
+ | Vietnamese | `vi` | ✅ Complete | SVO | — |
126
143
 
127
144
  ## API Reference
128
145
 
@@ -132,7 +149,7 @@ module.exports = {
132
149
  class HyperscriptTranslator {
133
150
  constructor(config: I18nConfig);
134
151
 
135
- // Translate hyperscript text
152
+ // Substitute keywords word-for-word (no parsing, no reordering)
136
153
  translate(text: string, options: TranslationOptions): string;
137
154
 
138
155
  // Get detailed translation with token information
@@ -211,33 +228,6 @@ const translator = new HyperscriptTranslator({
211
228
  });
212
229
  ```
213
230
 
214
- ### LSP Integration
215
-
216
- ```typescript
217
- import { I18nLanguageProvider } from '@lokascript/i18n/lsp';
218
-
219
- const provider = new I18nLanguageProvider('es');
220
-
221
- // Get completions
222
- const completions = await provider.provideCompletions(document, position);
223
-
224
- // Get hover information
225
- const hover = await provider.provideHover(document, position);
226
- ```
227
-
228
- ### CLI Usage
229
-
230
- ```bash
231
- # Install globally
232
- npm install -g @lokascript/i18n
233
-
234
- # Translate a file
235
- lokascript-translate input.html output.html --from es --to en
236
-
237
- # Translate a directory
238
- lokascript-translate src/ dist/ --from es --to en
239
- ```
240
-
241
231
  ## Contributing
242
232
 
243
233
  We welcome contributions, especially new language dictionaries!
package/dist/browser.cjs CHANGED
@@ -556,7 +556,8 @@ var es = {
556
556
  ms: "ms",
557
557
  s: "s",
558
558
  min: "min",
559
- h: "h"
559
+ h: "h",
560
+ times: "veces"
560
561
  },
561
562
  values: {
562
563
  true: "verdadero",
@@ -777,7 +778,8 @@ var ja = {
777
778
  ms: "ms",
778
779
  s: "\u79D2",
779
780
  min: "\u5206",
780
- h: "\u6642"
781
+ h: "\u6642",
782
+ times: "\u56DE"
781
783
  },
782
784
  values: {
783
785
  true: "\u771F",
@@ -996,7 +998,8 @@ var fr = {
996
998
  ms: "ms",
997
999
  s: "s",
998
1000
  min: "min",
999
- h: "h"
1001
+ h: "h",
1002
+ times: "fois"
1000
1003
  },
1001
1004
  values: {
1002
1005
  true: "vrai",
@@ -1226,7 +1229,8 @@ var de = {
1226
1229
  ms: "ms",
1227
1230
  s: "s",
1228
1231
  min: "min",
1229
- h: "std"
1232
+ h: "std",
1233
+ times: "mal"
1230
1234
  },
1231
1235
  values: {
1232
1236
  true: "wahr",
@@ -1450,12 +1454,13 @@ var ar = {
1450
1454
  ms: "\u0645.\u062B",
1451
1455
  s: "\u062B",
1452
1456
  min: "\u062F",
1453
- h: "\u0633"
1457
+ h: "\u0633",
1458
+ times: "\u0645\u0631\u0627\u062A"
1454
1459
  },
1455
1460
  values: {
1456
1461
  true: "\u0635\u062D\u064A\u062D",
1457
1462
  false: "\u062E\u0637\u0623",
1458
- null: "\u0641\u0627\u0631\u063A",
1463
+ null: "null",
1459
1464
  undefined: "\u063A\u064A\u0631 \u0645\u0639\u0631\u0641",
1460
1465
  it: "\u0647\u0648",
1461
1466
  its: "\u0644\u0647",
@@ -1670,7 +1675,8 @@ var ko = {
1670
1675
  ms: "ms",
1671
1676
  s: "\uCD08",
1672
1677
  min: "\uBD84",
1673
- h: "\uC2DC"
1678
+ h: "\uC2DC",
1679
+ times: "\uBC88"
1674
1680
  },
1675
1681
  values: {
1676
1682
  true: "\uCC38",
@@ -1898,7 +1904,8 @@ var zh = {
1898
1904
  ms: "\u6BEB\u79D2",
1899
1905
  s: "\u79D2",
1900
1906
  min: "\u5206",
1901
- h: "\u65F6"
1907
+ h: "\u65F6",
1908
+ times: "\u6B21"
1902
1909
  },
1903
1910
  values: {
1904
1911
  true: "\u771F",
@@ -2100,7 +2107,9 @@ var tr = {
2100
2107
  exists: "var",
2101
2108
  matches: "e\u015Fle\u015Fir",
2102
2109
  contains: "i\xE7erir",
2103
- includes: "dahil",
2110
+ // `includes` takes `contains`' word: both engines read them as one operator,
2111
+ // and `dahil` is `inclusive` (pick's range word), which the reader takes it for.
2112
+ includes: "i\xE7erir",
2104
2113
  equals: "e\u015Fittir",
2105
2114
  has: "var",
2106
2115
  have: "var",
@@ -2123,12 +2132,13 @@ var tr = {
2123
2132
  ms: "ms",
2124
2133
  s: "s",
2125
2134
  min: "dk",
2126
- h: "sa"
2135
+ h: "sa",
2136
+ times: "kez"
2127
2137
  },
2128
2138
  values: {
2129
2139
  true: "do\u011Fru",
2130
2140
  false: "yanl\u0131\u015F",
2131
- null: "bo\u015F",
2141
+ null: "null",
2132
2142
  undefined: "tan\u0131ms\u0131z",
2133
2143
  it: "o",
2134
2144
  its: "onun",
@@ -2362,12 +2372,13 @@ var id = {
2362
2372
  ms: "ms",
2363
2373
  s: "d",
2364
2374
  min: "mnt",
2365
- h: "j"
2375
+ h: "j",
2376
+ times: "kali"
2366
2377
  },
2367
2378
  values: {
2368
2379
  true: "benar",
2369
2380
  false: "salah",
2370
- null: "kosong",
2381
+ null: "null",
2371
2382
  undefined: "tidak_terdefinisi",
2372
2383
  it: "itu",
2373
2384
  its: "miliknya",
@@ -2579,7 +2590,7 @@ var qu = {
2579
2590
  logical: {
2580
2591
  when: "maykama",
2581
2592
  where: "maypi",
2582
- and: "chaymanta",
2593
+ and: "hinallataq",
2583
2594
  or: "utaq",
2584
2595
  not: "mana",
2585
2596
  is: "kanqa",
@@ -2613,12 +2624,13 @@ var qu = {
2613
2624
  ms: "ms",
2614
2625
  s: "s",
2615
2626
  min: "m",
2616
- h: "h"
2627
+ h: "h",
2628
+ times: "kuti"
2617
2629
  },
2618
2630
  values: {
2619
2631
  true: "cheqaq",
2620
2632
  false: "llulla",
2621
- null: "chusaq",
2633
+ null: "null",
2622
2634
  undefined: "mana_riqsisqa",
2623
2635
  it: "chay",
2624
2636
  its: "chaypaq",
@@ -2858,12 +2870,13 @@ var sw = {
2858
2870
  ms: "ms",
2859
2871
  s: "s",
2860
2872
  min: "dk",
2861
- h: "sa"
2873
+ h: "sa",
2874
+ times: "mara"
2862
2875
  },
2863
2876
  values: {
2864
2877
  true: "kweli",
2865
2878
  false: "uongo",
2866
- null: "tupu",
2879
+ null: "null",
2867
2880
  undefined: "haijafafanuliwa",
2868
2881
  it: "hiyo",
2869
2882
  its: "yake",
@@ -3089,7 +3102,8 @@ var pt = {
3089
3102
  ms: "ms",
3090
3103
  s: "s",
3091
3104
  min: "min",
3092
- h: "h"
3105
+ h: "h",
3106
+ times: "vezes"
3093
3107
  },
3094
3108
  values: {
3095
3109
  true: "verdadeiro",
@@ -3307,7 +3321,8 @@ var it = {
3307
3321
  ms: "ms",
3308
3322
  s: "s",
3309
3323
  min: "min",
3310
- h: "h"
3324
+ h: "h",
3325
+ times: "volte"
3311
3326
  },
3312
3327
  values: {
3313
3328
  true: "vero",
@@ -3752,7 +3767,8 @@ var pl = {
3752
3767
  ms: "ms",
3753
3768
  s: "s",
3754
3769
  min: "min",
3755
- h: "godz"
3770
+ h: "godz",
3771
+ times: "razy"
3756
3772
  },
3757
3773
  values: {
3758
3774
  true: "prawda",
@@ -3986,7 +4002,8 @@ var russianDictionary = {
3986
4002
  forever: "\u0432\u0441\u0435\u0433\u0434\u0430",
3987
4003
  once: "\u043E\u0434\u043D\u0430\u0436\u0434\u044B",
3988
4004
  every: "\u043A\u0430\u0436\u0434\u044B\u0439",
3989
- until: "\u0434\u043E"
4005
+ until: "\u0434\u043E",
4006
+ times: "\u0440\u0430\u0437"
3990
4007
  },
3991
4008
  values: {
3992
4009
  true: "\u0438\u0441\u0442\u0438\u043D\u0430",
@@ -4233,7 +4250,8 @@ var ukrainianDictionary = {
4233
4250
  forever: "\u0437\u0430\u0432\u0436\u0434\u0438",
4234
4251
  once: "\u043E\u0434\u0438\u043D_\u0440\u0430\u0437",
4235
4252
  every: "\u043A\u043E\u0436\u043D\u0438\u0439",
4236
- until: "\u0434\u043E"
4253
+ until: "\u0434\u043E",
4254
+ times: "\u0440\u0430\u0437\u0456\u0432"
4237
4255
  },
4238
4256
  values: {
4239
4257
  true: "\u0456\u0441\u0442\u0438\u043D\u0430",
@@ -4478,12 +4496,13 @@ var hindiDictionary = {
4478
4496
  forever: "\u0939\u092E\u0947\u0936\u093E",
4479
4497
  once: "\u090F\u0915_\u092C\u093E\u0930",
4480
4498
  every: "\u0939\u0930",
4481
- until: "\u0924\u0915"
4499
+ until: "\u0924\u0915",
4500
+ times: "\u092C\u093E\u0930"
4482
4501
  },
4483
4502
  values: {
4484
4503
  true: "\u0938\u091A",
4485
4504
  false: "\u091D\u0942\u0920",
4486
- null: "\u0916\u093E\u0932\u0940",
4505
+ null: "null",
4487
4506
  undefined: "\u0905\u092A\u0930\u093F\u092D\u093E\u0937\u093F\u0924",
4488
4507
  it: "\u092F\u0939",
4489
4508
  its: "\u0907\u0938\u0915\u093E",
@@ -4540,7 +4559,7 @@ var hindiDictionary = {
4540
4559
  parent: "\u092E\u0942\u0932",
4541
4560
  children: "\u092C\u091A\u094D\u091A\u0947",
4542
4561
  within: "\u0915\u0947_\u0905\u0902\u0926\u0930",
4543
- no: "\u0928\u0939\u0940\u0902",
4562
+ no: "\u0915\u094B\u0908 \u0928\u0939\u0940\u0902",
4544
4563
  empty: "\u0916\u093E\u0932\u0940",
4545
4564
  some: "\u0915\u0941\u091B",
4546
4565
  "starts with": "\u0938\u0947_\u0936\u0941\u0930\u0942",
@@ -4870,7 +4889,7 @@ var thaiDictionary = {
4870
4889
  empty: "\u0E27\u0E48\u0E32\u0E07",
4871
4890
  true: "\u0E08\u0E23\u0E34\u0E07",
4872
4891
  false: "\u0E40\u0E17\u0E47\u0E08",
4873
- null: "\u0E27\u0E48\u0E32\u0E07",
4892
+ null: "null",
4874
4893
  undefined: "\u0E44\u0E21\u0E48\u0E01\u0E33\u0E2B\u0E19\u0E14",
4875
4894
  end: "\u0E08\u0E1A",
4876
4895
  then: "\u0E41\u0E25\u0E49\u0E27",
@@ -5322,7 +5341,9 @@ var tagalogDictionary = {
5322
5341
  exists: "may",
5323
5342
  matches: "tumutugma",
5324
5343
  contains: "naglalaman",
5325
- includes: "kasama",
5344
+ // `includes` takes `contains`' word: both engines read them as one operator,
5345
+ // and `kasama` is `inclusive` (pick's range word), which the reader takes it for.
5346
+ includes: "naglalaman",
5326
5347
  equals: "katumbas",
5327
5348
  has: "may",
5328
5349
  have: "may",
@@ -5512,7 +5533,9 @@ var he = {
5512
5533
  when: "\u05DB\u05D0\u05E9\u05E8",
5513
5534
  where: "\u05D0\u05D9\u05E4\u05D4"
5514
5535
  },
5515
- temporal: {},
5536
+ temporal: {
5537
+ times: "\u05E4\u05E2\u05DE\u05D9\u05DD"
5538
+ },
5516
5539
  values: {
5517
5540
  body: "\u05D2\u05D5\u05E3",
5518
5541
  event: "\u05D0\u05D9\u05E8\u05D5\u05E2",