@prettifystudio/lyngo-cli 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -5
- package/bin/lyngo +47 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,6 +45,9 @@ already set up.
|
|
|
45
45
|
- With an agent: build as usual. The hook runs `lyngo localize` at the end of
|
|
46
46
|
every task.
|
|
47
47
|
- Without an agent: run `lyngo localize` before you commit.
|
|
48
|
+
- A repository that was never localized: `lyngo localize --all` once. It walks
|
|
49
|
+
every source file a scan would read, in batches, and leaves the result in
|
|
50
|
+
your working tree to review and commit. No pull request.
|
|
48
51
|
- Anything pushed without it still gets a pull request from the Lyngo GitHub
|
|
49
52
|
App.
|
|
50
53
|
|
|
@@ -56,7 +59,7 @@ already set up.
|
|
|
56
59
|
| `lyngo logout` | Revokes the token and deletes it from this machine |
|
|
57
60
|
| `lyngo whoami` | The account, the token prefix and your workspaces |
|
|
58
61
|
| `lyngo init` | Connects the repository (see above). Flags: `--languages`, `--workspace`, `--yes`, `--github` |
|
|
59
|
-
| `lyngo localize` | Localizes and translates what changed in the working tree. Flags: `--languages`, `--dry` |
|
|
62
|
+
| `lyngo localize` | Localizes and translates what changed in the working tree. Flags: `--all` (the whole repository, in batches of 30), `--languages`, `--no-translate`, `--dry` |
|
|
60
63
|
| `lyngo check <file>` | The user-facing strings of one file |
|
|
61
64
|
| `lyngo status` | The project as Lyngo knows it |
|
|
62
65
|
|
|
@@ -65,12 +68,14 @@ Configuration: `LYNGO_HOST` (default `https://lyngo.app`), `LYNGO_TOKEN`
|
|
|
65
68
|
|
|
66
69
|
## The Claude Code plugin (optional)
|
|
67
70
|
|
|
68
|
-
This repository is also a Claude Code plugin. It adds the
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
This repository is also a Claude Code plugin. It adds the commands
|
|
72
|
+
`/lyngo:init`, `/lyngo:localize`, `/lyngo:status` and `/lyngo:login`, and the
|
|
73
|
+
`lyngo-i18n` skill, which makes the agent check existing keys before it writes
|
|
74
|
+
new text. It needs the `lyngo` command from npm; `lyngo init` prints these two
|
|
75
|
+
lines when the plugin is not installed yet.
|
|
71
76
|
|
|
72
77
|
```bash
|
|
73
|
-
claude plugin marketplace add
|
|
78
|
+
claude plugin marketplace add prettifystudio/lyngo-claude-plugin
|
|
74
79
|
claude plugin install lyngo@lyngo
|
|
75
80
|
```
|
|
76
81
|
|
package/bin/lyngo
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// lyngo whoami who the token belongs to
|
|
9
9
|
// lyngo init [--languages fr,de] [--primary en] [--workspace <name>] [--yes] [--github]
|
|
10
10
|
// connect this repository: project, scaffolding, languages, agent hook
|
|
11
|
-
// lyngo localize [--languages fr,de] [--no-translate] [--dry]
|
|
11
|
+
// lyngo localize [--all] [--languages fr,de] [--no-translate] [--dry]
|
|
12
12
|
// localize (+ translate) the working tree's changes
|
|
13
13
|
// lyngo check <file> the user-facing strings of one file
|
|
14
14
|
// lyngo status the project as Lyngo knows it
|
|
@@ -367,6 +367,11 @@ function setUpClaudeCode(top, remote) {
|
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
369
|
console.log(`Claude Code: the lyngo MCP server is registered for this repository, and the Stop hook ${has ? 'was already' : 'is'} in .claude/settings.local.json.`);
|
|
370
|
+
// The slash commands (/lyngo:localize, /lyngo:init, /lyngo:status) come
|
|
371
|
+
// from the plugin; say how to get it when it is not installed yet.
|
|
372
|
+
let installed = false;
|
|
373
|
+
try { installed = /\blyngo\b/.test(run(['plugin', 'list'])); } catch { /* no plugin support, or none installed */ }
|
|
374
|
+
if (!installed) console.log('Slash commands for Claude Code (/lyngo:localize, /lyngo:init, /lyngo:status): claude plugin marketplace add prettifystudio/lyngo-claude-plugin && claude plugin install lyngo@lyngo');
|
|
370
375
|
}
|
|
371
376
|
|
|
372
377
|
async function init(opts) {
|
|
@@ -621,23 +626,48 @@ function changedFiles(top) {
|
|
|
621
626
|
return [...out].sort();
|
|
622
627
|
}
|
|
623
628
|
|
|
629
|
+
// Every tracked source file of the repository, as the scan would pick them:
|
|
630
|
+
// a quick local cut by extension and folder, then the server's own rules.
|
|
631
|
+
async function allSourceFiles(top) {
|
|
632
|
+
const tracked = git(['ls-files', '-z']).split('\0').filter(Boolean).filter((p) => SRC.test(p) && !SKIP.test(p) && fs.existsSync(path.join(top, p)));
|
|
633
|
+
if (tracked.length === 0) return [];
|
|
634
|
+
try {
|
|
635
|
+
const r = await call('select_files', { paths: tracked });
|
|
636
|
+
if (Array.isArray(r.paths)) return r.paths.filter((p) => tracked.includes(p));
|
|
637
|
+
} catch { /* an older server without the tool: the local cut stands */ }
|
|
638
|
+
return tracked;
|
|
639
|
+
}
|
|
640
|
+
|
|
624
641
|
async function localize(opts) {
|
|
625
642
|
const top = root();
|
|
626
643
|
process.chdir(top);
|
|
627
644
|
const status = await call('status', {});
|
|
628
|
-
const folder = (status.i18n?.catalog_folder || 'lang').replace(/\/+$/, '');
|
|
629
645
|
const langs = opts.languages || [status.primary_language, ...(status.languages || [])];
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
646
|
+
// Both catalog folders (Laravel's lang and the frontend's own), read again
|
|
647
|
+
// before EVERY call: a catalog the previous batch created must go back, or
|
|
648
|
+
// the server diffs it as new twice (corp1, 2026-10-18: "already exists").
|
|
649
|
+
const folders = [...new Set([status.i18n?.catalog_folder || 'lang', status.i18n?.js_catalog_folder].filter(Boolean).map((f) => f.replace(/\/+$/, '')))];
|
|
650
|
+
const catalogsNow = () => {
|
|
651
|
+
const out = [];
|
|
652
|
+
for (const folder of folders) for (const code of langs) {
|
|
653
|
+
const p = path.join(folder, code + '.json');
|
|
654
|
+
if (fs.existsSync(p)) out.push({ path: p, content: fs.readFileSync(p, 'utf8') });
|
|
655
|
+
}
|
|
656
|
+
return out;
|
|
657
|
+
};
|
|
658
|
+
// --all: the whole repository, not the changed files. The server picks the
|
|
659
|
+
// paths a scan would process out of the tracked tree (its own rules, so
|
|
660
|
+
// the two never drift); the batches of 30 below do the rest (2026-10-18).
|
|
661
|
+
let files = opts.all ? await allSourceFiles(top) : changedFiles(top);
|
|
662
|
+
if (files.length === 0) { console.log(opts.all ? 'lyngo: no source file of this project found in the repository.' : 'lyngo: nothing changed in the working tree.'); return null; }
|
|
663
|
+
const total = files.length;
|
|
664
|
+
if (opts.all) console.log(`lyngo: localizing ${total} file${total === 1 ? '' : 's'} in batches of 30 (${Math.ceil(total / 30)} call${total > 30 ? 's' : ''}); each batch applies before the next.`);
|
|
637
665
|
const report = { files: [], added: [], reused: [], languages: {} };
|
|
666
|
+
let batch = 0;
|
|
638
667
|
while (files.length) {
|
|
668
|
+
batch++;
|
|
639
669
|
const payload = files.map((p) => ({ path: p, content: fs.readFileSync(p, 'utf8') }));
|
|
640
|
-
const args = { files: payload, catalogs:
|
|
670
|
+
const args = { files: payload, catalogs: catalogsNow(), format: 'patch' };
|
|
641
671
|
if (opts.languages) args.languages = opts.languages.filter((l) => l !== status.primary_language);
|
|
642
672
|
// --no-translate: keys only, catalogs for translators. Without the flag the project's setting decides.
|
|
643
673
|
if (opts['no-translate']) args.translate = false;
|
|
@@ -661,6 +691,11 @@ async function localize(opts) {
|
|
|
661
691
|
report.languages[code] = cur;
|
|
662
692
|
}
|
|
663
693
|
files = r.deferred || [];
|
|
694
|
+
if (opts.all) {
|
|
695
|
+
const done = total - files.length;
|
|
696
|
+
const got = (r.report?.files || []).reduce((n, f) => n + (f.wrapped?.length || 0), 0);
|
|
697
|
+
console.log(` batch ${batch}: ${done}/${total} files, ${got} string${got === 1 ? '' : 's'} localized`);
|
|
698
|
+
}
|
|
664
699
|
}
|
|
665
700
|
const wrapped = report.files.reduce((n, f) => n + f.wrapped.length, 0);
|
|
666
701
|
console.log(`lyngo: ${wrapped} string${wrapped === 1 ? '' : 's'} localized in ${report.files.length} file${report.files.length === 1 ? '' : 's'}; ${report.added.length} new key${report.added.length === 1 ? '' : 's'}, ${report.reused.length} reused.`);
|
|
@@ -705,9 +740,10 @@ const HELP = `lyngo ${version()}: localization for your repository, from the ter
|
|
|
705
740
|
(--languages are the target languages; the source stays en unless --primary)
|
|
706
741
|
lyngo onboard --run=<id> [--languages fr,de]
|
|
707
742
|
the guided setup an agent follows, from lyngo.app/start; run it again to continue
|
|
708
|
-
lyngo localize [--languages fr,de] [--no-translate] [--dry]
|
|
743
|
+
lyngo localize [--all] [--languages fr,de] [--no-translate] [--dry]
|
|
709
744
|
localize what changed in the working tree, and translate it
|
|
710
745
|
(--no-translate: keys only; the project setting "Translate when localizing" is the default)
|
|
746
|
+
(--all: the whole repository instead of the changed files, in batches of 30)
|
|
711
747
|
lyngo translate <code> [<code>…] fill every key a language's catalog lacks, from the primary catalog
|
|
712
748
|
lyngo check <file> the user-facing strings of one file
|
|
713
749
|
lyngo status the project as Lyngo knows it
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prettifystudio/lyngo-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Localization for Laravel applications, from the terminal: Lyngo wraps user-facing text with your framework's i18n call, reuses your project's keys, translates and verifies the catalogs. Blade, Livewire, PHP, and Inertia with React, Vue or Svelte.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"lyngo": "bin/lyngo"
|