langctl 0.4.0 → 0.5.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/dist/index.js CHANGED
@@ -18,6 +18,7 @@ import { flagOverrides } from './core/config.js';
18
18
  import { CliError, ExitCode, usageError } from './core/errors.js';
19
19
  import { httpSettings } from './core/http.js';
20
20
  import { log, printJson, runtime } from './core/output.js';
21
+ import { finishUpdateCheck, startUpdateCheck } from './core/update-check.js';
21
22
  import { VERSION } from './version.js';
22
23
  const collect = (value, previous = []) => [...previous, value];
23
24
  /** Global flags, accepted before or after the subcommand (`langctl --json pull` and `langctl pull --json`). */
@@ -29,6 +30,7 @@ function withGlobals(cmd) {
29
30
  .option('-y, --yes', 'skip confirmation prompts (required for destructive commands in CI)')
30
31
  .option('--api-key <key>', 'API key (prefer the LANGCTL_API_KEY env var)')
31
32
  .option('--api-url <url>', 'API base URL (env: LANGCTL_API_URL)')
33
+ .option('--profile <name>', 'use a named credentials profile (env: LANGCTL_PROFILE)')
32
34
  .option('--timeout <seconds>', 'request timeout in seconds (env: LANGCTL_TIMEOUT)')
33
35
  .option('--no-color', 'disable colors (also honors NO_COLOR)');
34
36
  }
@@ -59,13 +61,17 @@ program.hook('preAction', (_root, action) => {
59
61
  flagOverrides.apiKey = o.apiKey;
60
62
  if (typeof o.apiUrl === 'string')
61
63
  flagOverrides.apiUrl = o.apiUrl;
64
+ if (typeof o.profile === 'string')
65
+ flagOverrides.profile = o.profile;
62
66
  if (o.timeout !== undefined) {
63
67
  const s = Number(o.timeout);
64
68
  if (!Number.isFinite(s) || s <= 0)
65
69
  throw usageError('--timeout must be a positive number of seconds');
66
70
  httpSettings.timeoutMs = s * 1000;
67
71
  }
72
+ updateCheck = startUpdateCheck();
68
73
  });
74
+ let updateCheck = null;
69
75
  // ── Setup & auth ────────────────────────────────────────────────
70
76
  withGlobals(program.command('init'))
71
77
  .description('set up this repository: authenticate if needed and write langctl.json')
@@ -98,6 +104,7 @@ withGlobals(program.command('pull [project]'))
98
104
  .option('--check', 'do not write; exit 7 if any file is out of date (for CI)')
99
105
  .option('--dry-run', 'show what would change without writing')
100
106
  .option('--require-complete', 'exit 1 if any language is missing translations')
107
+ .option('--strip-prefix <prefix>', 'only keys with this prefix, written without it (default: "prefix" in langctl.json)')
101
108
  .action(run((project, opts) => pullCommand(project, { ...opts, languages: opts.languages ?? opts.language })));
102
109
  withGlobals(program.command('push [project]'))
103
110
  .description('upload translation files (by default only the source language)')
@@ -107,6 +114,8 @@ withGlobals(program.command('push [project]'))
107
114
  .option('-m, --module <name>', 'assign new keys to this module')
108
115
  .option('--overwrite', 'replace existing translations (default: only add new keys/languages)')
109
116
  .option('--publish', 'publish the uploaded keys')
117
+ .option('--prefix <prefix>', 'add this prefix to every key (default: "prefix" in langctl.json)')
118
+ .option('--descriptions <file>', 'flat JSON { "key": "description" } stored with the keys (existing keys need --overwrite)')
110
119
  .option('--dry-run', 'show what would change without uploading')
111
120
  .action(run((project, opts) => pushCommand(project, opts)));
112
121
  withGlobals(program.command('export [project]'))
@@ -207,6 +216,7 @@ withGlobals(program.command('review [project]')).description('list AI translatio
207
216
  .option('--approve', 'approve the listed translations (asks to confirm; --yes in CI)')
208
217
  .option('-k, --keys <names>', 'only these keys (comma-separated)')
209
218
  .option('-l, --languages <codes>', 'only these languages (comma-separated)')
219
+ .option('-m, --module <name>', 'only keys in a module')
210
220
  .action(run((project, opts) => reviewCommand(project, opts)));
211
221
  // ── Team & org ──────────────────────────────────────────────────
212
222
  const team = program.command('team').description('manage team members (needs an API key with the org:admin scope)');
@@ -243,6 +253,7 @@ In CI (no config file needed):
243
253
  Exit codes:
244
254
  0 ok · 1 error · 2 invalid usage · 3 auth/permission · 4 not found
245
255
  5 network/API unavailable · 6 plan limit reached · 7 files out of date (--check)
256
+ 8 partial: some strings could not be AI-translated and need a human (translate)
246
257
 
247
258
  Docs: https://langctl.com/docs`);
248
259
  // ── Run ─────────────────────────────────────────────────────────
@@ -261,6 +272,7 @@ async function main() {
261
272
  catch (err) {
262
273
  process.exitCode = handleError(err);
263
274
  }
275
+ await finishUpdateCheck(updateCheck);
264
276
  }
265
277
  function handleError(err) {
266
278
  if (err instanceof CommanderError) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langctl",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Translation management CLI for developers: sync i18n files (JSON, Android, iOS, Flutter ARB) between your repo, CI and Langctl.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",