ai-i18n-tools 1.0.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/LICENSE +21 -0
- package/README.md +157 -0
- package/dist/api/openrouter.d.ts +115 -0
- package/dist/api/openrouter.d.ts.map +1 -0
- package/dist/api/openrouter.js +399 -0
- package/dist/api/openrouter.js.map +1 -0
- package/dist/cli/doc-translate.d.ts +90 -0
- package/dist/cli/doc-translate.d.ts.map +1 -0
- package/dist/cli/doc-translate.js +1153 -0
- package/dist/cli/doc-translate.js.map +1 -0
- package/dist/cli/export-ui-xliff.d.ts +32 -0
- package/dist/cli/export-ui-xliff.d.ts.map +1 -0
- package/dist/cli/export-ui-xliff.js +153 -0
- package/dist/cli/export-ui-xliff.js.map +1 -0
- package/dist/cli/extract-strings.d.ts +12 -0
- package/dist/cli/extract-strings.d.ts.map +1 -0
- package/dist/cli/extract-strings.js +80 -0
- package/dist/cli/extract-strings.js.map +1 -0
- package/dist/cli/file-utils.d.ts +10 -0
- package/dist/cli/file-utils.d.ts.map +1 -0
- package/dist/cli/file-utils.js +77 -0
- package/dist/cli/file-utils.js.map +1 -0
- package/dist/cli/format.d.ts +21 -0
- package/dist/cli/format.d.ts.map +1 -0
- package/dist/cli/format.js +75 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/helpers.d.ts +27 -0
- package/dist/cli/helpers.d.ts.map +1 -0
- package/dist/cli/helpers.js +84 -0
- package/dist/cli/helpers.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +772 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/log-output.d.ts +13 -0
- package/dist/cli/log-output.d.ts.map +1 -0
- package/dist/cli/log-output.js +75 -0
- package/dist/cli/log-output.js.map +1 -0
- package/dist/cli/translate-svg.d.ts +7 -0
- package/dist/cli/translate-svg.d.ts.map +1 -0
- package/dist/cli/translate-svg.js +167 -0
- package/dist/cli/translate-svg.js.map +1 -0
- package/dist/cli/translate-ui-strings.d.ts +27 -0
- package/dist/cli/translate-ui-strings.d.ts.map +1 -0
- package/dist/cli/translate-ui-strings.js +357 -0
- package/dist/cli/translate-ui-strings.js.map +1 -0
- package/dist/core/cache-tracking-keys.d.ts +12 -0
- package/dist/core/cache-tracking-keys.d.ts.map +1 -0
- package/dist/core/cache-tracking-keys.js +20 -0
- package/dist/core/cache-tracking-keys.js.map +1 -0
- package/dist/core/cache.d.ts +153 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +546 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/config.d.ts +58 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +392 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/doc-file-tracking.d.ts +8 -0
- package/dist/core/doc-file-tracking.d.ts.map +1 -0
- package/dist/core/doc-file-tracking.js +27 -0
- package/dist/core/doc-file-tracking.js.map +1 -0
- package/dist/core/errors.d.ts +19 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +23 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/locale-utils.d.ts +20 -0
- package/dist/core/locale-utils.d.ts.map +1 -0
- package/dist/core/locale-utils.js +75 -0
- package/dist/core/locale-utils.js.map +1 -0
- package/dist/core/output-paths.d.ts +22 -0
- package/dist/core/output-paths.d.ts.map +1 -0
- package/dist/core/output-paths.js +130 -0
- package/dist/core/output-paths.js.map +1 -0
- package/dist/core/prompt-builder.d.ts +62 -0
- package/dist/core/prompt-builder.d.ts.map +1 -0
- package/dist/core/prompt-builder.js +232 -0
- package/dist/core/prompt-builder.js.map +1 -0
- package/dist/core/prompts.d.ts +27 -0
- package/dist/core/prompts.d.ts.map +1 -0
- package/dist/core/prompts.js +57 -0
- package/dist/core/prompts.js.map +1 -0
- package/dist/core/svg-asset-paths.d.ts +40 -0
- package/dist/core/svg-asset-paths.d.ts.map +1 -0
- package/dist/core/svg-asset-paths.js +107 -0
- package/dist/core/svg-asset-paths.js.map +1 -0
- package/dist/core/types.d.ts +388 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +265 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/ui-languages.d.ts +66 -0
- package/dist/core/ui-languages.d.ts.map +1 -0
- package/dist/core/ui-languages.js +277 -0
- package/dist/core/ui-languages.js.map +1 -0
- package/dist/core/user-edited-model.d.ts +3 -0
- package/dist/core/user-edited-model.d.ts.map +1 -0
- package/dist/core/user-edited-model.js +3 -0
- package/dist/core/user-edited-model.js.map +1 -0
- package/dist/edit-cache-app/app.js +1326 -0
- package/dist/edit-cache-app/index.html +287 -0
- package/dist/edit-cache-app/styles.css +664 -0
- package/dist/extractors/base-extractor.d.ts +15 -0
- package/dist/extractors/base-extractor.d.ts.map +1 -0
- package/dist/extractors/base-extractor.js +23 -0
- package/dist/extractors/base-extractor.js.map +1 -0
- package/dist/extractors/classify-segment.d.ts +6 -0
- package/dist/extractors/classify-segment.d.ts.map +1 -0
- package/dist/extractors/classify-segment.js +20 -0
- package/dist/extractors/classify-segment.js.map +1 -0
- package/dist/extractors/json-extractor.d.ts +16 -0
- package/dist/extractors/json-extractor.d.ts.map +1 -0
- package/dist/extractors/json-extractor.js +128 -0
- package/dist/extractors/json-extractor.js.map +1 -0
- package/dist/extractors/markdown-extractor.d.ts +15 -0
- package/dist/extractors/markdown-extractor.d.ts.map +1 -0
- package/dist/extractors/markdown-extractor.js +205 -0
- package/dist/extractors/markdown-extractor.js.map +1 -0
- package/dist/extractors/svg-extractor.d.ts +19 -0
- package/dist/extractors/svg-extractor.d.ts.map +1 -0
- package/dist/extractors/svg-extractor.js +132 -0
- package/dist/extractors/svg-extractor.js.map +1 -0
- package/dist/extractors/ui-string-extractor.d.ts +40 -0
- package/dist/extractors/ui-string-extractor.d.ts.map +1 -0
- package/dist/extractors/ui-string-extractor.js +146 -0
- package/dist/extractors/ui-string-extractor.js.map +1 -0
- package/dist/extractors/ui-string-locations.d.ts +23 -0
- package/dist/extractors/ui-string-locations.d.ts.map +1 -0
- package/dist/extractors/ui-string-locations.js +138 -0
- package/dist/extractors/ui-string-locations.js.map +1 -0
- package/dist/glossary/glossary.d.ts +34 -0
- package/dist/glossary/glossary.d.ts.map +1 -0
- package/dist/glossary/glossary.js +260 -0
- package/dist/glossary/glossary.js.map +1 -0
- package/dist/glossary/matcher.d.ts +10 -0
- package/dist/glossary/matcher.d.ts.map +1 -0
- package/dist/glossary/matcher.js +12 -0
- package/dist/glossary/matcher.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/processors/admonition-placeholders.d.ts +8 -0
- package/dist/processors/admonition-placeholders.d.ts.map +1 -0
- package/dist/processors/admonition-placeholders.js +59 -0
- package/dist/processors/admonition-placeholders.js.map +1 -0
- package/dist/processors/anchor-placeholders.d.ts +8 -0
- package/dist/processors/anchor-placeholders.d.ts.map +1 -0
- package/dist/processors/anchor-placeholders.js +37 -0
- package/dist/processors/anchor-placeholders.js.map +1 -0
- package/dist/processors/batch-processor.d.ts +10 -0
- package/dist/processors/batch-processor.d.ts.map +1 -0
- package/dist/processors/batch-processor.js +33 -0
- package/dist/processors/batch-processor.js.map +1 -0
- package/dist/processors/bold-code-placeholders.d.ts +14 -0
- package/dist/processors/bold-code-placeholders.d.ts.map +1 -0
- package/dist/processors/bold-code-placeholders.js +116 -0
- package/dist/processors/bold-code-placeholders.js.map +1 -0
- package/dist/processors/doc-postprocess.d.ts +51 -0
- package/dist/processors/doc-postprocess.d.ts.map +1 -0
- package/dist/processors/doc-postprocess.js +215 -0
- package/dist/processors/doc-postprocess.js.map +1 -0
- package/dist/processors/emphasis-placeholders.d.ts +6 -0
- package/dist/processors/emphasis-placeholders.d.ts.map +1 -0
- package/dist/processors/emphasis-placeholders.js +262 -0
- package/dist/processors/emphasis-placeholders.js.map +1 -0
- package/dist/processors/flat-link-rewrite.d.ts +32 -0
- package/dist/processors/flat-link-rewrite.d.ts.map +1 -0
- package/dist/processors/flat-link-rewrite.js +90 -0
- package/dist/processors/flat-link-rewrite.js.map +1 -0
- package/dist/processors/glossary-force-placeholders.d.ts +12 -0
- package/dist/processors/glossary-force-placeholders.d.ts.map +1 -0
- package/dist/processors/glossary-force-placeholders.js +58 -0
- package/dist/processors/glossary-force-placeholders.js.map +1 -0
- package/dist/processors/inline-code-placeholders.d.ts +11 -0
- package/dist/processors/inline-code-placeholders.d.ts.map +1 -0
- package/dist/processors/inline-code-placeholders.js +87 -0
- package/dist/processors/inline-code-placeholders.js.map +1 -0
- package/dist/processors/placeholder-handler.d.ts +38 -0
- package/dist/processors/placeholder-handler.d.ts.map +1 -0
- package/dist/processors/placeholder-handler.js +55 -0
- package/dist/processors/placeholder-handler.js.map +1 -0
- package/dist/processors/translation-placeholder-leaks.d.ts +2 -0
- package/dist/processors/translation-placeholder-leaks.d.ts.map +1 -0
- package/dist/processors/translation-placeholder-leaks.js +9 -0
- package/dist/processors/translation-placeholder-leaks.js.map +1 -0
- package/dist/processors/url-placeholders.d.ts +10 -0
- package/dist/processors/url-placeholders.d.ts.map +1 -0
- package/dist/processors/url-placeholders.js +29 -0
- package/dist/processors/url-placeholders.js.map +1 -0
- package/dist/processors/validator.d.ts +23 -0
- package/dist/processors/validator.d.ts.map +1 -0
- package/dist/processors/validator.js +186 -0
- package/dist/processors/validator.js.map +1 -0
- package/dist/runtime/i18next-helpers.d.ts +146 -0
- package/dist/runtime/i18next-helpers.d.ts.map +1 -0
- package/dist/runtime/i18next-helpers.js +192 -0
- package/dist/runtime/i18next-helpers.js.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/template.d.ts +21 -0
- package/dist/runtime/template.d.ts.map +1 -0
- package/dist/runtime/template.js +28 -0
- package/dist/runtime/template.js.map +1 -0
- package/dist/runtime/ui-language-display.d.ts +16 -0
- package/dist/runtime/ui-language-display.d.ts.map +1 -0
- package/dist/runtime/ui-language-display.js +26 -0
- package/dist/runtime/ui-language-display.js.map +1 -0
- package/dist/server/translation-editor.d.ts +25 -0
- package/dist/server/translation-editor.d.ts.map +1 -0
- package/dist/server/translation-editor.js +583 -0
- package/dist/server/translation-editor.js.map +1 -0
- package/dist/utils/concurrency.d.ts +31 -0
- package/dist/utils/concurrency.d.ts.map +1 -0
- package/dist/utils/concurrency.js +103 -0
- package/dist/utils/concurrency.js.map +1 -0
- package/dist/utils/hash.d.ts +5 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +9 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/ignore-parser.d.ts +7 -0
- package/dist/utils/ignore-parser.d.ts.map +1 -0
- package/dist/utils/ignore-parser.js +26 -0
- package/dist/utils/ignore-parser.js.map +1 -0
- package/dist/utils/logger.d.ts +45 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +158 -0
- package/dist/utils/logger.js.map +1 -0
- package/docs/GETTING_STARTED.md +697 -0
- package/docs/PACKAGE_OVERVIEW.md +427 -0
- package/docs/ai-i18n-tools-context.md +481 -0
- package/package.json +117 -0
- package/translated-docs/README.de.md +157 -0
- package/translated-docs/README.es.md +157 -0
- package/translated-docs/README.fr.md +157 -0
- package/translated-docs/README.hi.md +157 -0
- package/translated-docs/README.ja.md +157 -0
- package/translated-docs/README.ko.md +157 -0
- package/translated-docs/README.pt-BR.md +157 -0
- package/translated-docs/README.zh-CN.md +157 -0
- package/translated-docs/README.zh-TW.md +157 -0
- package/translated-docs/docs/GETTING_STARTED.de.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.es.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.fr.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.hi.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.ja.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.ko.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.pt-BR.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.zh-CN.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.zh-TW.md +682 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.de.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.es.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.fr.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.hi.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.ja.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.ko.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.pt-BR.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.zh-CN.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.zh-TW.md +428 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { OpenRouterClient } from "../api/openrouter.js";
|
|
5
|
+
import { normalizeLocale, resolveUITranslationModels } from "../core/config.js";
|
|
6
|
+
import { resolveStringsJsonPath, writeAtomicUtf8 } from "./helpers.js";
|
|
7
|
+
import { timestamp, formatElapsedMmSs, printModelsTryInOrder } from "./format.js";
|
|
8
|
+
import { runMapWithConcurrency } from "../utils/concurrency.js";
|
|
9
|
+
import { Glossary } from "../glossary/glossary.js";
|
|
10
|
+
import { protectGlossaryForcedTerms, restoreGlossaryForcedTerms, } from "../processors/glossary-force-placeholders.js";
|
|
11
|
+
import { USER_EDITED_MODEL } from "../core/user-edited-model.js";
|
|
12
|
+
import { parse as parseCsv } from "csv-parse/sync";
|
|
13
|
+
const UI_CHUNK = 50;
|
|
14
|
+
const RULE = "-".repeat(100);
|
|
15
|
+
function localeEnglishLabel(config, locale) {
|
|
16
|
+
const n = normalizeLocale(locale);
|
|
17
|
+
return config.localeDisplayNames?.[n] ?? n;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Read `strings.json`, translate missing per-locale entries via OpenRouter (ordered models),
|
|
21
|
+
* write merged `strings.json` and flat `{locale}.json` maps (source → translation) under `ui.flatOutputDir`.
|
|
22
|
+
*/
|
|
23
|
+
export async function runTranslateUI(config, opts) {
|
|
24
|
+
if (!config.features.translateUIStrings) {
|
|
25
|
+
throw new Error("Enable features.translateUIStrings in config");
|
|
26
|
+
}
|
|
27
|
+
const stringsPath = resolveStringsJsonPath(config, opts.cwd);
|
|
28
|
+
if (!fs.existsSync(stringsPath)) {
|
|
29
|
+
throw new Error(`strings.json not found: ${stringsPath} (run extract first)`);
|
|
30
|
+
}
|
|
31
|
+
let strings;
|
|
32
|
+
try {
|
|
33
|
+
strings = JSON.parse(fs.readFileSync(stringsPath, "utf8"));
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
throw new Error(`Invalid strings.json: ${e instanceof Error ? e.message : String(e)}`);
|
|
37
|
+
}
|
|
38
|
+
const entries = Object.entries(strings);
|
|
39
|
+
const outDir = path.join(opts.cwd, config.ui.flatOutputDir);
|
|
40
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
41
|
+
const srcNorm = normalizeLocale(config.sourceLocale);
|
|
42
|
+
const targets = opts.locales.map((l) => normalizeLocale(l)).filter((l) => l !== srcNorm);
|
|
43
|
+
if (targets.length === 0) {
|
|
44
|
+
throw new Error("No target locales after excluding sourceLocale");
|
|
45
|
+
}
|
|
46
|
+
const glossaryUser = config.glossary?.userGlossary
|
|
47
|
+
? path.join(opts.cwd, config.glossary.userGlossary)
|
|
48
|
+
: undefined;
|
|
49
|
+
if (config.glossary?.autoAddUserEditedToGlossary !== false && glossaryUser && !opts.dryRun) {
|
|
50
|
+
const headers = ["Original language string", "locale", "Translation", "Force"];
|
|
51
|
+
let csvRows = [];
|
|
52
|
+
if (fs.existsSync(glossaryUser)) {
|
|
53
|
+
const raw = fs.readFileSync(glossaryUser, "utf8");
|
|
54
|
+
const records = parseCsv(raw, {
|
|
55
|
+
columns: true,
|
|
56
|
+
skip_empty_lines: true,
|
|
57
|
+
trim: true,
|
|
58
|
+
});
|
|
59
|
+
csvRows = records.map((r) => [
|
|
60
|
+
r["Original language string"] ?? r["en"] ?? "",
|
|
61
|
+
r["locale"] ?? "",
|
|
62
|
+
r["Translation"] ?? r["translation"] ?? "",
|
|
63
|
+
r["Force"] ?? r["force"] ?? "",
|
|
64
|
+
]);
|
|
65
|
+
}
|
|
66
|
+
const existingPairs = new Set(csvRows.map((r) => `${r[0]}\0${r[1]}`));
|
|
67
|
+
let addedToGlossary = 0;
|
|
68
|
+
for (const [, entry] of entries) {
|
|
69
|
+
if (!entry.source || !entry.models || !entry.translated)
|
|
70
|
+
continue;
|
|
71
|
+
for (const target of targets) {
|
|
72
|
+
if (entry.models[target] === USER_EDITED_MODEL) {
|
|
73
|
+
const translation = entry.translated[target];
|
|
74
|
+
if (translation && typeof translation === "string" && translation.trim() !== "") {
|
|
75
|
+
const pairKey = `${entry.source}\0${target}`;
|
|
76
|
+
const starKey = `${entry.source}\0*`;
|
|
77
|
+
if (!existingPairs.has(pairKey) && !existingPairs.has(starKey)) {
|
|
78
|
+
csvRows.push([entry.source, target, translation, ""]);
|
|
79
|
+
existingPairs.add(pairKey);
|
|
80
|
+
addedToGlossary++;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (addedToGlossary > 0) {
|
|
87
|
+
const csvEscapeCell = (s) => {
|
|
88
|
+
if (/[",\n\r]/.test(s))
|
|
89
|
+
return `"${s.replace(/"/g, '""')}"`;
|
|
90
|
+
return s;
|
|
91
|
+
};
|
|
92
|
+
const lines = [
|
|
93
|
+
headers.map(csvEscapeCell).join(","),
|
|
94
|
+
...csvRows.map((r) => r.map(csvEscapeCell).join(",")),
|
|
95
|
+
];
|
|
96
|
+
writeAtomicUtf8(glossaryUser, `${lines.join("\n")}\n`);
|
|
97
|
+
console.log(chalk.green(`[user-glossary] Added ${addedToGlossary} user-edited entr${addedToGlossary === 1 ? "y" : "ies"} to ${config.glossary.userGlossary}`));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const glossary = new Glossary(undefined, glossaryUser, targets);
|
|
101
|
+
let client = null;
|
|
102
|
+
if (!opts.dryRun) {
|
|
103
|
+
try {
|
|
104
|
+
client = new OpenRouterClient({
|
|
105
|
+
config,
|
|
106
|
+
translationModels: resolveUITranslationModels(config),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
throw new Error(`OPENROUTER_API_KEY required for UI translation: ${e instanceof Error ? e.message : String(e)}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const models = client?.getConfiguredModels() ?? [];
|
|
114
|
+
const parallelLimit = Math.max(1, Math.floor(opts.concurrency ?? config.concurrency ?? 4));
|
|
115
|
+
// Header block
|
|
116
|
+
console.log(chalk.gray("\n\n___UI Translation________________________________________________________________________________________\n\n") + chalk.bold(`🌐 Translating UI strings to ${targets.length} locale(s)\n`));
|
|
117
|
+
printModelsTryInOrder(models);
|
|
118
|
+
console.log(chalk.cyan(`Strings: `) + chalk.magenta(`${entries.length} total entries`));
|
|
119
|
+
console.log(chalk.cyan(`Glossary terms: `) + chalk.magenta(`${glossary.size}`));
|
|
120
|
+
console.log(chalk.cyan(`Output dir: `) + chalk.magenta(outDir));
|
|
121
|
+
if (opts.logPath) {
|
|
122
|
+
console.log(chalk.cyan(`Output log: `) + chalk.magenta(opts.logPath));
|
|
123
|
+
}
|
|
124
|
+
if (targets.length > 1) {
|
|
125
|
+
console.log(chalk.cyan(`Parallel translations: `) +
|
|
126
|
+
chalk.magenta(`up to ${Math.min(parallelLimit, targets.length)}`));
|
|
127
|
+
}
|
|
128
|
+
if (opts.dryRun) {
|
|
129
|
+
console.log(chalk.yellow(`\n⚠️ Dry run mode - no changes will be made`));
|
|
130
|
+
}
|
|
131
|
+
console.log("");
|
|
132
|
+
let stringsUpdated = 0;
|
|
133
|
+
let inputTokens = 0;
|
|
134
|
+
let outputTokens = 0;
|
|
135
|
+
let costUsd = 0;
|
|
136
|
+
const wallStart = Date.now();
|
|
137
|
+
const langProgress = { completed: 0, total: targets.length };
|
|
138
|
+
const runSingleLocaleSequential = async (locale) => {
|
|
139
|
+
const localeStart = Date.now();
|
|
140
|
+
const missing = entries.filter(([_hash, entry]) => {
|
|
141
|
+
const src = entry.source ?? "";
|
|
142
|
+
if (!src.trim()) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
if (opts.force) {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
const t = entry.translated?.[locale];
|
|
149
|
+
return t === undefined || String(t).trim() === "";
|
|
150
|
+
});
|
|
151
|
+
if (missing.length === 0) {
|
|
152
|
+
console.log(chalk.gray(`⏭️ ${timestamp()} - ${locale}: up to date`));
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
console.log(chalk.yellow(`🔃 ${timestamp()} - ${locale}: ${missing.length} string(s) to translate`));
|
|
156
|
+
for (let i = 0; i < missing.length; i += UI_CHUNK) {
|
|
157
|
+
const chunk = missing.slice(i, i + UI_CHUNK);
|
|
158
|
+
const sources = chunk.map(([, v]) => v.source ?? "");
|
|
159
|
+
const chunkNum = Math.floor(i / UI_CHUNK) + 1;
|
|
160
|
+
const chunkTotal = Math.ceil(missing.length / UI_CHUNK);
|
|
161
|
+
if (opts.dryRun || !client) {
|
|
162
|
+
if (opts.verbose) {
|
|
163
|
+
console.log(chalk.yellow(` ${timestamp()} - [dry-run] chunk ${chunkNum}/${chunkTotal} (${chunk.length} strings)`));
|
|
164
|
+
}
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (opts.verbose) {
|
|
168
|
+
console.log(chalk.gray(` ${timestamp()} - Chunk ${chunkNum}/${chunkTotal} (${chunk.length} strings)`));
|
|
169
|
+
}
|
|
170
|
+
const protectedSources = [];
|
|
171
|
+
const glossaryReplacementsPerString = [];
|
|
172
|
+
for (const src of sources) {
|
|
173
|
+
const g = protectGlossaryForcedTerms(src, glossary, locale);
|
|
174
|
+
protectedSources.push(g.text);
|
|
175
|
+
glossaryReplacementsPerString.push(g.replacements);
|
|
176
|
+
}
|
|
177
|
+
const hints = glossary.findTermsInText(protectedSources.join("\n"), locale);
|
|
178
|
+
const uiBatch = await client.translateUIBatch(protectedSources, locale, {
|
|
179
|
+
glossaryHints: hints,
|
|
180
|
+
});
|
|
181
|
+
inputTokens += uiBatch.usage.inputTokens;
|
|
182
|
+
outputTokens += uiBatch.usage.outputTokens;
|
|
183
|
+
costUsd += uiBatch.cost ?? 0;
|
|
184
|
+
chunk.forEach(([h], idx) => {
|
|
185
|
+
let tr = uiBatch.translations[idx];
|
|
186
|
+
if (tr !== undefined) {
|
|
187
|
+
tr = restoreGlossaryForcedTerms(tr, glossaryReplacementsPerString[idx] ?? []);
|
|
188
|
+
}
|
|
189
|
+
if (tr !== undefined && strings[h]) {
|
|
190
|
+
if (!strings[h].translated) {
|
|
191
|
+
strings[h].translated = {};
|
|
192
|
+
}
|
|
193
|
+
strings[h].translated[locale] = tr;
|
|
194
|
+
if (!strings[h].models) {
|
|
195
|
+
strings[h].models = {};
|
|
196
|
+
}
|
|
197
|
+
strings[h].models[locale] = uiBatch.model;
|
|
198
|
+
stringsUpdated++;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
if (!opts.dryRun && missing.length > 0) {
|
|
203
|
+
writeAtomicUtf8(stringsPath, `${JSON.stringify(strings, null, 2)}\n`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const flat = {};
|
|
207
|
+
for (const entry of Object.values(strings)) {
|
|
208
|
+
const src = entry.source ?? "";
|
|
209
|
+
const tx = entry.translated?.[locale];
|
|
210
|
+
if (src && tx) {
|
|
211
|
+
flat[src] = tx;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const localePath = path.join(outDir, `${locale}.json`);
|
|
215
|
+
if (!opts.dryRun) {
|
|
216
|
+
writeAtomicUtf8(localePath, `${JSON.stringify(flat, null, 2)}\n`);
|
|
217
|
+
if (opts.verbose) {
|
|
218
|
+
console.log(chalk.gray(` ${timestamp()} - wrote ${Object.keys(flat).length} keys → ${localePath}`));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const localeElapsed = Date.now() - localeStart;
|
|
222
|
+
if (localeElapsed > 0) {
|
|
223
|
+
console.log(chalk.gray(` [${locale}] Time: ${formatElapsedMmSs(localeElapsed)}`));
|
|
224
|
+
}
|
|
225
|
+
langProgress.completed += 1;
|
|
226
|
+
};
|
|
227
|
+
const translateLocaleParallelWave = async (locale) => {
|
|
228
|
+
const localeStart = Date.now();
|
|
229
|
+
const missing = entries.filter(([_hash, entry]) => {
|
|
230
|
+
const src = entry.source ?? "";
|
|
231
|
+
if (!src.trim()) {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
if (opts.force) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
const t = entry.translated?.[locale];
|
|
238
|
+
return t === undefined || String(t).trim() === "";
|
|
239
|
+
});
|
|
240
|
+
if (missing.length === 0) {
|
|
241
|
+
console.log(chalk.gray(`⏭️ ${timestamp()} - ${locale}: up to date`));
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
console.log(chalk.yellow(`🔃 ${timestamp()} - ${locale}: ${missing.length} string(s) to translate`));
|
|
245
|
+
for (let i = 0; i < missing.length; i += UI_CHUNK) {
|
|
246
|
+
const chunk = missing.slice(i, i + UI_CHUNK);
|
|
247
|
+
const sources = chunk.map(([, v]) => v.source ?? "");
|
|
248
|
+
const chunkNum = Math.floor(i / UI_CHUNK) + 1;
|
|
249
|
+
const chunkTotal = Math.ceil(missing.length / UI_CHUNK);
|
|
250
|
+
if (opts.dryRun || !client) {
|
|
251
|
+
if (opts.verbose) {
|
|
252
|
+
console.log(chalk.yellow(` ${timestamp()} - [dry-run] chunk ${chunkNum}/${chunkTotal} (${chunk.length} strings)`));
|
|
253
|
+
}
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (opts.verbose) {
|
|
257
|
+
console.log(chalk.gray(` ${timestamp()} - Chunk ${chunkNum}/${chunkTotal} (${chunk.length} strings)`));
|
|
258
|
+
}
|
|
259
|
+
const protectedSources = [];
|
|
260
|
+
const glossaryReplacementsPerString = [];
|
|
261
|
+
for (const src of sources) {
|
|
262
|
+
const g = protectGlossaryForcedTerms(src, glossary, locale);
|
|
263
|
+
protectedSources.push(g.text);
|
|
264
|
+
glossaryReplacementsPerString.push(g.replacements);
|
|
265
|
+
}
|
|
266
|
+
const hints = glossary.findTermsInText(protectedSources.join("\n"), locale);
|
|
267
|
+
const uiBatch = await client.translateUIBatch(protectedSources, locale, {
|
|
268
|
+
glossaryHints: hints,
|
|
269
|
+
});
|
|
270
|
+
inputTokens += uiBatch.usage.inputTokens;
|
|
271
|
+
outputTokens += uiBatch.usage.outputTokens;
|
|
272
|
+
costUsd += uiBatch.cost ?? 0;
|
|
273
|
+
chunk.forEach(([h], idx) => {
|
|
274
|
+
let tr = uiBatch.translations[idx];
|
|
275
|
+
if (tr !== undefined) {
|
|
276
|
+
tr = restoreGlossaryForcedTerms(tr, glossaryReplacementsPerString[idx] ?? []);
|
|
277
|
+
}
|
|
278
|
+
if (tr !== undefined && strings[h]) {
|
|
279
|
+
if (!strings[h].translated) {
|
|
280
|
+
strings[h].translated = {};
|
|
281
|
+
}
|
|
282
|
+
strings[h].translated[locale] = tr;
|
|
283
|
+
if (!strings[h].models) {
|
|
284
|
+
strings[h].models = {};
|
|
285
|
+
}
|
|
286
|
+
strings[h].models[locale] = uiBatch.model;
|
|
287
|
+
stringsUpdated++;
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const flat = {};
|
|
293
|
+
for (const entry of Object.values(strings)) {
|
|
294
|
+
const src = entry.source ?? "";
|
|
295
|
+
const tx = entry.translated?.[locale];
|
|
296
|
+
if (src && tx) {
|
|
297
|
+
flat[src] = tx;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
const localePath = path.join(outDir, `${locale}.json`);
|
|
301
|
+
if (!opts.dryRun) {
|
|
302
|
+
writeAtomicUtf8(localePath, `${JSON.stringify(flat, null, 2)}\n`);
|
|
303
|
+
if (opts.verbose) {
|
|
304
|
+
console.log(chalk.gray(` ${timestamp()} - wrote ${Object.keys(flat).length} keys → ${localePath}`));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const localeElapsed = Date.now() - localeStart;
|
|
308
|
+
if (localeElapsed > 0) {
|
|
309
|
+
console.log(chalk.gray(` [${locale}] Time: ${formatElapsedMmSs(localeElapsed)}`));
|
|
310
|
+
}
|
|
311
|
+
langProgress.completed += 1;
|
|
312
|
+
};
|
|
313
|
+
if (targets.length <= 1) {
|
|
314
|
+
await runSingleLocaleSequential(targets[0]);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
for (let i = 0; i < targets.length; i += parallelLimit) {
|
|
318
|
+
const batch = targets.slice(i, i + parallelLimit);
|
|
319
|
+
const langList = batch
|
|
320
|
+
.map((loc) => `${localeEnglishLabel(config, loc)} (${loc})`)
|
|
321
|
+
.join(" • ");
|
|
322
|
+
console.log(chalk.yellow(RULE));
|
|
323
|
+
console.log(chalk.yellow(` 🚀 Running in parallel: ${langList} ${langProgress.completed}/${langProgress.total}`));
|
|
324
|
+
console.log(chalk.yellow(RULE));
|
|
325
|
+
await runMapWithConcurrency(batch, batch.length, async (locale) => {
|
|
326
|
+
await translateLocaleParallelWave(locale);
|
|
327
|
+
return locale;
|
|
328
|
+
});
|
|
329
|
+
if (!opts.dryRun) {
|
|
330
|
+
console.log(chalk.blue(`💾 Writing strings.json`));
|
|
331
|
+
writeAtomicUtf8(stringsPath, `${JSON.stringify(strings, null, 2)}\n`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const wallElapsed = Date.now() - wallStart;
|
|
336
|
+
// Summary block
|
|
337
|
+
console.log(chalk.bold.green("\n✅ UI translation complete!\n"));
|
|
338
|
+
console.log(chalk.bold("📊 Summary:"));
|
|
339
|
+
console.log(` Total elapsed time: ${formatElapsedMmSs(wallElapsed)}`);
|
|
340
|
+
console.log(` Strings updated: ${stringsUpdated}`);
|
|
341
|
+
console.log(` Tokens used: ${(inputTokens + outputTokens).toLocaleString()} (in: ${inputTokens.toLocaleString()} / out: ${outputTokens.toLocaleString()})`);
|
|
342
|
+
if (costUsd > 0) {
|
|
343
|
+
console.log(chalk.green(` 💵 Total cost: $${costUsd.toFixed(6)}`));
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
console.log(` Total cost: $0.00 (all up to date or dry-run)`);
|
|
347
|
+
}
|
|
348
|
+
console.log("");
|
|
349
|
+
return {
|
|
350
|
+
stringsUpdated,
|
|
351
|
+
localesTouched: targets,
|
|
352
|
+
inputTokens,
|
|
353
|
+
outputTokens,
|
|
354
|
+
costUsd,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
//# sourceMappingURL=translate-ui-strings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate-ui-strings.js","sourceRoot":"","sources":["../../src/cli/translate-ui-strings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Namespace prefix for standalone SVG asset rows in `translations.filepath` / `file_tracking.filepath`. */
|
|
2
|
+
export declare const SVG_ASSETS_PREFIX = "svg-assets:";
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a cache key stored in `translations.filepath` or `file_tracking.filepath` to an absolute
|
|
5
|
+
* path on disk for existence checks (`cleanup`, orphan pruning).
|
|
6
|
+
*
|
|
7
|
+
* - `doc-block:*` — documentation file tracking (see {@link resolveDocTrackingKeyToAbs})
|
|
8
|
+
* - `svg-assets:*` — SVG source path relative to project root
|
|
9
|
+
* - any other string — treated as a path relative to project root
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveCacheTrackingKeyToAbs(projectRoot: string, key: string): string;
|
|
12
|
+
//# sourceMappingURL=cache-tracking-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-tracking-keys.d.ts","sourceRoot":"","sources":["../../src/core/cache-tracking-keys.ts"],"names":[],"mappings":"AAGA,4GAA4G;AAC5G,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAE/C;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAMrF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { resolveDocTrackingKeyToAbs } from "./doc-file-tracking.js";
|
|
3
|
+
/** Namespace prefix for standalone SVG asset rows in `translations.filepath` / `file_tracking.filepath`. */
|
|
4
|
+
export const SVG_ASSETS_PREFIX = "svg-assets:";
|
|
5
|
+
/**
|
|
6
|
+
* Resolve a cache key stored in `translations.filepath` or `file_tracking.filepath` to an absolute
|
|
7
|
+
* path on disk for existence checks (`cleanup`, orphan pruning).
|
|
8
|
+
*
|
|
9
|
+
* - `doc-block:*` — documentation file tracking (see {@link resolveDocTrackingKeyToAbs})
|
|
10
|
+
* - `svg-assets:*` — SVG source path relative to project root
|
|
11
|
+
* - any other string — treated as a path relative to project root
|
|
12
|
+
*/
|
|
13
|
+
export function resolveCacheTrackingKeyToAbs(projectRoot, key) {
|
|
14
|
+
if (key.startsWith(SVG_ASSETS_PREFIX)) {
|
|
15
|
+
const rel = key.slice(SVG_ASSETS_PREFIX.length);
|
|
16
|
+
return path.resolve(projectRoot, rel);
|
|
17
|
+
}
|
|
18
|
+
return resolveDocTrackingKeyToAbs(projectRoot, key);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=cache-tracking-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-tracking-keys.js","sourceRoot":"","sources":["../../src/core/cache-tracking-keys.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAEpE,4GAA4G;AAC5G,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAE/C;;;;;;;GAOG;AACH,MAAM,UAAU,4BAA4B,CAAC,WAAmB,EAAE,GAAW;IAC3E,IAAI,GAAG,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,0BAA0B,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import type { CacheEntry, CleanupStats, FileTracking, TranslationRow } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* SQLite translation cache. `better-sqlite3` uses a single native connection per instance
|
|
4
|
+
* (no JS-level pool); reuse one instance per process for best throughput.
|
|
5
|
+
*/
|
|
6
|
+
export declare class TranslationCache {
|
|
7
|
+
private db;
|
|
8
|
+
private readonly dbFilePath;
|
|
9
|
+
constructor(cachePath: string);
|
|
10
|
+
private applyMigrations;
|
|
11
|
+
/** Segment hash (normalized whitespace, SHA-256, 16 hex chars). */
|
|
12
|
+
static computeHash(content: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Cached segment text and model id (as stored on last successful translation).
|
|
15
|
+
* Updates `last_hit_at` / optional filepath tracking like {@link getSegment}.
|
|
16
|
+
*/
|
|
17
|
+
getSegmentDetails(sourceHash: string, locale: string, filepath?: string, startLine?: number): {
|
|
18
|
+
text: string;
|
|
19
|
+
model: string | null;
|
|
20
|
+
} | null;
|
|
21
|
+
getSegment(sourceHash: string, locale: string, filepath?: string, startLine?: number): string | null;
|
|
22
|
+
setSegment(sourceHash: string, locale: string, sourceText: string, translatedText: string, model: string, filepath?: string, startLine?: number | null): void;
|
|
23
|
+
getFileHash(filepath: string, locale: string): string | null;
|
|
24
|
+
setFileStatus(filepath: string, locale: string, sourceHash: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Remove file-tracking for one path/locale so the next run does not skip the file.
|
|
27
|
+
* Segment rows stay keyed by `(source_hash, locale)`; `--force` bypasses segment cache reads so rows refresh on re-translate.
|
|
28
|
+
*/
|
|
29
|
+
clearFile(filepath: string, locale: string): void;
|
|
30
|
+
getStats(): {
|
|
31
|
+
totalSegments: number;
|
|
32
|
+
totalFiles: number;
|
|
33
|
+
byLocale: Record<string, number>;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Aggregate documentation-cache stats for dashboards (stale vs active, per locale/model).
|
|
37
|
+
*/
|
|
38
|
+
getDetailedStats(): {
|
|
39
|
+
totalSegments: number;
|
|
40
|
+
totalFiles: number;
|
|
41
|
+
staleSegments: number;
|
|
42
|
+
activeSegments: number;
|
|
43
|
+
byLocale: {
|
|
44
|
+
locale: string;
|
|
45
|
+
total: number;
|
|
46
|
+
stale: number;
|
|
47
|
+
active: number;
|
|
48
|
+
}[];
|
|
49
|
+
byModel: {
|
|
50
|
+
model: string;
|
|
51
|
+
count: number;
|
|
52
|
+
}[];
|
|
53
|
+
byModelLocale: {
|
|
54
|
+
model: string;
|
|
55
|
+
locale: string;
|
|
56
|
+
count: number;
|
|
57
|
+
}[];
|
|
58
|
+
uniqueFilepaths: number;
|
|
59
|
+
};
|
|
60
|
+
clear(locale?: string): void;
|
|
61
|
+
/**
|
|
62
|
+
* Set `last_hit_at = NULL` for markdown segments that were not hit this run.
|
|
63
|
+
* Scoped to markdown-like paths only so JSON (and other) rows are not cleared.
|
|
64
|
+
* @param keysHit - entries as `sourceHash|locale`.
|
|
65
|
+
*/
|
|
66
|
+
resetLastHitAtForUnhitMarkdown(hitKeys: Set<string>): number;
|
|
67
|
+
/**
|
|
68
|
+
* Set `last_hit_at = NULL` for JSON UI/doc segments that were not hit this run.
|
|
69
|
+
* @param keysHit - entries as `sourceHash|locale`.
|
|
70
|
+
*/
|
|
71
|
+
resetLastHitAtForUnhitJson(hitKeys: Set<string>): number;
|
|
72
|
+
private resetLastHitAtForUnhitScoped;
|
|
73
|
+
/**
|
|
74
|
+
* Like {@link resetLastHitAtForUnhitMarkdown}, but only rows whose `filepath` is in `allowedRelPaths`
|
|
75
|
+
* (e.g. markdown files in scope for this translate run after path filters).
|
|
76
|
+
*/
|
|
77
|
+
resetLastHitAtForUnhitMarkdownInScope(hitKeys: Set<string>, allowedRelPaths: readonly string[]): number;
|
|
78
|
+
/**
|
|
79
|
+
* Like {@link resetLastHitAtForUnhitJson}, but only rows whose `filepath` is in `allowedRelPaths`.
|
|
80
|
+
*/
|
|
81
|
+
resetLastHitAtForUnhitJsonInScope(hitKeys: Set<string>, allowedRelPaths: readonly string[]): number;
|
|
82
|
+
private resetLastHitAtForUnhitScopedWithScope;
|
|
83
|
+
cleanupStaleTranslations(dryRun?: boolean): {
|
|
84
|
+
count: number;
|
|
85
|
+
deletedRows: {
|
|
86
|
+
source_hash: string;
|
|
87
|
+
locale: string;
|
|
88
|
+
filepath: string | null;
|
|
89
|
+
}[];
|
|
90
|
+
};
|
|
91
|
+
listTranslations(filters?: {
|
|
92
|
+
filename?: string;
|
|
93
|
+
locale?: string;
|
|
94
|
+
model?: string;
|
|
95
|
+
source_hash?: string;
|
|
96
|
+
source_text?: string;
|
|
97
|
+
translated_text?: string;
|
|
98
|
+
last_hit_at_null?: boolean;
|
|
99
|
+
/** When true, only rows with a non-null `last_hit_at` (active). Mutually exclusive with `last_hit_at_null` in normal use. */
|
|
100
|
+
last_hit_at_not_null?: boolean;
|
|
101
|
+
limit?: number;
|
|
102
|
+
offset?: number;
|
|
103
|
+
}): {
|
|
104
|
+
rows: TranslationRow[];
|
|
105
|
+
total: number;
|
|
106
|
+
};
|
|
107
|
+
updateTranslation(sourceHash: string, locale: string, translatedText: string): void;
|
|
108
|
+
deleteTranslation(sourceHash: string, locale: string): void;
|
|
109
|
+
deleteByFilters(filters?: {
|
|
110
|
+
filename?: string;
|
|
111
|
+
locale?: string;
|
|
112
|
+
model?: string;
|
|
113
|
+
source_hash?: string;
|
|
114
|
+
source_text?: string;
|
|
115
|
+
translated_text?: string;
|
|
116
|
+
last_hit_at_null?: boolean;
|
|
117
|
+
last_hit_at_not_null?: boolean;
|
|
118
|
+
}): number;
|
|
119
|
+
/** Deletes matching rows in `translations` only (see {@link deleteFileTrackingByPath} for tracking keys). */
|
|
120
|
+
deleteTranslationsByFilepath(filepath: string): number;
|
|
121
|
+
/** Deletes all `file_tracking` rows for this cache key (all locales). */
|
|
122
|
+
deleteFileTrackingByPath(filepath: string): number;
|
|
123
|
+
/** Distinct `filepath` values in `file_tracking` (cache keys: `doc-block:…`, `svg-assets:…`, etc.). */
|
|
124
|
+
listFileTrackingPaths(): string[];
|
|
125
|
+
/**
|
|
126
|
+
* Remove `file_tracking` rows whose resolved path does not exist on disk under `projectRoot`.
|
|
127
|
+
*/
|
|
128
|
+
pruneOrphanedFileTrackingByDisk(projectRoot: string, dryRun: boolean): number;
|
|
129
|
+
/**
|
|
130
|
+
* @deprecated Prefer {@link deleteTranslationsByFilepath} / {@link deleteFileTrackingByPath} explicitly.
|
|
131
|
+
* Deletes `translations` rows only (no longer deletes `file_tracking`).
|
|
132
|
+
*/
|
|
133
|
+
deleteByFilepath(filepath: string): number;
|
|
134
|
+
getUniqueLocales(): string[];
|
|
135
|
+
getUniqueFilepaths(): string[];
|
|
136
|
+
getUniqueModels(): string[];
|
|
137
|
+
close(): void;
|
|
138
|
+
getSegmentAsync(hash: string, locale: string): Promise<string | null>;
|
|
139
|
+
setSegmentAsync(entry: CacheEntry): Promise<void>;
|
|
140
|
+
getFileStatus(filepath: string, locale: string): Promise<FileTracking | null>;
|
|
141
|
+
setFileStatusAsync(filepath: string, locale: string, hash: string): Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* @param markdownKeys - `sourceHash|locale` for markdown segments hit this run (may be empty).
|
|
144
|
+
* @param jsonKeys - `sourceHash|locale` for JSON segments hit this run (may be empty).
|
|
145
|
+
*/
|
|
146
|
+
resetLastHitAtForUnhit(markdownKeys: string[], jsonKeys: string[]): Promise<void>;
|
|
147
|
+
cleanup(): Promise<CleanupStats>;
|
|
148
|
+
/** Hot SQLite backup to another file. */
|
|
149
|
+
backupTo(destinationPath: string): Promise<void>;
|
|
150
|
+
/** Replace the on-disk DB with a copied file; closes and reopens the connection. */
|
|
151
|
+
restoreFrom(sourcePath: string): void;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"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"}
|