locai 2.6.1 → 2.7.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/README.md +23 -25
- package/dist/cli/helpers.d.ts +34 -2
- package/dist/cli/helpers.js +96 -37
- package/dist/cli.js +40 -39
- package/dist/commands/review.d.ts +33 -8
- package/dist/commands/review.js +89 -22
- package/dist/commands/translator.d.ts +4 -2
- package/dist/commands/translator.js +1 -1
- package/dist/config/index.d.ts +53 -66
- package/dist/config/index.js +2 -1
- package/dist/config/setup.d.ts +3 -2
- package/dist/config/setup.js +5 -3
- package/dist/core/adapters/android-adapter.d.ts +3 -2
- package/dist/core/adapters/android-adapter.js +12 -13
- package/dist/core/adapters/base-adapter.d.ts +13 -2
- package/dist/core/adapters/ios-adapter.d.ts +3 -2
- package/dist/core/adapters/json-adapter.d.ts +4 -3
- package/dist/core/adapters/json-adapter.js +1 -3
- package/dist/core/adapters/po-adapter.d.ts +3 -2
- package/dist/core/adapters/po-adapter.js +4 -5
- package/dist/core/adapters/properties-adapter.d.ts +3 -2
- package/dist/core/adapters/properties-adapter.js +2 -4
- package/dist/core/adapters/yaml-adapter.d.ts +4 -3
- package/dist/core/adapters/yaml-adapter.js +1 -3
- package/dist/core/context-processor.d.ts +21 -6
- package/dist/core/context-processor.js +2 -7
- package/dist/core/detection/framework-detector.js +1 -1
- package/dist/core/detection/structure-detector.js +1 -1
- package/dist/core/fallback-provider.d.ts +3 -4
- package/dist/core/fallback-provider.js +15 -21
- package/dist/core/orchestrator.d.ts +98 -26
- package/dist/core/orchestrator.js +56 -116
- package/dist/core/pipeline/Pipeline.d.ts +2 -2
- package/dist/core/pipeline/Pipeline.js +1 -3
- package/dist/core/pipeline/context.d.ts +69 -13
- package/dist/core/pipeline/context.js +1 -7
- package/dist/core/pipeline/steps/CacheReadStep.d.ts +10 -7
- package/dist/core/pipeline/steps/CacheReadStep.js +1 -12
- package/dist/core/pipeline/steps/CacheWriteStep.d.ts +2 -2
- package/dist/core/pipeline/steps/CacheWriteStep.js +1 -8
- package/dist/core/pipeline/steps/ConfidenceCheckStep.d.ts +5 -0
- package/dist/core/pipeline/steps/ConfidenceCheckStep.js +24 -44
- package/dist/core/pipeline/steps/ContextEnrichmentStep.js +3 -14
- package/dist/core/pipeline/steps/QualityCheckStep.d.ts +1 -1
- package/dist/core/pipeline/steps/QualityCheckStep.js +0 -2
- package/dist/core/pipeline/steps/ToneCheckStep.js +1 -1
- package/dist/core/pipeline/steps/TranslationStep.d.ts +13 -3
- package/dist/core/pipeline/steps/TranslationStep.js +21 -23
- package/dist/core/pipeline/steps/VectorCacheReadStep.d.ts +9 -1
- package/dist/core/pipeline/steps/VectorCacheReadStep.js +3 -5
- package/dist/core/pipeline/steps/VectorCacheWriteStep.d.ts +2 -1
- package/dist/core/pipeline/steps/VectorCacheWriteStep.js +2 -1
- package/dist/core/provider-factory.d.ts +15 -9
- package/dist/core/provider-factory.js +42 -32
- package/dist/providers/anthropic.d.ts +5 -4
- package/dist/providers/anthropic.js +3 -2
- package/dist/providers/api-types.d.ts +74 -0
- package/dist/providers/api-types.js +5 -0
- package/dist/providers/base-provider.d.ts +27 -31
- package/dist/providers/base-provider.js +22 -46
- package/dist/providers/dashscope.js +0 -2
- package/dist/providers/deepseek.js +0 -1
- package/dist/providers/gemini.js +0 -1
- package/dist/providers/openai.d.ts +3 -3
- package/dist/providers/openai.js +0 -1
- package/dist/providers/xai.js +0 -1
- package/dist/services/embedding-provider.js +4 -2
- package/dist/services/language-processor.d.ts +5 -3
- package/dist/services/language-processor.js +38 -43
- package/dist/services/source-analyzer.d.ts +24 -0
- package/dist/services/source-analyzer.js +161 -68
- package/dist/services/translation-service.d.ts +31 -13
- package/dist/services/translation-service.js +116 -71
- package/dist/services/vector-store.d.ts +15 -2
- package/dist/services/vector-store.js +14 -10
- package/dist/types/index.d.ts +31 -33
- package/dist/utils/ai-context-analyzer.d.ts +12 -3
- package/dist/utils/ai-context-analyzer.js +18 -10
- package/dist/utils/confidence-scorer.d.ts +16 -19
- package/dist/utils/confidence-scorer.js +36 -125
- package/dist/utils/error-helper.d.ts +27 -6
- package/dist/utils/error-helper.js +10 -9
- package/dist/utils/file-manager.d.ts +8 -7
- package/dist/utils/file-manager.js +22 -23
- package/dist/utils/glossary-manager.d.ts +22 -3
- package/dist/utils/glossary-manager.js +47 -28
- package/dist/utils/graceful-shutdown.d.ts +7 -1
- package/dist/utils/graceful-shutdown.js +1 -2
- package/dist/utils/input-validator.d.ts +53 -66
- package/dist/utils/input-validator.js +100 -151
- package/dist/utils/locale-paths.d.ts +7 -0
- package/dist/utils/locale-paths.js +16 -0
- package/dist/utils/logger.d.ts +8 -8
- package/dist/utils/logger.js +7 -15
- package/dist/utils/object-transformer.d.ts +20 -5
- package/dist/utils/object-transformer.js +20 -28
- package/dist/utils/progress-tracker.js +2 -3
- package/dist/utils/prompt-templates.d.ts +45 -5
- package/dist/utils/prompt-templates.js +61 -5
- package/dist/utils/quality/base-checker.d.ts +40 -18
- package/dist/utils/quality/base-checker.js +1 -2
- package/dist/utils/quality/code-block-checker.d.ts +13 -5
- package/dist/utils/quality/index.d.ts +2 -1
- package/dist/utils/quality/index.js +8 -27
- package/dist/utils/quality/length-checker.d.ts +35 -5
- package/dist/utils/quality/length-checker.js +2 -3
- package/dist/utils/quality/markdown-checker.d.ts +14 -7
- package/dist/utils/quality/special-characters-checker.d.ts +18 -1
- package/dist/utils/quality/special-characters-checker.js +0 -1
- package/dist/utils/quality/style-guide-checker.d.ts +1 -1
- package/dist/utils/quality/style-guide-checker.js +0 -2
- package/dist/utils/quality/tone-verifier.js +1 -1
- package/dist/utils/rate-limiter.d.ts +17 -1
- package/dist/utils/rate-limiter.js +12 -11
- package/dist/utils/retry-helper.d.ts +21 -3
- package/dist/utils/retry-helper.js +11 -3
- package/dist/utils/review-queue.d.ts +45 -0
- package/dist/utils/review-queue.js +53 -0
- package/dist/utils/state-manager.d.ts +12 -3
- package/dist/utils/state-manager.js +32 -7
- package/dist/utils/statistics-manager.d.ts +11 -1
- package/dist/utils/statistics-manager.js +8 -0
- package/dist/utils/ui-manager.d.ts +2 -1
- package/dist/utils/ui-manager.js +15 -1
- package/package.json +22 -17
- package/dist/commands/interactive-review.d.ts +0 -9
- package/dist/commands/interactive-review.js +0 -109
- package/dist/core/pipeline/steps/__tests__/ToneCheckStep.test.d.ts +0 -1
- package/dist/core/pipeline/steps/__tests__/ToneCheckStep.test.js +0 -100
- package/dist/utils/quality/__tests__/tone-verifier.test.d.ts +0 -1
- package/dist/utils/quality/__tests__/tone-verifier.test.js +0 -91
|
@@ -1,6 +1,22 @@
|
|
|
1
|
-
import { Project, Node } from "ts-morph";
|
|
1
|
+
import { Project, Node, ts, } from "ts-morph";
|
|
2
2
|
import { log } from "../utils/logger.js";
|
|
3
3
|
import path from "path";
|
|
4
|
+
/** Longest usage snippet kept for a key, in characters. */
|
|
5
|
+
const MAX_SNIPPET_LENGTH = 200;
|
|
6
|
+
/** Source spans wider than this cannot shrink to a snippet, so they are not printed. */
|
|
7
|
+
const MAX_SNIPPET_SOURCE_WIDTH = 10 * MAX_SNIPPET_LENGTH;
|
|
8
|
+
/** Tooling directives (`eslint-disable-next-line`, `@ts-expect-error`, ...) say nothing about the text. */
|
|
9
|
+
const DIRECTIVE_COMMENT = /^(eslint-|@ts-|prettier-ignore\b|istanbul ignore\b|c8 ignore\b|biome-ignore\b)/;
|
|
10
|
+
/** Prints code without comments, for the usage snippet. */
|
|
11
|
+
const printer = ts.createPrinter({ removeComments: true });
|
|
12
|
+
/** Comment text without its markers (`//`, `/*`, `*\/`, JSDoc `*`), on one line. */
|
|
13
|
+
const commentText = (comment) => comment
|
|
14
|
+
.replace(/^\/\/+|^\/\*+|\*+\/$/g, "")
|
|
15
|
+
.replace(/^\s*\*+/gm, "")
|
|
16
|
+
.replace(/\s+/g, " ")
|
|
17
|
+
.trim();
|
|
18
|
+
/** Functions and methods: code in them runs later, not where they are written. */
|
|
19
|
+
const isFunction = (node) => Node.isFunctionLikeDeclaration(node) || Node.isFunctionExpression(node);
|
|
4
20
|
export class SourceCodeAnalyzer {
|
|
5
21
|
project;
|
|
6
22
|
keyUsageMap = new Map();
|
|
@@ -39,7 +55,8 @@ export class SourceCodeAnalyzer {
|
|
|
39
55
|
log(`Source analysis complete. Context extracted for ${this.keyUsageMap.size} keys.`);
|
|
40
56
|
}
|
|
41
57
|
catch (error) {
|
|
42
|
-
|
|
58
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
59
|
+
console.warn(`Error during source analysis: ${message}`);
|
|
43
60
|
// Don't throw to prevent blocking the whole app, just log
|
|
44
61
|
}
|
|
45
62
|
})();
|
|
@@ -75,75 +92,32 @@ export class SourceCodeAnalyzer {
|
|
|
75
92
|
}
|
|
76
93
|
}
|
|
77
94
|
extractContext(key, node, fullFilePath) {
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
//
|
|
81
|
-
let componentName = undefined;
|
|
82
|
-
// Use getAncestors() to find the parent safely
|
|
83
|
-
const componentNode = node
|
|
84
|
-
.getAncestors()
|
|
85
|
-
.find((n) => Node.isFunctionDeclaration(n) ||
|
|
86
|
-
Node.isClassDeclaration(n) ||
|
|
87
|
-
Node.isVariableDeclaration(n));
|
|
88
|
-
if (componentNode) {
|
|
89
|
-
if (Node.isFunctionDeclaration(componentNode) ||
|
|
90
|
-
Node.isClassDeclaration(componentNode)) {
|
|
91
|
-
componentName = componentNode.getName();
|
|
92
|
-
}
|
|
93
|
-
else if (Node.isVariableDeclaration(componentNode)) {
|
|
94
|
-
componentName = componentNode.getName();
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// Extract comments
|
|
98
|
-
// Look for leading comments on the statement
|
|
99
|
-
const statement = node
|
|
100
|
-
.getAncestors()
|
|
101
|
-
.find((n) => Node.isExpressionStatement(n) ||
|
|
102
|
-
Node.isVariableStatement(n) ||
|
|
103
|
-
Node.isJsxElement(n) ||
|
|
104
|
-
Node.isJsxExpression(n));
|
|
105
|
-
const comments = [];
|
|
106
|
-
const targetNode = statement || node;
|
|
107
|
-
const ranges = targetNode.getLeadingCommentRanges();
|
|
108
|
-
for (const range of ranges) {
|
|
109
|
-
comments.push(range
|
|
110
|
-
.getText()
|
|
111
|
-
.replace(/^\/\/\s*/, "")
|
|
112
|
-
.replace(/^\/\*\s*/, "")
|
|
113
|
-
.replace(/\s*\*\/$/, ""));
|
|
114
|
-
}
|
|
115
|
-
// Get props (simple heuristic for JSX)
|
|
95
|
+
const component = this.findComponent(node);
|
|
96
|
+
const comments = this.getComments(node, component?.declaration);
|
|
97
|
+
// Props of the JSX element the text belongs to
|
|
116
98
|
const props = {};
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
131
|
-
(value.startsWith("'") && value.endsWith("'"))) {
|
|
132
|
-
value = value.substring(1, value.length - 1);
|
|
133
|
-
}
|
|
134
|
-
props[name] = value;
|
|
99
|
+
this.findJsxElement(node)
|
|
100
|
+
?.getAttributes()
|
|
101
|
+
.forEach((attr) => {
|
|
102
|
+
if (Node.isJsxAttribute(attr)) {
|
|
103
|
+
// Safe name extraction
|
|
104
|
+
const nameNode = attr.getNameNode();
|
|
105
|
+
const name = nameNode ? nameNode.getText() : "unknown";
|
|
106
|
+
const initializer = attr.getInitializer();
|
|
107
|
+
let value = initializer ? initializer.getText() : "true";
|
|
108
|
+
// Strip quotes if string literal
|
|
109
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
110
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
111
|
+
value = value.substring(1, value.length - 1);
|
|
135
112
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
// Check for node.getParent() to avoid error if node is root (unlikely for call expression)
|
|
140
|
-
const parent = node.getParent();
|
|
141
|
-
const snippet = parent ? parent.getText() : node.getText();
|
|
113
|
+
props[name] = value;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
142
116
|
const context = {
|
|
143
|
-
filePath:
|
|
144
|
-
line,
|
|
145
|
-
component:
|
|
146
|
-
usageSnippet:
|
|
117
|
+
filePath: path.relative(this.rootDir, fullFilePath),
|
|
118
|
+
line: node.getStartLineNumber(),
|
|
119
|
+
component: component?.name,
|
|
120
|
+
usageSnippet: this.getSnippet(node),
|
|
147
121
|
comments: comments.length > 0 ? comments : undefined,
|
|
148
122
|
props: Object.keys(props).length > 0 ? props : undefined,
|
|
149
123
|
};
|
|
@@ -152,6 +126,125 @@ export class SourceCodeAnalyzer {
|
|
|
152
126
|
}
|
|
153
127
|
this.keyUsageMap.get(key)?.push(context);
|
|
154
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* The component the call is in: the nearest enclosing function, class or function-valued
|
|
131
|
+
* variable whose name starts with an uppercase letter, otherwise the nearest one of any name.
|
|
132
|
+
* A variable counts only when the call is inside a function in its initializer
|
|
133
|
+
* (`const Dialog = () => ...`), so `const label = t("key")` does not name a component.
|
|
134
|
+
*/
|
|
135
|
+
findComponent(node) {
|
|
136
|
+
let nearest;
|
|
137
|
+
let insideFunction = false;
|
|
138
|
+
for (const ancestor of node.getAncestors()) {
|
|
139
|
+
let found;
|
|
140
|
+
if (Node.isFunctionDeclaration(ancestor) ||
|
|
141
|
+
Node.isFunctionExpression(ancestor) ||
|
|
142
|
+
Node.isClassDeclaration(ancestor)) {
|
|
143
|
+
const name = ancestor.getName();
|
|
144
|
+
if (name)
|
|
145
|
+
found = { name, declaration: ancestor };
|
|
146
|
+
}
|
|
147
|
+
else if (insideFunction &&
|
|
148
|
+
Node.isVariableDeclaration(ancestor) &&
|
|
149
|
+
Node.isIdentifier(ancestor.getNameNode())) {
|
|
150
|
+
found = {
|
|
151
|
+
name: ancestor.getName(),
|
|
152
|
+
declaration: ancestor.getVariableStatement() ?? ancestor,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
insideFunction ||= isFunction(ancestor);
|
|
156
|
+
if (found && /^[A-Z]/.test(found.name))
|
|
157
|
+
return found;
|
|
158
|
+
nearest ??= found;
|
|
159
|
+
}
|
|
160
|
+
return nearest;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* The JSX element the text belongs to: the one whose attribute holds the call
|
|
164
|
+
* (`<Button title={t("key")} />`) or whose child it is (`<Button>{t("key")}</Button>`).
|
|
165
|
+
* A call inside a nested function (`onClick={() => alert(t("key"))}`) belongs to none.
|
|
166
|
+
*/
|
|
167
|
+
findJsxElement(node) {
|
|
168
|
+
for (const ancestor of node.getAncestors()) {
|
|
169
|
+
if (Node.isJsxOpeningElement(ancestor) || Node.isJsxSelfClosingElement(ancestor)) {
|
|
170
|
+
return ancestor;
|
|
171
|
+
}
|
|
172
|
+
if (Node.isJsxElement(ancestor))
|
|
173
|
+
return ancestor.getOpeningElement();
|
|
174
|
+
if (Node.isJsxFragment(ancestor) ||
|
|
175
|
+
Node.isStatement(ancestor) ||
|
|
176
|
+
isFunction(ancestor)) {
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Comments about the call, nearest first: comments right above the call's expression, JSX
|
|
184
|
+
* attribute, JSX element or statement, `{/* ... *\/}` comments right before its JSX element,
|
|
185
|
+
* and the comment above its component. Tooling directives are left out.
|
|
186
|
+
*/
|
|
187
|
+
getComments(node, component) {
|
|
188
|
+
// Raw comments by start position; nested nodes share their leading comments
|
|
189
|
+
const found = new Map();
|
|
190
|
+
for (let current = node; current && !Node.isSourceFile(current); current = current.getParent()) {
|
|
191
|
+
for (const range of current.getLeadingCommentRanges()) {
|
|
192
|
+
found.set(range.getPos(), range.getText());
|
|
193
|
+
}
|
|
194
|
+
const parent = current.getParent();
|
|
195
|
+
if (Node.isJsxElement(parent) || Node.isJsxFragment(parent)) {
|
|
196
|
+
// `{/* ... */}` children right before this one. Compiler nodes, so a long list
|
|
197
|
+
// of children is not wrapped again for every call in it.
|
|
198
|
+
const sourceFile = current.getSourceFile().compilerNode;
|
|
199
|
+
const siblings = parent.compilerNode.children;
|
|
200
|
+
const self = current.compilerNode;
|
|
201
|
+
for (let i = siblings.findIndex((child) => child === self) - 1; i >= 0; i--) {
|
|
202
|
+
const sibling = siblings[i];
|
|
203
|
+
if (ts.isJsxText(sibling) && sibling.containsOnlyTriviaWhiteSpaces)
|
|
204
|
+
continue;
|
|
205
|
+
if (!ts.isJsxExpression(sibling) || sibling.expression)
|
|
206
|
+
break;
|
|
207
|
+
const text = sibling.getText(sourceFile);
|
|
208
|
+
for (const match of text.matchAll(/\/\*[\s\S]*?\*\/|\/\/.*/g)) {
|
|
209
|
+
found.set(sibling.getStart(sourceFile) + match.index, match[0]);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (Node.isStatement(current))
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
for (const range of component?.getLeadingCommentRanges() ?? []) {
|
|
217
|
+
found.set(range.getPos(), range.getText());
|
|
218
|
+
}
|
|
219
|
+
return [...found.values()]
|
|
220
|
+
.map(commentText)
|
|
221
|
+
.filter((text) => text && !DIRECTIVE_COMMENT.test(text));
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* The code around the call with comments removed: the largest of the call, its enclosing
|
|
225
|
+
* expressions and its statement that fits in MAX_SNIPPET_LENGTH characters.
|
|
226
|
+
*/
|
|
227
|
+
getSnippet(node) {
|
|
228
|
+
const print = (target) => printer
|
|
229
|
+
.printNode(ts.EmitHint.Unspecified, target.compilerNode, target.getSourceFile().compilerNode)
|
|
230
|
+
.replace(/\s+/g, " ")
|
|
231
|
+
.trim();
|
|
232
|
+
let snippet = print(node);
|
|
233
|
+
for (const ancestor of node.getAncestors()) {
|
|
234
|
+
if (Node.isSourceFile(ancestor) || ancestor.getWidth() > MAX_SNIPPET_SOURCE_WIDTH) {
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
const text = print(ancestor);
|
|
238
|
+
if (text.length > MAX_SNIPPET_LENGTH)
|
|
239
|
+
break;
|
|
240
|
+
snippet = text;
|
|
241
|
+
if (Node.isStatement(ancestor))
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
return snippet.length > MAX_SNIPPET_LENGTH
|
|
245
|
+
? `${snippet.substring(0, MAX_SNIPPET_LENGTH)}...`
|
|
246
|
+
: snippet;
|
|
247
|
+
}
|
|
155
248
|
getContext(key) {
|
|
156
249
|
// Return duplicate functionality: prefer the first usage found or merge?
|
|
157
250
|
// For now return the first usage that has comments, or just the first usage.
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import { FlatTranslations } from "../utils/object-transformer.js";
|
|
1
2
|
import Orchestrator from "../core/orchestrator.js";
|
|
2
|
-
import StateManager from "../utils/state-manager.js";
|
|
3
|
+
import StateManager, { StateComparison } from "../utils/state-manager.js";
|
|
3
4
|
import { TranslationOptions, GlobalStats, LanguageProcessResult } from "../types/index.js";
|
|
5
|
+
/** Result of `locai fix` for one source file. */
|
|
6
|
+
export interface FixSummary {
|
|
7
|
+
/** Translations with a length issue. */
|
|
8
|
+
issues: number;
|
|
9
|
+
/** Of those, how many were re-translated successfully. */
|
|
10
|
+
fixed: number;
|
|
11
|
+
}
|
|
4
12
|
/**
|
|
5
13
|
* Service for handling file translation operations.
|
|
6
14
|
* Orchestrates the translation process including state management,
|
|
@@ -26,47 +34,56 @@ declare class TranslationService {
|
|
|
26
34
|
/**
|
|
27
35
|
* Initialize translation state and sync analysis.
|
|
28
36
|
* @param {string} resolvedFile - Path to resolved source file.
|
|
29
|
-
* @param {
|
|
37
|
+
* @param {FlatTranslations} flattenedSource - Flattened source content.
|
|
30
38
|
* @param {TranslationOptions} options - Translation options.
|
|
31
39
|
* @returns {Promise<Object>} - Initialized state components.
|
|
32
40
|
*/
|
|
33
|
-
initializeTranslationState(resolvedFile: string, flattenedSource:
|
|
41
|
+
initializeTranslationState(resolvedFile: string, flattenedSource: FlatTranslations, options: TranslationOptions): Promise<{
|
|
34
42
|
stateManager: StateManager;
|
|
35
43
|
projectRoot: string;
|
|
44
|
+
previousState: Record<string, string>;
|
|
36
45
|
currentState: Record<string, string>;
|
|
37
|
-
comparison:
|
|
46
|
+
comparison: StateComparison;
|
|
38
47
|
}>;
|
|
39
48
|
/**
|
|
40
49
|
* Process all target languages with concurrency.
|
|
41
50
|
* @param {string} resolvedFile - Path to source file.
|
|
42
|
-
* @param {
|
|
51
|
+
* @param {FlatTranslations} flattenedSource - Flattened source content.
|
|
43
52
|
* @param {TranslationOptions} options - Translation options.
|
|
44
53
|
* @param {GlobalStats} globalStats - Global statistics object to update.
|
|
45
|
-
* @param {
|
|
54
|
+
* @param {StateComparison} comparison - State comparison result.
|
|
46
55
|
*/
|
|
47
|
-
processAllLanguages(resolvedFile: string, flattenedSource:
|
|
56
|
+
processAllLanguages(resolvedFile: string, flattenedSource: FlatTranslations, options: TranslationOptions, globalStats: GlobalStats, comparison: StateComparison): Promise<void>;
|
|
48
57
|
/**
|
|
49
58
|
* Process a single language translation.
|
|
50
59
|
* @param {string} targetLang - Target language code.
|
|
51
60
|
* @param {string} sourceFile - Path to source file.
|
|
52
|
-
* @param {
|
|
61
|
+
* @param {FlatTranslations} flattenedSource - Flattened source content.
|
|
53
62
|
* @param {Orchestrator} orchestrator - Orchestrator instance.
|
|
54
63
|
* @param {TranslationOptions} options - Translation options.
|
|
55
64
|
* @param {GlobalStats} globalStats - Global statistics object.
|
|
56
|
-
* @param {
|
|
65
|
+
* @param {StateComparison} comparison - State comparison result.
|
|
57
66
|
* @returns {Promise<LanguageProcessResult>} - Status and messages for this language.
|
|
58
67
|
*/
|
|
59
|
-
processLanguage(targetLang: string, sourceFile: string, flattenedSource:
|
|
68
|
+
processLanguage(targetLang: string, sourceFile: string, flattenedSource: FlatTranslations, orchestrator: Orchestrator, options: TranslationOptions, globalStats: GlobalStats, comparison: StateComparison): Promise<LanguageProcessResult>;
|
|
60
69
|
/**
|
|
61
70
|
* Finalize translation process and save state.
|
|
62
71
|
* @param {StateManager} stateManager - State manager instance.
|
|
63
72
|
* @param {string} projectRoot - Project root directory.
|
|
64
|
-
* @param {
|
|
73
|
+
* @param {Record<string, string>} previousState - State loaded at the start of the run.
|
|
74
|
+
* @param {Record<string, string>} currentState - Current state (key → content hash).
|
|
75
|
+
* @param {StateComparison} comparison - New, modified and deleted keys of this run.
|
|
65
76
|
* @param {GlobalStats} globalStats - Global statistics object.
|
|
66
77
|
* @param {number} startTime - Process start timestamp.
|
|
67
78
|
* @param {TranslationOptions} options - Translation options.
|
|
68
79
|
*/
|
|
69
|
-
finalizeTranslation(stateManager: StateManager, projectRoot: string, currentState:
|
|
80
|
+
finalizeTranslation(stateManager: StateManager, projectRoot: string, previousState: Record<string, string>, currentState: Record<string, string>, comparison: StateComparison, globalStats: GlobalStats, startTime: number, options: TranslationOptions): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Print the confidence scores of the run and, when the review queue is enabled, add the
|
|
83
|
+
* flagged translations to `.localize-cache/review-queue.json`.
|
|
84
|
+
* @param {Orchestrator[]} orchestrators - The run's orchestrators (they share the settings).
|
|
85
|
+
*/
|
|
86
|
+
reportConfidence(orchestrators: Orchestrator[]): Promise<void>;
|
|
70
87
|
/**
|
|
71
88
|
* Remove deleted keys from all target language files.
|
|
72
89
|
* @param {string} sourceFile - Path to source file.
|
|
@@ -78,9 +95,10 @@ declare class TranslationService {
|
|
|
78
95
|
* Validate and fix existing translations that have length issues.
|
|
79
96
|
* @param {string} file - Path to source file.
|
|
80
97
|
* @param {TranslationOptions} options - Translation options.
|
|
98
|
+
* @returns {Promise<FixSummary>} - How many length issues were found and fixed.
|
|
81
99
|
* @throws {Error} If validation process fails.
|
|
82
100
|
*/
|
|
83
|
-
validateAndFixExistingTranslations(file: string, options: TranslationOptions): Promise<
|
|
101
|
+
validateAndFixExistingTranslations(file: string, options: TranslationOptions): Promise<FixSummary>;
|
|
84
102
|
/**
|
|
85
103
|
* Find locale files
|
|
86
104
|
*/
|