glotfile 0.8.7 → 0.8.9
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 +5 -5
- package/dist/server/cli.js +574 -152
- package/dist/server/server.js +146 -113
- package/dist/ui/assets/{index-CVA535xu.js → index-B64rdzp7.js} +326 -14
- package/dist/ui/index.html +1 -1
- package/package.json +2 -2
- package/skill/SKILL.md +28 -3
- package/skill/references/cli-reference.md +84 -1
- package/skill/references/conventions.md +17 -0
- package/skill/references/schema.md +21 -2
- package/skill/references/workflows.md +61 -16
package/dist/ui/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Glotfile</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-B64rdzp7.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-BaHu118N.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "glotfile",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.9",
|
|
4
4
|
"description": "Local-first, git-native translation management.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "James Dempster",
|
|
7
|
-
"homepage": "https://
|
|
7
|
+
"homepage": "https://glotfile.dev",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "git+https://github.com/jdempster/glotfile.git"
|
package/skill/SKILL.md
CHANGED
|
@@ -30,6 +30,23 @@ keys cannot be added in glotfile (trans-unit ids are content hashes). After the
|
|
|
30
30
|
context) — see "Angular projects" in `references/workflows.md` for the
|
|
31
31
|
extract → sync → translate → export loop.
|
|
32
32
|
|
|
33
|
+
## Work through the commands, not the raw file
|
|
34
|
+
|
|
35
|
+
On anything but a tiny catalog, **don't `Read` the whole state file or hand-edit its JSON.**
|
|
36
|
+
It can hold thousands of keys across many locales and is re-serialized deterministically,
|
|
37
|
+
so loading it wastes context and hand-edits are slow and easy to corrupt. Instead drive it
|
|
38
|
+
with the CLI:
|
|
39
|
+
|
|
40
|
+
- **Read / extract** with `glotfile get` (filter by key glob, `--locale`, `--state`),
|
|
41
|
+
`glotfile get --keys-only`, and `glotfile stats` (per-locale progress). All emit JSON.
|
|
42
|
+
- **Write** with `glotfile set` (source or `--locale` target), `glotfile set-state`,
|
|
43
|
+
`glotfile clear`, or `glotfile apply` (a JSON batch of edits applied in one atomic write).
|
|
44
|
+
|
|
45
|
+
These are the supported, stable way to inspect and change a glotfile from the CLI — prefer
|
|
46
|
+
them. Reach for a raw-file edit only for something no command covers, and then match the
|
|
47
|
+
deterministic format (`references/schema.md`). (Reading `config` directly is still fine —
|
|
48
|
+
it's small; see below.)
|
|
49
|
+
|
|
33
50
|
## Before you touch anything: discover the project's actual config
|
|
34
51
|
|
|
35
52
|
Do not assume the locales, providers, or output formats — read them. They live in the
|
|
@@ -46,13 +63,21 @@ unless asked.
|
|
|
46
63
|
|
|
47
64
|
| You want to… | Do this |
|
|
48
65
|
| --- | --- |
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
66
|
+
| Size up the catalog / what's left | `glotfile stats` (per-locale translated/reviewed/missing counts). |
|
|
67
|
+
| Extract specific values | `glotfile get [<key-glob>…] [--locale <list>] [--state <list>]` — JSON out; the way to read a large catalog. `--keys-only` for just names. |
|
|
68
|
+
| Add a new string | `glotfile set <key> "<source text>" --create`, then `glotfile translate` + `glotfile export`. (Angular: add it in code, not here.) See `references/workflows.md`. |
|
|
69
|
+
| Edit an existing source string | `glotfile set <key> "<new text>"` — flips downstream translations to `needs-review`. Then `glotfile translate --state needs-review` re-translates just those. See `references/workflows.md`. |
|
|
70
|
+
| Set or fix one translation | `glotfile set <key> "<text>" --locale <code>` (lands `reviewed`; `--state` to override). |
|
|
71
|
+
| Translate missing strings | `glotfile translate` (fills empties only). `--state needs-review` re-translates stale strings; `--all` redoes everything. |
|
|
72
|
+
| Mark a review state | `glotfile set-state <key|glob> <reviewed\|needs-review\|machine> [--locale <list>]`. |
|
|
73
|
+
| Empty a translation (force re-translate) | `glotfile clear <key|glob> --locale <list>`. |
|
|
74
|
+
| Make many edits at once | Pipe a JSON op list to `glotfile apply` — one atomic write; the right tool for bulk edits on a big file. |
|
|
52
75
|
| Write locale files | `glotfile export` |
|
|
53
76
|
| Find problems | `glotfile lint` (catalog issues) / `glotfile check` (lint + exports up to date) |
|
|
54
77
|
| Bootstrap from existing locale files | `glotfile import --format <adapter>` (or bare `glotfile import` to auto-detect) — see `references/workflows.md`. Every export adapter is importable. |
|
|
55
78
|
| Remove dead keys | `glotfile prune --unused` / `--empty-source` (dry-run unless `--write`). |
|
|
79
|
+
| Stop a live key being pruned | Add its glob to `config.scan.keep` (keys always counted as used). Never delete a `prune --unused` hit you know is live — `keep` it. See `references/schema.md`. |
|
|
80
|
+
| Exclude a key from translation | Set `skipTranslate: true` on the key (brand names, code, copy that must stay in the source language) — `translate` skips it and lint won't flag it as missing. |
|
|
56
81
|
| Enforce term translations | Glossary — see `references/workflows.md`. |
|
|
57
82
|
|
|
58
83
|
## Reference files — read the one you need
|
|
@@ -27,10 +27,14 @@ Adapter names: `flutter-arb`, `laravel-php`, `i18next-json`, `vue-i18n-json`,
|
|
|
27
27
|
`gettext-po`, `apple-strings`, `apple-stringsdict`, `angular-xliff`, `rails-yaml`.
|
|
28
28
|
|
|
29
29
|
## translate
|
|
30
|
-
`glotfile translate [--all] [--estimate] [--locale <list>] [--key <glob>] [--batch [--wait]]`
|
|
30
|
+
`glotfile translate [--all] [--state <list>] [--estimate] [--locale <list>] [--key <glob>] [--batch [--wait]]`
|
|
31
31
|
— AI-translate strings into the target locales and write the results back into the state file.
|
|
32
32
|
- By default only **empty** values are translated (existing translations are left alone).
|
|
33
33
|
- `--all` — re-translate every string, overwriting existing translations.
|
|
34
|
+
- `--state <list>` — re-translate only targets currently in these states (comma list of
|
|
35
|
+
`missing`, `machine`, `needs-review`, `reviewed`). The key one is **`--state needs-review`**:
|
|
36
|
+
it re-translates exactly the strings a source edit invalidated, without touching good
|
|
37
|
+
reviewed translations. (`--all` is the same as listing every state; default is `missing`.)
|
|
34
38
|
- `--estimate` — print batch/token/cost estimates and translate nothing.
|
|
35
39
|
- `--locale fr,de` — restrict to these target locales (alias: `--locales`).
|
|
36
40
|
- `--key <glob>` — only keys matching the glob (e.g. `auth.*`).
|
|
@@ -41,6 +45,75 @@ Adapter names: `flutter-arb`, `laravel-php`, `i18next-json`, `vue-i18n-json`,
|
|
|
41
45
|
|
|
42
46
|
Requires a configured AI provider + API key in per-machine local settings.
|
|
43
47
|
|
|
48
|
+
## get
|
|
49
|
+
`glotfile get [<key-glob>…] [--key <glob>] [--locale <list>] [--state <list>] [--fields <list>] [--keys-only] [--format json|ndjson]`
|
|
50
|
+
— extract values from the catalog **without loading the whole file**. Prints JSON to stdout.
|
|
51
|
+
This is how you read a large catalog.
|
|
52
|
+
- Positional `<key-glob>` args (and/or `--key`) select keys (e.g. `auth.*`); default: all keys.
|
|
53
|
+
- `--locale <list>` — locales to show (default: every configured locale, **source included**
|
|
54
|
+
so you always have the reference text).
|
|
55
|
+
- `--state <list>` — show only keys whose shown target locales are in these effective states:
|
|
56
|
+
`source`, `missing` (empty/untranslated), `machine`, `needs-review`, `reviewed`. The source
|
|
57
|
+
locale is always shown as the reference and doesn't gate the filter. So
|
|
58
|
+
`glotfile get --locale en,de --state missing` is "every key still untranslated in `de`, with
|
|
59
|
+
the English source beside it" — the translation work queue.
|
|
60
|
+
- `--fields <list>` — cell projection: `value,state` (default), add `updatedAt`, or `all` for
|
|
61
|
+
the full key entry (context/notes/tags/placeholders/plural + values).
|
|
62
|
+
- `--keys-only` — print just the matched key names, one per line (the cheapest overview).
|
|
63
|
+
- `--format ndjson` — one flat `{key, locale, value, state}` row per line (stream-friendly for
|
|
64
|
+
huge result sets); default is a nested JSON object `{ key: { locale: { value, state } } }`.
|
|
65
|
+
|
|
66
|
+
## stats
|
|
67
|
+
`glotfile stats [--locale <list>] [--format json|text]` — per-locale progress counts
|
|
68
|
+
(`reviewed` / `machine` / `needs-review` / `missing`) plus totals. Use it to size up the work
|
|
69
|
+
before a big translate or to report completion. JSON by default; `--format text` for a table.
|
|
70
|
+
|
|
71
|
+
## set
|
|
72
|
+
`glotfile set <key> [value] [--locale <code>] [--state <state>] [--create]`
|
|
73
|
+
— set a single value. The value is the positional, or `--value`, or piped on stdin (multi-line).
|
|
74
|
+
- **No `--locale` ⇒ the source string.** Editing it flips every downstream `reviewed`/`machine`
|
|
75
|
+
translation to `needs-review` (it tells you how many) — then `glotfile translate --state
|
|
76
|
+
needs-review` re-fills just those. This is the "write back the source language, mark the
|
|
77
|
+
others stale" path.
|
|
78
|
+
- `--locale <code>` — set that target's value. It lands `reviewed` (a deliberate, authoritative
|
|
79
|
+
edit); pass `--state machine|needs-review` to override.
|
|
80
|
+
- `--create` — create the key (scalar) if it doesn't exist yet (source writes only).
|
|
81
|
+
- Plural keys are edited via `apply` (`set-source-forms` / `set-forms`), not `set`.
|
|
82
|
+
|
|
83
|
+
## set-state
|
|
84
|
+
`glotfile set-state <key|glob> <state> [--locale <list>]` — flip the review state
|
|
85
|
+
(`machine` / `needs-review` / `reviewed`) of one key, or many via a glob, across locales
|
|
86
|
+
(default: every target locale). E.g. `glotfile set-state auth.* reviewed --locale fr` approves
|
|
87
|
+
all of `auth.*`'s French. Only cells that already have a value are touched.
|
|
88
|
+
|
|
89
|
+
## clear
|
|
90
|
+
`glotfile clear <key|glob> --locale <list>` — empty the given target value(s) so they read as
|
|
91
|
+
**untranslated**, which makes a plain `glotfile translate` refill them. `--locale` is required
|
|
92
|
+
and cannot be the source locale (edit that with `set`).
|
|
93
|
+
|
|
94
|
+
## apply
|
|
95
|
+
`glotfile apply [--dry-run] [--continue-on-error]` — read a JSON **array of write operations**
|
|
96
|
+
from stdin and apply them all in one load → mutate → save. Use this for bulk edits on a large
|
|
97
|
+
catalog: one file rewrite instead of N. Each op is one object:
|
|
98
|
+
|
|
99
|
+
```jsonc
|
|
100
|
+
[
|
|
101
|
+
{ "op": "set-source", "key": "auth.title", "value": "Sign in" },
|
|
102
|
+
{ "op": "set-target", "key": "auth.title", "locale": "fr", "value": "Connexion", "state": "reviewed" },
|
|
103
|
+
{ "op": "set-source-forms", "key": "cart.items", "forms": { "one": "{count} item", "other": "{count} items" } },
|
|
104
|
+
{ "op": "set-forms", "key": "cart.items", "locale": "pl", "forms": { "one": "…", "few": "…", "many": "…", "other": "…" } },
|
|
105
|
+
{ "op": "set-state", "key": "auth.title", "locale": "de", "state": "reviewed" },
|
|
106
|
+
{ "op": "clear", "key": "auth.title", "locale": "es" },
|
|
107
|
+
{ "op": "create", "key": "home.cta", "value": "Get started" }
|
|
108
|
+
]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- **Atomic by default:** if any op fails, nothing is written (the file is untouched) and the
|
|
112
|
+
command exits non-zero, reporting which op failed.
|
|
113
|
+
- `--continue-on-error` — apply the ops that succeed, skip the ones that fail, and save anyway.
|
|
114
|
+
- `--dry-run` — report what would change without writing.
|
|
115
|
+
- Prints `{ applied, keysTouched, saved, dryRun, errors }`.
|
|
116
|
+
|
|
44
117
|
## lint
|
|
45
118
|
`glotfile lint [--format text|json|sarif] [--locale <list>] [--rule <list>] [--max-warnings <n>] [--include-suppressed] [--accept]`
|
|
46
119
|
— check the catalog for problems (placeholder mismatches, length, glossary violations,
|
|
@@ -99,6 +172,10 @@ batch API (anthropic only), like `translate --batch`.
|
|
|
99
172
|
(`angular-xliff`), the regex scanner can't see content-hash ids, so `scan` instead rebuilds
|
|
100
173
|
the index from the source locations recorded in `messages.xlf`.
|
|
101
174
|
|
|
175
|
+
Tune it via `config.scan` when the heuristic misses (`include`/`exclude` file globs,
|
|
176
|
+
Flutter `accessors`, custom `patterns` regexes, and **`keep`** — see below). See
|
|
177
|
+
`references/schema.md` for the full shape.
|
|
178
|
+
|
|
102
179
|
## prune
|
|
103
180
|
`glotfile prune (--empty-source | --unused) [--write]` — remove keys. **Dry-run (lists
|
|
104
181
|
only) unless `--write` is given.**
|
|
@@ -107,6 +184,12 @@ only) unless `--write` is given.**
|
|
|
107
184
|
For Angular, "unused" is computed from a fresh extraction (keys gone from `messages.xlf`),
|
|
108
185
|
so run `ng extract-i18n` before pruning.
|
|
109
186
|
|
|
187
|
+
`--unused` is heuristic. A key referenced only dynamically or through a wrapper the scanner
|
|
188
|
+
doesn't recognise can show up as a false positive. **Don't delete a key you know is live —
|
|
189
|
+
add its glob to `config.scan.keep`** (keys always treated as used) and re-run. `keep` is also
|
|
190
|
+
the right home for keys consumed by code the scanner can never see (framework internals,
|
|
191
|
+
vendored packages, server-driven UIs).
|
|
192
|
+
|
|
110
193
|
## split
|
|
111
194
|
`glotfile split` — convert a single `glotfile.json` into a `glotfile/` directory
|
|
112
195
|
(`config.json`, `keys.json`, `locales/<code>.json`). Produces smaller, more reviewable
|
|
@@ -24,6 +24,23 @@ saved to the state file, exported, and committed.
|
|
|
24
24
|
- Commit the state file and the regenerated outputs together, so the catalog and the
|
|
25
25
|
locale files never drift apart in history. `glotfile check` verifies they're in sync.
|
|
26
26
|
|
|
27
|
+
## Work surgically — don't load or hand-edit a large catalog
|
|
28
|
+
|
|
29
|
+
The state file is the source of truth, but it is not your editing surface. On any
|
|
30
|
+
non-trivial catalog, reading the whole `glotfile.json` into context or hand-editing its
|
|
31
|
+
JSON is wasteful and error-prone (it's re-serialized deterministically, so manual edits
|
|
32
|
+
must match exactly). Use the commands that read and write it precisely:
|
|
33
|
+
|
|
34
|
+
- **Read:** `glotfile get` (filter by key glob, `--locale`, `--state`), `get --keys-only`,
|
|
35
|
+
`glotfile stats`.
|
|
36
|
+
- **Write:** `glotfile set` (source or `--locale` target), `glotfile set-state`,
|
|
37
|
+
`glotfile clear`, and `glotfile apply` for a batch of edits in one atomic write.
|
|
38
|
+
|
|
39
|
+
Editing the **source** value (`glotfile set <key> "<text>"`) automatically flips the other
|
|
40
|
+
locales to `needs-review`; re-fill just those with `glotfile translate --state needs-review`.
|
|
41
|
+
Reading `config` directly is fine — it's small. Hand-edit a key only for something no
|
|
42
|
+
command covers, and then match the deterministic format (`references/schema.md`).
|
|
43
|
+
|
|
27
44
|
## Two on-disk layouts — support both
|
|
28
45
|
|
|
29
46
|
A project is either single-file (`glotfile.json`) or split (`glotfile/` directory).
|
|
@@ -36,7 +36,12 @@ In **split** layout this is spread across `glotfile/config.json` (holds `version
|
|
|
36
36
|
"autoExport": true, // serve re-exports on change (default)
|
|
37
37
|
"spelling": { "customWords": [] },
|
|
38
38
|
"lint": { "rules": {}, "ignore": [], "spelling": {} },
|
|
39
|
-
"scan": {
|
|
39
|
+
"scan": { // tunes `scan` / `prune --unused`
|
|
40
|
+
"include": [], "exclude": [], // globs limiting which files are scanned
|
|
41
|
+
"accessors": [], // extra Flutter accessor names
|
|
42
|
+
"patterns": [], // custom usage regexes (capture group 1 = key)
|
|
43
|
+
"keep": ["analytics.*"] // key globs ALWAYS treated as used (never pruned)
|
|
44
|
+
}
|
|
40
45
|
}
|
|
41
46
|
```
|
|
42
47
|
|
|
@@ -44,6 +49,20 @@ In **split** layout this is spread across `glotfile/config.json` (holds `version
|
|
|
44
49
|
**Saving Settings from the UI replaces the whole `config` object** — any new `config.*`
|
|
45
50
|
section must be modeled in the round-trip or it is silently wiped.
|
|
46
51
|
|
|
52
|
+
### `config.scan` — keeping the scanner honest
|
|
53
|
+
|
|
54
|
+
`scan` (and therefore `prune --unused` and the UI usage tree) infers which keys the code
|
|
55
|
+
references. Tune it when the heuristic misses:
|
|
56
|
+
|
|
57
|
+
- `include` / `exclude` — globs narrowing which files are scanned.
|
|
58
|
+
- `accessors` — extra accessor names for Flutter's gen_l10n object (auto-detection covers
|
|
59
|
+
most projects; this is the escape hatch).
|
|
60
|
+
- `patterns` — custom regexes for project-specific i18n call sites (capture group 1 is the key).
|
|
61
|
+
- **`keep`** — key globs **always counted as used**, so `prune --unused` never flags them.
|
|
62
|
+
Use it for keys consumed by code the scanner can't see: framework internals, vendored
|
|
63
|
+
packages, server-driven UIs, or keys built from a fully dynamic name. This is the fix when
|
|
64
|
+
`prune --unused` lists a key you know is live — add the glob to `keep`, don't delete it.
|
|
65
|
+
|
|
47
66
|
## KeyEntry
|
|
48
67
|
|
|
49
68
|
```jsonc
|
|
@@ -54,7 +73,7 @@ section must be modeled in the round-trip or it is silently wiped.
|
|
|
54
73
|
"tags": ["checkout"],
|
|
55
74
|
"maxLength": 40, // lint flags overflow
|
|
56
75
|
"screenshot": "…", // path; used by vision providers
|
|
57
|
-
"skipTranslate": false,
|
|
76
|
+
"skipTranslate": false, // true => translate skips it; not "missing"
|
|
58
77
|
"plural": { "arg": "count" }, // presence => plural message
|
|
59
78
|
"placeholders": { // typed placeholder metadata
|
|
60
79
|
"count": { "type": "int", "format": "compact", "example": "1,000" }
|
|
@@ -8,33 +8,46 @@ when no command fits (then match the deterministic format — see `references/sc
|
|
|
8
8
|
|
|
9
9
|
1. Pick a key name that matches the project's existing convention (look at sibling keys —
|
|
10
10
|
dotted `auth.login.title`, flat, etc.).
|
|
11
|
-
2.
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
"context": "Heading on the empty-cart screen",
|
|
15
|
-
"values": { "en": { "value": "Your cart is empty", "state": "source" } }
|
|
16
|
-
}
|
|
11
|
+
2. Create it with its source value:
|
|
12
|
+
```sh
|
|
13
|
+
glotfile set cart.empty.title "Your cart is empty" --create
|
|
17
14
|
```
|
|
18
15
|
Add `context` when the string is ambiguous out of context — it measurably improves
|
|
19
|
-
translation quality
|
|
16
|
+
translation quality (set it in the UI, or hand-edit the key's `context` field; see
|
|
17
|
+
`references/schema.md`).
|
|
20
18
|
3. `glotfile translate` to fill the other locales (or `--key "cart.*"` to scope it).
|
|
21
19
|
4. `glotfile export` to write the locale files.
|
|
22
20
|
5. Wire the key up in the app code using the project's i18n accessor, then commit.
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
instead of
|
|
26
|
-
|
|
22
|
+
Adding many at once? Batch them through `glotfile apply` (a list of `create` ops) — one
|
|
23
|
+
write instead of one per key. For a **plural** message, create it then set its forms via
|
|
24
|
+
`apply` (`set-source-forms`), or hand-edit the key with a `plural: { "arg": "count" }`
|
|
25
|
+
marker and `forms` instead of `value` (see `references/schema.md`). Use ICU placeholders
|
|
26
|
+
like `{count}` and keep them identical across locales — the lint placeholder rule enforces
|
|
27
|
+
this.
|
|
27
28
|
|
|
28
29
|
## Edit an existing source string
|
|
29
30
|
|
|
30
|
-
1.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
1. Write the new source value:
|
|
32
|
+
```sh
|
|
33
|
+
glotfile set checkout.title "Review your order"
|
|
34
|
+
```
|
|
35
|
+
This flips every `reviewed`/`machine` translation of that key to `needs-review` (it
|
|
36
|
+
reports how many) — they're now stale.
|
|
37
|
+
2. Re-translate just the stale ones:
|
|
38
|
+
```sh
|
|
39
|
+
glotfile translate --state needs-review
|
|
40
|
+
```
|
|
41
|
+
(Scope with `--key "checkout.*"` if you only want this key.) Use `--state needs-review`,
|
|
42
|
+
**not** `--all` — a plain `glotfile translate` fills only *empty* values so it would skip
|
|
43
|
+
the stale-but-non-empty ones, while `--all` would also overwrite good `reviewed`
|
|
44
|
+
translations elsewhere. `--state needs-review` re-does exactly what the edit invalidated.
|
|
34
45
|
3. `glotfile export`, then commit.
|
|
35
46
|
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
Editing many sources at once? Batch the `set-source` ops through `glotfile apply`, then run
|
|
48
|
+
the single `glotfile translate --state needs-review`. Never edit a translation in an
|
|
49
|
+
exported file to "fix" it — fix it in the catalog (`glotfile set <key> --locale <code>`,
|
|
50
|
+
which lands `reviewed`) and re-export.
|
|
38
51
|
|
|
39
52
|
## Onboard a repo that already has locale files
|
|
40
53
|
|
|
@@ -128,3 +141,35 @@ with the glossary applied.
|
|
|
128
141
|
`glotfile scan` (index code references) → `glotfile build-context` (AI writes a short
|
|
129
142
|
`context` per key from how it's used in code) → `glotfile translate`. Keys with good
|
|
130
143
|
`context` translate far more accurately, especially short or ambiguous strings.
|
|
144
|
+
|
|
145
|
+
## Work a large catalog from the CLI
|
|
146
|
+
|
|
147
|
+
A real catalog can be thousands of keys across a dozen-plus locales. Don't read or
|
|
148
|
+
hand-edit the file — query and edit it surgically.
|
|
149
|
+
|
|
150
|
+
1. **Survey:** `glotfile stats` for per-locale completion; `glotfile stats --format text`
|
|
151
|
+
for a quick table. `glotfile get --keys-only --key "<glob>"` to enumerate a namespace.
|
|
152
|
+
2. **Pull only what you need:** the source plus the cells still to do —
|
|
153
|
+
```sh
|
|
154
|
+
glotfile get --locale en,de --state missing,needs-review --key "checkout.*"
|
|
155
|
+
```
|
|
156
|
+
gives the English source beside every `de` cell that's empty or stale for `checkout.*`.
|
|
157
|
+
Add `--format ndjson` when the result is large and you want to stream/grep it.
|
|
158
|
+
3. **Make the edits as one batch.** Build a JSON op list and pipe it in — one atomic write,
|
|
159
|
+
no diff churn, no per-edit race:
|
|
160
|
+
```sh
|
|
161
|
+
cat <<'JSON' | glotfile apply
|
|
162
|
+
[
|
|
163
|
+
{ "op": "set-target", "key": "checkout.title", "locale": "de", "value": "Kasse", "state": "reviewed" },
|
|
164
|
+
{ "op": "set-target", "key": "checkout.pay", "locale": "de", "value": "Bezahlen", "state": "reviewed" }
|
|
165
|
+
]
|
|
166
|
+
JSON
|
|
167
|
+
```
|
|
168
|
+
Preview first with `glotfile apply --dry-run`. On any bad op the whole batch is rejected
|
|
169
|
+
(nothing written) unless you pass `--continue-on-error`.
|
|
170
|
+
4. **Or let AI do the gaps:** `glotfile translate --locale de --key "checkout.*"` fills the
|
|
171
|
+
empties; after a source edit, `glotfile translate --state needs-review` re-does the stale
|
|
172
|
+
ones. Then `glotfile export` and commit.
|
|
173
|
+
|
|
174
|
+
Rule of thumb: **`get` to read, `set`/`apply` to write, `translate` for the AI gaps** —
|
|
175
|
+
reach for a raw-file edit only when no command covers what you need.
|