@tolkbot/cli 0.4.0 → 0.6.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 +877 -205
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -559,7 +559,7 @@ var require_to_regex_range = __commonJS({
|
|
|
559
559
|
let zipped = zip(start, stop);
|
|
560
560
|
let digits = zipped.length;
|
|
561
561
|
let pattern = "";
|
|
562
|
-
let
|
|
562
|
+
let count2 = 0;
|
|
563
563
|
for (let i = 0; i < digits; i++) {
|
|
564
564
|
let [startDigit, stopDigit] = zipped[i];
|
|
565
565
|
if (startDigit === stopDigit) {
|
|
@@ -567,13 +567,13 @@ var require_to_regex_range = __commonJS({
|
|
|
567
567
|
} else if (startDigit !== "0" || stopDigit !== "9") {
|
|
568
568
|
pattern += toCharacterClass(startDigit, stopDigit, options);
|
|
569
569
|
} else {
|
|
570
|
-
|
|
570
|
+
count2++;
|
|
571
571
|
}
|
|
572
572
|
}
|
|
573
|
-
if (
|
|
573
|
+
if (count2) {
|
|
574
574
|
pattern += options.shorthand === true ? "\\d" : "[0-9]";
|
|
575
575
|
}
|
|
576
|
-
return { pattern, count: [
|
|
576
|
+
return { pattern, count: [count2], digits };
|
|
577
577
|
}
|
|
578
578
|
function splitToPatterns(min, max, tok, options) {
|
|
579
579
|
let ranges = splitToRanges(min, max);
|
|
@@ -2320,13 +2320,13 @@ var require_parse2 = __commonJS({
|
|
|
2320
2320
|
consume(token.value);
|
|
2321
2321
|
};
|
|
2322
2322
|
const negate = () => {
|
|
2323
|
-
let
|
|
2323
|
+
let count2 = 1;
|
|
2324
2324
|
while (peek() === "!" && (peek(2) !== "(" || peek(3) === "?")) {
|
|
2325
2325
|
advance();
|
|
2326
2326
|
state.start++;
|
|
2327
|
-
|
|
2327
|
+
count2++;
|
|
2328
2328
|
}
|
|
2329
|
-
if (
|
|
2329
|
+
if (count2 % 2 === 0) {
|
|
2330
2330
|
return false;
|
|
2331
2331
|
}
|
|
2332
2332
|
state.negated = true;
|
|
@@ -5784,10 +5784,10 @@ var require_out4 = __commonJS({
|
|
|
5784
5784
|
});
|
|
5785
5785
|
|
|
5786
5786
|
// src/main.ts
|
|
5787
|
-
import { Command as
|
|
5787
|
+
import { Command as Command9, CommanderError, Option as Option2 } from "commander";
|
|
5788
5788
|
|
|
5789
5789
|
// package.json
|
|
5790
|
-
var version = "0.
|
|
5790
|
+
var version = "0.6.0";
|
|
5791
5791
|
|
|
5792
5792
|
// src/commands/auth/index.ts
|
|
5793
5793
|
import { Command } from "commander";
|
|
@@ -6315,7 +6315,7 @@ import { ConvexHttpClient } from "convex/browser";
|
|
|
6315
6315
|
var BACKEND_METHODS = /* @__PURE__ */ new Set(["query", "mutation", "action"]);
|
|
6316
6316
|
var client = null;
|
|
6317
6317
|
function getConvexClient() {
|
|
6318
|
-
client ??= new ConvexHttpClient(requireConvexUrl());
|
|
6318
|
+
client ??= new ConvexHttpClient(requireConvexUrl(), { logger: false });
|
|
6319
6319
|
return client;
|
|
6320
6320
|
}
|
|
6321
6321
|
function translateAuthError(error62, resolved) {
|
|
@@ -8068,14 +8068,14 @@ function codePointLength(str) {
|
|
|
8068
8068
|
const units = str.length;
|
|
8069
8069
|
if (!highSurrogate.test(str))
|
|
8070
8070
|
return units;
|
|
8071
|
-
let
|
|
8071
|
+
let count2 = units;
|
|
8072
8072
|
for (let i = 0; i < units - 1; i++) {
|
|
8073
8073
|
if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {
|
|
8074
|
-
|
|
8074
|
+
count2--;
|
|
8075
8075
|
i++;
|
|
8076
8076
|
}
|
|
8077
8077
|
}
|
|
8078
|
-
return
|
|
8078
|
+
return count2;
|
|
8079
8079
|
}
|
|
8080
8080
|
function getLengthableOrigin(input2) {
|
|
8081
8081
|
if (Array.isArray(input2))
|
|
@@ -12432,8 +12432,8 @@ function az_default() {
|
|
|
12432
12432
|
localeError: error2()
|
|
12433
12433
|
};
|
|
12434
12434
|
}
|
|
12435
|
-
function getBelarusianPlural(
|
|
12436
|
-
const absCount = Math.abs(
|
|
12435
|
+
function getBelarusianPlural(count2, one, few, many) {
|
|
12436
|
+
const absCount = Math.abs(count2);
|
|
12437
12437
|
const lastDigit = absCount % 10;
|
|
12438
12438
|
const lastTwoDigits = absCount % 100;
|
|
12439
12439
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -15038,8 +15038,8 @@ function hu_default() {
|
|
|
15038
15038
|
localeError: error23()
|
|
15039
15039
|
};
|
|
15040
15040
|
}
|
|
15041
|
-
function getArmenianPlural(
|
|
15042
|
-
return Math.abs(
|
|
15041
|
+
function getArmenianPlural(count2, one, many) {
|
|
15042
|
+
return Math.abs(count2) === 1 ? one : many;
|
|
15043
15043
|
}
|
|
15044
15044
|
function withDefiniteArticle(word) {
|
|
15045
15045
|
if (!word)
|
|
@@ -17731,8 +17731,8 @@ function ro_default() {
|
|
|
17731
17731
|
localeError: error45()
|
|
17732
17732
|
};
|
|
17733
17733
|
}
|
|
17734
|
-
function getRussianPlural(
|
|
17735
|
-
const absCount = Math.abs(
|
|
17734
|
+
function getRussianPlural(count2, one, few, many) {
|
|
17735
|
+
const absCount = Math.abs(count2);
|
|
17736
17736
|
const lastDigit = absCount % 10;
|
|
17737
17737
|
const lastTwoDigits = absCount % 100;
|
|
17738
17738
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -26823,6 +26823,75 @@ var SUPPORTED_LOCALES = [
|
|
|
26823
26823
|
"eu",
|
|
26824
26824
|
"gl"
|
|
26825
26825
|
];
|
|
26826
|
+
var LOCALE_NAMES = {
|
|
26827
|
+
en: "English",
|
|
26828
|
+
"en-us": "English (US)",
|
|
26829
|
+
"en-gb": "English (UK)",
|
|
26830
|
+
"en-au": "English (Australia)",
|
|
26831
|
+
"en-ca": "English (Canada)",
|
|
26832
|
+
es: "Spanish",
|
|
26833
|
+
"es-es": "Spanish (Spain)",
|
|
26834
|
+
"es-mx": "Spanish (Mexico)",
|
|
26835
|
+
"es-ar": "Spanish (Argentina)",
|
|
26836
|
+
pt: "Portuguese",
|
|
26837
|
+
"pt-br": "Portuguese (Brazil)",
|
|
26838
|
+
"pt-pt": "Portuguese (Portugal)",
|
|
26839
|
+
zh: "Chinese",
|
|
26840
|
+
"zh-cn": "Chinese (Simplified)",
|
|
26841
|
+
"zh-tw": "Chinese (Traditional)",
|
|
26842
|
+
"zh-hk": "Chinese (Hong Kong)",
|
|
26843
|
+
fr: "French",
|
|
26844
|
+
"fr-fr": "French (France)",
|
|
26845
|
+
"fr-ca": "French (Canada)",
|
|
26846
|
+
de: "German",
|
|
26847
|
+
"de-de": "German (Germany)",
|
|
26848
|
+
"de-at": "German (Austria)",
|
|
26849
|
+
"de-ch": "German (Switzerland)",
|
|
26850
|
+
no: "Norwegian",
|
|
26851
|
+
nb: "Norwegian Bokm\xE5l",
|
|
26852
|
+
nn: "Norwegian Nynorsk",
|
|
26853
|
+
sv: "Swedish",
|
|
26854
|
+
da: "Danish",
|
|
26855
|
+
fi: "Finnish",
|
|
26856
|
+
is: "Icelandic",
|
|
26857
|
+
it: "Italian",
|
|
26858
|
+
nl: "Dutch",
|
|
26859
|
+
"nl-be": "Dutch (Belgium)",
|
|
26860
|
+
pl: "Polish",
|
|
26861
|
+
cs: "Czech",
|
|
26862
|
+
sk: "Slovak",
|
|
26863
|
+
hu: "Hungarian",
|
|
26864
|
+
ro: "Romanian",
|
|
26865
|
+
bg: "Bulgarian",
|
|
26866
|
+
hr: "Croatian",
|
|
26867
|
+
sl: "Slovenian",
|
|
26868
|
+
sr: "Serbian",
|
|
26869
|
+
uk: "Ukrainian",
|
|
26870
|
+
el: "Greek",
|
|
26871
|
+
tr: "Turkish",
|
|
26872
|
+
ru: "Russian",
|
|
26873
|
+
ja: "Japanese",
|
|
26874
|
+
ko: "Korean",
|
|
26875
|
+
th: "Thai",
|
|
26876
|
+
vi: "Vietnamese",
|
|
26877
|
+
id: "Indonesian",
|
|
26878
|
+
ms: "Malay",
|
|
26879
|
+
tl: "Tagalog",
|
|
26880
|
+
hi: "Hindi",
|
|
26881
|
+
bn: "Bengali",
|
|
26882
|
+
ta: "Tamil",
|
|
26883
|
+
ar: "Arabic",
|
|
26884
|
+
he: "Hebrew",
|
|
26885
|
+
fa: "Persian",
|
|
26886
|
+
af: "Afrikaans",
|
|
26887
|
+
sw: "Swahili",
|
|
26888
|
+
et: "Estonian",
|
|
26889
|
+
lv: "Latvian",
|
|
26890
|
+
lt: "Lithuanian",
|
|
26891
|
+
ca: "Catalan",
|
|
26892
|
+
eu: "Basque",
|
|
26893
|
+
gl: "Galician"
|
|
26894
|
+
};
|
|
26826
26895
|
var DEFAULT_BEHAVIORAL_SETTINGS = {
|
|
26827
26896
|
tonePreset: "formal",
|
|
26828
26897
|
toneInstructions: "Use a formal, professional tone. Avoid slang.",
|
|
@@ -27354,6 +27423,7 @@ var analyticsEventNames = [
|
|
|
27354
27423
|
"glossary_imported",
|
|
27355
27424
|
"translation_job_viewed",
|
|
27356
27425
|
"translation_logs_viewed",
|
|
27426
|
+
"activity_timeline_viewed",
|
|
27357
27427
|
"cli_login_completed",
|
|
27358
27428
|
"cli_command_completed",
|
|
27359
27429
|
"cli_init_completed",
|
|
@@ -28316,6 +28386,16 @@ async function loadPlanContext(cwd) {
|
|
|
28316
28386
|
framework: config3.config.framework
|
|
28317
28387
|
};
|
|
28318
28388
|
}
|
|
28389
|
+
async function readCreditBalance(ctx) {
|
|
28390
|
+
try {
|
|
28391
|
+
const balance = await ctx.client.query(api.usage.getCreditBalance, {
|
|
28392
|
+
organizationId: ctx.project.organizationId
|
|
28393
|
+
});
|
|
28394
|
+
return balance?.total ?? null;
|
|
28395
|
+
} catch {
|
|
28396
|
+
return null;
|
|
28397
|
+
}
|
|
28398
|
+
}
|
|
28319
28399
|
function describePlan(plan) {
|
|
28320
28400
|
const { summary } = plan;
|
|
28321
28401
|
const lines = [
|
|
@@ -28331,9 +28411,9 @@ function describeLeftOut(plan) {
|
|
|
28331
28411
|
const lines = [];
|
|
28332
28412
|
const protectedCount = plan.protectedKeys.length;
|
|
28333
28413
|
if (protectedCount > 0) {
|
|
28334
|
-
const
|
|
28414
|
+
const reasons2 = Object.entries(summary.protected).map(([reason, n]) => `${n} ${reason}`).join(", ");
|
|
28335
28415
|
lines.push(
|
|
28336
|
-
`${protectedCount} changed but kept for a person (${
|
|
28416
|
+
`${protectedCount} changed but kept for a person (${reasons2})`
|
|
28337
28417
|
);
|
|
28338
28418
|
}
|
|
28339
28419
|
if (summary.held > 0)
|
|
@@ -28551,11 +28631,11 @@ function flattenValues(data) {
|
|
|
28551
28631
|
const values = /* @__PURE__ */ new Map();
|
|
28552
28632
|
function walk(obj, prefix) {
|
|
28553
28633
|
for (const [key, value] of Object.entries(obj)) {
|
|
28554
|
-
const
|
|
28634
|
+
const fullKey6 = prefix ? `${prefix}.${key}` : key;
|
|
28555
28635
|
if (typeof value === "string") {
|
|
28556
|
-
values.set(
|
|
28636
|
+
values.set(fullKey6, value);
|
|
28557
28637
|
} else if (typeof value === "object" && value !== null) {
|
|
28558
|
-
walk(value,
|
|
28638
|
+
walk(value, fullKey6);
|
|
28559
28639
|
}
|
|
28560
28640
|
}
|
|
28561
28641
|
}
|
|
@@ -31310,6 +31390,13 @@ var BILLING_BLOCKED = "BILLING_BLOCKED";
|
|
|
31310
31390
|
|
|
31311
31391
|
// ../shared/src/projects/localeSetup.ts
|
|
31312
31392
|
var LOCALE_SETUP_STALE_MS = 15 * 60 * 1e3;
|
|
31393
|
+
function localeSetupState(row, now) {
|
|
31394
|
+
if (!row) return "not-set-up";
|
|
31395
|
+
if (row.status === "onboarded") return "set-up";
|
|
31396
|
+
if (row.onboardingError !== void 0) return "failed";
|
|
31397
|
+
if (row.onboardingRequestedAt === void 0) return "not-set-up";
|
|
31398
|
+
return now - row.onboardingRequestedAt > LOCALE_SETUP_STALE_MS ? "failed" : "running";
|
|
31399
|
+
}
|
|
31313
31400
|
|
|
31314
31401
|
// ../shared/src/projects/index.ts
|
|
31315
31402
|
var PROJECT_ARCHIVED = "PROJECT_ARCHIVED";
|
|
@@ -31343,6 +31430,7 @@ var ERROR_CODES = {
|
|
|
31343
31430
|
login_failed: EXIT_CODES.failure,
|
|
31344
31431
|
// 2: usage
|
|
31345
31432
|
usage: EXIT_CODES.usage,
|
|
31433
|
+
unsupported_locale: EXIT_CODES.usage,
|
|
31346
31434
|
// 3: not authenticated, or not allowed
|
|
31347
31435
|
not_authenticated: EXIT_CODES.auth,
|
|
31348
31436
|
token_expired: EXIT_CODES.auth,
|
|
@@ -31665,24 +31753,377 @@ jobsCommand.command("cancel").description("Cancel a running translation job").ar
|
|
|
31665
31753
|
await runJobsCancel(validateOrExit(schema, { ...opts, jobId }));
|
|
31666
31754
|
});
|
|
31667
31755
|
|
|
31668
|
-
// src/commands/
|
|
31669
|
-
import { Command as Command4 } from "commander";
|
|
31756
|
+
// src/commands/languages/index.ts
|
|
31757
|
+
import { Command as Command4, Option } from "commander";
|
|
31670
31758
|
import { z as z6 } from "zod/v4";
|
|
31671
31759
|
|
|
31672
|
-
// src/commands/
|
|
31760
|
+
// src/commands/languages/add.tsx
|
|
31673
31761
|
import { Spinner as Spinner9 } from "@inkjs/ui";
|
|
31674
|
-
import { Box as Box12,
|
|
31762
|
+
import { Box as Box12, Text as Text12 } from "ink";
|
|
31763
|
+
|
|
31764
|
+
// src/commands/languages/languages-core.ts
|
|
31765
|
+
var DEFAULT_EXISTING_MODE = "trust";
|
|
31766
|
+
var MAX_SUGGESTIONS = 6;
|
|
31767
|
+
function editDistance(a, b) {
|
|
31768
|
+
let previous = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
31769
|
+
for (let i = 1; i <= a.length; i++) {
|
|
31770
|
+
const current = [i];
|
|
31771
|
+
for (let j = 1; j <= b.length; j++) {
|
|
31772
|
+
current[j] = Math.min(
|
|
31773
|
+
(previous[j] ?? 0) + 1,
|
|
31774
|
+
(current[j - 1] ?? 0) + 1,
|
|
31775
|
+
(previous[j - 1] ?? 0) + (a[i - 1] === b[j - 1] ? 0 : 1)
|
|
31776
|
+
);
|
|
31777
|
+
}
|
|
31778
|
+
previous = current;
|
|
31779
|
+
}
|
|
31780
|
+
return previous[b.length] ?? 0;
|
|
31781
|
+
}
|
|
31782
|
+
function closestLocales(input2) {
|
|
31783
|
+
const typed = input2.trim().toLowerCase().replace(/_/g, "-");
|
|
31784
|
+
const language = typed.split("-")[0] ?? "";
|
|
31785
|
+
const found = /* @__PURE__ */ new Set();
|
|
31786
|
+
for (const locale of SUPPORTED_LOCALES) {
|
|
31787
|
+
if (locale.split("-")[0] === language) found.add(locale);
|
|
31788
|
+
}
|
|
31789
|
+
if (typed.length >= 3) {
|
|
31790
|
+
for (const locale of SUPPORTED_LOCALES) {
|
|
31791
|
+
if (LOCALE_NAMES[locale].toLowerCase().includes(typed))
|
|
31792
|
+
found.add(locale);
|
|
31793
|
+
}
|
|
31794
|
+
}
|
|
31795
|
+
for (const locale of SUPPORTED_LOCALES) {
|
|
31796
|
+
if (editDistance(locale, typed) === 1) found.add(locale);
|
|
31797
|
+
}
|
|
31798
|
+
return [...found].slice(0, MAX_SUGGESTIONS);
|
|
31799
|
+
}
|
|
31800
|
+
function resolveLocales(inputs) {
|
|
31801
|
+
const resolved = [];
|
|
31802
|
+
const unsupported = [];
|
|
31803
|
+
for (const input2 of inputs) {
|
|
31804
|
+
const locale = canonicalGlossaryLocale(input2.trim());
|
|
31805
|
+
if (!locale) {
|
|
31806
|
+
unsupported.push(input2);
|
|
31807
|
+
continue;
|
|
31808
|
+
}
|
|
31809
|
+
if (!resolved.includes(locale)) resolved.push(locale);
|
|
31810
|
+
}
|
|
31811
|
+
if (unsupported.length === 0) return resolved;
|
|
31812
|
+
const lines = unsupported.map((input2) => {
|
|
31813
|
+
const close = closestLocales(input2);
|
|
31814
|
+
return close.length > 0 ? `For ${input2}, the closest supported codes are ${close.join(", ")}.` : `Nothing supported is close to ${input2}.`;
|
|
31815
|
+
});
|
|
31816
|
+
const anyWithout = unsupported.some((i) => closestLocales(i).length === 0);
|
|
31817
|
+
if (anyWithout) {
|
|
31818
|
+
lines.push(`Supported codes: ${SUPPORTED_LOCALES.join(", ")}.`);
|
|
31819
|
+
}
|
|
31820
|
+
throw new CliError(
|
|
31821
|
+
`TolkBot does not support ${unsupported.join(", ")}.`,
|
|
31822
|
+
lines.join(" "),
|
|
31823
|
+
"unsupported_locale"
|
|
31824
|
+
);
|
|
31825
|
+
}
|
|
31826
|
+
function planAdd(project, rows, locales, now) {
|
|
31827
|
+
const base = locales.find((l) => sameLocale(l, project.baseLanguage));
|
|
31828
|
+
if (base) {
|
|
31829
|
+
throw new UsageError(
|
|
31830
|
+
`${base} is the project's base language, so it cannot be added as a target.`,
|
|
31831
|
+
"Name a language to translate into."
|
|
31832
|
+
);
|
|
31833
|
+
}
|
|
31834
|
+
return locales.map((locale) => {
|
|
31835
|
+
const onProject = project.targetLanguages.some(
|
|
31836
|
+
(t) => sameLocale(t, locale)
|
|
31837
|
+
);
|
|
31838
|
+
if (!onProject)
|
|
31839
|
+
return { locale, action: "add", setup: "not-on-project" };
|
|
31840
|
+
const row = rows.find((r) => sameLocale(r.locale, locale));
|
|
31841
|
+
const setup = localeSetupState(row, now);
|
|
31842
|
+
const action = setup === "set-up" || setup === "running" ? "none" : "set_up";
|
|
31843
|
+
return { locale, action, setup };
|
|
31844
|
+
});
|
|
31845
|
+
}
|
|
31846
|
+
function targetsAfter(project, plan) {
|
|
31847
|
+
return [
|
|
31848
|
+
...project.targetLanguages,
|
|
31849
|
+
...plan.filter((p) => p.action === "add").map((p) => p.locale)
|
|
31850
|
+
];
|
|
31851
|
+
}
|
|
31852
|
+
function localeName(locale) {
|
|
31853
|
+
return LOCALE_NAMES[locale] ?? locale;
|
|
31854
|
+
}
|
|
31855
|
+
function describeOutcome(outcome) {
|
|
31856
|
+
const name = `${outcome.locale} (${localeName(outcome.locale)})`;
|
|
31857
|
+
switch (outcome.outcome) {
|
|
31858
|
+
case "added":
|
|
31859
|
+
return `\u2713 ${name} added and set up.`;
|
|
31860
|
+
case "set_up":
|
|
31861
|
+
return `\u2713 ${name} was on the project; now set up.`;
|
|
31862
|
+
case "unchanged":
|
|
31863
|
+
return outcome.setup === "running" ? `- ${name} is already on the project and being set up.` : `- ${name} is already on the project.`;
|
|
31864
|
+
case "failed":
|
|
31865
|
+
return `\u2717 ${name} is on the project, but setting it up failed: ${outcome.error}`;
|
|
31866
|
+
}
|
|
31867
|
+
}
|
|
31868
|
+
function describeNextSteps(ready, autoCreatePR) {
|
|
31869
|
+
if (ready.length === 0) return [];
|
|
31870
|
+
const lines = [
|
|
31871
|
+
"Next, fill the files now:",
|
|
31872
|
+
...ready.map((l) => ` ${translateCommand(l)}`)
|
|
31873
|
+
];
|
|
31874
|
+
if (autoCreatePR) {
|
|
31875
|
+
lines.push(
|
|
31876
|
+
"Or wait: pull requests are on for this project, so the next push that changes the base file opens one per language, with the keys that push added or changed."
|
|
31877
|
+
);
|
|
31878
|
+
}
|
|
31879
|
+
return lines;
|
|
31880
|
+
}
|
|
31881
|
+
function translateCommand(locale) {
|
|
31882
|
+
return `tolkbot translate --dst ${locale}`;
|
|
31883
|
+
}
|
|
31884
|
+
|
|
31885
|
+
// src/commands/languages/add.tsx
|
|
31675
31886
|
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
31887
|
+
async function runLanguagesAdd(opts) {
|
|
31888
|
+
const locales = resolveLocales(opts.locales);
|
|
31889
|
+
const ctx = await loadPlanContext(process.cwd());
|
|
31890
|
+
const { project } = ctx;
|
|
31891
|
+
const ids = {
|
|
31892
|
+
organizationId: project.organizationId,
|
|
31893
|
+
projectId: project._id
|
|
31894
|
+
};
|
|
31895
|
+
const rows = await ctx.client.query(api.projectLocales.list, ids);
|
|
31896
|
+
const plan = planAdd(project, rows, locales, Date.now());
|
|
31897
|
+
const outcomes = [];
|
|
31898
|
+
const progress = renderTransient(
|
|
31899
|
+
/* @__PURE__ */ jsxs12(Box12, { children: [
|
|
31900
|
+
/* @__PURE__ */ jsx12(Spinner9, {}),
|
|
31901
|
+
/* @__PURE__ */ jsxs12(Text12, { children: [
|
|
31902
|
+
" ",
|
|
31903
|
+
"Adding ",
|
|
31904
|
+
locales.join(", "),
|
|
31905
|
+
" to ",
|
|
31906
|
+
project.name,
|
|
31907
|
+
"\u2026"
|
|
31908
|
+
] })
|
|
31909
|
+
] })
|
|
31910
|
+
);
|
|
31911
|
+
try {
|
|
31912
|
+
if (plan.some((p) => p.action === "add")) {
|
|
31913
|
+
await ctx.client.mutation(api.projects.update, {
|
|
31914
|
+
...ids,
|
|
31915
|
+
patch: {
|
|
31916
|
+
targetLanguages: targetsAfter(project, plan)
|
|
31917
|
+
}
|
|
31918
|
+
});
|
|
31919
|
+
}
|
|
31920
|
+
const client3 = await getAuthenticatedConvexClient();
|
|
31921
|
+
for (const { locale, action, setup } of plan) {
|
|
31922
|
+
if (action === "none") {
|
|
31923
|
+
outcomes.push({
|
|
31924
|
+
locale,
|
|
31925
|
+
outcome: "unchanged",
|
|
31926
|
+
setup: setup === "running" ? "running" : "set-up"
|
|
31927
|
+
});
|
|
31928
|
+
continue;
|
|
31929
|
+
}
|
|
31930
|
+
try {
|
|
31931
|
+
await client3.action(api.actions.onboardLocale.onboardLocale, {
|
|
31932
|
+
...ids,
|
|
31933
|
+
locale,
|
|
31934
|
+
mode: opts.existing
|
|
31935
|
+
});
|
|
31936
|
+
outcomes.push({
|
|
31937
|
+
locale,
|
|
31938
|
+
outcome: action === "add" ? "added" : "set_up"
|
|
31939
|
+
});
|
|
31940
|
+
} catch (error62) {
|
|
31941
|
+
outcomes.push({
|
|
31942
|
+
locale,
|
|
31943
|
+
outcome: "failed",
|
|
31944
|
+
error: toCliError(error62).baseMessage
|
|
31945
|
+
});
|
|
31946
|
+
}
|
|
31947
|
+
}
|
|
31948
|
+
} finally {
|
|
31949
|
+
progress.unmount();
|
|
31950
|
+
}
|
|
31951
|
+
const ready = outcomes.filter((o) => o.outcome === "added" || o.outcome === "set_up").map((o) => o.locale);
|
|
31952
|
+
const autoCreatePR = project.workflow?.autoCreatePR ?? DEFAULT_BEHAVIORAL_SETTINGS.workflow.autoCreatePR;
|
|
31953
|
+
const failed = outcomes.filter((o) => o.outcome === "failed");
|
|
31954
|
+
const payload = {
|
|
31955
|
+
project: { name: project.name, slug: project.slug },
|
|
31956
|
+
existing: opts.existing,
|
|
31957
|
+
changed: ready.length > 0 || plan.some((p) => p.action === "add"),
|
|
31958
|
+
languages: outcomes,
|
|
31959
|
+
targetLanguages: targetsAfter(project, plan),
|
|
31960
|
+
next: {
|
|
31961
|
+
translate: ready.map(translateCommand),
|
|
31962
|
+
pullRequestOnPush: autoCreatePR
|
|
31963
|
+
}
|
|
31964
|
+
};
|
|
31965
|
+
const failure2 = failed.length > 0 ? new CliError(
|
|
31966
|
+
`Setting up ${failed.map((o) => o.locale).join(", ")} failed.`,
|
|
31967
|
+
"Run the same command again to retry, or set it up from the project's Translations page."
|
|
31968
|
+
) : null;
|
|
31969
|
+
if (opts.json) {
|
|
31970
|
+
if (!failure2) jsonSuccess(payload);
|
|
31971
|
+
jsonResult(payload, 1);
|
|
31972
|
+
fail(failure2);
|
|
31973
|
+
}
|
|
31974
|
+
for (const outcome of outcomes) console.log(describeOutcome(outcome));
|
|
31975
|
+
if (!payload.changed) console.log("Nothing changed.");
|
|
31976
|
+
const next = describeNextSteps(ready, autoCreatePR);
|
|
31977
|
+
if (next.length > 0) {
|
|
31978
|
+
console.log("");
|
|
31979
|
+
for (const line of next) console.log(line);
|
|
31980
|
+
}
|
|
31981
|
+
if (failure2) fail(failure2);
|
|
31982
|
+
}
|
|
31983
|
+
|
|
31984
|
+
// src/commands/languages/list.ts
|
|
31985
|
+
var SETUP_WORDS = {
|
|
31986
|
+
"set-up": "set up",
|
|
31987
|
+
running: "being set up",
|
|
31988
|
+
failed: "setup failed",
|
|
31989
|
+
"not-set-up": "not set up"
|
|
31990
|
+
};
|
|
31991
|
+
async function runLanguagesList(opts) {
|
|
31992
|
+
const ctx = await loadPlanContext(process.cwd());
|
|
31993
|
+
const { project } = ctx;
|
|
31994
|
+
const rows = await ctx.client.query(api.projectLocales.list, {
|
|
31995
|
+
organizationId: project.organizationId,
|
|
31996
|
+
projectId: project._id
|
|
31997
|
+
});
|
|
31998
|
+
const scope = scopeOf(project);
|
|
31999
|
+
const files = await listLocaleFiles(ctx.root, scope);
|
|
32000
|
+
const sourceFiles = filesForLocale(files, project.baseLanguage);
|
|
32001
|
+
const found = (file2) => ({
|
|
32002
|
+
path: file2.relativePath,
|
|
32003
|
+
exists: true
|
|
32004
|
+
});
|
|
32005
|
+
const fromPattern = (locale) => {
|
|
32006
|
+
const existing = filesForLocale(files, locale);
|
|
32007
|
+
if (existing.length > 0) return existing.map(found);
|
|
32008
|
+
return [
|
|
32009
|
+
{
|
|
32010
|
+
path: replaceLocalePlaceholder(fullPattern(scope), locale),
|
|
32011
|
+
exists: false
|
|
32012
|
+
}
|
|
32013
|
+
];
|
|
32014
|
+
};
|
|
32015
|
+
const base = {
|
|
32016
|
+
locale: project.baseLanguage,
|
|
32017
|
+
name: localeName(project.baseLanguage),
|
|
32018
|
+
files: fromPattern(project.baseLanguage)
|
|
32019
|
+
};
|
|
32020
|
+
const now = Date.now();
|
|
32021
|
+
const targets = project.targetLanguages.map((locale) => ({
|
|
32022
|
+
locale,
|
|
32023
|
+
name: localeName(locale),
|
|
32024
|
+
setup: localeSetupState(
|
|
32025
|
+
rows.find((r) => sameLocale(r.locale, locale)),
|
|
32026
|
+
now
|
|
32027
|
+
),
|
|
32028
|
+
files: sourceFiles.length === 0 ? fromPattern(locale) : sourceFiles.map((source) => {
|
|
32029
|
+
const target = targetFileFor(
|
|
32030
|
+
source,
|
|
32031
|
+
locale,
|
|
32032
|
+
files,
|
|
32033
|
+
scope
|
|
32034
|
+
);
|
|
32035
|
+
return {
|
|
32036
|
+
path: target.relativePath,
|
|
32037
|
+
exists: target.existing !== null
|
|
32038
|
+
};
|
|
32039
|
+
})
|
|
32040
|
+
}));
|
|
32041
|
+
if (opts.json) {
|
|
32042
|
+
jsonSuccess({
|
|
32043
|
+
project: { name: project.name, slug: project.slug },
|
|
32044
|
+
pattern: fullPattern(scope),
|
|
32045
|
+
base,
|
|
32046
|
+
targets
|
|
32047
|
+
});
|
|
32048
|
+
}
|
|
32049
|
+
console.log(
|
|
32050
|
+
`${project.name} (${project.slug}), files ${fullPattern(scope)}`
|
|
32051
|
+
);
|
|
32052
|
+
console.log("");
|
|
32053
|
+
const printFiles = (language) => {
|
|
32054
|
+
for (const file2 of language.files) {
|
|
32055
|
+
console.log(
|
|
32056
|
+
` ${file2.path}${file2.exists ? "" : " (no file yet)"}`
|
|
32057
|
+
);
|
|
32058
|
+
}
|
|
32059
|
+
};
|
|
32060
|
+
console.log(`${base.locale} (${base.name}), base language`);
|
|
32061
|
+
printFiles(base);
|
|
32062
|
+
for (const target of targets) {
|
|
32063
|
+
console.log(
|
|
32064
|
+
`${target.locale} (${target.name}), ${SETUP_WORDS[target.setup]}`
|
|
32065
|
+
);
|
|
32066
|
+
printFiles(target);
|
|
32067
|
+
}
|
|
32068
|
+
if (targets.length === 0) {
|
|
32069
|
+
console.log("");
|
|
32070
|
+
console.log(
|
|
32071
|
+
"No target languages yet. Add one with 'tolkbot languages add <code>'."
|
|
32072
|
+
);
|
|
32073
|
+
}
|
|
32074
|
+
}
|
|
32075
|
+
|
|
32076
|
+
// src/commands/languages/index.ts
|
|
32077
|
+
var languagesCommand = new Command4("languages").description(
|
|
32078
|
+
"List the project's languages and add target languages"
|
|
32079
|
+
);
|
|
32080
|
+
var JSON_HELP2 = "Output as JSON (machine-readable)";
|
|
32081
|
+
languagesCommand.command("list").description(
|
|
32082
|
+
"The base language and the target languages, with the files each one maps to and whether they exist"
|
|
32083
|
+
).option("--json", JSON_HELP2).action(async (opts) => {
|
|
32084
|
+
const schema = z6.object({ json: z6.boolean().optional() });
|
|
32085
|
+
await runLanguagesList(validateOrExit(schema, opts));
|
|
32086
|
+
});
|
|
32087
|
+
languagesCommand.command("add").description(
|
|
32088
|
+
"Add target languages to the project and set them up, as the dashboard's Add language dialog does. Translating is 'tolkbot translate'"
|
|
32089
|
+
).argument("<locales...>", "Locale codes, e.g. nb de pt-BR").addOption(
|
|
32090
|
+
new Option(
|
|
32091
|
+
"--existing <mode>",
|
|
32092
|
+
"What to do with translations the repository already has: keep them as written by a person (trust), or flag them for review"
|
|
32093
|
+
).choices(["trust", "review"]).default(DEFAULT_EXISTING_MODE)
|
|
32094
|
+
).option("--json", JSON_HELP2).addHelpText(
|
|
32095
|
+
"after",
|
|
32096
|
+
`
|
|
32097
|
+
Examples:
|
|
32098
|
+
$ tolkbot languages add nb
|
|
32099
|
+
$ tolkbot languages add de fr --existing review`
|
|
32100
|
+
).action(async (locales, opts) => {
|
|
32101
|
+
const schema = z6.object({
|
|
32102
|
+
locales: z6.array(z6.string().min(1)).min(1),
|
|
32103
|
+
existing: z6.enum(["trust", "review"]),
|
|
32104
|
+
json: z6.boolean().optional()
|
|
32105
|
+
});
|
|
32106
|
+
await runLanguagesAdd(validateOrExit(schema, { ...opts, locales }));
|
|
32107
|
+
});
|
|
32108
|
+
|
|
32109
|
+
// src/commands/learnings/index.ts
|
|
32110
|
+
import { Command as Command5 } from "commander";
|
|
32111
|
+
import { z as z7 } from "zod/v4";
|
|
32112
|
+
|
|
32113
|
+
// src/commands/learnings/archive.tsx
|
|
32114
|
+
import { Spinner as Spinner10 } from "@inkjs/ui";
|
|
32115
|
+
import { Box as Box13, render as render12, Text as Text13 } from "ink";
|
|
32116
|
+
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
31676
32117
|
function ArchiveUI({ state }) {
|
|
31677
32118
|
if (state.type === "archiving") {
|
|
31678
|
-
return /* @__PURE__ */
|
|
31679
|
-
/* @__PURE__ */
|
|
31680
|
-
/* @__PURE__ */
|
|
32119
|
+
return /* @__PURE__ */ jsxs13(Box13, { children: [
|
|
32120
|
+
/* @__PURE__ */ jsx13(Spinner10, {}),
|
|
32121
|
+
/* @__PURE__ */ jsx13(Text13, { children: " Archiving learning\u2026" })
|
|
31681
32122
|
] });
|
|
31682
32123
|
}
|
|
31683
|
-
return /* @__PURE__ */
|
|
31684
|
-
/* @__PURE__ */
|
|
31685
|
-
/* @__PURE__ */
|
|
32124
|
+
return /* @__PURE__ */ jsxs13(Box13, { children: [
|
|
32125
|
+
/* @__PURE__ */ jsx13(Text13, { color: "green", children: "\u2713" }),
|
|
32126
|
+
/* @__PURE__ */ jsx13(Text13, { children: " Learning archived" })
|
|
31686
32127
|
] });
|
|
31687
32128
|
}
|
|
31688
32129
|
async function runLearningsArchive(opts) {
|
|
@@ -31699,20 +32140,20 @@ async function runLearningsArchive(opts) {
|
|
|
31699
32140
|
jsonSuccess({ id: opts.id, ok: true });
|
|
31700
32141
|
}
|
|
31701
32142
|
const { unmount } = renderTransient(
|
|
31702
|
-
/* @__PURE__ */
|
|
32143
|
+
/* @__PURE__ */ jsx13(ArchiveUI, { state: { type: "archiving" } })
|
|
31703
32144
|
);
|
|
31704
32145
|
try {
|
|
31705
32146
|
await run();
|
|
31706
32147
|
} finally {
|
|
31707
32148
|
unmount();
|
|
31708
32149
|
}
|
|
31709
|
-
render12(/* @__PURE__ */
|
|
32150
|
+
render12(/* @__PURE__ */ jsx13(ArchiveUI, { state: { type: "success" } })).unmount();
|
|
31710
32151
|
}
|
|
31711
32152
|
|
|
31712
32153
|
// src/commands/learnings/list.tsx
|
|
31713
|
-
import { Spinner as
|
|
31714
|
-
import { Box as
|
|
31715
|
-
import { jsx as
|
|
32154
|
+
import { Spinner as Spinner11 } from "@inkjs/ui";
|
|
32155
|
+
import { Box as Box14, render as render13, Text as Text14 } from "ink";
|
|
32156
|
+
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
31716
32157
|
var feedbackLabels = {
|
|
31717
32158
|
"incorrect-term": "Incorrect term",
|
|
31718
32159
|
"wrong-tone": "Wrong tone",
|
|
@@ -31722,47 +32163,47 @@ var feedbackLabels = {
|
|
|
31722
32163
|
};
|
|
31723
32164
|
function LearningsListUI({ state }) {
|
|
31724
32165
|
if (state.type === "loading") {
|
|
31725
|
-
return /* @__PURE__ */
|
|
31726
|
-
/* @__PURE__ */
|
|
31727
|
-
/* @__PURE__ */
|
|
32166
|
+
return /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
32167
|
+
/* @__PURE__ */ jsx14(Spinner11, {}),
|
|
32168
|
+
/* @__PURE__ */ jsx14(Text14, { children: " Loading learnings\u2026" })
|
|
31728
32169
|
] });
|
|
31729
32170
|
}
|
|
31730
32171
|
const { learnings } = state;
|
|
31731
32172
|
if (learnings.length === 0) {
|
|
31732
|
-
return /* @__PURE__ */
|
|
32173
|
+
return /* @__PURE__ */ jsx14(Box14, { children: /* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "No learnings found." }) });
|
|
31733
32174
|
}
|
|
31734
|
-
return /* @__PURE__ */
|
|
31735
|
-
/* @__PURE__ */
|
|
32175
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
32176
|
+
/* @__PURE__ */ jsx14(Box14, { marginBottom: 1, children: /* @__PURE__ */ jsxs14(Text14, { bold: true, children: [
|
|
31736
32177
|
learnings.length,
|
|
31737
32178
|
" learning",
|
|
31738
32179
|
learnings.length === 1 ? "" : "s"
|
|
31739
32180
|
] }) }),
|
|
31740
|
-
learnings.map((l) => /* @__PURE__ */
|
|
31741
|
-
/* @__PURE__ */
|
|
31742
|
-
/* @__PURE__ */
|
|
32181
|
+
learnings.map((l) => /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", marginBottom: 1, children: [
|
|
32182
|
+
/* @__PURE__ */ jsxs14(Box14, { gap: 1, children: [
|
|
32183
|
+
/* @__PURE__ */ jsxs14(Text14, { bold: true, children: [
|
|
31743
32184
|
l.srcLocale,
|
|
31744
32185
|
" \u2192 ",
|
|
31745
32186
|
l.dstLocale
|
|
31746
32187
|
] }),
|
|
31747
|
-
/* @__PURE__ */
|
|
32188
|
+
/* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
31748
32189
|
"[",
|
|
31749
32190
|
feedbackLabels[l.feedbackType] ?? l.feedbackType,
|
|
31750
32191
|
"]"
|
|
31751
32192
|
] }),
|
|
31752
|
-
l.status === "archived" && /* @__PURE__ */
|
|
32193
|
+
l.status === "archived" && /* @__PURE__ */ jsx14(Text14, { color: "yellow", children: "[archived]" })
|
|
31753
32194
|
] }),
|
|
31754
|
-
/* @__PURE__ */
|
|
32195
|
+
/* @__PURE__ */ jsx14(Box14, { paddingLeft: 2, children: /* @__PURE__ */ jsxs14(Text14, { children: [
|
|
31755
32196
|
'"',
|
|
31756
32197
|
l.sourceText,
|
|
31757
32198
|
'" \u2192 "',
|
|
31758
32199
|
l.suggestedTranslation,
|
|
31759
32200
|
'"'
|
|
31760
32201
|
] }) }),
|
|
31761
|
-
l.reasoning && /* @__PURE__ */
|
|
32202
|
+
l.reasoning && /* @__PURE__ */ jsx14(Box14, { paddingLeft: 2, children: /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
31762
32203
|
"Reason: ",
|
|
31763
32204
|
l.reasoning
|
|
31764
32205
|
] }) }),
|
|
31765
|
-
/* @__PURE__ */
|
|
32206
|
+
/* @__PURE__ */ jsx14(Box14, { paddingLeft: 2, children: /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
31766
32207
|
"ID: ",
|
|
31767
32208
|
l._id
|
|
31768
32209
|
] }) })
|
|
@@ -31797,7 +32238,7 @@ async function runLearningsList(opts) {
|
|
|
31797
32238
|
});
|
|
31798
32239
|
}
|
|
31799
32240
|
const { unmount } = renderTransient(
|
|
31800
|
-
/* @__PURE__ */
|
|
32241
|
+
/* @__PURE__ */ jsx14(LearningsListUI, { state: { type: "loading" } })
|
|
31801
32242
|
);
|
|
31802
32243
|
let learnings;
|
|
31803
32244
|
try {
|
|
@@ -31806,24 +32247,24 @@ async function runLearningsList(opts) {
|
|
|
31806
32247
|
unmount();
|
|
31807
32248
|
}
|
|
31808
32249
|
render13(
|
|
31809
|
-
/* @__PURE__ */
|
|
32250
|
+
/* @__PURE__ */ jsx14(LearningsListUI, { state: { type: "success", learnings } })
|
|
31810
32251
|
).unmount();
|
|
31811
32252
|
}
|
|
31812
32253
|
|
|
31813
32254
|
// src/commands/learnings/remove.tsx
|
|
31814
|
-
import { Spinner as
|
|
31815
|
-
import { Box as
|
|
31816
|
-
import { jsx as
|
|
32255
|
+
import { Spinner as Spinner12 } from "@inkjs/ui";
|
|
32256
|
+
import { Box as Box15, render as render14, Text as Text15 } from "ink";
|
|
32257
|
+
import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
31817
32258
|
function RemoveUI2({ state }) {
|
|
31818
32259
|
if (state.type === "removing") {
|
|
31819
|
-
return /* @__PURE__ */
|
|
31820
|
-
/* @__PURE__ */
|
|
31821
|
-
/* @__PURE__ */
|
|
32260
|
+
return /* @__PURE__ */ jsxs15(Box15, { children: [
|
|
32261
|
+
/* @__PURE__ */ jsx15(Spinner12, {}),
|
|
32262
|
+
/* @__PURE__ */ jsx15(Text15, { children: " Removing learning\u2026" })
|
|
31822
32263
|
] });
|
|
31823
32264
|
}
|
|
31824
|
-
return /* @__PURE__ */
|
|
31825
|
-
/* @__PURE__ */
|
|
31826
|
-
/* @__PURE__ */
|
|
32265
|
+
return /* @__PURE__ */ jsxs15(Box15, { children: [
|
|
32266
|
+
/* @__PURE__ */ jsx15(Text15, { color: "green", children: "\u2713" }),
|
|
32267
|
+
/* @__PURE__ */ jsx15(Text15, { children: " Learning removed" })
|
|
31827
32268
|
] });
|
|
31828
32269
|
}
|
|
31829
32270
|
async function runLearningsRemove(opts) {
|
|
@@ -31840,62 +32281,62 @@ async function runLearningsRemove(opts) {
|
|
|
31840
32281
|
jsonSuccess({ id: opts.id, ok: true });
|
|
31841
32282
|
}
|
|
31842
32283
|
const { unmount } = renderTransient(
|
|
31843
|
-
/* @__PURE__ */
|
|
32284
|
+
/* @__PURE__ */ jsx15(RemoveUI2, { state: { type: "removing" } })
|
|
31844
32285
|
);
|
|
31845
32286
|
try {
|
|
31846
32287
|
await run();
|
|
31847
32288
|
} finally {
|
|
31848
32289
|
unmount();
|
|
31849
32290
|
}
|
|
31850
|
-
render14(/* @__PURE__ */
|
|
32291
|
+
render14(/* @__PURE__ */ jsx15(RemoveUI2, { state: { type: "success" } })).unmount();
|
|
31851
32292
|
}
|
|
31852
32293
|
|
|
31853
32294
|
// src/commands/learnings/show.tsx
|
|
31854
|
-
import { Spinner as
|
|
31855
|
-
import { Box as
|
|
31856
|
-
import { jsx as
|
|
32295
|
+
import { Spinner as Spinner13 } from "@inkjs/ui";
|
|
32296
|
+
import { Box as Box16, render as render15, Text as Text16 } from "ink";
|
|
32297
|
+
import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
31857
32298
|
function LearningShowUI({ state }) {
|
|
31858
32299
|
if (state.type === "loading") {
|
|
31859
|
-
return /* @__PURE__ */
|
|
31860
|
-
/* @__PURE__ */
|
|
31861
|
-
/* @__PURE__ */
|
|
32300
|
+
return /* @__PURE__ */ jsxs16(Box16, { children: [
|
|
32301
|
+
/* @__PURE__ */ jsx16(Spinner13, {}),
|
|
32302
|
+
/* @__PURE__ */ jsx16(Text16, { children: " Loading learning\u2026" })
|
|
31862
32303
|
] });
|
|
31863
32304
|
}
|
|
31864
32305
|
const { learning } = state;
|
|
31865
|
-
return /* @__PURE__ */
|
|
31866
|
-
/* @__PURE__ */
|
|
31867
|
-
/* @__PURE__ */
|
|
31868
|
-
/* @__PURE__ */
|
|
32306
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
|
|
32307
|
+
/* @__PURE__ */ jsxs16(Box16, { gap: 1, children: [
|
|
32308
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: "Source text:" }),
|
|
32309
|
+
/* @__PURE__ */ jsx16(Text16, { children: learning.sourceText })
|
|
31869
32310
|
] }),
|
|
31870
|
-
/* @__PURE__ */
|
|
31871
|
-
/* @__PURE__ */
|
|
31872
|
-
/* @__PURE__ */
|
|
32311
|
+
/* @__PURE__ */ jsxs16(Box16, { gap: 1, children: [
|
|
32312
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: "Suggested translation:" }),
|
|
32313
|
+
/* @__PURE__ */ jsx16(Text16, { children: learning.suggestedTranslation })
|
|
31873
32314
|
] }),
|
|
31874
|
-
/* @__PURE__ */
|
|
31875
|
-
/* @__PURE__ */
|
|
31876
|
-
/* @__PURE__ */
|
|
32315
|
+
/* @__PURE__ */ jsxs16(Box16, { gap: 1, children: [
|
|
32316
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: "Locales:" }),
|
|
32317
|
+
/* @__PURE__ */ jsxs16(Text16, { children: [
|
|
31877
32318
|
learning.srcLocale,
|
|
31878
32319
|
" \u2192 ",
|
|
31879
32320
|
learning.dstLocale
|
|
31880
32321
|
] })
|
|
31881
32322
|
] }),
|
|
31882
|
-
/* @__PURE__ */
|
|
31883
|
-
/* @__PURE__ */
|
|
31884
|
-
/* @__PURE__ */
|
|
32323
|
+
/* @__PURE__ */ jsxs16(Box16, { gap: 1, children: [
|
|
32324
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: "Feedback type:" }),
|
|
32325
|
+
/* @__PURE__ */ jsx16(Text16, { children: learning.feedbackType })
|
|
31885
32326
|
] }),
|
|
31886
|
-
/* @__PURE__ */
|
|
31887
|
-
/* @__PURE__ */
|
|
31888
|
-
/* @__PURE__ */
|
|
32327
|
+
/* @__PURE__ */ jsxs16(Box16, { gap: 1, children: [
|
|
32328
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: "Reasoning:" }),
|
|
32329
|
+
/* @__PURE__ */ jsx16(Text16, { children: learning.reasoning })
|
|
31889
32330
|
] }),
|
|
31890
|
-
/* @__PURE__ */
|
|
31891
|
-
/* @__PURE__ */
|
|
31892
|
-
/* @__PURE__ */
|
|
32331
|
+
/* @__PURE__ */ jsxs16(Box16, { gap: 1, children: [
|
|
32332
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: "Status:" }),
|
|
32333
|
+
/* @__PURE__ */ jsx16(Text16, { color: learning.status === "active" ? "green" : "yellow", children: learning.status })
|
|
31893
32334
|
] }),
|
|
31894
|
-
/* @__PURE__ */
|
|
31895
|
-
/* @__PURE__ */
|
|
31896
|
-
/* @__PURE__ */
|
|
32335
|
+
/* @__PURE__ */ jsxs16(Box16, { gap: 1, children: [
|
|
32336
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: "Source:" }),
|
|
32337
|
+
/* @__PURE__ */ jsx16(Text16, { children: learning.source })
|
|
31897
32338
|
] }),
|
|
31898
|
-
/* @__PURE__ */
|
|
32339
|
+
/* @__PURE__ */ jsx16(Box16, { marginTop: 1, children: /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
|
|
31899
32340
|
"ID: ",
|
|
31900
32341
|
learning._id
|
|
31901
32342
|
] }) })
|
|
@@ -31933,7 +32374,7 @@ async function runLearningsShow(opts) {
|
|
|
31933
32374
|
});
|
|
31934
32375
|
}
|
|
31935
32376
|
const { unmount } = renderTransient(
|
|
31936
|
-
/* @__PURE__ */
|
|
32377
|
+
/* @__PURE__ */ jsx16(LearningShowUI, { state: { type: "loading" } })
|
|
31937
32378
|
);
|
|
31938
32379
|
let learning;
|
|
31939
32380
|
try {
|
|
@@ -31941,50 +32382,287 @@ async function runLearningsShow(opts) {
|
|
|
31941
32382
|
} finally {
|
|
31942
32383
|
unmount();
|
|
31943
32384
|
}
|
|
31944
|
-
render15(/* @__PURE__ */
|
|
32385
|
+
render15(/* @__PURE__ */ jsx16(LearningShowUI, { state: { type: "success", learning } })).unmount();
|
|
31945
32386
|
}
|
|
31946
32387
|
|
|
31947
32388
|
// src/commands/learnings/index.ts
|
|
31948
|
-
var learningsCommand = new
|
|
32389
|
+
var learningsCommand = new Command5("learnings").description(
|
|
31949
32390
|
"View and manage translation learnings"
|
|
31950
32391
|
);
|
|
31951
32392
|
learningsCommand.command("list").description("List translation learnings for the current project").option("--status <status>", "Filter by status (active or archived)").option("--limit <n>", "Max number of results", (v) => Number(v), 100).option("--json", "Output as JSON (machine-readable)").action(async (opts) => {
|
|
31952
|
-
const schema =
|
|
31953
|
-
status:
|
|
31954
|
-
limit:
|
|
31955
|
-
json:
|
|
32393
|
+
const schema = z7.object({
|
|
32394
|
+
status: z7.enum(["active", "archived"]).optional(),
|
|
32395
|
+
limit: z7.coerce.number().int().positive().default(100),
|
|
32396
|
+
json: z7.boolean().optional()
|
|
31956
32397
|
});
|
|
31957
32398
|
const parsed = validateOrExit(schema, opts);
|
|
31958
32399
|
await runLearningsList(parsed);
|
|
31959
32400
|
});
|
|
31960
32401
|
learningsCommand.command("show").description("Show details of a learning").requiredOption("--id <learningId>", "Learning ID").option("--json", "Output as JSON (machine-readable)").action(async (opts) => {
|
|
31961
|
-
const schema =
|
|
31962
|
-
id:
|
|
31963
|
-
json:
|
|
32402
|
+
const schema = z7.object({
|
|
32403
|
+
id: z7.string().min(1),
|
|
32404
|
+
json: z7.boolean().optional()
|
|
31964
32405
|
});
|
|
31965
32406
|
const parsed = validateOrExit(schema, opts);
|
|
31966
32407
|
await runLearningsShow(parsed);
|
|
31967
32408
|
});
|
|
31968
32409
|
learningsCommand.command("archive").description("Archive a learning (keeps it but excludes from translations)").requiredOption("--id <learningId>", "Learning ID").option("--json", "Output as JSON (machine-readable)").action(async (opts) => {
|
|
31969
|
-
const schema =
|
|
31970
|
-
id:
|
|
31971
|
-
json:
|
|
32410
|
+
const schema = z7.object({
|
|
32411
|
+
id: z7.string().min(1),
|
|
32412
|
+
json: z7.boolean().optional()
|
|
31972
32413
|
});
|
|
31973
32414
|
const parsed = validateOrExit(schema, opts);
|
|
31974
32415
|
await runLearningsArchive(parsed);
|
|
31975
32416
|
});
|
|
31976
32417
|
learningsCommand.command("remove").description("Permanently remove a learning").requiredOption("--id <learningId>", "Learning ID").option("--json", "Output as JSON (machine-readable)").action(async (opts) => {
|
|
31977
|
-
const schema =
|
|
31978
|
-
id:
|
|
31979
|
-
json:
|
|
32418
|
+
const schema = z7.object({
|
|
32419
|
+
id: z7.string().min(1),
|
|
32420
|
+
json: z7.boolean().optional()
|
|
31980
32421
|
});
|
|
31981
32422
|
const parsed = validateOrExit(schema, opts);
|
|
31982
32423
|
await runLearningsRemove(parsed);
|
|
31983
32424
|
});
|
|
31984
32425
|
|
|
32426
|
+
// src/commands/status/index.ts
|
|
32427
|
+
import { Command as Command6 } from "commander";
|
|
32428
|
+
import { z as z8 } from "zod/v4";
|
|
32429
|
+
|
|
32430
|
+
// src/commands/status/status.tsx
|
|
32431
|
+
import { Spinner as Spinner14 } from "@inkjs/ui";
|
|
32432
|
+
import { Box as Box17, Text as Text17 } from "ink";
|
|
32433
|
+
|
|
32434
|
+
// src/commands/status/status-core.ts
|
|
32435
|
+
function fullKey4(namespace, key) {
|
|
32436
|
+
return namespace ? `${namespace}.${key}` : key;
|
|
32437
|
+
}
|
|
32438
|
+
function isPersonHold(reason) {
|
|
32439
|
+
return reason === "locked" || reason === "pending-draft";
|
|
32440
|
+
}
|
|
32441
|
+
function count(reasons2) {
|
|
32442
|
+
const byReason = {};
|
|
32443
|
+
for (const reason of reasons2)
|
|
32444
|
+
byReason[reason] = (byReason[reason] ?? 0) + 1;
|
|
32445
|
+
return { total: reasons2.length, byReason };
|
|
32446
|
+
}
|
|
32447
|
+
function openPullRequest(rows, locale) {
|
|
32448
|
+
const row = rows.find(
|
|
32449
|
+
(r) => r.prState === "open" && r.prUrl !== void 0 && sameLocale(r.targetLanguage, locale)
|
|
32450
|
+
);
|
|
32451
|
+
if (!row?.prUrl) return null;
|
|
32452
|
+
return { number: row.prNumber ?? null, url: row.prUrl };
|
|
32453
|
+
}
|
|
32454
|
+
function languageStatus(locale, plan, pullRequests, opts = {}) {
|
|
32455
|
+
const { summary } = plan;
|
|
32456
|
+
const held = [
|
|
32457
|
+
...plan.heldKeys,
|
|
32458
|
+
...plan.protectedKeys.flatMap(
|
|
32459
|
+
({ key, reason }) => isPersonHold(reason) ? [{ key, reason }] : []
|
|
32460
|
+
)
|
|
32461
|
+
];
|
|
32462
|
+
const kept = plan.protectedKeys.flatMap(
|
|
32463
|
+
({ key, reason }) => isPersonHold(reason) ? [] : [{ key, reason }]
|
|
32464
|
+
);
|
|
32465
|
+
const tasks = (reason) => plan.tasks.filter((t) => t.reason === reason).map((t) => fullKey4(t.namespace, t.key));
|
|
32466
|
+
return {
|
|
32467
|
+
locale,
|
|
32468
|
+
expected: summary.totalKeys,
|
|
32469
|
+
upToDate: summary.upToDate,
|
|
32470
|
+
missing: summary.missing,
|
|
32471
|
+
changed: summary.changed,
|
|
32472
|
+
heldByPerson: count(held.map((h) => h.reason)),
|
|
32473
|
+
keptForPerson: count(kept.map((k) => k.reason)),
|
|
32474
|
+
untracked: summary.untracked,
|
|
32475
|
+
pullRequest: openPullRequest(pullRequests, locale),
|
|
32476
|
+
...opts.keys ? {
|
|
32477
|
+
keys: {
|
|
32478
|
+
missing: tasks("missing"),
|
|
32479
|
+
changed: tasks("changed"),
|
|
32480
|
+
heldByPerson: held,
|
|
32481
|
+
keptForPerson: kept,
|
|
32482
|
+
untracked: plan.untrackedKeys.map((k) => k.key)
|
|
32483
|
+
}
|
|
32484
|
+
} : {}
|
|
32485
|
+
};
|
|
32486
|
+
}
|
|
32487
|
+
function needsTranslation(language) {
|
|
32488
|
+
return language.missing > 0 || language.changed > 0;
|
|
32489
|
+
}
|
|
32490
|
+
var REASON_WORDS = {
|
|
32491
|
+
locked: "locked",
|
|
32492
|
+
"pending-draft": "pending draft",
|
|
32493
|
+
manual: "written by a person",
|
|
32494
|
+
"target-edited": "edited since TolkBot wrote it",
|
|
32495
|
+
unknown: "no record of who wrote it"
|
|
32496
|
+
};
|
|
32497
|
+
function reasons(counts) {
|
|
32498
|
+
return Object.entries(counts.byReason).map(
|
|
32499
|
+
([reason, n]) => `${n} ${REASON_WORDS[reason]}`
|
|
32500
|
+
).join(", ");
|
|
32501
|
+
}
|
|
32502
|
+
function describeLanguage(language) {
|
|
32503
|
+
const counts = [
|
|
32504
|
+
`${language.expected} expected`,
|
|
32505
|
+
`${language.upToDate} up to date`,
|
|
32506
|
+
`${language.missing} missing`,
|
|
32507
|
+
`${language.changed} changed since translated`
|
|
32508
|
+
].join(", ");
|
|
32509
|
+
const mark = needsTranslation(language) ? "\u2022" : "\u2713";
|
|
32510
|
+
const lines = [`${mark} ${language.locale}: ${counts}`];
|
|
32511
|
+
if (language.heldByPerson.total > 0) {
|
|
32512
|
+
lines.push(
|
|
32513
|
+
` ${language.heldByPerson.total} held by a person (${reasons(language.heldByPerson)})`
|
|
32514
|
+
);
|
|
32515
|
+
}
|
|
32516
|
+
if (language.keptForPerson.total > 0) {
|
|
32517
|
+
lines.push(
|
|
32518
|
+
` ${language.keptForPerson.total} changed but kept for a person (${reasons(language.keptForPerson)})`
|
|
32519
|
+
);
|
|
32520
|
+
}
|
|
32521
|
+
if (language.untracked > 0) {
|
|
32522
|
+
lines.push(
|
|
32523
|
+
` ${language.untracked} untracked: TolkBot has no record of them`
|
|
32524
|
+
);
|
|
32525
|
+
}
|
|
32526
|
+
if (language.pullRequest) {
|
|
32527
|
+
lines.push(` Pull request: ${language.pullRequest.url}`);
|
|
32528
|
+
}
|
|
32529
|
+
const { keys } = language;
|
|
32530
|
+
if (keys) {
|
|
32531
|
+
const list = (label, names) => {
|
|
32532
|
+
if (names.length === 0) return;
|
|
32533
|
+
lines.push(` ${label}:`);
|
|
32534
|
+
for (const name of names) lines.push(` ${name}`);
|
|
32535
|
+
};
|
|
32536
|
+
list("Missing", keys.missing);
|
|
32537
|
+
list("Changed", keys.changed);
|
|
32538
|
+
list(
|
|
32539
|
+
"Held by a person",
|
|
32540
|
+
keys.heldByPerson.map(
|
|
32541
|
+
(k) => `${k.key} (${REASON_WORDS[k.reason]})`
|
|
32542
|
+
)
|
|
32543
|
+
);
|
|
32544
|
+
list(
|
|
32545
|
+
"Kept for a person",
|
|
32546
|
+
keys.keptForPerson.map(
|
|
32547
|
+
(k) => `${k.key} (${REASON_WORDS[k.reason]})`
|
|
32548
|
+
)
|
|
32549
|
+
);
|
|
32550
|
+
list("Untracked", keys.untracked);
|
|
32551
|
+
}
|
|
32552
|
+
return lines;
|
|
32553
|
+
}
|
|
32554
|
+
|
|
32555
|
+
// src/commands/status/status.tsx
|
|
32556
|
+
import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
32557
|
+
var OFFLINE_HINT = "Without a login, 'tolkbot validate' checks the files on this machine.";
|
|
32558
|
+
async function runStatus(opts) {
|
|
32559
|
+
let ctx;
|
|
32560
|
+
try {
|
|
32561
|
+
ctx = await loadPlanContext(process.cwd());
|
|
32562
|
+
} catch (error62) {
|
|
32563
|
+
if (error62 instanceof AuthError) {
|
|
32564
|
+
throw new AuthError(
|
|
32565
|
+
error62.baseMessage,
|
|
32566
|
+
[error62.hint, OFFLINE_HINT].filter(Boolean).join(" "),
|
|
32567
|
+
error62.code
|
|
32568
|
+
);
|
|
32569
|
+
}
|
|
32570
|
+
throw error62;
|
|
32571
|
+
}
|
|
32572
|
+
const { project } = ctx;
|
|
32573
|
+
const srcLocale = project.baseLanguage;
|
|
32574
|
+
const locales = project.targetLanguages;
|
|
32575
|
+
const progress = renderTransient(
|
|
32576
|
+
/* @__PURE__ */ jsxs17(Box17, { children: [
|
|
32577
|
+
/* @__PURE__ */ jsx17(Spinner14, {}),
|
|
32578
|
+
/* @__PURE__ */ jsxs17(Text17, { children: [
|
|
32579
|
+
" Reading the status of ",
|
|
32580
|
+
project.name,
|
|
32581
|
+
"\u2026"
|
|
32582
|
+
] })
|
|
32583
|
+
] })
|
|
32584
|
+
);
|
|
32585
|
+
const languages = [];
|
|
32586
|
+
let credits;
|
|
32587
|
+
try {
|
|
32588
|
+
const pullRequests = locales.length === 0 ? [] : await ctx.client.query(api.prJobs.listByProject, {
|
|
32589
|
+
organizationId: project.organizationId,
|
|
32590
|
+
projectId: project._id
|
|
32591
|
+
});
|
|
32592
|
+
for (const locale of locales) {
|
|
32593
|
+
const plan = await planForLocale(ctx, srcLocale, locale);
|
|
32594
|
+
languages.push(
|
|
32595
|
+
languageStatus(locale, plan, pullRequests, {
|
|
32596
|
+
keys: opts.keys
|
|
32597
|
+
})
|
|
32598
|
+
);
|
|
32599
|
+
}
|
|
32600
|
+
credits = await readCreditBalance(ctx);
|
|
32601
|
+
} finally {
|
|
32602
|
+
progress.unmount();
|
|
32603
|
+
}
|
|
32604
|
+
const payload = {
|
|
32605
|
+
project: {
|
|
32606
|
+
name: project.name,
|
|
32607
|
+
slug: project.slug,
|
|
32608
|
+
url: `${env.TOLKBOT_WEB_URL}/projects/${project.slug}`,
|
|
32609
|
+
baseLanguage: srcLocale,
|
|
32610
|
+
pattern: fullPattern(scopeOf(project)),
|
|
32611
|
+
autoCreatePR: project.workflow?.autoCreatePR ?? DEFAULT_BEHAVIORAL_SETTINGS.workflow.autoCreatePR
|
|
32612
|
+
},
|
|
32613
|
+
credits: { balance: credits },
|
|
32614
|
+
languages
|
|
32615
|
+
};
|
|
32616
|
+
const outOfDate = languages.some(needsTranslation);
|
|
32617
|
+
const exitCode = opts.exitCode && outOfDate ? 1 : 0;
|
|
32618
|
+
if (opts.json) {
|
|
32619
|
+
if (exitCode === 0) jsonSuccess(payload);
|
|
32620
|
+
jsonResult(payload, exitCode);
|
|
32621
|
+
return;
|
|
32622
|
+
}
|
|
32623
|
+
const { project: p } = payload;
|
|
32624
|
+
console.log(`${p.name} (${p.slug}) ${p.url}`);
|
|
32625
|
+
console.log(
|
|
32626
|
+
`Base language ${p.baseLanguage}, files ${p.pattern}, auto-create pull requests ${p.autoCreatePR ? "on" : "off"}`
|
|
32627
|
+
);
|
|
32628
|
+
console.log(
|
|
32629
|
+
credits === null ? "Credits left: could not be read" : `Credits left: ${credits}`
|
|
32630
|
+
);
|
|
32631
|
+
console.log("");
|
|
32632
|
+
if (languages.length === 0) {
|
|
32633
|
+
console.log(
|
|
32634
|
+
`No target languages configured. Add them in the project settings at ${p.url}/settings.`
|
|
32635
|
+
);
|
|
32636
|
+
}
|
|
32637
|
+
for (const language of languages) {
|
|
32638
|
+
for (const line of describeLanguage(language)) console.log(line);
|
|
32639
|
+
}
|
|
32640
|
+
if (outOfDate) {
|
|
32641
|
+
console.log(
|
|
32642
|
+
"\nRun 'tolkbot translate --all' to translate what is missing or changed."
|
|
32643
|
+
);
|
|
32644
|
+
}
|
|
32645
|
+
process.exitCode = exitCode;
|
|
32646
|
+
}
|
|
32647
|
+
|
|
32648
|
+
// src/commands/status/index.ts
|
|
32649
|
+
var statusCommand = new Command6("status").description(
|
|
32650
|
+
"Show what each language is missing, what waits for a person, the open pull requests and the credits left"
|
|
32651
|
+
).option("--keys", "List the keys by name under each language").option(
|
|
32652
|
+
"--exit-code",
|
|
32653
|
+
"Exit 1 when any language has missing or changed keys"
|
|
32654
|
+
).option("--json", "Output as JSON (machine-readable)").action(async (opts) => {
|
|
32655
|
+
const schema = z8.object({
|
|
32656
|
+
keys: z8.boolean().optional(),
|
|
32657
|
+
exitCode: z8.boolean().optional(),
|
|
32658
|
+
json: z8.boolean().optional()
|
|
32659
|
+
});
|
|
32660
|
+
await runStatus(validateOrExit(schema, opts));
|
|
32661
|
+
});
|
|
32662
|
+
|
|
31985
32663
|
// src/commands/telemetry.ts
|
|
31986
|
-
import { Command as
|
|
31987
|
-
import { z as
|
|
32664
|
+
import { Command as Command7 } from "commander";
|
|
32665
|
+
import { z as z9 } from "zod/v4";
|
|
31988
32666
|
var REASONS = {
|
|
31989
32667
|
env: `disabled by $${TELEMETRY_ENV_VAR}`,
|
|
31990
32668
|
"do-not-track": `disabled by $${DO_NOT_TRACK_ENV_VAR}`,
|
|
@@ -32005,12 +32683,12 @@ async function printStatus(json2) {
|
|
|
32005
32683
|
`Turn it off with \`tolkbot telemetry off\`, $${TELEMETRY_ENV_VAR}=0 or $${DO_NOT_TRACK_ENV_VAR}=1.`
|
|
32006
32684
|
);
|
|
32007
32685
|
}
|
|
32008
|
-
var telemetryCommand = new
|
|
32686
|
+
var telemetryCommand = new Command7("telemetry").description(
|
|
32009
32687
|
"Control anonymous usage reporting"
|
|
32010
32688
|
);
|
|
32011
32689
|
telemetryCommand.command("status", { isDefault: true }).description("Show whether telemetry is on and why").option("--json", "Output as JSON (machine-readable)").action(async (opts) => {
|
|
32012
32690
|
const parsed = validateOrExit(
|
|
32013
|
-
|
|
32691
|
+
z9.object({ json: z9.boolean().optional() }),
|
|
32014
32692
|
opts
|
|
32015
32693
|
);
|
|
32016
32694
|
await printStatus(parsed.json);
|
|
@@ -32027,8 +32705,8 @@ telemetryCommand.command("on").description("Resume reporting usage from this mac
|
|
|
32027
32705
|
});
|
|
32028
32706
|
|
|
32029
32707
|
// src/commands/translate/index.ts
|
|
32030
|
-
import { Command as
|
|
32031
|
-
import { z as
|
|
32708
|
+
import { Command as Command8 } from "commander";
|
|
32709
|
+
import { z as z10 } from "zod/v4";
|
|
32032
32710
|
|
|
32033
32711
|
// src/commands/translate/adopt.tsx
|
|
32034
32712
|
var STAMP_CHUNK2 = 200;
|
|
@@ -32078,7 +32756,7 @@ async function runAdopt(opts) {
|
|
|
32078
32756
|
if (locales.length === 0) {
|
|
32079
32757
|
throw opts.all ? new CliError(
|
|
32080
32758
|
"No target languages configured for this project.",
|
|
32081
|
-
|
|
32759
|
+
"Add one with 'tolkbot languages add <code>'.",
|
|
32082
32760
|
"no_target_languages"
|
|
32083
32761
|
) : new UsageError(
|
|
32084
32762
|
"Either --dst <locale> or --all must be provided."
|
|
@@ -32109,8 +32787,8 @@ async function runAdopt(opts) {
|
|
|
32109
32787
|
|
|
32110
32788
|
// src/commands/translate/edit.tsx
|
|
32111
32789
|
import path10 from "path";
|
|
32112
|
-
import { Spinner as
|
|
32113
|
-
import { Box as
|
|
32790
|
+
import { Spinner as Spinner15 } from "@inkjs/ui";
|
|
32791
|
+
import { Box as Box18, render as render16, Text as Text18 } from "ink";
|
|
32114
32792
|
|
|
32115
32793
|
// src/utils/locale-files.ts
|
|
32116
32794
|
import path9 from "path";
|
|
@@ -32148,25 +32826,25 @@ function resolveKeyInFile(key, targetFile, fileCount, namespace) {
|
|
|
32148
32826
|
}
|
|
32149
32827
|
|
|
32150
32828
|
// src/commands/translate/edit.tsx
|
|
32151
|
-
import { jsx as
|
|
32829
|
+
import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
32152
32830
|
function EditUI({ state }) {
|
|
32153
32831
|
if (state.type === "editing") {
|
|
32154
|
-
return /* @__PURE__ */
|
|
32155
|
-
/* @__PURE__ */
|
|
32156
|
-
/* @__PURE__ */
|
|
32832
|
+
return /* @__PURE__ */ jsxs18(Box18, { children: [
|
|
32833
|
+
/* @__PURE__ */ jsx18(Spinner15, {}),
|
|
32834
|
+
/* @__PURE__ */ jsx18(Text18, { children: " Editing translation\u2026" })
|
|
32157
32835
|
] });
|
|
32158
32836
|
}
|
|
32159
|
-
return /* @__PURE__ */
|
|
32160
|
-
/* @__PURE__ */
|
|
32161
|
-
/* @__PURE__ */
|
|
32162
|
-
/* @__PURE__ */
|
|
32837
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
|
|
32838
|
+
/* @__PURE__ */ jsxs18(Box18, { children: [
|
|
32839
|
+
/* @__PURE__ */ jsx18(Text18, { color: "green", children: "\u2713" }),
|
|
32840
|
+
/* @__PURE__ */ jsxs18(Text18, { children: [
|
|
32163
32841
|
" ",
|
|
32164
32842
|
"Updated ",
|
|
32165
|
-
/* @__PURE__ */
|
|
32843
|
+
/* @__PURE__ */ jsx18(Text18, { bold: true, children: state.key })
|
|
32166
32844
|
] })
|
|
32167
32845
|
] }),
|
|
32168
|
-
/* @__PURE__ */
|
|
32169
|
-
/* @__PURE__ */
|
|
32846
|
+
/* @__PURE__ */ jsx18(Box18, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: state.value }) }),
|
|
32847
|
+
/* @__PURE__ */ jsx18(Box18, { marginTop: 1, children: /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
|
|
32170
32848
|
"File: ",
|
|
32171
32849
|
state.filePath
|
|
32172
32850
|
] }) })
|
|
@@ -32223,20 +32901,20 @@ async function runEdit(opts) {
|
|
|
32223
32901
|
value: result2.value
|
|
32224
32902
|
});
|
|
32225
32903
|
}
|
|
32226
|
-
const { unmount } = renderTransient(/* @__PURE__ */
|
|
32904
|
+
const { unmount } = renderTransient(/* @__PURE__ */ jsx18(EditUI, { state: { type: "editing" } }));
|
|
32227
32905
|
let result;
|
|
32228
32906
|
try {
|
|
32229
32907
|
result = await performEdit(opts);
|
|
32230
32908
|
} finally {
|
|
32231
32909
|
unmount();
|
|
32232
32910
|
}
|
|
32233
|
-
render16(/* @__PURE__ */
|
|
32911
|
+
render16(/* @__PURE__ */ jsx18(EditUI, { state: { type: "success", ...result } })).unmount();
|
|
32234
32912
|
}
|
|
32235
32913
|
|
|
32236
32914
|
// src/commands/translate/translate.tsx
|
|
32237
|
-
import { Spinner as
|
|
32238
|
-
import { Box as
|
|
32239
|
-
import { jsx as
|
|
32915
|
+
import { Spinner as Spinner16 } from "@inkjs/ui";
|
|
32916
|
+
import { Box as Box19, Text as Text19 } from "ink";
|
|
32917
|
+
import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
32240
32918
|
function planOutput(plan) {
|
|
32241
32919
|
return {
|
|
32242
32920
|
...plan.summary,
|
|
@@ -32245,7 +32923,7 @@ function planOutput(plan) {
|
|
|
32245
32923
|
untrackedKeys: plan.untrackedKeys.map((k) => k.key)
|
|
32246
32924
|
};
|
|
32247
32925
|
}
|
|
32248
|
-
function
|
|
32926
|
+
function fullKey5(namespace, key) {
|
|
32249
32927
|
return namespace ? `${namespace}.${key}` : key;
|
|
32250
32928
|
}
|
|
32251
32929
|
function characters(text) {
|
|
@@ -32257,7 +32935,7 @@ function targetLocales(ctx, opts) {
|
|
|
32257
32935
|
if (locales.length === 0) {
|
|
32258
32936
|
throw new CliError(
|
|
32259
32937
|
"No target languages configured.",
|
|
32260
|
-
|
|
32938
|
+
"Add one with 'tolkbot languages add <code>'.",
|
|
32261
32939
|
"no_target_languages"
|
|
32262
32940
|
);
|
|
32263
32941
|
}
|
|
@@ -32273,21 +32951,11 @@ async function runTranslate(opts) {
|
|
|
32273
32951
|
}
|
|
32274
32952
|
await runLanguages(ctx, srcLocale, dstLocales, opts);
|
|
32275
32953
|
}
|
|
32276
|
-
async function creditBalance(ctx) {
|
|
32277
|
-
try {
|
|
32278
|
-
const balance = await ctx.client.query(api.usage.getCreditBalance, {
|
|
32279
|
-
organizationId: ctx.project.organizationId
|
|
32280
|
-
});
|
|
32281
|
-
return balance?.total ?? null;
|
|
32282
|
-
} catch {
|
|
32283
|
-
return null;
|
|
32284
|
-
}
|
|
32285
|
-
}
|
|
32286
32954
|
var NO_ESTIMATE = "No credit estimate exists for this project yet. Keys and characters are what a run would send.";
|
|
32287
32955
|
async function runDryRun(ctx, srcLocale, dstLocales, opts) {
|
|
32288
32956
|
const languages = [];
|
|
32289
32957
|
const progress = renderTransient(
|
|
32290
|
-
/* @__PURE__ */
|
|
32958
|
+
/* @__PURE__ */ jsx19(Working, { text: `Planning ${dstLocales.join(", ")}\u2026` })
|
|
32291
32959
|
);
|
|
32292
32960
|
try {
|
|
32293
32961
|
for (const dstLocale of dstLocales) {
|
|
@@ -32302,7 +32970,7 @@ async function runDryRun(ctx, srcLocale, dstLocales, opts) {
|
|
|
32302
32970
|
0
|
|
32303
32971
|
),
|
|
32304
32972
|
tasks: plan.tasks.map((task) => ({
|
|
32305
|
-
key:
|
|
32973
|
+
key: fullKey5(task.namespace, task.key),
|
|
32306
32974
|
path: task.path,
|
|
32307
32975
|
reason: task.reason,
|
|
32308
32976
|
...opts.verbose ? { src: task.src } : {}
|
|
@@ -32317,7 +32985,7 @@ async function runDryRun(ctx, srcLocale, dstLocales, opts) {
|
|
|
32317
32985
|
keys: languages.reduce((n, l) => n + l.keys, 0),
|
|
32318
32986
|
characters: languages.reduce((n, l) => n + l.characters, 0)
|
|
32319
32987
|
};
|
|
32320
|
-
const balance = await
|
|
32988
|
+
const balance = await readCreditBalance(ctx);
|
|
32321
32989
|
track("cli_translate_completed", {
|
|
32322
32990
|
mode: "plan",
|
|
32323
32991
|
key_count: total.keys,
|
|
@@ -32365,9 +33033,9 @@ In all: ${total.keys} key(s), ${total.characters} characters.` + (balance === nu
|
|
|
32365
33033
|
console.log("Nothing was started. Run without --dry-run to translate.");
|
|
32366
33034
|
}
|
|
32367
33035
|
function Working({ text }) {
|
|
32368
|
-
return /* @__PURE__ */
|
|
32369
|
-
/* @__PURE__ */
|
|
32370
|
-
/* @__PURE__ */
|
|
33036
|
+
return /* @__PURE__ */ jsxs19(Box19, { children: [
|
|
33037
|
+
/* @__PURE__ */ jsx19(Spinner16, {}),
|
|
33038
|
+
/* @__PURE__ */ jsxs19(Text19, { children: [
|
|
32371
33039
|
" ",
|
|
32372
33040
|
text
|
|
32373
33041
|
] })
|
|
@@ -32378,7 +33046,7 @@ function progressText(dstLocale, summary) {
|
|
|
32378
33046
|
const done = summary.completed + summary.failed;
|
|
32379
33047
|
return `${dstLocale}: translating ${done}/${summary.total}\u2026`;
|
|
32380
33048
|
}
|
|
32381
|
-
function
|
|
33049
|
+
function describeOutcome2(outcome) {
|
|
32382
33050
|
const { dstLocale, status, keys, written } = outcome;
|
|
32383
33051
|
const wrote = written ? `, ${written.keys} written to ${written.files} file(s)` : "";
|
|
32384
33052
|
const notApplied = outcome.notApplied.length > 0 ? `, ${outcome.notApplied.length} not applied` : "";
|
|
@@ -32413,14 +33081,14 @@ async function runLanguages(ctx, srcLocale, dstLocales, opts) {
|
|
|
32413
33081
|
const report = (outcome) => {
|
|
32414
33082
|
outcomes.push(outcome);
|
|
32415
33083
|
if (json2) return;
|
|
32416
|
-
console.log(
|
|
33084
|
+
console.log(describeOutcome2(outcome));
|
|
32417
33085
|
for (const line of describeNotApplied(outcome.notApplied)) {
|
|
32418
33086
|
console.log(` ${line}`);
|
|
32419
33087
|
}
|
|
32420
33088
|
};
|
|
32421
33089
|
for (const dstLocale of dstLocales) {
|
|
32422
33090
|
const progress = renderTransient(
|
|
32423
|
-
/* @__PURE__ */
|
|
33091
|
+
/* @__PURE__ */ jsx19(Working, { text: `${dstLocale}: planning\u2026` })
|
|
32424
33092
|
);
|
|
32425
33093
|
try {
|
|
32426
33094
|
const { tasks, plan } = await generateTasks(
|
|
@@ -32453,7 +33121,7 @@ async function runLanguages(ctx, srcLocale, dstLocales, opts) {
|
|
|
32453
33121
|
printNotes(json2, leftOut);
|
|
32454
33122
|
continue;
|
|
32455
33123
|
}
|
|
32456
|
-
progress.rerender(/* @__PURE__ */
|
|
33124
|
+
progress.rerender(/* @__PURE__ */ jsx19(Working, { text: progressText(dstLocale, null) }));
|
|
32457
33125
|
let jobId;
|
|
32458
33126
|
try {
|
|
32459
33127
|
jobId = await startTranslationJob({
|
|
@@ -32490,7 +33158,7 @@ async function runLanguages(ctx, srcLocale, dstLocales, opts) {
|
|
|
32490
33158
|
project.organizationId,
|
|
32491
33159
|
jobId,
|
|
32492
33160
|
(latest) => progress.rerender(
|
|
32493
|
-
/* @__PURE__ */
|
|
33161
|
+
/* @__PURE__ */ jsx19(Working, { text: progressText(dstLocale, latest) })
|
|
32494
33162
|
)
|
|
32495
33163
|
);
|
|
32496
33164
|
} catch (error62) {
|
|
@@ -32515,7 +33183,7 @@ async function runLanguages(ctx, srcLocale, dstLocales, opts) {
|
|
|
32515
33183
|
};
|
|
32516
33184
|
if (summary.status !== "cancelled") {
|
|
32517
33185
|
progress.rerender(
|
|
32518
|
-
/* @__PURE__ */
|
|
33186
|
+
/* @__PURE__ */ jsx19(Working, { text: `${dstLocale}: writing the files\u2026` })
|
|
32519
33187
|
);
|
|
32520
33188
|
const applied = await applyJob(ctx, jobId);
|
|
32521
33189
|
finished.written = { files: applied.files, keys: applied.keys };
|
|
@@ -32579,7 +33247,7 @@ function checkTranslateOptions(opts) {
|
|
|
32579
33247
|
|
|
32580
33248
|
// src/commands/translate/index.ts
|
|
32581
33249
|
var RETRANSLATE_UNTRACKED_HELP = "Also retranslate translations TolkBot has no record of (kept by default)";
|
|
32582
|
-
var
|
|
33250
|
+
var translateCommand2 = new Command8("translate").description(
|
|
32583
33251
|
"Translate what is missing or changed, and write the results into your locale files"
|
|
32584
33252
|
).option(
|
|
32585
33253
|
"--src <locale>",
|
|
@@ -32595,31 +33263,31 @@ var translateCommand = new Command6("translate").description(
|
|
|
32595
33263
|
"Run 'tolkbot translate --help'. Jobs are under 'tolkbot jobs'."
|
|
32596
33264
|
);
|
|
32597
33265
|
}
|
|
32598
|
-
const schema =
|
|
32599
|
-
src:
|
|
32600
|
-
dst:
|
|
32601
|
-
all:
|
|
32602
|
-
dryRun:
|
|
32603
|
-
wait:
|
|
32604
|
-
retranslateUntracked:
|
|
32605
|
-
verbose:
|
|
32606
|
-
json:
|
|
33266
|
+
const schema = z10.object({
|
|
33267
|
+
src: z10.string().min(1).optional(),
|
|
33268
|
+
dst: z10.string().min(1).optional(),
|
|
33269
|
+
all: z10.boolean().optional(),
|
|
33270
|
+
dryRun: z10.boolean().optional(),
|
|
33271
|
+
wait: z10.boolean(),
|
|
33272
|
+
retranslateUntracked: z10.boolean().optional(),
|
|
33273
|
+
verbose: z10.boolean().optional(),
|
|
33274
|
+
json: z10.boolean().optional()
|
|
32607
33275
|
});
|
|
32608
33276
|
const parsed = validateOrExit(schema, opts);
|
|
32609
33277
|
checkTranslateOptions(parsed);
|
|
32610
33278
|
await runTranslate(parsed);
|
|
32611
33279
|
});
|
|
32612
|
-
|
|
33280
|
+
translateCommand2.command("adopt").description(
|
|
32613
33281
|
"Record existing translations TolkBot has no baseline for as reviewed, so they are kept until their source changes"
|
|
32614
33282
|
).option(
|
|
32615
33283
|
"--src <locale>",
|
|
32616
33284
|
"Source locale (defaults to the project's base language)"
|
|
32617
33285
|
).option("--dst <locale>", "Destination locale").option("--all", "Every target language").option("--json", "Output as JSON (machine-readable)").action(async (opts) => {
|
|
32618
|
-
const schema =
|
|
32619
|
-
src:
|
|
32620
|
-
dst:
|
|
32621
|
-
all:
|
|
32622
|
-
json:
|
|
33286
|
+
const schema = z10.object({
|
|
33287
|
+
src: z10.string().min(1).optional(),
|
|
33288
|
+
dst: z10.string().min(1).optional(),
|
|
33289
|
+
all: z10.boolean().optional(),
|
|
33290
|
+
json: z10.boolean().optional()
|
|
32623
33291
|
});
|
|
32624
33292
|
const parsed = validateOrExit(schema, opts);
|
|
32625
33293
|
if (parsed.dst && parsed.all) {
|
|
@@ -32627,20 +33295,20 @@ translateCommand.command("adopt").description(
|
|
|
32627
33295
|
}
|
|
32628
33296
|
await runAdopt(parsed);
|
|
32629
33297
|
});
|
|
32630
|
-
|
|
32631
|
-
const schema =
|
|
32632
|
-
key:
|
|
32633
|
-
locale:
|
|
32634
|
-
value:
|
|
32635
|
-
namespace:
|
|
32636
|
-
json:
|
|
33298
|
+
translateCommand2.command("edit").description("Edit a translation value in a locale file").requiredOption("--key <key>", "Translation key (e.g. common.hello)").requiredOption("--locale <locale>", "Target locale (e.g. fr, de)").requiredOption("--value <text>", "New translation value").option("--namespace <ns>", "Namespace to resolve file (if ambiguous)").option("--json", "Output as JSON (machine-readable)").action(async (opts) => {
|
|
33299
|
+
const schema = z10.object({
|
|
33300
|
+
key: z10.string().min(1),
|
|
33301
|
+
locale: z10.string().min(1),
|
|
33302
|
+
value: z10.string().min(1),
|
|
33303
|
+
namespace: z10.string().optional(),
|
|
33304
|
+
json: z10.boolean().optional()
|
|
32637
33305
|
});
|
|
32638
33306
|
const parsed = validateOrExit(schema, opts);
|
|
32639
33307
|
await runEdit(parsed);
|
|
32640
33308
|
});
|
|
32641
33309
|
|
|
32642
33310
|
// src/commands/validate.tsx
|
|
32643
|
-
import { Box as
|
|
33311
|
+
import { Box as Box20, render as render17, Text as Text20 } from "ink";
|
|
32644
33312
|
|
|
32645
33313
|
// ../ai/src/validators/placeholders.ts
|
|
32646
33314
|
var IDENTIFIER = /^[A-Za-z0-9_$][A-Za-z0-9_$.[\]-]*$/;
|
|
@@ -33733,7 +34401,7 @@ function finalize2(issues, stats, strict) {
|
|
|
33733
34401
|
}
|
|
33734
34402
|
|
|
33735
34403
|
// src/commands/validate.tsx
|
|
33736
|
-
import { jsx as
|
|
34404
|
+
import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
33737
34405
|
var LEVEL_COLOR = {
|
|
33738
34406
|
error: "red",
|
|
33739
34407
|
warning: "yellow",
|
|
@@ -33742,12 +34410,12 @@ var LEVEL_COLOR = {
|
|
|
33742
34410
|
var GUTTER = 9;
|
|
33743
34411
|
function IssueLine({ issue: issue2 }) {
|
|
33744
34412
|
const location = [issue2.file, issue2.key].filter(Boolean).join(" \xB7 ");
|
|
33745
|
-
return /* @__PURE__ */
|
|
33746
|
-
/* @__PURE__ */
|
|
33747
|
-
/* @__PURE__ */
|
|
33748
|
-
/* @__PURE__ */
|
|
34413
|
+
return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
|
|
34414
|
+
/* @__PURE__ */ jsxs20(Box20, { children: [
|
|
34415
|
+
/* @__PURE__ */ jsx20(Box20, { width: GUTTER, flexShrink: 0, children: /* @__PURE__ */ jsx20(Text20, { color: LEVEL_COLOR[issue2.level], children: issue2.level }) }),
|
|
34416
|
+
/* @__PURE__ */ jsx20(Box20, { flexGrow: 1, children: /* @__PURE__ */ jsx20(Text20, { children: issue2.message }) })
|
|
33749
34417
|
] }),
|
|
33750
|
-
/* @__PURE__ */
|
|
34418
|
+
/* @__PURE__ */ jsx20(Box20, { marginLeft: GUTTER, children: /* @__PURE__ */ jsxs20(Text20, { dimColor: true, children: [
|
|
33751
34419
|
issue2.rule,
|
|
33752
34420
|
location ? ` \u2014 ${location}` : ""
|
|
33753
34421
|
] }) })
|
|
@@ -33756,20 +34424,20 @@ function IssueLine({ issue: issue2 }) {
|
|
|
33756
34424
|
function ReportUI({ report }) {
|
|
33757
34425
|
const { counts, stats } = report;
|
|
33758
34426
|
const summary = ["error", "warning", "info"].filter((level) => counts[level] > 0).map((level) => `${counts[level]} ${level}(s)`).join(", ");
|
|
33759
|
-
return /* @__PURE__ */
|
|
33760
|
-
/* @__PURE__ */
|
|
33761
|
-
/* @__PURE__ */
|
|
33762
|
-
/* @__PURE__ */
|
|
34427
|
+
return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
|
|
34428
|
+
/* @__PURE__ */ jsxs20(Box20, { children: [
|
|
34429
|
+
/* @__PURE__ */ jsx20(Text20, { color: report.valid ? "green" : "red", children: report.valid ? "\u2713" : "\u2717" }),
|
|
34430
|
+
/* @__PURE__ */ jsxs20(Text20, { children: [
|
|
33763
34431
|
" Validation ",
|
|
33764
34432
|
report.valid ? "passed" : "failed"
|
|
33765
34433
|
] }),
|
|
33766
|
-
summary ? /* @__PURE__ */
|
|
34434
|
+
summary ? /* @__PURE__ */ jsxs20(Text20, { dimColor: true, children: [
|
|
33767
34435
|
" \u2014 ",
|
|
33768
34436
|
summary
|
|
33769
34437
|
] }) : null
|
|
33770
34438
|
] }),
|
|
33771
|
-
stats.locales.length > 0 && /* @__PURE__ */
|
|
33772
|
-
/* @__PURE__ */
|
|
34439
|
+
stats.locales.length > 0 && /* @__PURE__ */ jsxs20(Box20, { marginTop: 1, flexDirection: "column", children: [
|
|
34440
|
+
/* @__PURE__ */ jsxs20(Text20, { dimColor: true, children: [
|
|
33773
34441
|
stats.filesChecked,
|
|
33774
34442
|
" ",
|
|
33775
34443
|
stats.format,
|
|
@@ -33778,18 +34446,18 @@ function ReportUI({ report }) {
|
|
|
33778
34446
|
stats.totalKeys,
|
|
33779
34447
|
" keys"
|
|
33780
34448
|
] }),
|
|
33781
|
-
/* @__PURE__ */
|
|
34449
|
+
/* @__PURE__ */ jsxs20(Text20, { dimColor: true, children: [
|
|
33782
34450
|
"Locales: ",
|
|
33783
34451
|
stats.locales.join(", "),
|
|
33784
34452
|
stats.baseLocale ? ` (base: ${stats.baseLocale})` : ""
|
|
33785
34453
|
] }),
|
|
33786
|
-
stats.pattern && /* @__PURE__ */
|
|
34454
|
+
stats.pattern && /* @__PURE__ */ jsxs20(Text20, { dimColor: true, children: [
|
|
33787
34455
|
"Pattern: ",
|
|
33788
34456
|
stats.pattern
|
|
33789
34457
|
] })
|
|
33790
34458
|
] }),
|
|
33791
|
-
report.issues.length > 0 && /* @__PURE__ */
|
|
33792
|
-
!report.strict && counts.warning > 0 && report.valid && /* @__PURE__ */
|
|
34459
|
+
report.issues.length > 0 && /* @__PURE__ */ jsx20(Box20, { marginTop: 1, flexDirection: "column", gap: 1, children: report.issues.map((issue2, idx) => /* @__PURE__ */ jsx20(IssueLine, { issue: issue2 }, idx)) }),
|
|
34460
|
+
!report.strict && counts.warning > 0 && report.valid && /* @__PURE__ */ jsx20(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text20, { dimColor: true, children: "Warnings did not fail this run. Use --strict to treat them as errors." }) })
|
|
33793
34461
|
] });
|
|
33794
34462
|
}
|
|
33795
34463
|
function emit(report, json2) {
|
|
@@ -33809,7 +34477,7 @@ function emit(report, json2) {
|
|
|
33809
34477
|
if (!report.valid) fail(validationFailure(report));
|
|
33810
34478
|
return;
|
|
33811
34479
|
}
|
|
33812
|
-
render17(/* @__PURE__ */
|
|
34480
|
+
render17(/* @__PURE__ */ jsx20(ReportUI, { report })).unmount();
|
|
33813
34481
|
process.exitCode = exitCode;
|
|
33814
34482
|
}
|
|
33815
34483
|
function validationFailure(report) {
|
|
@@ -33868,7 +34536,7 @@ function commandPath(command) {
|
|
|
33868
34536
|
return names.join(" ");
|
|
33869
34537
|
}
|
|
33870
34538
|
function buildProgram() {
|
|
33871
|
-
const program = new
|
|
34539
|
+
const program = new Command9().name("tolkbot").description("Localization workflow for your repo").version(version, "-v, --version", "Output the version number").helpOption("-h, --help", "Show help").helpCommand("help [command]", "Show help for a command").option("--token <token>", TOKEN_HELP).enablePositionalOptions();
|
|
33872
34540
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
33873
34541
|
const { token } = actionCommand.optsWithGlobals();
|
|
33874
34542
|
setTokenOverride(token);
|
|
@@ -33897,9 +34565,11 @@ function buildProgram() {
|
|
|
33897
34565
|
program.addCommand(authCommand);
|
|
33898
34566
|
program.addCommand(glossaryCommand);
|
|
33899
34567
|
program.addCommand(jobsCommand);
|
|
34568
|
+
program.addCommand(languagesCommand);
|
|
33900
34569
|
program.addCommand(learningsCommand);
|
|
34570
|
+
program.addCommand(statusCommand);
|
|
33901
34571
|
program.addCommand(telemetryCommand);
|
|
33902
|
-
program.addCommand(
|
|
34572
|
+
program.addCommand(translateCommand2);
|
|
33903
34573
|
program.addHelpText("after", PROGRAM_HELP_FOOTER);
|
|
33904
34574
|
forEachCommand(program, (command) => {
|
|
33905
34575
|
if (command !== program) addTokenOption(command);
|
|
@@ -33915,7 +34585,7 @@ function forEachCommand(command, visit2) {
|
|
|
33915
34585
|
var TOKEN_HELP = `Auth token to use for this invocation (overrides $${TOKEN_ENV_VAR} and the stored token)`;
|
|
33916
34586
|
function addTokenOption(command) {
|
|
33917
34587
|
if (command.options.some((o) => o.long === "--token")) return;
|
|
33918
|
-
command.addOption(new
|
|
34588
|
+
command.addOption(new Option2("--token <token>", TOKEN_HELP).hideHelp());
|
|
33919
34589
|
}
|
|
33920
34590
|
function jsonOptionOf(command) {
|
|
33921
34591
|
return command.options.find((option) => option.long === "--json");
|
|
@@ -33955,6 +34625,8 @@ var PROGRAM_HELP_FOOTER = `
|
|
|
33955
34625
|
Examples:
|
|
33956
34626
|
$ tolkbot auth login
|
|
33957
34627
|
$ tolkbot init
|
|
34628
|
+
$ tolkbot status
|
|
34629
|
+
$ tolkbot languages add nb
|
|
33958
34630
|
$ tolkbot translate --all
|
|
33959
34631
|
$ tolkbot translate --all --dry-run
|
|
33960
34632
|
$ tolkbot jobs list
|