@verbatra/sdk 0.6.2 → 0.6.4
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 +27 -13
- package/dist/index.cjs +127 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -10
- package/dist/index.d.ts +64 -10
- package/dist/index.js +127 -64
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -31,27 +31,31 @@ var translationMemorySchema = z.object({
|
|
|
31
31
|
function cacheFilePath(cwd) {
|
|
32
32
|
return resolve(cwd, CACHE_FILE_NAME);
|
|
33
33
|
}
|
|
34
|
+
var UNUSABLE = { memory: EMPTY_MEMORY, writable: true };
|
|
34
35
|
async function readTranslationMemory(path, fs) {
|
|
35
36
|
let read;
|
|
36
37
|
try {
|
|
37
38
|
read = await fs.readFileBounded(path, MAX_CACHE_FILE_BYTES);
|
|
38
39
|
} catch {
|
|
39
|
-
return
|
|
40
|
+
return UNUSABLE;
|
|
40
41
|
}
|
|
41
42
|
if (read.kind !== "ok") {
|
|
42
|
-
return
|
|
43
|
+
return UNUSABLE;
|
|
43
44
|
}
|
|
44
45
|
let parsed;
|
|
45
46
|
try {
|
|
46
47
|
parsed = JSON.parse(read.content);
|
|
47
48
|
} catch {
|
|
48
|
-
return
|
|
49
|
+
return UNUSABLE;
|
|
49
50
|
}
|
|
50
51
|
const result = translationMemorySchema.safeParse(parsed);
|
|
51
|
-
if (!result.success
|
|
52
|
-
return
|
|
52
|
+
if (!result.success) {
|
|
53
|
+
return UNUSABLE;
|
|
53
54
|
}
|
|
54
|
-
|
|
55
|
+
if (result.data.version !== CURRENT_VERSION) {
|
|
56
|
+
return { memory: EMPTY_MEMORY, writable: false };
|
|
57
|
+
}
|
|
58
|
+
return { memory: result.data, writable: true };
|
|
55
59
|
}
|
|
56
60
|
function lookupMemory(memory, fingerprint, locale, contentHash2) {
|
|
57
61
|
return memory.entries[fingerprint]?.[locale]?.[contentHash2];
|
|
@@ -103,7 +107,10 @@ async function feedTranslationMemory(cwd, fs, fingerprint, additionsByLocale) {
|
|
|
103
107
|
}
|
|
104
108
|
try {
|
|
105
109
|
const path = cacheFilePath(cwd);
|
|
106
|
-
const memory = await readTranslationMemory(path, fs);
|
|
110
|
+
const { memory, writable } = await readTranslationMemory(path, fs);
|
|
111
|
+
if (!writable) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
107
114
|
await writeTranslationMemory(path, applyAdditions(memory, fingerprint, additionsByLocale), fs);
|
|
108
115
|
} catch {
|
|
109
116
|
}
|
|
@@ -115,6 +122,18 @@ function defineConfig(config) {
|
|
|
115
122
|
}
|
|
116
123
|
|
|
117
124
|
// src/errors.ts
|
|
125
|
+
function errorMessage(error) {
|
|
126
|
+
return error instanceof Error ? error.message : String(error);
|
|
127
|
+
}
|
|
128
|
+
function stringCode(error) {
|
|
129
|
+
if (error instanceof Error && "code" in error && typeof error.code === "string") {
|
|
130
|
+
return error.code;
|
|
131
|
+
}
|
|
132
|
+
return void 0;
|
|
133
|
+
}
|
|
134
|
+
function describeError(error, fallbackCode) {
|
|
135
|
+
return { code: stringCode(error) ?? fallbackCode, message: errorMessage(error) };
|
|
136
|
+
}
|
|
118
137
|
var SdkError = class extends Error {
|
|
119
138
|
/** The stable {@link SdkErrorCode} for this failure; branch on this, not the message. */
|
|
120
139
|
code;
|
|
@@ -1912,7 +1931,7 @@ async function loadExplicitWithMeta(explorer, configPath, cwd, fs) {
|
|
|
1912
1931
|
try {
|
|
1913
1932
|
result = await explorer.load(resolved);
|
|
1914
1933
|
} catch (error) {
|
|
1915
|
-
const detail =
|
|
1934
|
+
const detail = errorMessage(error);
|
|
1916
1935
|
throw new SdkError("CONFIG_INVALID", `Failed to load the verbatra configuration: ${detail}`);
|
|
1917
1936
|
}
|
|
1918
1937
|
const parsed = parseConfig(result?.config);
|
|
@@ -1937,7 +1956,7 @@ async function loadConfigWithMeta(options = {}) {
|
|
|
1937
1956
|
try {
|
|
1938
1957
|
result = await explorer.search(options.cwd);
|
|
1939
1958
|
} catch (error) {
|
|
1940
|
-
const detail =
|
|
1959
|
+
const detail = errorMessage(error);
|
|
1941
1960
|
throw new SdkError("CONFIG_INVALID", `Failed to load the verbatra configuration: ${detail}`);
|
|
1942
1961
|
}
|
|
1943
1962
|
if (result === null || result.isEmpty === true) {
|
|
@@ -2022,15 +2041,15 @@ async function acquireLock(path, fs, pollIntervalMs, deadline, notify) {
|
|
|
2022
2041
|
if (await fs.createExclusive(path, lockPayload())) {
|
|
2023
2042
|
return;
|
|
2024
2043
|
}
|
|
2044
|
+
if (notify !== void 0) {
|
|
2045
|
+
await notify();
|
|
2046
|
+
}
|
|
2025
2047
|
if (Date.now() >= deadline) {
|
|
2026
2048
|
throw new SdkError(
|
|
2027
2049
|
"LOCK_CONTENDED",
|
|
2028
2050
|
`Could not acquire the write lock at ${path}: another process may be holding it. If no verbatra process is currently running, this lock file was likely left behind by one that was killed; delete it and retry.`
|
|
2029
2051
|
);
|
|
2030
2052
|
}
|
|
2031
|
-
if (notify !== void 0) {
|
|
2032
|
-
await notify();
|
|
2033
|
-
}
|
|
2034
2053
|
const jitter = Math.random() * pollIntervalMs;
|
|
2035
2054
|
await sleep(pollIntervalMs + jitter);
|
|
2036
2055
|
}
|
|
@@ -2620,6 +2639,9 @@ async function fsyncDirBestEffort(path) {
|
|
|
2620
2639
|
}
|
|
2621
2640
|
}
|
|
2622
2641
|
var nodeOps = {
|
|
2642
|
+
mkdir: async (path) => {
|
|
2643
|
+
await mkdir(path, { recursive: true });
|
|
2644
|
+
},
|
|
2623
2645
|
writeFile: (path, data) => writeFile(path, data, "utf8"),
|
|
2624
2646
|
fsyncFile: (path) => fsyncPath(path),
|
|
2625
2647
|
rename: (from, to) => rename(from, to),
|
|
@@ -2636,8 +2658,10 @@ function tempFileName2(path) {
|
|
|
2636
2658
|
return join(dirname(path), `.${basename(path)}.tmp-${process.pid}-${Date.now()}-${randomUUID()}`);
|
|
2637
2659
|
}
|
|
2638
2660
|
async function atomicWriteFile(path, data, ops = nodeOps) {
|
|
2661
|
+
const directory = dirname(path);
|
|
2639
2662
|
const tmp = tempFileName2(path);
|
|
2640
2663
|
try {
|
|
2664
|
+
await ops.mkdir(directory);
|
|
2641
2665
|
await ops.writeFile(tmp, data);
|
|
2642
2666
|
await ops.fsyncFile(tmp);
|
|
2643
2667
|
await ops.rename(tmp, path);
|
|
@@ -2646,7 +2670,7 @@ async function atomicWriteFile(path, data, ops = nodeOps) {
|
|
|
2646
2670
|
throw error;
|
|
2647
2671
|
}
|
|
2648
2672
|
try {
|
|
2649
|
-
await ops.fsyncDir(
|
|
2673
|
+
await ops.fsyncDir(directory);
|
|
2650
2674
|
} catch {
|
|
2651
2675
|
}
|
|
2652
2676
|
}
|
|
@@ -3309,6 +3333,12 @@ function extractPropertiesPlaceholders(value) {
|
|
|
3309
3333
|
var UNICODE_ESCAPE = /^[0-9a-fA-F]{4}$/;
|
|
3310
3334
|
var LEADING_WHITESPACE = /^[ \t\f]+/;
|
|
3311
3335
|
var TRAILING_TERMINATOR = /(?:\r\n|\r|\n)$/;
|
|
3336
|
+
function detectLineTerminator(content) {
|
|
3337
|
+
if (content.includes("\r\n")) {
|
|
3338
|
+
return "\r\n";
|
|
3339
|
+
}
|
|
3340
|
+
return content.includes("\r") ? "\r" : "\n";
|
|
3341
|
+
}
|
|
3312
3342
|
function isPropertiesWhitespace(char) {
|
|
3313
3343
|
return char === " " || char === " " || char === "\f";
|
|
3314
3344
|
}
|
|
@@ -3514,7 +3544,7 @@ async function readStructure(filePath) {
|
|
|
3514
3544
|
outcome = await readBounded2(filePath);
|
|
3515
3545
|
} catch (error) {
|
|
3516
3546
|
if (isFileNotFound(error)) {
|
|
3517
|
-
return [];
|
|
3547
|
+
return { items: [], terminator: "\n" };
|
|
3518
3548
|
}
|
|
3519
3549
|
throw new AdapterError("INVALID_STRUCTURE", "The destination file could not be read.");
|
|
3520
3550
|
}
|
|
@@ -3524,13 +3554,16 @@ async function readStructure(filePath) {
|
|
|
3524
3554
|
if (outcome.kind === "too-large") {
|
|
3525
3555
|
throw new AdapterError("INPUT_TOO_LARGE", "The file exceeds the maximum allowed size.");
|
|
3526
3556
|
}
|
|
3527
|
-
return
|
|
3557
|
+
return {
|
|
3558
|
+
items: parseItems(outcome.content),
|
|
3559
|
+
terminator: detectLineTerminator(outcome.content)
|
|
3560
|
+
};
|
|
3528
3561
|
}
|
|
3529
3562
|
async function serializePropertiesEntries(entries, filePath) {
|
|
3530
|
-
const
|
|
3563
|
+
const { items, terminator } = await readStructure(filePath);
|
|
3531
3564
|
const emitted = /* @__PURE__ */ new Set();
|
|
3532
3565
|
const lines = [];
|
|
3533
|
-
for (const item of
|
|
3566
|
+
for (const item of items) {
|
|
3534
3567
|
if (item.kind === "raw") {
|
|
3535
3568
|
lines.push(item.text);
|
|
3536
3569
|
continue;
|
|
@@ -3546,8 +3579,7 @@ async function serializePropertiesEntries(entries, filePath) {
|
|
|
3546
3579
|
lines.push(formatEntry(key, entry.value));
|
|
3547
3580
|
}
|
|
3548
3581
|
}
|
|
3549
|
-
return lines.length === 0 ? "" : `${lines.join(
|
|
3550
|
-
`;
|
|
3582
|
+
return lines.length === 0 ? "" : `${lines.join(terminator)}${terminator}`;
|
|
3551
3583
|
}
|
|
3552
3584
|
function createPropertiesAdapter() {
|
|
3553
3585
|
return createFlatFileAdapter({
|
|
@@ -3999,7 +4031,7 @@ async function readSource(config, cwd, fs, adapter) {
|
|
|
3999
4031
|
try {
|
|
4000
4032
|
return await adapter.read(sourcePath, config.sourceLocale);
|
|
4001
4033
|
} catch (error) {
|
|
4002
|
-
const detail =
|
|
4034
|
+
const detail = errorMessage(error);
|
|
4003
4035
|
throw new SdkError(
|
|
4004
4036
|
"SOURCE_INVALID",
|
|
4005
4037
|
`The source locale file at ${sourcePath} could not be read: ${detail}`
|
|
@@ -4100,6 +4132,9 @@ function gateCandidateValue(sourceEntry, candidateValue, adapter) {
|
|
|
4100
4132
|
if (assessValueDegeneracy(sourceEntry.value, candidateValue).degenerate) {
|
|
4101
4133
|
return { accepted: false, reason: "degenerate" };
|
|
4102
4134
|
}
|
|
4135
|
+
if (sourceEntry.value.trim() !== "" && candidateValue.trim() === "") {
|
|
4136
|
+
return { accepted: false, reason: "empty" };
|
|
4137
|
+
}
|
|
4103
4138
|
return { accepted: true };
|
|
4104
4139
|
}
|
|
4105
4140
|
|
|
@@ -4296,7 +4331,7 @@ function selectProvider(config, createProvider = buildProvider) {
|
|
|
4296
4331
|
try {
|
|
4297
4332
|
return createProvider(config);
|
|
4298
4333
|
} catch (error) {
|
|
4299
|
-
const detail =
|
|
4334
|
+
const detail = errorMessage(error);
|
|
4300
4335
|
throw new SdkError(
|
|
4301
4336
|
"PROVIDER_CONSTRUCTION_FAILED",
|
|
4302
4337
|
`Failed to construct provider "${config.id}": ${detail}`
|
|
@@ -4519,13 +4554,6 @@ function budgetExceededNotice(tracker) {
|
|
|
4519
4554
|
}
|
|
4520
4555
|
|
|
4521
4556
|
// src/flow/locale-failure.ts
|
|
4522
|
-
function describeError(error) {
|
|
4523
|
-
if (error instanceof Error) {
|
|
4524
|
-
const code = error.code;
|
|
4525
|
-
return { code: typeof code === "string" ? code : "LOCALE_FAILED", message: error.message };
|
|
4526
|
-
}
|
|
4527
|
-
return { code: "LOCALE_FAILED", message: String(error) };
|
|
4528
|
-
}
|
|
4529
4557
|
function failureSummary(locale, error) {
|
|
4530
4558
|
return {
|
|
4531
4559
|
locale,
|
|
@@ -4545,7 +4573,7 @@ function failureSummary(locale, error) {
|
|
|
4545
4573
|
unfilled: [],
|
|
4546
4574
|
malformedRows: [],
|
|
4547
4575
|
duplicateKeys: [],
|
|
4548
|
-
error: describeError(error)
|
|
4576
|
+
error: describeError(error, "LOCALE_FAILED")
|
|
4549
4577
|
};
|
|
4550
4578
|
}
|
|
4551
4579
|
function deriveLocaleStatus(parts) {
|
|
@@ -4949,6 +4977,10 @@ function fanOutAccepted(params, group, acceptedRepresentative, outcome) {
|
|
|
4949
4977
|
if (source === void 0) {
|
|
4950
4978
|
continue;
|
|
4951
4979
|
}
|
|
4980
|
+
if (!gateCandidateValue(source, acceptedRepresentative.value, params.adapter).accepted) {
|
|
4981
|
+
outcome.integrityMismatches.push(key);
|
|
4982
|
+
continue;
|
|
4983
|
+
}
|
|
4952
4984
|
outcome.accepted.set(key, { value: acceptedRepresentative.value, source });
|
|
4953
4985
|
if (flag !== void 0) {
|
|
4954
4986
|
outcome.reviewFlags.set(key, flag);
|
|
@@ -4975,6 +5007,12 @@ function buildRequest3(params, entries) {
|
|
|
4975
5007
|
...params.adapter.comparePlaceholders !== void 0 ? { comparePlaceholders: params.adapter.comparePlaceholders } : {}
|
|
4976
5008
|
};
|
|
4977
5009
|
}
|
|
5010
|
+
async function shouldWriteTarget(params, path, changed) {
|
|
5011
|
+
if (changed.accepted > 0 || changed.pruned > 0 || changed.generated > 0) {
|
|
5012
|
+
return true;
|
|
5013
|
+
}
|
|
5014
|
+
return !await params.fs.fileExists(path);
|
|
5015
|
+
}
|
|
4978
5016
|
async function runLocale(params) {
|
|
4979
5017
|
const target = await readTargetResource({
|
|
4980
5018
|
cwd: params.cwd,
|
|
@@ -5060,15 +5098,22 @@ async function runLocale(params) {
|
|
|
5060
5098
|
merged.set(form.targetKey, { ...form.entry, namespace: target.namespace });
|
|
5061
5099
|
}
|
|
5062
5100
|
const path = localeFilePath(params.cwd, params.filesPattern, params.targetLocale);
|
|
5063
|
-
await params
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5101
|
+
const writeNeeded = await shouldWriteTarget(params, path, {
|
|
5102
|
+
accepted: accepted.size,
|
|
5103
|
+
pruned: pruned.length,
|
|
5104
|
+
generated: generation.accepted.length
|
|
5105
|
+
});
|
|
5106
|
+
if (writeNeeded) {
|
|
5107
|
+
await params.adapter.write(
|
|
5108
|
+
{
|
|
5109
|
+
locale: params.targetLocale,
|
|
5110
|
+
namespace: target.namespace,
|
|
5111
|
+
format: params.format,
|
|
5112
|
+
entries: merged
|
|
5113
|
+
},
|
|
5114
|
+
path
|
|
5115
|
+
);
|
|
5116
|
+
}
|
|
5072
5117
|
const pluralNotices = params.generatePlurals ? pluralNoticeFor(params, merged) : sdkNotices;
|
|
5073
5118
|
const notices = [
|
|
5074
5119
|
...pluralNotices,
|
|
@@ -5340,14 +5385,21 @@ async function createRunCacheState(input, config, cwd, dryRun, fs) {
|
|
|
5340
5385
|
if (dryRun || input.cache === false) {
|
|
5341
5386
|
return void 0;
|
|
5342
5387
|
}
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5388
|
+
const { memory, writable } = await readTranslationMemory(cacheFilePath(cwd), fs);
|
|
5389
|
+
return { memory, writable, fingerprint: computeFingerprint(config), additions: /* @__PURE__ */ new Map() };
|
|
5390
|
+
}
|
|
5391
|
+
function withCacheNotices(summaries, cache) {
|
|
5392
|
+
if (cache === void 0 || cache.writable) {
|
|
5393
|
+
return [...summaries];
|
|
5394
|
+
}
|
|
5395
|
+
const notice = {
|
|
5396
|
+
code: "CACHE_VERSION_UNRECOGNIZED",
|
|
5397
|
+
message: `${CACHE_FILE_NAME} carries a version this build does not recognize, so it was written by a newer verbatra. It was left untouched and this run used no cache. Upgrade verbatra, or delete the file to rebuild it in this build's format.`
|
|
5347
5398
|
};
|
|
5399
|
+
return summaries.map((summary) => ({ ...summary, notices: [...summary.notices, notice] }));
|
|
5348
5400
|
}
|
|
5349
5401
|
async function recordCacheAdditions(cwd, cache, fs) {
|
|
5350
|
-
if (cache === void 0 || cache.additions.size === 0) {
|
|
5402
|
+
if (cache === void 0 || cache.additions.size === 0 || !cache.writable) {
|
|
5351
5403
|
return;
|
|
5352
5404
|
}
|
|
5353
5405
|
try {
|
|
@@ -5434,18 +5486,25 @@ async function runLocaleAt(context, targetLocales, localeIndex, runOne, results)
|
|
|
5434
5486
|
context.onProgress?.({
|
|
5435
5487
|
type: "locale-finished",
|
|
5436
5488
|
locale: targetLocale,
|
|
5437
|
-
translated: summary.translated.length
|
|
5489
|
+
translated: summary.translated.length,
|
|
5490
|
+
localeIndex,
|
|
5491
|
+
totalLocales: targetLocales.length
|
|
5438
5492
|
});
|
|
5439
5493
|
}
|
|
5440
5494
|
async function runLocalesWithProgress(context, targetLocales, runOne, concurrency) {
|
|
5441
5495
|
const totalLocales = targetLocales.length;
|
|
5442
5496
|
const results = new Array(totalLocales);
|
|
5443
5497
|
let nextIndex = 0;
|
|
5498
|
+
let abort;
|
|
5444
5499
|
async function worker() {
|
|
5445
|
-
while (nextIndex < totalLocales) {
|
|
5500
|
+
while (abort === void 0 && nextIndex < totalLocales) {
|
|
5446
5501
|
const localeIndex = nextIndex;
|
|
5447
5502
|
nextIndex += 1;
|
|
5448
|
-
|
|
5503
|
+
try {
|
|
5504
|
+
await runLocaleAt(context, targetLocales, localeIndex, runOne, results);
|
|
5505
|
+
} catch (error) {
|
|
5506
|
+
abort ??= { reason: error };
|
|
5507
|
+
}
|
|
5449
5508
|
}
|
|
5450
5509
|
}
|
|
5451
5510
|
const workerCount = Math.min(concurrency, totalLocales);
|
|
@@ -5454,6 +5513,9 @@ async function runLocalesWithProgress(context, targetLocales, runOne, concurrenc
|
|
|
5454
5513
|
workers.push(worker());
|
|
5455
5514
|
}
|
|
5456
5515
|
await Promise.all(workers);
|
|
5516
|
+
if (abort !== void 0) {
|
|
5517
|
+
throw abort.reason;
|
|
5518
|
+
}
|
|
5457
5519
|
return results.filter((summary) => summary !== void 0);
|
|
5458
5520
|
}
|
|
5459
5521
|
async function runAllLocalesDry(context, targetLocales, concurrency) {
|
|
@@ -5530,7 +5592,8 @@ async function translate2(input, deps = {}) {
|
|
|
5530
5592
|
};
|
|
5531
5593
|
const summaries = dryRun ? await runAllLocalesDry(context, config.targetLocales, concurrency) : await runAllLocalesLive(context, config.targetLocales, concurrency);
|
|
5532
5594
|
input.onProgress?.({ type: "run-finished", localesCompleted: summaries.length });
|
|
5533
|
-
const
|
|
5595
|
+
const locales = withCacheNotices(summaries, cache);
|
|
5596
|
+
const { succeeded, partial, failed } = partition(locales);
|
|
5534
5597
|
const usage = summaries.reduce(
|
|
5535
5598
|
(total, summary2) => combineUsage(total, summary2.usage),
|
|
5536
5599
|
void 0
|
|
@@ -5538,7 +5601,7 @@ async function translate2(input, deps = {}) {
|
|
|
5538
5601
|
const budgetSummary = toBudgetSummary(budget);
|
|
5539
5602
|
const summary = {
|
|
5540
5603
|
dryRun,
|
|
5541
|
-
locales
|
|
5604
|
+
locales,
|
|
5542
5605
|
succeeded,
|
|
5543
5606
|
partial,
|
|
5544
5607
|
failed,
|
|
@@ -6110,12 +6173,12 @@ function classifyClear(row, sourceEntry, buckets) {
|
|
|
6110
6173
|
buckets.withheld.add(row.key);
|
|
6111
6174
|
return;
|
|
6112
6175
|
}
|
|
6113
|
-
buckets.accepted.set(row.key, { value: "", source: sourceEntry });
|
|
6176
|
+
buckets.accepted.set(row.key, { value: "", source: sourceEntry, cleared: true });
|
|
6114
6177
|
}
|
|
6115
|
-
function classifyRows(params, buckets) {
|
|
6178
|
+
function classifyRows(params, buckets, liveCandidates) {
|
|
6116
6179
|
for (const row of params.sheet.rows) {
|
|
6117
6180
|
if (row.translation === "") {
|
|
6118
|
-
if (row.
|
|
6181
|
+
if (liveCandidates.has(row.key)) {
|
|
6119
6182
|
buckets.unfilled.push(row.key);
|
|
6120
6183
|
}
|
|
6121
6184
|
trackBlankDrift(row, params, buckets);
|
|
@@ -6134,7 +6197,11 @@ function classifyRows(params, buckets) {
|
|
|
6134
6197
|
}
|
|
6135
6198
|
const reason = judge(row, sourceEntry, params.adapter);
|
|
6136
6199
|
if (reason === void 0) {
|
|
6137
|
-
buckets.accepted.set(row.key, {
|
|
6200
|
+
buckets.accepted.set(row.key, {
|
|
6201
|
+
value: row.translation,
|
|
6202
|
+
source: sourceEntry,
|
|
6203
|
+
cleared: false
|
|
6204
|
+
});
|
|
6138
6205
|
} else {
|
|
6139
6206
|
buckets.mismatches.push(row.key);
|
|
6140
6207
|
buckets.withheld.add(row.key);
|
|
@@ -6156,7 +6223,7 @@ function importLocale(params) {
|
|
|
6156
6223
|
blankDrifted: /* @__PURE__ */ new Set(),
|
|
6157
6224
|
unfilled: []
|
|
6158
6225
|
};
|
|
6159
|
-
classifyRows(params, buckets);
|
|
6226
|
+
classifyRows(params, buckets, /* @__PURE__ */ new Set([...diff2.missing, ...diff2.changed]));
|
|
6160
6227
|
const rowKeys = new Set(params.sheet.rows.map((row) => row.key));
|
|
6161
6228
|
const invalidIcuSource = [...new Set(params.sourceInvalidIcuKeys)].filter((key) => rowKeys.has(key)).sort();
|
|
6162
6229
|
const translated = [...buckets.accepted.keys()].sort();
|
|
@@ -6214,8 +6281,10 @@ function mergeAccepted(target, accepted) {
|
|
|
6214
6281
|
}
|
|
6215
6282
|
function sheetCacheAdditions(accepted) {
|
|
6216
6283
|
const record = {};
|
|
6217
|
-
for (const [, { value, source }] of accepted) {
|
|
6218
|
-
|
|
6284
|
+
for (const [, { value, source, cleared }] of accepted) {
|
|
6285
|
+
if (!cleared) {
|
|
6286
|
+
record[contentHash(source)] = value;
|
|
6287
|
+
}
|
|
6219
6288
|
}
|
|
6220
6289
|
return record;
|
|
6221
6290
|
}
|
|
@@ -6304,7 +6373,7 @@ async function importWorkbook(input, deps = {}) {
|
|
|
6304
6373
|
try {
|
|
6305
6374
|
data = await readWorkbook(bytes);
|
|
6306
6375
|
} catch (error) {
|
|
6307
|
-
throw new SdkError("SOURCE_INVALID", error
|
|
6376
|
+
throw new SdkError("SOURCE_INVALID", errorMessage(error));
|
|
6308
6377
|
}
|
|
6309
6378
|
const lock = await readLockFile(lockFilePath(cwd), fs);
|
|
6310
6379
|
const ctx = {
|
|
@@ -6390,17 +6459,11 @@ function defaultRunTranslate(deps) {
|
|
|
6390
6459
|
|
|
6391
6460
|
// src/watch/watch.ts
|
|
6392
6461
|
var DEFAULT_DEBOUNCE_MS = 300;
|
|
6393
|
-
function describeError2(error) {
|
|
6394
|
-
if (error instanceof Error) {
|
|
6395
|
-
const code = error.code;
|
|
6396
|
-
return { code: typeof code === "string" ? code : "WATCH_RUN_FAILED", message: error.message };
|
|
6397
|
-
}
|
|
6398
|
-
return { code: "WATCH_RUN_FAILED", message: String(error) };
|
|
6399
|
-
}
|
|
6400
6462
|
async function watch(input, deps = {}) {
|
|
6401
6463
|
const cwd = input.cwd ?? process.cwd();
|
|
6402
6464
|
const debounceMs = input.debounceMs ?? DEFAULT_DEBOUNCE_MS;
|
|
6403
6465
|
const fs = deps.fs ?? defaultFs;
|
|
6466
|
+
resolveRunConcurrency(input.concurrency, false, input.config);
|
|
6404
6467
|
const sourcePath = localeFilePath(cwd, input.config.files.pattern, input.config.sourceLocale);
|
|
6405
6468
|
if (!await fs.fileExists(sourcePath)) {
|
|
6406
6469
|
throw new SdkError(
|
|
@@ -6427,7 +6490,7 @@ async function watch(input, deps = {}) {
|
|
|
6427
6490
|
try {
|
|
6428
6491
|
input.onRun({ status: "succeeded", summary: await runTranslate(runInput) });
|
|
6429
6492
|
} catch (error) {
|
|
6430
|
-
input.onRun({ status: "failed", error:
|
|
6493
|
+
input.onRun({ status: "failed", error: describeError(error, "WATCH_RUN_FAILED") });
|
|
6431
6494
|
}
|
|
6432
6495
|
}
|
|
6433
6496
|
function startRun() {
|