lino-i18n 0.2.0 → 0.4.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/CHANGELOG.md +40 -0
- package/README.md +106 -1
- package/bin/lino-i18n.js +67 -34
- package/package.json +226 -20
- package/src/browser.d.ts +58 -0
- package/src/browser.js +58 -0
- package/src/catalogs.js +512 -0
- package/src/compiler.d.ts +53 -0
- package/src/compiler.js +72 -0
- package/src/content.js +135 -0
- package/src/converters/react-intl.js +10 -26
- package/src/dictionary.js +169 -0
- package/src/eslint.d.ts +15 -0
- package/src/eslint.js +244 -0
- package/src/extract-bindings.js +41 -0
- package/src/extract-derived.js +85 -0
- package/src/extract-dictionary.js +122 -0
- package/src/extract-jsx.js +176 -0
- package/src/extract-project.js +314 -0
- package/src/extract.js +365 -0
- package/src/format.js +23 -23
- package/src/i18n.js +4 -29
- package/src/index.d.ts +25 -7
- package/src/index.js +13 -2
- package/src/intl.d.ts +176 -0
- package/src/intl.js +407 -0
- package/src/language.js +46 -0
- package/src/loaders.js +9 -481
- package/src/message-schema.js +26 -0
- package/src/messages.d.ts +187 -0
- package/src/messages.js +397 -0
- package/src/native-state.js +72 -0
- package/src/next/client.d.ts +62 -0
- package/src/next/client.js +159 -0
- package/src/next/proxy.d.ts +17 -0
- package/src/next/proxy.js +39 -0
- package/src/next/server.d.ts +28 -0
- package/src/next/server.js +101 -0
- package/src/node-i18n.js +25 -0
- package/src/node.d.ts +37 -0
- package/src/node.js +61 -0
- package/src/providers/gt-locales.d.ts +2 -0
- package/src/providers/gt-locales.js +5 -0
- package/src/providers/gt.d.ts +75 -0
- package/src/providers/gt.js +158 -0
- package/src/python-extract.d.ts +16 -0
- package/src/python-extract.js +134 -0
- package/src/python-extract.py +300 -0
- package/src/react-content.js +69 -0
- package/src/react-native.d.ts +92 -0
- package/src/react-native.js +110 -0
- package/src/react-server.d.ts +14 -0
- package/src/react-server.js +28 -0
- package/src/react.d.ts +112 -9
- package/src/react.js +162 -8
- package/src/remark.d.ts +11 -0
- package/src/remark.js +35 -0
- package/src/rrweb/catalog.d.ts +29 -0
- package/src/rrweb/catalog.js +158 -0
- package/src/rrweb/harvest.d.ts +24 -0
- package/src/rrweb/harvest.js +102 -0
- package/src/rrweb/index.d.ts +36 -0
- package/src/rrweb/index.js +135 -0
- package/src/rrweb/replay.d.ts +1 -0
- package/src/rrweb/replay.js +3 -0
- package/src/server.d.ts +26 -0
- package/src/server.js +137 -0
- package/src/source-project-files.js +170 -0
- package/src/static-values.js +122 -0
- package/src/tanstack-start/client.d.ts +20 -0
- package/src/tanstack-start/client.js +97 -0
- package/src/tanstack-start/server.d.ts +19 -0
- package/src/tanstack-start/server.js +41 -0
- package/src/tooling-files.js +134 -0
- package/src/tooling.d.ts +56 -0
- package/src/tooling.js +90 -0
- package/src/transform-jsx.js +236 -0
- package/src/vue-content.js +82 -0
- package/src/vue-extract.d.ts +8 -0
- package/src/vue-extract.js +303 -0
- package/src/vue.d.ts +120 -0
- package/src/vue.js +309 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# lino-i18n Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add source-message and ICU translation, rich React content and branches,
|
|
8
|
+
request-isolated server helpers, locale utilities, lazy catalog caching,
|
|
9
|
+
AST extraction, catalog validation, provider-based translation candidates,
|
|
10
|
+
and a Vite/Rollup extraction plugin over Links Notation.
|
|
11
|
+
Add finite static derivation, ICU dictionaries and source-change review checks.
|
|
12
|
+
Add typed dictionary schemas, canonical/custom locale configuration, scoped Node
|
|
13
|
+
request access, automatic JSX/attribute compilation and an optional GT SDK bridge.
|
|
14
|
+
Round-trip quoted source keys without interpreting prototype property names.
|
|
15
|
+
Preserve complete ICU semantics when converting compiled FormatJS catalogs.
|
|
16
|
+
|
|
17
|
+
Add an optional Next 16 App Router adapter for request-scoped server access, hydration, locale proxy/cookies, localized navigation, static params and SEO, verified with a production build and browser tests.
|
|
18
|
+
|
|
19
|
+
Resolve shared translator factories, imported finite derivation and dictionary schemas through bounded static module graphs in the CLI and Vite/Rollup plugin.
|
|
20
|
+
|
|
21
|
+
Add optional Vue 3.5 reactive source components, formatting, lazy initialization and SSR snapshots, plus SFC/module-aware extraction and CLI integration with compiler and browser regression coverage.
|
|
22
|
+
|
|
23
|
+
Add bounded Python AST extraction into shared manifests, optional upstream Markdown helpers with safe entity serialization, and a GT service locale registry bridge.
|
|
24
|
+
|
|
25
|
+
Add an injected React Native Text adapter with rich content, native formatter wrappers, headless selectors, serialized locale persistence and matching JSX extraction.
|
|
26
|
+
|
|
27
|
+
Add optional TanStack Start request middleware and Router hydration/navigation adapters, verified with actual server functions, a production build and browser tests.
|
|
28
|
+
|
|
29
|
+
Add optional rrweb recording/replay over `.lino` catalogs using the published GT player/recorder, bounded ICU harvesting, stable variable leaves and protected source values, with an actual browser privacy/playback regression.
|
|
30
|
+
|
|
31
|
+
Add an optional ESLint flat-config plugin sharing the static extractor, with source/JSX/headless-Branch diagnostics, explicit named-variable suggestions and bounded analysis.
|
|
32
|
+
|
|
33
|
+
Repair release verification and CI change detection, audit dependencies, and preserve translation behavior while resolving lint warnings.
|
|
34
|
+
|
|
35
|
+
Update all JavaScript dependencies to their latest releases (`links-notation` 0.23, `lino-objects-codec` 0.9, ESLint 10.12, Prettier 3.9, Playwright 1.64, React 19.3 typings) and raise the supported Node.js floor to 22.11, which `lino-objects-codec` 0.9 requires; Node.js 20 reached end of life on 2026-04-30.
|
|
36
|
+
|
|
37
|
+
## 0.3.0
|
|
38
|
+
|
|
39
|
+
### Minor Changes
|
|
40
|
+
|
|
41
|
+
- f73aa48: Add a tree-shakeable browser entry point with URL-based Links Notation catalog loading, navigator language detection, and the shared translation runtime.
|
|
42
|
+
|
|
3
43
|
## 0.2.0
|
|
4
44
|
|
|
5
45
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -7,12 +7,45 @@
|
|
|
7
7
|
Universal internationalization for JavaScript with translations stored in
|
|
8
8
|
[Links Notation](https://github.com/linksplatform/Protocols.Lino) (`.lino`).
|
|
9
9
|
|
|
10
|
-
Runs on Node.js (≥
|
|
10
|
+
Runs on Node.js (≥ 22.11), Bun, Deno, and bundlers like Vite/Webpack/esbuild.
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
13
|
npm install lino-i18n
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
## Source messages and tooling
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
import { createTranslator, msg } from 'lino-i18n/messages';
|
|
20
|
+
const i18n = createTranslator({
|
|
21
|
+
locales: { fr: { greeting: 'Bonjour {name}' } },
|
|
22
|
+
defaultLocale: 'fr',
|
|
23
|
+
});
|
|
24
|
+
i18n.gt(msg('Hello {name}', { id: 'greeting' }), { name: 'Ada' });
|
|
25
|
+
i18n.gt('{n, plural, one {# file} other {# files}}', { n: 2 });
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`lino-i18n/react` provides source `T`, `Var`, `Derive`, `Branch`, `Plural` and
|
|
29
|
+
formatting components alongside the existing keyed adapter. Optional exports
|
|
30
|
+
include `messages`, `intl`, `server`, `react-server`, `tooling` and `compiler`.
|
|
31
|
+
[Optional Vue components and SFC extraction](../docs/vue.md) provide reactive
|
|
32
|
+
source messages, SSR/hydration and template-scope diagnostics.
|
|
33
|
+
[TanStack Start integration](../docs/tanstack-start.md) adds request middleware,
|
|
34
|
+
server functions, loader snapshots and localized Router navigation.
|
|
35
|
+
The native browser entry retains its dependency-free keyed runtime; source ICU
|
|
36
|
+
and React browser applications use a bundler.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
lino-i18n extract --in src --out locales --locale en
|
|
40
|
+
lino-i18n check --dir locales --manifest locales/messages.json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The complete [source-message guide](../docs/source-messages.md)
|
|
44
|
+
covers dictionaries, static derivation, provider candidates, versioned loading,
|
|
45
|
+
request isolation and snapshot hydration. The
|
|
46
|
+
[GT capability study](../docs/case-studies/issue-25/README.md)
|
|
47
|
+
records supported workflows and remaining ecosystem integrations.
|
|
48
|
+
|
|
16
49
|
## Usage
|
|
17
50
|
|
|
18
51
|
```js
|
|
@@ -33,6 +66,64 @@ i18n.t('role', { context: 'female' }); // → "She is a developer"
|
|
|
33
66
|
i18n.t('telegram.help.solve.alias.detail'); // → "Tool aliases imply `--tool <tool>`"
|
|
34
67
|
```
|
|
35
68
|
|
|
69
|
+
## Browser
|
|
70
|
+
|
|
71
|
+
Import `lino-i18n/browser` for native ES modules or browser bundles. This
|
|
72
|
+
entry point has no Node built-ins and uses the same translation engine and
|
|
73
|
+
`t(key, params, options)` API as the main entry point:
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
import { createI18n, detectLanguage, loadCatalogs } from 'lino-i18n/browser';
|
|
77
|
+
|
|
78
|
+
const locales = await loadCatalogs(['/locales/en.lino', '/locales/ru.lino']);
|
|
79
|
+
const i18n = createI18n({
|
|
80
|
+
locales,
|
|
81
|
+
defaultLocale: detectLanguage('auto', {
|
|
82
|
+
supportedLanguages: Object.keys(locales),
|
|
83
|
+
defaultLocale: 'en',
|
|
84
|
+
}),
|
|
85
|
+
fallback: ['en'],
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
i18n.t('greeting', { name: 'Ada' });
|
|
89
|
+
i18n.setLocale('ru');
|
|
90
|
+
i18n.t('greeting', { name: 'Ada' });
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`loadCatalogs(urls, options)` fetches URLs concurrently and merges every locale
|
|
94
|
+
root in URL order. Later catalogs override earlier values for matching keys.
|
|
95
|
+
It returns locale tables ready for `createI18n`; errors reject the promise and
|
|
96
|
+
identify the failing URL. `options.requestInit` forwards fetch options such as
|
|
97
|
+
`cache`, `credentials`, and `signal`. `options.fetch` overrides the platform
|
|
98
|
+
fetch, and `options.compatibilityAliases` enables migration aliases after merging.
|
|
99
|
+
|
|
100
|
+
`detectLanguage(preference, options)` checks an explicit preference first, then
|
|
101
|
+
`navigator.languages` in preference order. It uses `navigator.language` when
|
|
102
|
+
the language list is empty. `resolveLanguage(preference, candidates, options)`
|
|
103
|
+
performs the same matching with a supplied list, without reading the navigator.
|
|
104
|
+
Both accept `supportedLanguages` (default `['en']`) and `defaultLocale` (default
|
|
105
|
+
`'en'`). Tags are compared without case sensitivity, underscores become hyphens,
|
|
106
|
+
and exact tags are tried before parent tags (`pt-BR` before `pt`). An unsupported
|
|
107
|
+
preference or `'auto'` defers to candidates, then the default locale, then the
|
|
108
|
+
first supported locale. With no supported locales, the default is returned.
|
|
109
|
+
Detection also works in environments without a navigator.
|
|
110
|
+
|
|
111
|
+
The browser instance includes `subscribe`, `addLocale`, and `loadLocale` and
|
|
112
|
+
works with `lino-i18n/react`. File methods `loadLocaleFile` and `loadDirectory`
|
|
113
|
+
are available through the main entry point. URL loading stays explicit: fetch
|
|
114
|
+
more catalogs with `loadCatalogs`, then register their tables with `addLocale`.
|
|
115
|
+
ES module exports and `sideEffects: false` let bundlers remove unused helpers.
|
|
116
|
+
For TypeScript browser hooks, pass the exported `I18nCoreInstance` type to
|
|
117
|
+
`useI18n<I18nCoreInstance>()` or `useTranslation<I18nCoreInstance>()`. Their
|
|
118
|
+
default type preserves the main entry point's existing file-loading API.
|
|
119
|
+
|
|
120
|
+
Run the static browser example from `js/`:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
node examples/browser-usage/server.mjs
|
|
124
|
+
# Open http://127.0.0.1:4173/examples/browser-usage/
|
|
125
|
+
```
|
|
126
|
+
|
|
36
127
|
## React
|
|
37
128
|
|
|
38
129
|
React is an optional peer dependency. The `lino-i18n/react` adapter uses the
|
|
@@ -191,9 +282,23 @@ Run `npx lino-i18n --help` for every option.
|
|
|
191
282
|
|
|
192
283
|
```bash
|
|
193
284
|
npm test # node --test --test-timeout=30000 tests/*.test.js
|
|
285
|
+
npm run test:types # browser and React TypeScript API checks
|
|
286
|
+
npx playwright install chromium
|
|
287
|
+
npm run test:browser # real browser catalog loading and runtime language switching
|
|
194
288
|
```
|
|
195
289
|
|
|
196
290
|
## License
|
|
197
291
|
|
|
198
292
|
Released into the public domain under the
|
|
199
293
|
[Unlicense](https://unlicense.org/).
|
|
294
|
+
|
|
295
|
+
See [Python extraction, Markdown helpers and GT locale data](../docs/ecosystem-tools.md) for optional source and content tools.
|
|
296
|
+
|
|
297
|
+
See [React Native source messages](../docs/react-native.md) for native text,
|
|
298
|
+
formatters, selectors and persisted locale choices.
|
|
299
|
+
|
|
300
|
+
See [session recording and replay](../docs/rrweb.md) for the optional published GT recorder/player, `.lino` overlays and protected recorded variables.
|
|
301
|
+
|
|
302
|
+
See [source-message lint rules](../docs/eslint.md) for optional ESLint diagnostics.
|
|
303
|
+
The [Sanity investigation](../docs/sanity.md) records a deferred integration and
|
|
304
|
+
the upstream dependency-review blocker.
|
package/bin/lino-i18n.js
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// `lino-i18n` command-line entry point.
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
// priority chain as the rest of the Link Foundation stack: CLI flags
|
|
7
|
-
// > environment variables > config file > defaults.
|
|
5
|
+
// Configuration priority: CLI flags > JSON `--config` file > defaults.
|
|
8
6
|
|
|
9
7
|
import { promises as fs } from 'node:fs';
|
|
10
8
|
import path from 'node:path';
|
|
@@ -32,12 +30,20 @@ function usage() {
|
|
|
32
30
|
' convert Convert i18next / i18n-js / react-intl JSON files to .lino',
|
|
33
31
|
' check Compare locales against a reference locale and report missing keys',
|
|
34
32
|
' t Translate a key from the CLI for quick debugging',
|
|
33
|
+
' extract Extract source messages and JSX to .lino and a manifest',
|
|
34
|
+
' translate-catalog Generate validated candidates with a provider module',
|
|
35
35
|
'',
|
|
36
36
|
'Run `lino-i18n <command> --help` for command-specific options.',
|
|
37
37
|
].join('\n');
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
function commandHelp(command) {
|
|
41
|
+
if (command === 'extract') {
|
|
42
|
+
return 'Usage: lino-i18n extract --in <source file or directory> --out <directory> [--locale en] [--syntax js|vue|python] [--max-files 1000] [--max-bytes 10485760]';
|
|
43
|
+
}
|
|
44
|
+
if (command === 'translate-catalog') {
|
|
45
|
+
return 'Usage: lino-i18n translate-catalog --manifest <messages.json> --dir <catalogs> --locale <locale> --provider <module.mjs> --out <locale.lino>';
|
|
46
|
+
}
|
|
41
47
|
if (command === 'convert') {
|
|
42
48
|
return [
|
|
43
49
|
'Usage: lino-i18n convert --in <path> --out <dir> [options]',
|
|
@@ -60,6 +66,8 @@ function commandHelp(command) {
|
|
|
60
66
|
' --dir <dir> Directory containing .lino files',
|
|
61
67
|
' --reference <locale> Reference locale to diff against (default: en)',
|
|
62
68
|
' --config <path> Read command defaults from a JSON config file',
|
|
69
|
+
' --manifest <path> Validate ICU syntax and variables against extraction',
|
|
70
|
+
' --previous-manifest <path> Flag stable ids whose source changed for review',
|
|
63
71
|
].join('\n');
|
|
64
72
|
}
|
|
65
73
|
if (command === 't') {
|
|
@@ -175,6 +183,27 @@ async function readJsonInput(inputPath) {
|
|
|
175
183
|
return out;
|
|
176
184
|
}
|
|
177
185
|
|
|
186
|
+
function convertInputs(inputs, requestedFormat, flags, err) {
|
|
187
|
+
const aggregated = {};
|
|
188
|
+
for (const { data, baseName } of inputs) {
|
|
189
|
+
const format = requestedFormat || detectFormat(data);
|
|
190
|
+
const convert = pickConverter(format);
|
|
191
|
+
if (!convert) {
|
|
192
|
+
err(`lino-i18n convert: no converter for format '${format}'`);
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const result = convert(data, {
|
|
196
|
+
locale: flags.locale || baseName,
|
|
197
|
+
defaultLocale: flags.default || 'en',
|
|
198
|
+
});
|
|
199
|
+
for (const [locale, table] of Object.entries(result)) {
|
|
200
|
+
aggregated[locale] = { ...(aggregated[locale] || {}), ...table };
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return aggregated;
|
|
205
|
+
}
|
|
206
|
+
|
|
178
207
|
async function commandConvert(flags, log = console.log, err = console.error) {
|
|
179
208
|
if (!flags.in || !flags.out) {
|
|
180
209
|
err('lino-i18n convert: --in and --out are required');
|
|
@@ -196,21 +225,9 @@ async function commandConvert(flags, log = console.log, err = console.error) {
|
|
|
196
225
|
return 1;
|
|
197
226
|
}
|
|
198
227
|
|
|
199
|
-
const aggregated =
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const convert = pickConverter(format);
|
|
203
|
-
if (!convert) {
|
|
204
|
-
err(`lino-i18n convert: no converter for format '${format}'`);
|
|
205
|
-
return 1;
|
|
206
|
-
}
|
|
207
|
-
const result = convert(data, {
|
|
208
|
-
locale: flags.locale || baseName,
|
|
209
|
-
defaultLocale: flags.default || 'en',
|
|
210
|
-
});
|
|
211
|
-
for (const [locale, table] of Object.entries(result)) {
|
|
212
|
-
aggregated[locale] = { ...(aggregated[locale] || {}), ...table };
|
|
213
|
-
}
|
|
228
|
+
const aggregated = convertInputs(inputs, requestedFormat, flags, err);
|
|
229
|
+
if (!aggregated) {
|
|
230
|
+
return 1;
|
|
214
231
|
}
|
|
215
232
|
|
|
216
233
|
const singleFile = flagValue(flags, 'single-file', 'singleFile');
|
|
@@ -241,6 +258,15 @@ async function commandCheck(flags, log = console.log, err = console.error) {
|
|
|
241
258
|
}
|
|
242
259
|
const reference = flags.reference || 'en';
|
|
243
260
|
const catalogues = await loadLocalesFromDirectory(flags.dir);
|
|
261
|
+
if (flags.manifest) {
|
|
262
|
+
const { checkManifest } = await import('../src/tooling-files.js');
|
|
263
|
+
return checkManifest(
|
|
264
|
+
flags.manifest,
|
|
265
|
+
catalogues,
|
|
266
|
+
log,
|
|
267
|
+
flags['previous-manifest']
|
|
268
|
+
);
|
|
269
|
+
}
|
|
244
270
|
if (!catalogues[reference]) {
|
|
245
271
|
err(
|
|
246
272
|
`lino-i18n check: reference locale '${reference}' not found in ${flags.dir}`
|
|
@@ -253,18 +279,10 @@ async function commandCheck(flags, log = console.log, err = console.error) {
|
|
|
253
279
|
if (locale === reference) {
|
|
254
280
|
continue;
|
|
255
281
|
}
|
|
256
|
-
const missing = []
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
missing.push(key);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
for (const key of Object.keys(table)) {
|
|
264
|
-
if (!referenceKeys.has(key)) {
|
|
265
|
-
unknown.push(key);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
282
|
+
const missing = [...referenceKeys].filter(
|
|
283
|
+
(key) => !Object.prototype.hasOwnProperty.call(table, key)
|
|
284
|
+
);
|
|
285
|
+
const unknown = Object.keys(table).filter((key) => !referenceKeys.has(key));
|
|
268
286
|
if (missing.length === 0 && unknown.length === 0) {
|
|
269
287
|
continue;
|
|
270
288
|
}
|
|
@@ -339,18 +357,33 @@ export async function runCli(argv, io = {}) {
|
|
|
339
357
|
}
|
|
340
358
|
const configuredFlags = await withConfig(command, flags);
|
|
341
359
|
switch (command) {
|
|
360
|
+
case 'extract': {
|
|
361
|
+
const { commandExtract } = await import('../src/tooling-files.js');
|
|
362
|
+
return commandExtract(configuredFlags, log, err);
|
|
363
|
+
}
|
|
364
|
+
case 'translate-catalog': {
|
|
365
|
+
const { commandTranslateCatalog } =
|
|
366
|
+
await import('../src/tooling-files.js');
|
|
367
|
+
return commandTranslateCatalog(configuredFlags, log, err);
|
|
368
|
+
}
|
|
342
369
|
case 'convert':
|
|
343
370
|
return commandConvert(configuredFlags, log, err);
|
|
344
371
|
case 'check':
|
|
345
372
|
return commandCheck(configuredFlags, log, err);
|
|
346
373
|
case 't':
|
|
347
|
-
case 'translate':
|
|
348
374
|
return commandTranslate(configuredFlags, positional, log, err);
|
|
349
375
|
default:
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
376
|
+
return unknownCommand(command, configuredFlags, positional, log, err);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function unknownCommand(command, flags, rest, log, err) {
|
|
381
|
+
if (command === 'translate') {
|
|
382
|
+
return commandTranslate(flags, rest, log, err);
|
|
353
383
|
}
|
|
384
|
+
err(`Unknown command: ${command}`);
|
|
385
|
+
err(usage());
|
|
386
|
+
return 1;
|
|
354
387
|
}
|
|
355
388
|
|
|
356
389
|
function isCliEntryPoint() {
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lino-i18n",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Universal i18n library that stores translations in Links Notation (.lino) instead of JSON.",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
6
7
|
"main": "./src/index.js",
|
|
7
8
|
"types": "./src/index.d.ts",
|
|
8
9
|
"bin": {
|
|
@@ -22,23 +23,130 @@
|
|
|
22
23
|
},
|
|
23
24
|
"./converters": "./src/converters/index.js",
|
|
24
25
|
"./loaders": "./src/loaders.js",
|
|
26
|
+
"./browser": {
|
|
27
|
+
"types": "./src/browser.d.ts",
|
|
28
|
+
"import": "./src/browser.js"
|
|
29
|
+
},
|
|
25
30
|
"./react": {
|
|
26
31
|
"types": "./src/react.d.ts",
|
|
27
32
|
"import": "./src/react.js"
|
|
33
|
+
},
|
|
34
|
+
"./messages": {
|
|
35
|
+
"types": "./src/messages.d.ts",
|
|
36
|
+
"import": "./src/messages.js"
|
|
37
|
+
},
|
|
38
|
+
"./intl": {
|
|
39
|
+
"types": "./src/intl.d.ts",
|
|
40
|
+
"import": "./src/intl.js"
|
|
41
|
+
},
|
|
42
|
+
"./server": {
|
|
43
|
+
"types": "./src/server.d.ts",
|
|
44
|
+
"import": "./src/server.js"
|
|
45
|
+
},
|
|
46
|
+
"./react-server": {
|
|
47
|
+
"types": "./src/react-server.d.ts",
|
|
48
|
+
"import": "./src/react-server.js"
|
|
49
|
+
},
|
|
50
|
+
"./node": {
|
|
51
|
+
"types": "./src/node.d.ts",
|
|
52
|
+
"import": "./src/node.js"
|
|
53
|
+
},
|
|
54
|
+
"./tooling": {
|
|
55
|
+
"types": "./src/tooling.d.ts",
|
|
56
|
+
"import": "./src/tooling.js"
|
|
57
|
+
},
|
|
58
|
+
"./compiler": {
|
|
59
|
+
"types": "./src/compiler.d.ts",
|
|
60
|
+
"import": "./src/compiler.js"
|
|
61
|
+
},
|
|
62
|
+
"./providers/gt": {
|
|
63
|
+
"types": "./src/providers/gt.d.ts",
|
|
64
|
+
"import": "./src/providers/gt.js"
|
|
65
|
+
},
|
|
66
|
+
"./next/server": {
|
|
67
|
+
"types": "./src/next/server.d.ts",
|
|
68
|
+
"import": "./src/next/server.js"
|
|
69
|
+
},
|
|
70
|
+
"./next/client": {
|
|
71
|
+
"types": "./src/next/client.d.ts",
|
|
72
|
+
"import": "./src/next/client.js"
|
|
73
|
+
},
|
|
74
|
+
"./next/proxy": {
|
|
75
|
+
"types": "./src/next/proxy.d.ts",
|
|
76
|
+
"import": "./src/next/proxy.js"
|
|
77
|
+
},
|
|
78
|
+
"./vue": {
|
|
79
|
+
"types": "./src/vue.d.ts",
|
|
80
|
+
"import": "./src/vue.js"
|
|
81
|
+
},
|
|
82
|
+
"./vue/extract": {
|
|
83
|
+
"types": "./src/vue-extract.d.ts",
|
|
84
|
+
"import": "./src/vue-extract.js"
|
|
85
|
+
},
|
|
86
|
+
"./python/extract": {
|
|
87
|
+
"types": "./src/python-extract.d.ts",
|
|
88
|
+
"import": "./src/python-extract.js"
|
|
89
|
+
},
|
|
90
|
+
"./remark": {
|
|
91
|
+
"types": "./src/remark.d.ts",
|
|
92
|
+
"import": "./src/remark.js"
|
|
93
|
+
},
|
|
94
|
+
"./providers/gt-locales": {
|
|
95
|
+
"types": "./src/providers/gt-locales.d.ts",
|
|
96
|
+
"import": "./src/providers/gt-locales.js"
|
|
97
|
+
},
|
|
98
|
+
"./react-native": {
|
|
99
|
+
"types": "./src/react-native.d.ts",
|
|
100
|
+
"import": "./src/react-native.js"
|
|
101
|
+
},
|
|
102
|
+
"./tanstack-start/server": {
|
|
103
|
+
"types": "./src/tanstack-start/server.d.ts",
|
|
104
|
+
"import": "./src/tanstack-start/server.js"
|
|
105
|
+
},
|
|
106
|
+
"./tanstack-start/client": {
|
|
107
|
+
"types": "./src/tanstack-start/client.d.ts",
|
|
108
|
+
"import": "./src/tanstack-start/client.js"
|
|
109
|
+
},
|
|
110
|
+
"./rrweb": {
|
|
111
|
+
"types": "./src/rrweb/index.d.ts",
|
|
112
|
+
"import": "./src/rrweb/index.js"
|
|
113
|
+
},
|
|
114
|
+
"./rrweb/catalog": {
|
|
115
|
+
"types": "./src/rrweb/catalog.d.ts",
|
|
116
|
+
"import": "./src/rrweb/catalog.js"
|
|
117
|
+
},
|
|
118
|
+
"./rrweb/harvest": {
|
|
119
|
+
"types": "./src/rrweb/harvest.d.ts",
|
|
120
|
+
"import": "./src/rrweb/harvest.js"
|
|
121
|
+
},
|
|
122
|
+
"./rrweb/replay": {
|
|
123
|
+
"types": "./src/rrweb/replay.d.ts",
|
|
124
|
+
"import": "./src/rrweb/replay.js"
|
|
125
|
+
},
|
|
126
|
+
"./eslint": {
|
|
127
|
+
"types": "./src/eslint.d.ts",
|
|
128
|
+
"import": "./src/eslint.js"
|
|
28
129
|
}
|
|
29
130
|
},
|
|
30
131
|
"scripts": {
|
|
31
|
-
"test": "node --test --test-timeout=30000 tests/*.test.js",
|
|
32
|
-
"
|
|
132
|
+
"test": "node --throw-deprecation --test --test-timeout=30000 tests/*.test.js",
|
|
133
|
+
"test:browser": "playwright test",
|
|
134
|
+
"test:types": "tsc --project tests/types/tsconfig.json && tsc --project tests/types/tsconfig.next.json && tsc --project tests/types/tsconfig.native.json && tsc --project tests/types/tsconfig.tanstack.json && tsc --project tests/types/tsconfig.rrweb.json",
|
|
135
|
+
"lint": "eslint . --max-warnings 0",
|
|
33
136
|
"lint:fix": "eslint . --fix",
|
|
34
137
|
"format": "prettier --write .",
|
|
35
138
|
"format:check": "prettier --check .",
|
|
36
|
-
"check:duplication": "jscpd .",
|
|
139
|
+
"check:duplication": "jscpd --fail-on-empty .",
|
|
37
140
|
"check": "npm run lint && npm run format:check && npm run check:duplication",
|
|
38
141
|
"changeset": "changeset",
|
|
39
|
-
"changeset:version": "changeset
|
|
142
|
+
"changeset:version": "node scripts/changeset-version.mjs",
|
|
40
143
|
"changeset:publish": "changeset publish",
|
|
41
|
-
"pack:dry-run": "npm pack --dry-run"
|
|
144
|
+
"pack:dry-run": "npm pack --dry-run",
|
|
145
|
+
"lint:secrets": "secretlint \"bin/**\" \"src/**\" \"scripts/**\" \"tests/**\" \"../scripts/**\" \"../rust/scripts/**\" \"../rust/lino-i18n/src/**\" \"../rust/lino-i18n/tests/**\" \"../rust/lino-i18n-macros/src/**\" \"../.github/**\" \"../.githooks/**\"",
|
|
146
|
+
"test:next": "playwright test --config playwright-next.config.js",
|
|
147
|
+
"build:next": "next build examples/next-usage --webpack",
|
|
148
|
+
"build:tanstack": "vite build --config examples/tanstack-usage/vite.config.js",
|
|
149
|
+
"test:tanstack": "playwright test --config playwright-tanstack.config.js"
|
|
42
150
|
},
|
|
43
151
|
"keywords": [
|
|
44
152
|
"i18n",
|
|
@@ -63,33 +171,131 @@
|
|
|
63
171
|
"provenance": true
|
|
64
172
|
},
|
|
65
173
|
"engines": {
|
|
66
|
-
"node": ">=
|
|
174
|
+
"node": ">=22.11.0"
|
|
67
175
|
},
|
|
68
176
|
"dependencies": {
|
|
69
|
-
"
|
|
177
|
+
"@babel/generator": "^7.29.8",
|
|
178
|
+
"@babel/parser": "^7.29.9",
|
|
179
|
+
"@babel/traverse": "^7.29.10",
|
|
180
|
+
"@babel/types": "^7.29.8",
|
|
181
|
+
"@formatjs/icu-messageformat-parser": "^3.5.21",
|
|
182
|
+
"intl-messageformat": "^12.1.3",
|
|
183
|
+
"links-notation": "^0.23.0",
|
|
70
184
|
"lino-arguments": "^0.3.0",
|
|
71
|
-
"lino-objects-codec": "^0.
|
|
185
|
+
"lino-objects-codec": "^0.9.0"
|
|
72
186
|
},
|
|
73
187
|
"devDependencies": {
|
|
74
|
-
"@
|
|
188
|
+
"@babel/core": "^8.0.7",
|
|
189
|
+
"@babel/eslint-parser": "^8.0.7",
|
|
190
|
+
"@changesets/cli": "^3.0.3",
|
|
75
191
|
"@eslint/js": "^10.0.1",
|
|
76
|
-
"@
|
|
77
|
-
"@
|
|
78
|
-
"
|
|
192
|
+
"@generaltranslation/supported-locales": "2.1.41",
|
|
193
|
+
"@playwright/test": "^1.64.0",
|
|
194
|
+
"@rrweb/record": "2.1.7",
|
|
195
|
+
"@rrweb/replay": "2.1.7",
|
|
196
|
+
"@rrweb/types": "2.1.7",
|
|
197
|
+
"@secretlint/secretlint-rule-preset-recommend": "^13.0.7",
|
|
198
|
+
"@tanstack/react-router": "1.170.41",
|
|
199
|
+
"@tanstack/react-start": "1.168.60",
|
|
200
|
+
"@testing-library/react": "^16.3.3",
|
|
201
|
+
"@types/eslint": "^9.6.1",
|
|
202
|
+
"@types/node": "^26.6.4",
|
|
203
|
+
"@types/react": "^19.3.0",
|
|
204
|
+
"@vitejs/plugin-react": "6.1.2",
|
|
205
|
+
"@vue/compiler-sfc": "3.5.43",
|
|
206
|
+
"@vue/server-renderer": "3.5.43",
|
|
207
|
+
"esbuild": "^0.28.2",
|
|
208
|
+
"eslint": "^10.12.0",
|
|
79
209
|
"eslint-config-prettier": "^10.1.8",
|
|
80
|
-
"eslint-plugin-prettier": "^5.5.
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
210
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
211
|
+
"eslint9": "npm:eslint@^9.39.5",
|
|
212
|
+
"generaltranslation": "9.5.5",
|
|
213
|
+
"gt-remark": "1.0.12",
|
|
214
|
+
"gt-rrweb": "0.2.0",
|
|
215
|
+
"jscpd": "^5.4.0",
|
|
216
|
+
"jsdom": "^30.1.2",
|
|
217
|
+
"next": "16.4.0",
|
|
218
|
+
"prettier": "^3.9.9",
|
|
219
|
+
"react": "^19.3.0",
|
|
220
|
+
"react-dom": "^19.3.0",
|
|
221
|
+
"react-native-web": "0.21.4",
|
|
222
|
+
"remark-mdx": "3.1.1",
|
|
223
|
+
"remark-parse": "11.0.0",
|
|
224
|
+
"remark-stringify": "11.0.0",
|
|
225
|
+
"rollup": "^4.64.2",
|
|
226
|
+
"secretlint": "^13.0.7",
|
|
227
|
+
"srvx": "0.11.22",
|
|
228
|
+
"test-anywhere": "^0.9.1",
|
|
229
|
+
"typescript": "^7.0.2",
|
|
230
|
+
"unified": "11.0.5",
|
|
231
|
+
"vite": "8.3.4",
|
|
232
|
+
"vue": "3.5.43"
|
|
86
233
|
},
|
|
87
234
|
"peerDependencies": {
|
|
88
|
-
"
|
|
235
|
+
"@generaltranslation/supported-locales": ">=2.1.41 <3",
|
|
236
|
+
"@rrweb/record": ">=2.1 <3",
|
|
237
|
+
"@rrweb/replay": ">=2.1 <3",
|
|
238
|
+
"@rrweb/types": ">=2.1 <3",
|
|
239
|
+
"@tanstack/react-router": ">=1.170 <2",
|
|
240
|
+
"@tanstack/react-start": ">=1.168 <2",
|
|
241
|
+
"@vue/compiler-sfc": ">=3.5 <4",
|
|
242
|
+
"eslint": ">=9 <11",
|
|
243
|
+
"generaltranslation": ">=9.5.5 <10",
|
|
244
|
+
"gt-remark": ">=1.0.12 <2",
|
|
245
|
+
"gt-rrweb": ">=0.2 <0.3",
|
|
246
|
+
"next": ">=16 <17",
|
|
247
|
+
"react": ">=18.0.0",
|
|
248
|
+
"react-dom": ">=18",
|
|
249
|
+
"vue": ">=3.5 <4"
|
|
89
250
|
},
|
|
90
251
|
"peerDependenciesMeta": {
|
|
252
|
+
"next": {
|
|
253
|
+
"optional": true
|
|
254
|
+
},
|
|
255
|
+
"generaltranslation": {
|
|
256
|
+
"optional": true
|
|
257
|
+
},
|
|
91
258
|
"react": {
|
|
92
259
|
"optional": true
|
|
260
|
+
},
|
|
261
|
+
"vue": {
|
|
262
|
+
"optional": true
|
|
263
|
+
},
|
|
264
|
+
"@vue/compiler-sfc": {
|
|
265
|
+
"optional": true
|
|
266
|
+
},
|
|
267
|
+
"gt-remark": {
|
|
268
|
+
"optional": true
|
|
269
|
+
},
|
|
270
|
+
"@generaltranslation/supported-locales": {
|
|
271
|
+
"optional": true
|
|
272
|
+
},
|
|
273
|
+
"@tanstack/react-start": {
|
|
274
|
+
"optional": true
|
|
275
|
+
},
|
|
276
|
+
"@tanstack/react-router": {
|
|
277
|
+
"optional": true
|
|
278
|
+
},
|
|
279
|
+
"gt-rrweb": {
|
|
280
|
+
"optional": true
|
|
281
|
+
},
|
|
282
|
+
"@rrweb/record": {
|
|
283
|
+
"optional": true
|
|
284
|
+
},
|
|
285
|
+
"@rrweb/replay": {
|
|
286
|
+
"optional": true
|
|
287
|
+
},
|
|
288
|
+
"@rrweb/types": {
|
|
289
|
+
"optional": true
|
|
290
|
+
},
|
|
291
|
+
"react-dom": {
|
|
292
|
+
"optional": true
|
|
293
|
+
},
|
|
294
|
+
"eslint": {
|
|
295
|
+
"optional": true
|
|
93
296
|
}
|
|
297
|
+
},
|
|
298
|
+
"allowScripts": {
|
|
299
|
+
"esbuild@0.28.2": true
|
|
94
300
|
}
|
|
95
301
|
}
|