@intlayer/cli 6.0.2 → 6.1.1
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 +249 -56
- package/dist/cjs/build.cjs +8 -0
- package/dist/cjs/build.cjs.map +1 -1
- package/dist/cjs/cli.cjs +32 -5
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/fill/index.cjs +114 -59
- package/dist/cjs/fill/index.cjs.map +1 -1
- package/dist/cjs/index.cjs +4 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/liveSync.cjs +6 -30
- package/dist/cjs/liveSync.cjs.map +1 -1
- package/dist/cjs/pull.cjs +1 -1
- package/dist/cjs/pull.cjs.map +1 -1
- package/dist/cjs/push/pullLog.cjs.map +1 -0
- package/dist/cjs/{push.cjs → push/push.cjs} +2 -2
- package/dist/cjs/push/push.cjs.map +1 -0
- package/dist/cjs/reviewDoc.cjs +148 -96
- package/dist/cjs/reviewDoc.cjs.map +1 -1
- package/dist/cjs/test/index.cjs +2 -0
- package/dist/cjs/test/index.cjs.map +1 -1
- package/dist/cjs/translateDoc.cjs +39 -42
- package/dist/cjs/translateDoc.cjs.map +1 -1
- package/dist/cjs/utils/mapChunksBetweenFiles.cjs +145 -0
- package/dist/cjs/utils/mapChunksBetweenFiles.cjs.map +1 -0
- package/dist/cjs/watch.cjs +42 -0
- package/dist/cjs/watch.cjs.map +1 -0
- package/dist/esm/build.mjs +12 -1
- package/dist/esm/build.mjs.map +1 -1
- package/dist/esm/cli.mjs +32 -5
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/fill/index.mjs +114 -59
- package/dist/esm/fill/index.mjs.map +1 -1
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/liveSync.mjs +10 -31
- package/dist/esm/liveSync.mjs.map +1 -1
- package/dist/esm/pull.mjs +1 -1
- package/dist/esm/pull.mjs.map +1 -1
- package/dist/esm/push/pullLog.mjs.map +1 -0
- package/dist/esm/{push.mjs → push/push.mjs} +2 -2
- package/dist/esm/push/push.mjs.map +1 -0
- package/dist/esm/reviewDoc.mjs +151 -97
- package/dist/esm/reviewDoc.mjs.map +1 -1
- package/dist/esm/test/index.mjs +2 -0
- package/dist/esm/test/index.mjs.map +1 -1
- package/dist/esm/translateDoc.mjs +41 -43
- package/dist/esm/translateDoc.mjs.map +1 -1
- package/dist/esm/utils/mapChunksBetweenFiles.mjs +121 -0
- package/dist/esm/utils/mapChunksBetweenFiles.mjs.map +1 -0
- package/dist/esm/watch.mjs +21 -0
- package/dist/esm/watch.mjs.map +1 -0
- package/dist/types/build.d.ts +2 -0
- package/dist/types/build.d.ts.map +1 -1
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/fill/index.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/liveSync.d.ts +1 -1
- package/dist/types/liveSync.d.ts.map +1 -1
- package/dist/types/push/pullLog.d.ts.map +1 -0
- package/dist/types/push/push.d.ts.map +1 -0
- package/dist/types/reviewDoc.d.ts +2 -2
- package/dist/types/reviewDoc.d.ts.map +1 -1
- package/dist/types/test/index.d.ts.map +1 -1
- package/dist/types/translateDoc.d.ts.map +1 -1
- package/dist/types/utils/mapChunksBetweenFiles.d.ts +12 -0
- package/dist/types/utils/mapChunksBetweenFiles.d.ts.map +1 -0
- package/dist/types/watch.d.ts +13 -0
- package/dist/types/watch.d.ts.map +1 -0
- package/package.json +21 -21
- package/dist/cjs/pullLog.cjs.map +0 -1
- package/dist/cjs/push.cjs.map +0 -1
- package/dist/esm/pullLog.mjs.map +0 -1
- package/dist/esm/push.mjs.map +0 -1
- package/dist/types/pullLog.d.ts.map +0 -1
- package/dist/types/push.d.ts.map +0 -1
- /package/dist/cjs/{pullLog.cjs → push/pullLog.cjs} +0 -0
- /package/dist/esm/{pullLog.mjs → push/pullLog.mjs} +0 -0
- /package/dist/types/{pullLog.d.ts → push/pullLog.d.ts} +0 -0
- /package/dist/types/{push.d.ts → push/push.d.ts} +0 -0
package/dist/cjs/reviewDoc.cjs
CHANGED
|
@@ -38,7 +38,6 @@ var import_core = require("@intlayer/core");
|
|
|
38
38
|
var import_fast_glob = __toESM(require("fast-glob"));
|
|
39
39
|
var import_fs = require("fs");
|
|
40
40
|
var import_promises = require("fs/promises");
|
|
41
|
-
var import_p_limit = __toESM(require("p-limit"));
|
|
42
41
|
var import_path = require("path");
|
|
43
42
|
var import_url = require("url");
|
|
44
43
|
var import_calculateChunks = require('./utils/calculateChunks.cjs');
|
|
@@ -48,11 +47,13 @@ var import_chunkInference = require('./utils/chunkInference.cjs');
|
|
|
48
47
|
var import_fixChunkStartEndChars = require('./utils/fixChunkStartEndChars.cjs');
|
|
49
48
|
var import_getChunk = require('./utils/getChunk.cjs');
|
|
50
49
|
var import_getOutputFilePath = require('./utils/getOutputFilePath.cjs');
|
|
50
|
+
var import_mapChunksBetweenFiles = require('./utils/mapChunksBetweenFiles.cjs');
|
|
51
51
|
const import_meta = {};
|
|
52
52
|
const isESModule = typeof import_meta.url === "string";
|
|
53
53
|
const dir = isESModule ? (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url)) : __dirname;
|
|
54
|
-
const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions,
|
|
54
|
+
const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions, configOptions, customInstructions, changedLines) => {
|
|
55
55
|
try {
|
|
56
|
+
const configuration = (0, import_config.getConfiguration)(configOptions);
|
|
56
57
|
const appLogger = (0, import_config.getAppLogger)(configuration, {
|
|
57
58
|
config: {
|
|
58
59
|
prefix: ""
|
|
@@ -63,79 +64,124 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
63
64
|
let updatedFileContent = fileToReviewContent;
|
|
64
65
|
let fileResultContent = "";
|
|
65
66
|
const basePrompt = (await (0, import_promises.readFile)((0, import_path.join)(dir, "./prompts/REVIEW_PROMPT.md"), "utf-8")).replaceAll("{{localeName}}", `${(0, import_chokidar.formatLocale)(locale, false)}`).replaceAll("{{baseLocaleName}}", `${(0, import_chokidar.formatLocale)(baseLocale, false)}`).replace("{{applicationContext}}", aiOptions?.applicationContext ?? "-").replace("{{customInstructions}}", customInstructions ?? "-");
|
|
66
|
-
const baseChunks = (0, import_calculateChunks.chunkText)(basedFileContent, 800, 0);
|
|
67
67
|
const filePrexixText = `${import_config.ANSIColors.GREY_DARK}[${(0, import_chokidar.formatPath)(baseFilePath)}${import_config.ANSIColors.GREY_DARK}] `;
|
|
68
68
|
const filePrefix = [
|
|
69
69
|
(0, import_config.colon)(filePrexixText, { colSize: 40 }),
|
|
70
70
|
`\u2192 ${import_config.ANSIColors.RESET}`
|
|
71
71
|
].join("");
|
|
72
72
|
const prefixText = `${import_config.ANSIColors.GREY_DARK}[${(0, import_chokidar.formatPath)(baseFilePath)}${import_config.ANSIColors.GREY_DARK}][${(0, import_chokidar.formatLocale)(locale)}${import_config.ANSIColors.GREY_DARK}] `;
|
|
73
|
-
const prefix = [
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
73
|
+
const prefix = [
|
|
74
|
+
(0, import_config.colon)(prefixText, { colSize: 40 }),
|
|
75
|
+
`\u2192 ${import_config.ANSIColors.RESET}`
|
|
76
|
+
].join("");
|
|
77
|
+
if (changedLines && changedLines.length > 0) {
|
|
78
|
+
appLogger(
|
|
79
|
+
`${filePrefix}Using optimization with ${(0, import_config.colorizeNumber)(changedLines.length)} changed lines`
|
|
80
|
+
);
|
|
81
|
+
const chunkMappings = (0, import_mapChunksBetweenFiles.mapChunksBetweenFiles)(
|
|
82
|
+
basedFileContent,
|
|
83
|
+
updatedFileContent,
|
|
84
|
+
800,
|
|
85
|
+
changedLines
|
|
86
|
+
);
|
|
87
|
+
appLogger(
|
|
88
|
+
`${filePrefix}Base file mapped to ${(0, import_config.colorizeNumber)(chunkMappings.length)} chunk mappings`
|
|
89
|
+
);
|
|
90
|
+
for await (const [i, mapping] of chunkMappings.entries()) {
|
|
91
|
+
const { baseChunk, updatedChunk, hasChanges } = mapping;
|
|
92
|
+
if (!hasChanges && updatedChunk) {
|
|
84
93
|
appLogger(
|
|
85
|
-
|
|
94
|
+
`${prefix}No changes found for chunk ${(0, import_config.colorizeNumber)(i + 1)}, preserving existing translation`
|
|
86
95
|
);
|
|
87
|
-
const
|
|
88
|
-
lineStart:
|
|
89
|
-
lineLength:
|
|
96
|
+
const existingChunk = (0, import_getChunk.getChunk)(fileToReviewContent, {
|
|
97
|
+
lineStart: updatedChunk.lineStart,
|
|
98
|
+
lineLength: updatedChunk.lineLength
|
|
90
99
|
});
|
|
91
|
-
fileResultContent +=
|
|
100
|
+
fileResultContent += existingChunk;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (!updatedChunk) {
|
|
104
|
+
appLogger(
|
|
105
|
+
`${prefix}Chunk ${(0, import_config.colorizeNumber)(i + 1)} was deleted, skipping`
|
|
106
|
+
);
|
|
92
107
|
continue;
|
|
93
108
|
}
|
|
109
|
+
const baseChunkContext = baseChunk;
|
|
110
|
+
const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} of ${chunkMappings.length}** is the base chunk in ${(0, import_chokidar.formatLocale)(baseLocale, false)} as reference.
|
|
111
|
+
///chunksStart///` + baseChunkContext.content + `///chunksEnd///`;
|
|
112
|
+
const getChunkToReviewPrompt = () => `**CHUNK ${i + 1} of ${chunkMappings.length}** is the current chunk to review in ${(0, import_chokidar.formatLocale)(locale, false)}.
|
|
113
|
+
///chunksStart///` + updatedChunk.content + `///chunksEnd///`;
|
|
114
|
+
let reviewedChunkResult = await (0, import_config.retryManager)(async () => {
|
|
115
|
+
const result = await (0, import_chunkInference.chunkInference)(
|
|
116
|
+
[
|
|
117
|
+
{ role: "system", content: basePrompt },
|
|
118
|
+
{ role: "system", content: getBaseChunkContextPrompt() },
|
|
119
|
+
{ role: "system", content: getChunkToReviewPrompt() },
|
|
120
|
+
{
|
|
121
|
+
role: "system",
|
|
122
|
+
content: `The next user message will be the **CHUNK ${(0, import_config.colorizeNumber)(i + 1)} of ${(0, import_config.colorizeNumber)(chunkMappings.length)}** that should be translated in ${(0, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale}).`
|
|
123
|
+
},
|
|
124
|
+
{ role: "user", content: baseChunkContext.content }
|
|
125
|
+
],
|
|
126
|
+
aiOptions,
|
|
127
|
+
configuration
|
|
128
|
+
);
|
|
129
|
+
appLogger(
|
|
130
|
+
`${prefix}${(0, import_config.colorizeNumber)(result.tokenUsed)} tokens used - Chunk ${(0, import_config.colorizeNumber)(i + 1)} of ${(0, import_config.colorizeNumber)(chunkMappings.length)}`
|
|
131
|
+
);
|
|
132
|
+
const fixedReviewedChunkResult = (0, import_fixChunkStartEndChars.fixChunkStartEndChars)(
|
|
133
|
+
result?.fileContent,
|
|
134
|
+
baseChunkContext.content
|
|
135
|
+
);
|
|
136
|
+
return fixedReviewedChunkResult;
|
|
137
|
+
})();
|
|
138
|
+
fileResultContent += reviewedChunkResult;
|
|
94
139
|
}
|
|
95
|
-
|
|
140
|
+
} else {
|
|
141
|
+
appLogger(`${filePrefix}Processing all chunks (no optimization)`);
|
|
142
|
+
const baseChunks = (0, import_calculateChunks.chunkText)(basedFileContent, 800, 0);
|
|
143
|
+
appLogger(
|
|
144
|
+
`${filePrefix}Base file splitted into ${(0, import_config.colorizeNumber)(baseChunks.length)} chunks`
|
|
145
|
+
);
|
|
146
|
+
for await (const [i, baseChunk] of baseChunks.entries()) {
|
|
147
|
+
const baseChunkContext = baseChunk;
|
|
148
|
+
const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${(0, import_chokidar.formatLocale)(baseLocale, false)} as reference.
|
|
96
149
|
///chunksStart///` + (baseChunks[i - 1]?.content ?? "") + baseChunkContext.content + (baseChunks[i + 1]?.content ?? "") + `///chunksEnd///`;
|
|
97
|
-
|
|
150
|
+
const getChunkToReviewPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the current chunk to review in ${(0, import_chokidar.formatLocale)(locale, false)} as reference.
|
|
98
151
|
///chunksStart///` + (0, import_getChunk.getChunk)(updatedFileContent, {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
result?.fileContent,
|
|
130
|
-
baseChunkContext.content
|
|
152
|
+
lineStart: baseChunks[i - 1]?.lineStart ?? 0,
|
|
153
|
+
lineLength: (baseChunks[i - 1]?.lineLength ?? 0) + baseChunkContext.lineLength + (baseChunks[i + 1]?.lineLength ?? 0)
|
|
154
|
+
}) + `///chunksEnd///`;
|
|
155
|
+
let reviewedChunkResult = await (0, import_config.retryManager)(async () => {
|
|
156
|
+
const result = await (0, import_chunkInference.chunkInference)(
|
|
157
|
+
[
|
|
158
|
+
{ role: "system", content: basePrompt },
|
|
159
|
+
{ role: "system", content: getBaseChunkContextPrompt() },
|
|
160
|
+
{ role: "system", content: getChunkToReviewPrompt() },
|
|
161
|
+
{
|
|
162
|
+
role: "system",
|
|
163
|
+
content: `The next user message will be the **CHUNK ${(0, import_config.colorizeNumber)(i + 1)} of ${(0, import_config.colorizeNumber)(baseChunks.length)}** that should be translated in ${(0, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale}).`
|
|
164
|
+
},
|
|
165
|
+
{ role: "user", content: baseChunkContext.content }
|
|
166
|
+
],
|
|
167
|
+
aiOptions,
|
|
168
|
+
configuration
|
|
169
|
+
);
|
|
170
|
+
appLogger(
|
|
171
|
+
`${prefix}${(0, import_config.colorizeNumber)(result.tokenUsed)} tokens used - Chunk ${(0, import_config.colorizeNumber)(i + 1)} of ${(0, import_config.colorizeNumber)(baseChunks.length)}`
|
|
172
|
+
);
|
|
173
|
+
const fixedReviewedChunkResult = (0, import_fixChunkStartEndChars.fixChunkStartEndChars)(
|
|
174
|
+
result?.fileContent,
|
|
175
|
+
baseChunkContext.content
|
|
176
|
+
);
|
|
177
|
+
return fixedReviewedChunkResult;
|
|
178
|
+
})();
|
|
179
|
+
updatedFileContent = updatedFileContent.replace(
|
|
180
|
+
baseChunkContext.content,
|
|
181
|
+
reviewedChunkResult
|
|
131
182
|
);
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
updatedFileContent = updatedFileContent.replace(
|
|
135
|
-
baseChunkContext.content,
|
|
136
|
-
reviewedChunkResult
|
|
137
|
-
);
|
|
138
|
-
fileResultContent += reviewedChunkResult;
|
|
183
|
+
fileResultContent += reviewedChunkResult;
|
|
184
|
+
}
|
|
139
185
|
}
|
|
140
186
|
(0, import_fs.mkdirSync)((0, import_path.dirname)(outputFilePath), { recursive: true });
|
|
141
187
|
(0, import_fs.writeFileSync)(outputFilePath, fileResultContent);
|
|
@@ -177,7 +223,6 @@ const reviewDoc = async ({
|
|
|
177
223
|
);
|
|
178
224
|
nbSimultaneousFileProcessed = 10;
|
|
179
225
|
}
|
|
180
|
-
const limit = (0, import_p_limit.default)(nbSimultaneousFileProcessed ?? 3);
|
|
181
226
|
let docList = import_fast_glob.default.sync(docPattern, {
|
|
182
227
|
ignore: excludedGlobPattern
|
|
183
228
|
});
|
|
@@ -196,44 +241,51 @@ const reviewDoc = async ({
|
|
|
196
241
|
appLogger(`Reviewing ${(0, import_config.colorizeNumber)(docList.length)} files:`);
|
|
197
242
|
appLogger(docList.map((path) => ` - ${(0, import_chokidar.formatPath)(path)}
|
|
198
243
|
`));
|
|
199
|
-
const
|
|
200
|
-
(docPath) => locales.
|
|
201
|
-
(
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
let changedLines = void 0;
|
|
223
|
-
await reviewFile(
|
|
244
|
+
const allTasks = docList.flatMap(
|
|
245
|
+
(docPath) => locales.map((locale) => async () => {
|
|
246
|
+
appLogger(
|
|
247
|
+
`Reviewing file: ${(0, import_chokidar.formatPath)(docPath)} to ${(0, import_chokidar.formatLocale)(locale)}`
|
|
248
|
+
);
|
|
249
|
+
const absoluteBaseFilePath = (0, import_path.join)(configuration.content.baseDir, docPath);
|
|
250
|
+
const outputFilePath = (0, import_getOutputFilePath.getOutputFilePath)(
|
|
251
|
+
absoluteBaseFilePath,
|
|
252
|
+
locale,
|
|
253
|
+
baseLocale
|
|
254
|
+
);
|
|
255
|
+
const fileModificationData = (0, import_checkFileModifiedRange.checkFileModifiedRange)(outputFilePath, {
|
|
256
|
+
skipIfModifiedBefore,
|
|
257
|
+
skipIfModifiedAfter
|
|
258
|
+
});
|
|
259
|
+
if (fileModificationData.isSkipped) {
|
|
260
|
+
appLogger(fileModificationData.message);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
let changedLines = void 0;
|
|
264
|
+
if (gitOptions) {
|
|
265
|
+
const gitChangedLines = await (0, import_chokidar.listGitLines)(
|
|
224
266
|
absoluteBaseFilePath,
|
|
225
|
-
|
|
226
|
-
locale,
|
|
227
|
-
baseLocale,
|
|
228
|
-
aiOptions,
|
|
229
|
-
configuration,
|
|
230
|
-
customInstructions,
|
|
231
|
-
changedLines
|
|
267
|
+
gitOptions
|
|
232
268
|
);
|
|
233
|
-
|
|
234
|
-
|
|
269
|
+
appLogger(`Git changed lines: ${gitChangedLines.join(", ")}`);
|
|
270
|
+
changedLines = gitChangedLines;
|
|
271
|
+
}
|
|
272
|
+
await reviewFile(
|
|
273
|
+
absoluteBaseFilePath,
|
|
274
|
+
outputFilePath,
|
|
275
|
+
locale,
|
|
276
|
+
baseLocale,
|
|
277
|
+
aiOptions,
|
|
278
|
+
configOptions,
|
|
279
|
+
customInstructions,
|
|
280
|
+
changedLines
|
|
281
|
+
);
|
|
282
|
+
})
|
|
283
|
+
);
|
|
284
|
+
await (0, import_chokidar.parallelize)(
|
|
285
|
+
allTasks,
|
|
286
|
+
(task) => task(),
|
|
287
|
+
nbSimultaneousFileProcessed ?? 3
|
|
235
288
|
);
|
|
236
|
-
await Promise.all(tasks);
|
|
237
289
|
};
|
|
238
290
|
// Annotate the CommonJS export names for ESM import in node:
|
|
239
291
|
0 && (module.exports = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/reviewDoc.ts"],"sourcesContent":["import { AIOptions } from '@intlayer/api'; // OAuth handled by API proxy\nimport {\n formatLocale,\n formatPath,\n listGitFiles,\n ListGitFilesOptions,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeNumber,\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n IntlayerConfig,\n Locales,\n retryManager,\n} from '@intlayer/config';\nimport { getLocaleName } from '@intlayer/core';\nimport fg from 'fast-glob';\nimport { mkdirSync, writeFileSync } from 'fs';\nimport { readFile } from 'fs/promises';\nimport pLimit from 'p-limit';\nimport { dirname, join, relative } from 'path';\nimport { fileURLToPath } from 'url';\nimport { chunkText } from './utils/calculateChunks';\nimport { checkAIAccess } from './utils/checkAccess';\nimport { checkFileModifiedRange } from './utils/checkFileModifiedRange';\nimport { chunkInference } from './utils/chunkInference';\nimport { fixChunkStartEndChars } from './utils/fixChunkStartEndChars';\nimport { getChunk } from './utils/getChunk';\nimport { getOutputFilePath } from './utils/getOutputFilePath';\n\nconst isESModule = typeof import.meta.url === 'string';\n\nconst dir = isESModule ? dirname(fileURLToPath(import.meta.url)) : __dirname;\n\n/**\n * Translate a single file for a given locale\n */\nexport const reviewFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locales,\n baseLocale: Locales,\n aiOptions?: AIOptions,\n configuration: IntlayerConfig = getConfiguration(),\n customInstructions?: string,\n changedLines?: number[]\n) => {\n try {\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const basedFileContent = await readFile(baseFilePath, 'utf-8');\n const fileToReviewContent = await readFile(outputFilePath, 'utf-8');\n\n let updatedFileContent = fileToReviewContent;\n let fileResultContent = '';\n\n // Prepare the base prompt for ChatGPT\n const basePrompt = (\n await readFile(join(dir, './prompts/REVIEW_PROMPT.md'), 'utf-8')\n )\n .replaceAll('{{localeName}}', `${formatLocale(locale, false)}`)\n .replaceAll('{{baseLocaleName}}', `${formatLocale(baseLocale, false)}`)\n .replace('{{applicationContext}}', aiOptions?.applicationContext ?? '-')\n .replace('{{customInstructions}}', customInstructions ?? '-');\n\n const baseChunks = chunkText(basedFileContent, 800, 0);\n\n const filePrexixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}] `;\n const filePrefix = [\n colon(filePrexixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n const prefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `;\n const prefix = [colon(prefixText, { colSize: 40 })].join('');\n\n appLogger(\n `${filePrefix}Base file splitted into ${colorizeNumber(baseChunks.length)} chunks`\n );\n\n for await (const [i, baseChunk] of baseChunks.entries()) {\n const baseChunkContext = baseChunk;\n\n if (changedLines) {\n const hasChangedLinesInChunk = changedLines.some(\n (line) =>\n line > baseChunkContext.lineStart &&\n line < baseChunkContext.lineStart + baseChunkContext.lineLength\n );\n\n if (!hasChangedLinesInChunk) {\n appLogger(\n `No git changed lines found for chunk ${colorizeNumber(i + 1)}`\n );\n\n const chunkWithNoChange = getChunk(updatedFileContent, {\n lineStart: baseChunkContext.lineStart,\n lineLength: baseChunkContext.lineLength,\n });\n\n fileResultContent += chunkWithNoChange;\n\n continue;\n }\n }\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n (baseChunks[i - 1]?.content ?? '') +\n baseChunkContext.content +\n (baseChunks[i + 1]?.content ?? '') +\n `///chunksEnd///`;\n\n const getChunkToReviewPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the current chunk to review in ${formatLocale(locale, false)} as reference.\\n` +\n `///chunksStart///` +\n getChunk(updatedFileContent, {\n lineStart: baseChunks[i - 1]?.lineStart ?? 0,\n lineLength:\n (baseChunks[i - 1]?.lineLength ?? 0) +\n baseChunkContext.lineLength +\n (baseChunks[i + 1]?.lineLength ?? 0),\n }) +\n `///chunksEnd///`;\n\n // Make the actual translation call\n let reviewedChunkResult = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n { role: 'system', content: getBaseChunkContextPrompt() },\n { role: 'system', content: getChunkToReviewPrompt() },\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`,\n },\n { role: 'user', content: baseChunkContext.content },\n ],\n aiOptions,\n configuration\n );\n\n appLogger(\n [\n `${prefix}`,\n `${ANSIColors.GREY_DARK}[Chunk `,\n colorizeNumber(i + 1),\n `${ANSIColors.GREY_DARK} of `,\n colorizeNumber(baseChunks.length),\n `${ANSIColors.GREY_DARK}] →${ANSIColors.RESET} `,\n `${colorizeNumber(result.tokenUsed)} tokens used`,\n ].join('')\n );\n\n const fixedReviewedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n baseChunkContext.content\n );\n\n return fixedReviewedChunkResult;\n })();\n\n updatedFileContent = updatedFileContent.replace(\n baseChunkContext.content,\n reviewedChunkResult\n );\n\n fileResultContent += reviewedChunkResult;\n }\n\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, fileResultContent);\n\n const relativePath = relative(\n configuration.content.baseDir,\n outputFilePath\n );\n\n appLogger(\n `${colorize('✔', ANSIColors.GREEN)} File ${formatPath(relativePath)} created/updated successfully.`\n );\n } catch (error) {\n console.error(error);\n }\n};\n\ntype ReviewDocOptions = {\n docPattern: string[];\n locales: Locales[];\n excludedGlobPattern: string[];\n baseLocale: Locales;\n aiOptions?: AIOptions;\n nbSimultaneousFileProcessed?: number;\n configOptions?: GetConfigurationOptions;\n customInstructions?: string;\n skipIfModifiedBefore?: number | string | Date;\n skipIfModifiedAfter?: number | string | Date;\n gitOptions?: ListGitFilesOptions;\n};\n\n/**\n * Main audit function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then audits them to each locale in LOCALE_LIST.\n */\nexport const reviewDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n gitOptions,\n}: ReviewDocOptions) => {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\n\n if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {\n appLogger(\n `Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`\n );\n nbSimultaneousFileProcessed = 10; // Limit the number of simultaneous file processed to 10\n }\n\n const limit = pLimit(nbSimultaneousFileProcessed ?? 3);\n\n let docList: string[] = fg.sync(docPattern, {\n ignore: excludedGlobPattern,\n });\n\n if (gitOptions) {\n const gitChangedFiles = await listGitFiles(gitOptions);\n\n if (gitChangedFiles) {\n // Convert dictionary file paths to be relative to git root for comparison\n\n // Filter dictionaries based on git changed files\n docList = docList.filter((path) =>\n gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile)\n );\n }\n }\n\n // OAuth handled by API proxy internally\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Reviewing ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Reviewing ${colorizeNumber(docList.length)} files:`);\n appLogger(docList.map((path) => ` - ${formatPath(path)}\\n`));\n\n const tasks = docList.map((docPath) =>\n locales.flatMap((locale) =>\n limit(async () => {\n appLogger(\n `Reviewing file: ${formatPath(docPath)} to ${formatLocale(locale)}`\n );\n\n const absoluteBaseFilePath = join(\n configuration.content.baseDir,\n docPath\n );\n const outputFilePath = getOutputFilePath(\n absoluteBaseFilePath,\n locale,\n baseLocale\n );\n\n const fileModificationData = checkFileModifiedRange(outputFilePath, {\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n });\n\n if (fileModificationData.isSkipped) {\n appLogger(fileModificationData.message);\n return;\n }\n\n let changedLines: number[] | undefined = undefined;\n // Disabled for now because it's leading to file format issues\n // if (gitOptions) {\n // const gitChangedLines = await listGitLines(\n // absoluteBaseFilePath,\n // gitOptions\n // );\n\n // appLogger(`Git changed lines: ${gitChangedLines.join(', ')}`);\n\n // changedLines = gitChangedLines;\n // }\n\n await reviewFile(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locales,\n baseLocale,\n aiOptions,\n configuration,\n customInstructions,\n changedLines\n );\n })\n )\n );\n\n await Promise.all(tasks);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,sBAKO;AACP,oBAWO;AACP,kBAA8B;AAC9B,uBAAe;AACf,gBAAyC;AACzC,sBAAyB;AACzB,qBAAmB;AACnB,kBAAwC;AACxC,iBAA8B;AAC9B,6BAA0B;AAC1B,yBAA8B;AAC9B,oCAAuC;AACvC,4BAA+B;AAC/B,mCAAsC;AACtC,sBAAyB;AACzB,+BAAkC;AAhClC;AAkCA,MAAM,aAAa,OAAO,YAAY,QAAQ;AAE9C,MAAM,MAAM,iBAAa,yBAAQ,0BAAc,YAAY,GAAG,CAAC,IAAI;AAK5D,MAAM,aAAa,OACxB,cACA,gBACA,QACA,YACA,WACA,oBAAgC,gCAAiB,GACjD,oBACA,iBACG;AACH,MAAI;AACF,UAAM,gBAAY,4BAAa,eAAe;AAAA,MAC5C,QAAQ;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAED,UAAM,mBAAmB,UAAM,0BAAS,cAAc,OAAO;AAC7D,UAAM,sBAAsB,UAAM,0BAAS,gBAAgB,OAAO;AAElE,QAAI,qBAAqB;AACzB,QAAI,oBAAoB;AAGxB,UAAM,cACJ,UAAM,8BAAS,kBAAK,KAAK,4BAA4B,GAAG,OAAO,GAE9D,WAAW,kBAAkB,OAAG,8BAAa,QAAQ,KAAK,CAAC,EAAE,EAC7D,WAAW,sBAAsB,OAAG,8BAAa,YAAY,KAAK,CAAC,EAAE,EACrE,QAAQ,0BAA0B,WAAW,sBAAsB,GAAG,EACtE,QAAQ,0BAA0B,sBAAsB,GAAG;AAE9D,UAAM,iBAAa,kCAAU,kBAAkB,KAAK,CAAC;AAErD,UAAM,iBAAiB,GAAG,yBAAW,SAAS,QAAI,4BAAW,YAAY,CAAC,GAAG,yBAAW,SAAS;AACjG,UAAM,aAAa;AAAA,UACjB,qBAAM,gBAAgB,EAAE,SAAS,GAAG,CAAC;AAAA,MACrC,UAAK,yBAAW,KAAK;AAAA,IACvB,EAAE,KAAK,EAAE;AAET,UAAM,aAAa,GAAG,yBAAW,SAAS,QAAI,4BAAW,YAAY,CAAC,GAAG,yBAAW,SAAS,SAAK,8BAAa,MAAM,CAAC,GAAG,yBAAW,SAAS;AAC7I,UAAM,SAAS,KAAC,qBAAM,YAAY,EAAE,SAAS,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE;AAE3D;AAAA,MACE,GAAG,UAAU,+BAA2B,8BAAe,WAAW,MAAM,CAAC;AAAA,IAC3E;AAEA,qBAAiB,CAAC,GAAG,SAAS,KAAK,WAAW,QAAQ,GAAG;AACvD,YAAM,mBAAmB;AAEzB,UAAI,cAAc;AAChB,cAAM,yBAAyB,aAAa;AAAA,UAC1C,CAAC,SACC,OAAO,iBAAiB,aACxB,OAAO,iBAAiB,YAAY,iBAAiB;AAAA,QACzD;AAEA,YAAI,CAAC,wBAAwB;AAC3B;AAAA,YACE,4CAAwC,8BAAe,IAAI,CAAC,CAAC;AAAA,UAC/D;AAEA,gBAAM,wBAAoB,0BAAS,oBAAoB;AAAA,YACrD,WAAW,iBAAiB;AAAA,YAC5B,YAAY,iBAAiB;AAAA,UAC/B,CAAC;AAED,+BAAqB;AAErB;AAAA,QACF;AAAA,MACF;AAEA,YAAM,4BAA4B,MAChC,WAAW,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,GAAG,WAAW,MAAM,CAAC,OAAO,WAAW,MAAM,+BAA2B,8BAAa,YAAY,KAAK,CAAC;AAAA,sBAE1I,WAAW,IAAI,CAAC,GAAG,WAAW,MAC/B,iBAAiB,WAChB,WAAW,IAAI,CAAC,GAAG,WAAW,MAC/B;AAEF,YAAM,yBAAyB,MAC7B,WAAW,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,GAAG,WAAW,MAAM,CAAC,OAAO,WAAW,MAAM,4CAAwC,8BAAa,QAAQ,KAAK,CAAC;AAAA,yBAEpJ,0BAAS,oBAAoB;AAAA,QAC3B,WAAW,WAAW,IAAI,CAAC,GAAG,aAAa;AAAA,QAC3C,aACG,WAAW,IAAI,CAAC,GAAG,cAAc,KAClC,iBAAiB,cAChB,WAAW,IAAI,CAAC,GAAG,cAAc;AAAA,MACtC,CAAC,IACD;AAGF,UAAI,sBAAsB,UAAM,4BAAa,YAAY;AACvD,cAAM,SAAS,UAAM;AAAA,UACnB;AAAA,YACE,EAAE,MAAM,UAAU,SAAS,WAAW;AAAA,YACtC,EAAE,MAAM,UAAU,SAAS,0BAA0B,EAAE;AAAA,YACvD,EAAE,MAAM,UAAU,SAAS,uBAAuB,EAAE;AAAA,YACpD;AAAA,cACE,MAAM;AAAA,cACN,SAAS,iDAA6C,8BAAe,IAAI,CAAC,CAAC,WAAO,8BAAe,WAAW,MAAM,CAAC,uCAAmC,2BAAc,QAAQ,sBAAQ,OAAO,CAAC,KAAK,MAAM;AAAA,YACzM;AAAA,YACA,EAAE,MAAM,QAAQ,SAAS,iBAAiB,QAAQ;AAAA,UACpD;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAEA;AAAA,UACE;AAAA,YACE,GAAG,MAAM;AAAA,YACT,GAAG,yBAAW,SAAS;AAAA,gBACvB,8BAAe,IAAI,CAAC;AAAA,YACpB,GAAG,yBAAW,SAAS;AAAA,gBACvB,8BAAe,WAAW,MAAM;AAAA,YAChC,GAAG,yBAAW,SAAS,WAAM,yBAAW,KAAK;AAAA,YAC7C,OAAG,8BAAe,OAAO,SAAS,CAAC;AAAA,UACrC,EAAE,KAAK,EAAE;AAAA,QACX;AAEA,cAAM,+BAA2B;AAAA,UAC/B,QAAQ;AAAA,UACR,iBAAiB;AAAA,QACnB;AAEA,eAAO;AAAA,MACT,CAAC,EAAE;AAEH,2BAAqB,mBAAmB;AAAA,QACtC,iBAAiB;AAAA,QACjB;AAAA,MACF;AAEA,2BAAqB;AAAA,IACvB;AAEA,iCAAU,qBAAQ,cAAc,GAAG,EAAE,WAAW,KAAK,CAAC;AACtD,iCAAc,gBAAgB,iBAAiB;AAE/C,UAAM,mBAAe;AAAA,MACnB,cAAc,QAAQ;AAAA,MACtB;AAAA,IACF;AAEA;AAAA,MACE,OAAG,wBAAS,UAAK,yBAAW,KAAK,CAAC,aAAS,4BAAW,YAAY,CAAC;AAAA,IACrE;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,KAAK;AAAA,EACrB;AACF;AAoBO,MAAM,YAAY,OAAO;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAwB;AACtB,QAAM,oBAAgB,gCAAiB,aAAa;AACpD,QAAM,gBAAY,4BAAa,eAAe;AAAA,IAC5C,QAAQ;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF,CAAC;AAED,QAAM,aAAa,UAAM,kCAAc,eAAe,SAAS;AAE/D,MAAI,CAAC,WAAY;AAEjB,MAAI,+BAA+B,8BAA8B,IAAI;AACnE;AAAA,MACE,kDAAkD,2BAA2B;AAAA,IAC/E;AACA,kCAA8B;AAAA,EAChC;AAEA,QAAM,YAAQ,eAAAA,SAAO,+BAA+B,CAAC;AAErD,MAAI,UAAoB,iBAAAC,QAAG,KAAK,YAAY;AAAA,IAC1C,QAAQ;AAAA,EACV,CAAC;AAED,MAAI,YAAY;AACd,UAAM,kBAAkB,UAAM,8BAAa,UAAU;AAErD,QAAI,iBAAiB;AAInB,gBAAU,QAAQ;AAAA,QAAO,CAAC,SACxB,gBAAgB,KAAK,CAAC,gBAAY,kBAAK,QAAQ,IAAI,GAAG,IAAI,MAAM,OAAO;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AAIA,YAAU,sBAAkB,8BAAa,UAAU,CAAC,EAAE;AACtD;AAAA,IACE,iBAAa,8BAAe,QAAQ,MAAM,CAAC,mBAAe,8BAAa,OAAO,CAAC;AAAA,EACjF;AAEA,YAAU,iBAAa,8BAAe,QAAQ,MAAM,CAAC,SAAS;AAC9D,YAAU,QAAQ,IAAI,CAAC,SAAS,UAAM,4BAAW,IAAI,CAAC;AAAA,CAAI,CAAC;AAE3D,QAAM,QAAQ,QAAQ;AAAA,IAAI,CAAC,YACzB,QAAQ;AAAA,MAAQ,CAAC,WACf,MAAM,YAAY;AAChB;AAAA,UACE,uBAAmB,4BAAW,OAAO,CAAC,WAAO,8BAAa,MAAM,CAAC;AAAA,QACnE;AAEA,cAAM,2BAAuB;AAAA,UAC3B,cAAc,QAAQ;AAAA,UACtB;AAAA,QACF;AACA,cAAM,qBAAiB;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAEA,cAAM,2BAAuB,sDAAuB,gBAAgB;AAAA,UAClE;AAAA,UACA;AAAA,QACF,CAAC;AAED,YAAI,qBAAqB,WAAW;AAClC,oBAAU,qBAAqB,OAAO;AACtC;AAAA,QACF;AAEA,YAAI,eAAqC;AAazC,cAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,KAAK;AACzB;","names":["pLimit","fg"]}
|
|
1
|
+
{"version":3,"sources":["../../src/reviewDoc.ts"],"sourcesContent":["import { AIOptions } from '@intlayer/api'; // OAuth handled by API proxy\nimport {\n formatLocale,\n formatPath,\n listGitFiles,\n ListGitFilesOptions,\n listGitLines,\n parallelize,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeNumber,\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n Locales,\n retryManager,\n} from '@intlayer/config';\nimport { getLocaleName } from '@intlayer/core';\nimport fg from 'fast-glob';\nimport { mkdirSync, writeFileSync } from 'fs';\nimport { readFile } from 'fs/promises';\nimport { dirname, join, relative } from 'path';\nimport { fileURLToPath } from 'url';\nimport { chunkText } from './utils/calculateChunks';\nimport { checkAIAccess } from './utils/checkAccess';\nimport { checkFileModifiedRange } from './utils/checkFileModifiedRange';\nimport { chunkInference } from './utils/chunkInference';\nimport { fixChunkStartEndChars } from './utils/fixChunkStartEndChars';\nimport { getChunk } from './utils/getChunk';\nimport { getOutputFilePath } from './utils/getOutputFilePath';\nimport { mapChunksBetweenFiles } from './utils/mapChunksBetweenFiles';\n\nconst isESModule = typeof import.meta.url === 'string';\n\nconst dir = isESModule ? dirname(fileURLToPath(import.meta.url)) : __dirname;\n\n/**\n * Translate a single file for a given locale\n */\nexport const reviewFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locales,\n baseLocale: Locales,\n aiOptions?: AIOptions,\n configOptions?: GetConfigurationOptions,\n customInstructions?: string,\n changedLines?: number[]\n) => {\n try {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const basedFileContent = await readFile(baseFilePath, 'utf-8');\n const fileToReviewContent = await readFile(outputFilePath, 'utf-8');\n\n let updatedFileContent = fileToReviewContent;\n let fileResultContent = '';\n\n // Prepare the base prompt for ChatGPT\n const basePrompt = (\n await readFile(join(dir, './prompts/REVIEW_PROMPT.md'), 'utf-8')\n )\n .replaceAll('{{localeName}}', `${formatLocale(locale, false)}`)\n .replaceAll('{{baseLocaleName}}', `${formatLocale(baseLocale, false)}`)\n .replace('{{applicationContext}}', aiOptions?.applicationContext ?? '-')\n .replace('{{customInstructions}}', customInstructions ?? '-');\n\n const filePrexixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}] `;\n const filePrefix = [\n colon(filePrexixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n const prefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `;\n const prefix = [\n colon(prefixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n // FIXED: Use proper chunk mapping when changed lines are available\n if (changedLines && changedLines.length > 0) {\n appLogger(\n `${filePrefix}Using optimization with ${colorizeNumber(changedLines.length)} changed lines`\n );\n\n // Map chunks between base and updated files properly\n const chunkMappings = mapChunksBetweenFiles(\n basedFileContent,\n updatedFileContent,\n 800,\n changedLines\n );\n\n appLogger(\n `${filePrefix}Base file mapped to ${colorizeNumber(chunkMappings.length)} chunk mappings`\n );\n\n for await (const [i, mapping] of chunkMappings.entries()) {\n const { baseChunk, updatedChunk, hasChanges } = mapping;\n\n if (!hasChanges && updatedChunk) {\n // No changes detected, use the existing translated content\n appLogger(\n `${prefix}No changes found for chunk ${colorizeNumber(i + 1)}, preserving existing translation`\n );\n\n // Extract the corresponding chunk from the existing translated file\n const existingChunk = getChunk(fileToReviewContent, {\n lineStart: updatedChunk.lineStart,\n lineLength: updatedChunk.lineLength,\n });\n\n fileResultContent += existingChunk;\n continue;\n }\n\n if (!updatedChunk) {\n // Chunk was completely deleted, skip it\n appLogger(\n `${prefix}Chunk ${colorizeNumber(i + 1)} was deleted, skipping`\n );\n continue;\n }\n\n // Process chunks with changes\n const baseChunkContext = baseChunk;\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} of ${chunkMappings.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n baseChunkContext.content +\n `///chunksEnd///`;\n\n const getChunkToReviewPrompt = () =>\n `**CHUNK ${i + 1} of ${chunkMappings.length}** is the current chunk to review in ${formatLocale(locale, false)}.\\n` +\n `///chunksStart///` +\n updatedChunk.content +\n `///chunksEnd///`;\n\n // Make the actual translation call\n let reviewedChunkResult = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n { role: 'system', content: getBaseChunkContextPrompt() },\n { role: 'system', content: getChunkToReviewPrompt() },\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(chunkMappings.length)}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`,\n },\n { role: 'user', content: baseChunkContext.content },\n ],\n aiOptions,\n configuration\n );\n\n appLogger(\n `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(chunkMappings.length)}`\n );\n\n const fixedReviewedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n baseChunkContext.content\n );\n\n return fixedReviewedChunkResult;\n })();\n\n fileResultContent += reviewedChunkResult;\n }\n } else {\n // FALLBACK: Process all chunks when no optimization is available\n appLogger(`${filePrefix}Processing all chunks (no optimization)`);\n\n const baseChunks = chunkText(basedFileContent, 800, 0);\n appLogger(\n `${filePrefix}Base file splitted into ${colorizeNumber(baseChunks.length)} chunks`\n );\n\n for await (const [i, baseChunk] of baseChunks.entries()) {\n const baseChunkContext = baseChunk;\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n (baseChunks[i - 1]?.content ?? '') +\n baseChunkContext.content +\n (baseChunks[i + 1]?.content ?? '') +\n `///chunksEnd///`;\n\n const getChunkToReviewPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the current chunk to review in ${formatLocale(locale, false)} as reference.\\n` +\n `///chunksStart///` +\n getChunk(updatedFileContent, {\n lineStart: baseChunks[i - 1]?.lineStart ?? 0,\n lineLength:\n (baseChunks[i - 1]?.lineLength ?? 0) +\n baseChunkContext.lineLength +\n (baseChunks[i + 1]?.lineLength ?? 0),\n }) +\n `///chunksEnd///`;\n\n // Make the actual translation call\n let reviewedChunkResult = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n { role: 'system', content: getBaseChunkContextPrompt() },\n { role: 'system', content: getChunkToReviewPrompt() },\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`,\n },\n { role: 'user', content: baseChunkContext.content },\n ],\n aiOptions,\n configuration\n );\n\n appLogger(\n `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}`\n );\n\n const fixedReviewedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n baseChunkContext.content\n );\n\n return fixedReviewedChunkResult;\n })();\n\n updatedFileContent = updatedFileContent.replace(\n baseChunkContext.content,\n reviewedChunkResult\n );\n\n fileResultContent += reviewedChunkResult;\n }\n }\n\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, fileResultContent);\n\n const relativePath = relative(\n configuration.content.baseDir,\n outputFilePath\n );\n\n appLogger(\n `${colorize('✔', ANSIColors.GREEN)} File ${formatPath(relativePath)} created/updated successfully.`\n );\n } catch (error) {\n console.error(error);\n }\n};\n\ntype ReviewDocOptions = {\n docPattern: string[];\n locales: Locales[];\n excludedGlobPattern: string[];\n baseLocale: Locales;\n aiOptions?: AIOptions;\n nbSimultaneousFileProcessed?: number;\n configOptions?: GetConfigurationOptions;\n customInstructions?: string;\n skipIfModifiedBefore?: number | string | Date;\n skipIfModifiedAfter?: number | string | Date;\n gitOptions?: ListGitFilesOptions;\n};\n\n/**\n * Main audit function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then audits them to each locale in LOCALE_LIST.\n */\nexport const reviewDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n gitOptions,\n}: ReviewDocOptions) => {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\n\n if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {\n appLogger(\n `Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`\n );\n nbSimultaneousFileProcessed = 10; // Limit the number of simultaneous file processed to 10\n }\n\n let docList: string[] = fg.sync(docPattern, {\n ignore: excludedGlobPattern,\n });\n\n if (gitOptions) {\n const gitChangedFiles = await listGitFiles(gitOptions);\n\n if (gitChangedFiles) {\n // Convert dictionary file paths to be relative to git root for comparison\n\n // Filter dictionaries based on git changed files\n docList = docList.filter((path) =>\n gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile)\n );\n }\n }\n\n // OAuth handled by API proxy internally\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Reviewing ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Reviewing ${colorizeNumber(docList.length)} files:`);\n appLogger(docList.map((path) => ` - ${formatPath(path)}\\n`));\n\n // Create all tasks to be processed\n const allTasks = docList.flatMap((docPath) =>\n locales.map((locale) => async () => {\n appLogger(\n `Reviewing file: ${formatPath(docPath)} to ${formatLocale(locale)}`\n );\n\n const absoluteBaseFilePath = join(configuration.content.baseDir, docPath);\n const outputFilePath = getOutputFilePath(\n absoluteBaseFilePath,\n locale,\n baseLocale\n );\n\n const fileModificationData = checkFileModifiedRange(outputFilePath, {\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n });\n\n if (fileModificationData.isSkipped) {\n appLogger(fileModificationData.message);\n return;\n }\n\n let changedLines: number[] | undefined = undefined;\n // FIXED: Enable git optimization that was previously commented out\n if (gitOptions) {\n const gitChangedLines = await listGitLines(\n absoluteBaseFilePath,\n gitOptions\n );\n\n appLogger(`Git changed lines: ${gitChangedLines.join(', ')}`);\n changedLines = gitChangedLines;\n }\n\n await reviewFile(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locales,\n baseLocale,\n aiOptions,\n configOptions,\n customInstructions,\n changedLines\n );\n })\n );\n\n await parallelize(\n allTasks,\n (task) => task(),\n nbSimultaneousFileProcessed ?? 3\n );\n};\n"],"mappings":"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","names":["fg"]}
|
package/dist/cjs/test/index.cjs
CHANGED
|
@@ -69,6 +69,7 @@ const testMissingTranslations = (options) => {
|
|
|
69
69
|
);
|
|
70
70
|
appLogger(
|
|
71
71
|
`Total missing locales: ${(0, import_config.colorizeNumber)(result.missingLocales.length, {
|
|
72
|
+
one: import_config.ANSIColors.RED,
|
|
72
73
|
other: import_config.ANSIColors.RED,
|
|
73
74
|
zero: import_config.ANSIColors.GREEN
|
|
74
75
|
})}`
|
|
@@ -77,6 +78,7 @@ const testMissingTranslations = (options) => {
|
|
|
77
78
|
`Total missing required locales: ${(0, import_config.colorizeNumber)(
|
|
78
79
|
result.missingRequiredLocales.length,
|
|
79
80
|
{
|
|
81
|
+
one: import_config.ANSIColors.RED,
|
|
80
82
|
other: import_config.ANSIColors.RED,
|
|
81
83
|
zero: import_config.ANSIColors.GREEN
|
|
82
84
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/test/index.ts"],"sourcesContent":["import { formatLocale, formatPath } from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeKey,\n colorizeNumber,\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n} from '@intlayer/config';\nimport { listMissingTranslations } from './listMissingTranslations';\n\nexport { listMissingTranslations };\n\ntype ListMissingTranslationsOptions = {\n configOptions?: GetConfigurationOptions;\n};\n\nexport const testMissingTranslations = (\n options?: ListMissingTranslationsOptions\n) => {\n const config = getConfiguration(options?.configOptions);\n const { locales, requiredLocales } = config.internationalization;\n\n const appLogger = getAppLogger(config, {\n config: {\n prefix: '',\n },\n });\n\n const result = listMissingTranslations(undefined, options?.configOptions);\n\n const maxKeyColSize = result.missingTranslations\n .map((t) => ` - ${t.key}`)\n .reduce((max, t) => Math.max(max, t.length), 0);\n const maxLocalesColSize = result.missingTranslations\n .map((t) => formatLocale(t.locales, false))\n .reduce((max, t) => Math.max(max, t.length), 0);\n\n const formattedMissingTranslations = result.missingTranslations.map(\n (translation) =>\n [\n colon(` - ${colorizeKey(translation.key)}`, {\n colSize: maxKeyColSize,\n maxSize: 40,\n }),\n ' - ',\n colon(formatLocale(translation.locales, ANSIColors.RED), {\n colSize: maxLocalesColSize,\n maxSize: 40,\n }),\n ' - ',\n translation.filePath ? formatPath(translation.filePath) : 'Remote',\n ].join('')\n );\n\n appLogger(`Missing translations:`, {\n level: 'info',\n });\n\n formattedMissingTranslations.forEach((t) => {\n appLogger(t, {\n level: 'info',\n });\n });\n\n appLogger(`Locales: ${formatLocale(locales)}`);\n appLogger(`Required locales: ${formatLocale(requiredLocales ?? locales)}`);\n appLogger(\n `Missing locales: ${result.missingLocales.length === 0 ? colorize('-', ANSIColors.GREEN) : formatLocale(result.missingLocales, ANSIColors.RED)}`\n );\n\n appLogger(\n `Missing required locales: ${result.missingRequiredLocales.length === 0 ? colorize('-', ANSIColors.GREEN) : formatLocale(result.missingRequiredLocales, ANSIColors.RED)}`\n );\n appLogger(\n `Total missing locales: ${colorizeNumber(result.missingLocales.length, {\n other: ANSIColors.RED,\n zero: ANSIColors.GREEN,\n })}`\n );\n appLogger(\n `Total missing required locales: ${colorizeNumber(\n result.missingRequiredLocales.length,\n {\n other: ANSIColors.RED,\n zero: ANSIColors.GREEN,\n }\n )}`\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAyC;AACzC,oBASO;AACP,qCAAwC;AAQjC,MAAM,0BAA0B,CACrC,YACG;AACH,QAAM,aAAS,gCAAiB,SAAS,aAAa;AACtD,QAAM,EAAE,SAAS,gBAAgB,IAAI,OAAO;AAE5C,QAAM,gBAAY,4BAAa,QAAQ;AAAA,IACrC,QAAQ;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF,CAAC;AAED,QAAM,aAAS,wDAAwB,QAAW,SAAS,aAAa;AAExE,QAAM,gBAAgB,OAAO,oBAC1B,IAAI,CAAC,MAAM,MAAM,EAAE,GAAG,EAAE,EACxB,OAAO,CAAC,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,MAAM,GAAG,CAAC;AAChD,QAAM,oBAAoB,OAAO,oBAC9B,IAAI,CAAC,UAAM,8BAAa,EAAE,SAAS,KAAK,CAAC,EACzC,OAAO,CAAC,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,MAAM,GAAG,CAAC;AAEhD,QAAM,+BAA+B,OAAO,oBAAoB;AAAA,IAC9D,CAAC,gBACC;AAAA,UACE,qBAAM,UAAM,2BAAY,YAAY,GAAG,CAAC,IAAI;AAAA,QAC1C,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,MACD;AAAA,UACA,yBAAM,8BAAa,YAAY,SAAS,yBAAW,GAAG,GAAG;AAAA,QACvD,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,MACD;AAAA,MACA,YAAY,eAAW,4BAAW,YAAY,QAAQ,IAAI;AAAA,IAC5D,EAAE,KAAK,EAAE;AAAA,EACb;AAEA,YAAU,yBAAyB;AAAA,IACjC,OAAO;AAAA,EACT,CAAC;AAED,+BAA6B,QAAQ,CAAC,MAAM;AAC1C,cAAU,GAAG;AAAA,MACX,OAAO;AAAA,IACT,CAAC;AAAA,EACH,CAAC;AAED,YAAU,gBAAY,8BAAa,OAAO,CAAC,EAAE;AAC7C,YAAU,yBAAqB,8BAAa,mBAAmB,OAAO,CAAC,EAAE;AACzE;AAAA,IACE,oBAAoB,OAAO,eAAe,WAAW,QAAI,wBAAS,KAAK,yBAAW,KAAK,QAAI,8BAAa,OAAO,gBAAgB,yBAAW,GAAG,CAAC;AAAA,EAChJ;AAEA;AAAA,IACE,6BAA6B,OAAO,uBAAuB,WAAW,QAAI,wBAAS,KAAK,yBAAW,KAAK,QAAI,8BAAa,OAAO,wBAAwB,yBAAW,GAAG,CAAC;AAAA,EACzK;AACA;AAAA,IACE,8BAA0B,8BAAe,OAAO,eAAe,QAAQ;AAAA,MACrE,OAAO,yBAAW;AAAA,MAClB,MAAM,yBAAW;AAAA,IACnB,CAAC,CAAC;AAAA,EACJ;AACA;AAAA,IACE,uCAAmC;AAAA,MACjC,OAAO,uBAAuB;AAAA,MAC9B;AAAA,QACE,OAAO,yBAAW;AAAA,QAClB,MAAM,yBAAW;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/test/index.ts"],"sourcesContent":["import { formatLocale, formatPath } from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeKey,\n colorizeNumber,\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n} from '@intlayer/config';\nimport { listMissingTranslations } from './listMissingTranslations';\n\nexport { listMissingTranslations };\n\ntype ListMissingTranslationsOptions = {\n configOptions?: GetConfigurationOptions;\n};\n\nexport const testMissingTranslations = (\n options?: ListMissingTranslationsOptions\n) => {\n const config = getConfiguration(options?.configOptions);\n const { locales, requiredLocales } = config.internationalization;\n\n const appLogger = getAppLogger(config, {\n config: {\n prefix: '',\n },\n });\n\n const result = listMissingTranslations(undefined, options?.configOptions);\n\n const maxKeyColSize = result.missingTranslations\n .map((t) => ` - ${t.key}`)\n .reduce((max, t) => Math.max(max, t.length), 0);\n const maxLocalesColSize = result.missingTranslations\n .map((t) => formatLocale(t.locales, false))\n .reduce((max, t) => Math.max(max, t.length), 0);\n\n const formattedMissingTranslations = result.missingTranslations.map(\n (translation) =>\n [\n colon(` - ${colorizeKey(translation.key)}`, {\n colSize: maxKeyColSize,\n maxSize: 40,\n }),\n ' - ',\n colon(formatLocale(translation.locales, ANSIColors.RED), {\n colSize: maxLocalesColSize,\n maxSize: 40,\n }),\n ' - ',\n translation.filePath ? formatPath(translation.filePath) : 'Remote',\n ].join('')\n );\n\n appLogger(`Missing translations:`, {\n level: 'info',\n });\n\n formattedMissingTranslations.forEach((t) => {\n appLogger(t, {\n level: 'info',\n });\n });\n\n appLogger(`Locales: ${formatLocale(locales)}`);\n appLogger(`Required locales: ${formatLocale(requiredLocales ?? locales)}`);\n appLogger(\n `Missing locales: ${result.missingLocales.length === 0 ? colorize('-', ANSIColors.GREEN) : formatLocale(result.missingLocales, ANSIColors.RED)}`\n );\n\n appLogger(\n `Missing required locales: ${result.missingRequiredLocales.length === 0 ? colorize('-', ANSIColors.GREEN) : formatLocale(result.missingRequiredLocales, ANSIColors.RED)}`\n );\n appLogger(\n `Total missing locales: ${colorizeNumber(result.missingLocales.length, {\n one: ANSIColors.RED,\n other: ANSIColors.RED,\n zero: ANSIColors.GREEN,\n })}`\n );\n appLogger(\n `Total missing required locales: ${colorizeNumber(\n result.missingRequiredLocales.length,\n {\n one: ANSIColors.RED,\n other: ANSIColors.RED,\n zero: ANSIColors.GREEN,\n }\n )}`\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAyC;AACzC,oBASO;AACP,qCAAwC;AAQjC,MAAM,0BAA0B,CACrC,YACG;AACH,QAAM,aAAS,gCAAiB,SAAS,aAAa;AACtD,QAAM,EAAE,SAAS,gBAAgB,IAAI,OAAO;AAE5C,QAAM,gBAAY,4BAAa,QAAQ;AAAA,IACrC,QAAQ;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF,CAAC;AAED,QAAM,aAAS,wDAAwB,QAAW,SAAS,aAAa;AAExE,QAAM,gBAAgB,OAAO,oBAC1B,IAAI,CAAC,MAAM,MAAM,EAAE,GAAG,EAAE,EACxB,OAAO,CAAC,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,MAAM,GAAG,CAAC;AAChD,QAAM,oBAAoB,OAAO,oBAC9B,IAAI,CAAC,UAAM,8BAAa,EAAE,SAAS,KAAK,CAAC,EACzC,OAAO,CAAC,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,MAAM,GAAG,CAAC;AAEhD,QAAM,+BAA+B,OAAO,oBAAoB;AAAA,IAC9D,CAAC,gBACC;AAAA,UACE,qBAAM,UAAM,2BAAY,YAAY,GAAG,CAAC,IAAI;AAAA,QAC1C,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,MACD;AAAA,UACA,yBAAM,8BAAa,YAAY,SAAS,yBAAW,GAAG,GAAG;AAAA,QACvD,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,MACD;AAAA,MACA,YAAY,eAAW,4BAAW,YAAY,QAAQ,IAAI;AAAA,IAC5D,EAAE,KAAK,EAAE;AAAA,EACb;AAEA,YAAU,yBAAyB;AAAA,IACjC,OAAO;AAAA,EACT,CAAC;AAED,+BAA6B,QAAQ,CAAC,MAAM;AAC1C,cAAU,GAAG;AAAA,MACX,OAAO;AAAA,IACT,CAAC;AAAA,EACH,CAAC;AAED,YAAU,gBAAY,8BAAa,OAAO,CAAC,EAAE;AAC7C,YAAU,yBAAqB,8BAAa,mBAAmB,OAAO,CAAC,EAAE;AACzE;AAAA,IACE,oBAAoB,OAAO,eAAe,WAAW,QAAI,wBAAS,KAAK,yBAAW,KAAK,QAAI,8BAAa,OAAO,gBAAgB,yBAAW,GAAG,CAAC;AAAA,EAChJ;AAEA;AAAA,IACE,6BAA6B,OAAO,uBAAuB,WAAW,QAAI,wBAAS,KAAK,yBAAW,KAAK,QAAI,8BAAa,OAAO,wBAAwB,yBAAW,GAAG,CAAC;AAAA,EACzK;AACA;AAAA,IACE,8BAA0B,8BAAe,OAAO,eAAe,QAAQ;AAAA,MACrE,KAAK,yBAAW;AAAA,MAChB,OAAO,yBAAW;AAAA,MAClB,MAAM,yBAAW;AAAA,IACnB,CAAC,CAAC;AAAA,EACJ;AACA;AAAA,IACE,uCAAmC;AAAA,MACjC,OAAO,uBAAuB;AAAA,MAC9B;AAAA,QACE,KAAK,yBAAW;AAAA,QAChB,OAAO,yBAAW;AAAA,QAClB,MAAM,yBAAW;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH;AACF;","names":[]}
|
|
@@ -37,7 +37,6 @@ var import_config = require("@intlayer/config");
|
|
|
37
37
|
var import_fast_glob = __toESM(require("fast-glob"));
|
|
38
38
|
var import_fs = require("fs");
|
|
39
39
|
var import_promises = require("fs/promises");
|
|
40
|
-
var import_p_limit = __toESM(require("p-limit"));
|
|
41
40
|
var import_path = require("path");
|
|
42
41
|
var import_url = require("url");
|
|
43
42
|
var import_calculateChunks = require('./utils/calculateChunks.cjs');
|
|
@@ -156,7 +155,6 @@ const translateDoc = async ({
|
|
|
156
155
|
);
|
|
157
156
|
nbSimultaneousFileProcessed = 10;
|
|
158
157
|
}
|
|
159
|
-
const limit = (0, import_p_limit.default)(nbSimultaneousFileProcessed ?? 3);
|
|
160
158
|
let docList = import_fast_glob.default.sync(docPattern, {
|
|
161
159
|
ignore: excludedGlobPattern
|
|
162
160
|
});
|
|
@@ -177,47 +175,46 @@ const translateDoc = async ({
|
|
|
177
175
|
appLogger(`Translating ${(0, import_config.colorizeNumber)(docList.length)} files:`);
|
|
178
176
|
appLogger(docList.map((path) => ` - ${(0, import_chokidar.formatPath)(path)}
|
|
179
177
|
`));
|
|
180
|
-
const
|
|
181
|
-
(docPath) => locales.
|
|
182
|
-
(
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
178
|
+
const allTasks = docList.flatMap(
|
|
179
|
+
(docPath) => locales.map((locale) => async () => {
|
|
180
|
+
appLogger(
|
|
181
|
+
`Translating file: ${(0, import_chokidar.formatPath)(docPath)} to ${(0, import_chokidar.formatLocale)(locale)}`
|
|
182
|
+
);
|
|
183
|
+
const absoluteBaseFilePath = (0, import_path.join)(configuration.content.baseDir, docPath);
|
|
184
|
+
const outputFilePath = (0, import_getOutputFilePath.getOutputFilePath)(
|
|
185
|
+
absoluteBaseFilePath,
|
|
186
|
+
locale,
|
|
187
|
+
baseLocale
|
|
188
|
+
);
|
|
189
|
+
if (!(0, import_fs.existsSync)(outputFilePath)) {
|
|
190
|
+
appLogger(`File ${outputFilePath} does not exist, creating it...`);
|
|
191
|
+
(0, import_fs.mkdirSync)((0, import_path.dirname)(outputFilePath), { recursive: true });
|
|
192
|
+
(0, import_fs.writeFileSync)(outputFilePath, "");
|
|
193
|
+
}
|
|
194
|
+
const fileModificationData = (0, import_checkFileModifiedRange.checkFileModifiedRange)(outputFilePath, {
|
|
195
|
+
skipIfModifiedBefore,
|
|
196
|
+
skipIfModifiedAfter
|
|
197
|
+
});
|
|
198
|
+
if (fileModificationData.isSkipped) {
|
|
199
|
+
appLogger(fileModificationData.message);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
await translateFile(
|
|
203
|
+
absoluteBaseFilePath,
|
|
204
|
+
outputFilePath,
|
|
205
|
+
locale,
|
|
206
|
+
baseLocale,
|
|
207
|
+
aiOptions,
|
|
208
|
+
configuration,
|
|
209
|
+
customInstructions
|
|
210
|
+
);
|
|
211
|
+
})
|
|
212
|
+
);
|
|
213
|
+
await (0, import_chokidar.parallelize)(
|
|
214
|
+
allTasks,
|
|
215
|
+
(task) => task(),
|
|
216
|
+
nbSimultaneousFileProcessed ?? 3
|
|
219
217
|
);
|
|
220
|
-
await Promise.all(tasks);
|
|
221
218
|
};
|
|
222
219
|
// Annotate the CommonJS export names for ESM import in node:
|
|
223
220
|
0 && (module.exports = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/translateDoc.ts"],"sourcesContent":["import { AIOptions } from '@intlayer/api';\nimport {\n formatLocale,\n formatPath,\n listGitFiles,\n ListGitFilesOptions,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeNumber,\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n IntlayerConfig,\n Locales,\n retryManager,\n} from '@intlayer/config';\nimport fg from 'fast-glob';\nimport { existsSync, mkdirSync, writeFileSync } from 'fs';\nimport { readFile } from 'fs/promises';\nimport pLimit from 'p-limit';\nimport { dirname, join, relative } from 'path';\nimport { fileURLToPath } from 'url';\nimport { chunkText } from './utils/calculateChunks';\nimport { checkAIAccess } from './utils/checkAccess';\nimport { checkFileModifiedRange } from './utils/checkFileModifiedRange';\nimport { chunkInference } from './utils/chunkInference';\nimport { fixChunkStartEndChars } from './utils/fixChunkStartEndChars';\nimport { getChunk } from './utils/getChunk';\nimport { getOutputFilePath } from './utils/getOutputFilePath';\n\nconst isESModule = typeof import.meta.url === 'string';\n\nconst dir = isESModule ? dirname(fileURLToPath(import.meta.url)) : __dirname;\n\n/**\n * Translate a single file for a given locale\n */\nexport const translateFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locales,\n baseLocale: Locales,\n aiOptions?: AIOptions,\n configuration: IntlayerConfig = getConfiguration(),\n customInstructions?: string\n) => {\n try {\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n // Determine the target locale file path\n const fileContent = await readFile(baseFilePath, 'utf-8');\n let fileResultContent = fileContent;\n\n // Prepare the base prompt for ChatGPT\n const basePrompt = (\n await readFile(join(dir, './prompts/TRANSLATE_PROMPT.md'), 'utf-8')\n )\n .replaceAll('{{localeName}}', `${formatLocale(locale, false)}`)\n .replaceAll('{{baseLocaleName}}', `${formatLocale(baseLocale, false)}`)\n .replace('{{applicationContext}}', aiOptions?.applicationContext ?? '-')\n .replace('{{customInstructions}}', customInstructions ?? '-');\n\n const filePrexixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}] `;\n const filePrefix = [\n colon(filePrexixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n const prefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `;\n const prefix = [\n colon(prefixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n // 1. Chunk the file by number of lines instead of characters\n const chunks = chunkText(fileContent);\n appLogger(\n `${filePrefix}Base file splitted into ${colorizeNumber(chunks.length)} chunks`\n );\n\n for await (const [i, chunk] of chunks.entries()) {\n const isFirstChunk = i === 0;\n\n // Build the chunk-specific prompt\n const getPrevChunkPrompt = () =>\n `**CHUNK ${i} of ${chunks.length}** that has been translated in ${formatLocale(locale)}:\\n` +\n `///chunkStart///` +\n getChunk(fileResultContent, chunks[i - 1]) +\n `///chunkEnd///`;\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, chunks.length)} of ${chunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n (chunks[i - 1]?.content ?? '') +\n chunks[i].content +\n (chunks[i + 1]?.content ?? '') +\n `///chunksEnd///`;\n\n const fileToTranslateCurrentChunk = chunk.content;\n\n // Make the actual translation call\n let chunkTranslation = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n\n { role: 'system', content: getBaseChunkContextPrompt() },\n ...(isFirstChunk\n ? []\n : [{ role: 'system', content: getPrevChunkPrompt() } as const]),\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(chunks.length)}** in ${formatLocale(baseLocale, false)} to translate in ${formatLocale(locale, false)}:`,\n },\n { role: 'user', content: fileToTranslateCurrentChunk },\n ],\n aiOptions,\n configuration\n );\n\n appLogger(\n [\n `${prefix}`,\n `${ANSIColors.GREY_DARK}[Chunk `,\n colorizeNumber(i + 1),\n `${ANSIColors.GREY_DARK} of `,\n colorizeNumber(chunks.length),\n `${ANSIColors.GREY_DARK}] →${ANSIColors.RESET} `,\n `${colorizeNumber(result.tokenUsed)} tokens used`,\n ].join('')\n );\n\n const fixedTranslatedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n fileToTranslateCurrentChunk\n );\n\n return fixedTranslatedChunkResult;\n })();\n\n // Replace the chunk in the file content\n fileResultContent = fileResultContent.replace(\n fileToTranslateCurrentChunk,\n chunkTranslation\n );\n }\n\n // 4. Write the final translation to the appropriate file path\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, fileResultContent);\n\n const relativePath = relative(\n configuration.content.baseDir,\n outputFilePath\n );\n\n appLogger(\n `${colorize('✔', ANSIColors.GREEN)} File ${formatPath(relativePath)} created/updated successfully.`\n );\n } catch (error) {\n console.error(error);\n }\n};\n\ntype TranslateDocOptions = {\n docPattern: string[];\n locales: Locales[];\n excludedGlobPattern: string[];\n baseLocale: Locales;\n aiOptions?: AIOptions;\n nbSimultaneousFileProcessed?: number;\n configOptions?: GetConfigurationOptions;\n customInstructions?: string;\n skipIfModifiedBefore?: number | string | Date;\n skipIfModifiedAfter?: number | string | Date;\n gitOptions?: ListGitFilesOptions;\n};\n\n/**\n * Main translate function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then translates them to each locale in LOCALE_LIST.\n */\nexport const translateDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n gitOptions,\n}: TranslateDocOptions) => {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {\n appLogger(\n `Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`\n );\n nbSimultaneousFileProcessed = 10; // Limit the number of simultaneous file processed to 10\n }\n\n const limit = pLimit(nbSimultaneousFileProcessed ?? 3);\n\n let docList: string[] = fg.sync(docPattern, {\n ignore: excludedGlobPattern,\n });\n\n const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\n\n if (gitOptions) {\n const gitChangedFiles = await listGitFiles(gitOptions);\n\n if (gitChangedFiles) {\n // Convert dictionary file paths to be relative to git root for comparison\n\n // Filter dictionaries based on git changed files\n docList = docList.filter((path) =>\n gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile)\n );\n }\n }\n\n // OAuth handled by API proxy internally\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Translating ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Translating ${colorizeNumber(docList.length)} files:`);\n appLogger(docList.map((path) => ` - ${formatPath(path)}\\n`));\n\n const tasks = docList.map((docPath) =>\n locales.flatMap((locale) =>\n limit(async () => {\n appLogger(\n `Translating file: ${formatPath(docPath)} to ${formatLocale(locale)}`\n );\n\n const absoluteBaseFilePath = join(\n configuration.content.baseDir,\n docPath\n );\n const outputFilePath = getOutputFilePath(\n absoluteBaseFilePath,\n locale,\n baseLocale\n );\n\n // check if the file exist, otherwise create it\n if (!existsSync(outputFilePath)) {\n appLogger(`File ${outputFilePath} does not exist, creating it...`);\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, '');\n }\n\n const fileModificationData = checkFileModifiedRange(outputFilePath, {\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n });\n\n if (fileModificationData.isSkipped) {\n appLogger(fileModificationData.message);\n return;\n }\n\n await translateFile(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locales,\n baseLocale,\n aiOptions,\n configuration,\n customInstructions\n );\n })\n )\n );\n\n await Promise.all(tasks);\n};\n"],"mappings":"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","names":["pLimit","fg"]}
|
|
1
|
+
{"version":3,"sources":["../../src/translateDoc.ts"],"sourcesContent":["import { AIOptions } from '@intlayer/api';\nimport {\n formatLocale,\n formatPath,\n listGitFiles,\n ListGitFilesOptions,\n parallelize,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeNumber,\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n IntlayerConfig,\n Locales,\n retryManager,\n} from '@intlayer/config';\nimport fg from 'fast-glob';\nimport { existsSync, mkdirSync, writeFileSync } from 'fs';\nimport { readFile } from 'fs/promises';\nimport { dirname, join, relative } from 'path';\nimport { fileURLToPath } from 'url';\nimport { chunkText } from './utils/calculateChunks';\nimport { checkAIAccess } from './utils/checkAccess';\nimport { checkFileModifiedRange } from './utils/checkFileModifiedRange';\nimport { chunkInference } from './utils/chunkInference';\nimport { fixChunkStartEndChars } from './utils/fixChunkStartEndChars';\nimport { getChunk } from './utils/getChunk';\nimport { getOutputFilePath } from './utils/getOutputFilePath';\n\nconst isESModule = typeof import.meta.url === 'string';\n\nconst dir = isESModule ? dirname(fileURLToPath(import.meta.url)) : __dirname;\n\n/**\n * Translate a single file for a given locale\n */\nexport const translateFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locales,\n baseLocale: Locales,\n aiOptions?: AIOptions,\n configuration: IntlayerConfig = getConfiguration(),\n customInstructions?: string\n) => {\n try {\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n // Determine the target locale file path\n const fileContent = await readFile(baseFilePath, 'utf-8');\n let fileResultContent = fileContent;\n\n // Prepare the base prompt for ChatGPT\n const basePrompt = (\n await readFile(join(dir, './prompts/TRANSLATE_PROMPT.md'), 'utf-8')\n )\n .replaceAll('{{localeName}}', `${formatLocale(locale, false)}`)\n .replaceAll('{{baseLocaleName}}', `${formatLocale(baseLocale, false)}`)\n .replace('{{applicationContext}}', aiOptions?.applicationContext ?? '-')\n .replace('{{customInstructions}}', customInstructions ?? '-');\n\n const filePrexixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}] `;\n const filePrefix = [\n colon(filePrexixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n const prefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `;\n const prefix = [\n colon(prefixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n // 1. Chunk the file by number of lines instead of characters\n const chunks = chunkText(fileContent);\n appLogger(\n `${filePrefix}Base file splitted into ${colorizeNumber(chunks.length)} chunks`\n );\n\n for await (const [i, chunk] of chunks.entries()) {\n const isFirstChunk = i === 0;\n\n // Build the chunk-specific prompt\n const getPrevChunkPrompt = () =>\n `**CHUNK ${i} of ${chunks.length}** that has been translated in ${formatLocale(locale)}:\\n` +\n `///chunkStart///` +\n getChunk(fileResultContent, chunks[i - 1]) +\n `///chunkEnd///`;\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, chunks.length)} of ${chunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n (chunks[i - 1]?.content ?? '') +\n chunks[i].content +\n (chunks[i + 1]?.content ?? '') +\n `///chunksEnd///`;\n\n const fileToTranslateCurrentChunk = chunk.content;\n\n // Make the actual translation call\n let chunkTranslation = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n\n { role: 'system', content: getBaseChunkContextPrompt() },\n ...(isFirstChunk\n ? []\n : [{ role: 'system', content: getPrevChunkPrompt() } as const]),\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(chunks.length)}** in ${formatLocale(baseLocale, false)} to translate in ${formatLocale(locale, false)}:`,\n },\n { role: 'user', content: fileToTranslateCurrentChunk },\n ],\n aiOptions,\n configuration\n );\n\n appLogger(\n [\n `${prefix}`,\n `${ANSIColors.GREY_DARK}[Chunk `,\n colorizeNumber(i + 1),\n `${ANSIColors.GREY_DARK} of `,\n colorizeNumber(chunks.length),\n `${ANSIColors.GREY_DARK}] →${ANSIColors.RESET} `,\n `${colorizeNumber(result.tokenUsed)} tokens used`,\n ].join('')\n );\n\n const fixedTranslatedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n fileToTranslateCurrentChunk\n );\n\n return fixedTranslatedChunkResult;\n })();\n\n // Replace the chunk in the file content\n fileResultContent = fileResultContent.replace(\n fileToTranslateCurrentChunk,\n chunkTranslation\n );\n }\n\n // 4. Write the final translation to the appropriate file path\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, fileResultContent);\n\n const relativePath = relative(\n configuration.content.baseDir,\n outputFilePath\n );\n\n appLogger(\n `${colorize('✔', ANSIColors.GREEN)} File ${formatPath(relativePath)} created/updated successfully.`\n );\n } catch (error) {\n console.error(error);\n }\n};\n\ntype TranslateDocOptions = {\n docPattern: string[];\n locales: Locales[];\n excludedGlobPattern: string[];\n baseLocale: Locales;\n aiOptions?: AIOptions;\n nbSimultaneousFileProcessed?: number;\n configOptions?: GetConfigurationOptions;\n customInstructions?: string;\n skipIfModifiedBefore?: number | string | Date;\n skipIfModifiedAfter?: number | string | Date;\n gitOptions?: ListGitFilesOptions;\n};\n\n/**\n * Main translate function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then translates them to each locale in LOCALE_LIST.\n */\nexport const translateDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n gitOptions,\n}: TranslateDocOptions) => {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {\n appLogger(\n `Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`\n );\n nbSimultaneousFileProcessed = 10; // Limit the number of simultaneous file processed to 10\n }\n\n let docList: string[] = fg.sync(docPattern, {\n ignore: excludedGlobPattern,\n });\n\n const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\n\n if (gitOptions) {\n const gitChangedFiles = await listGitFiles(gitOptions);\n\n if (gitChangedFiles) {\n // Convert dictionary file paths to be relative to git root for comparison\n\n // Filter dictionaries based on git changed files\n docList = docList.filter((path) =>\n gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile)\n );\n }\n }\n\n // OAuth handled by API proxy internally\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Translating ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Translating ${colorizeNumber(docList.length)} files:`);\n appLogger(docList.map((path) => ` - ${formatPath(path)}\\n`));\n\n // Create all tasks to be processed\n const allTasks = docList.flatMap((docPath) =>\n locales.map((locale) => async () => {\n appLogger(\n `Translating file: ${formatPath(docPath)} to ${formatLocale(locale)}`\n );\n\n const absoluteBaseFilePath = join(configuration.content.baseDir, docPath);\n const outputFilePath = getOutputFilePath(\n absoluteBaseFilePath,\n locale,\n baseLocale\n );\n\n // check if the file exist, otherwise create it\n if (!existsSync(outputFilePath)) {\n appLogger(`File ${outputFilePath} does not exist, creating it...`);\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, '');\n }\n\n const fileModificationData = checkFileModifiedRange(outputFilePath, {\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n });\n\n if (fileModificationData.isSkipped) {\n appLogger(fileModificationData.message);\n return;\n }\n\n await translateFile(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locales,\n baseLocale,\n aiOptions,\n configuration,\n customInstructions\n );\n })\n );\n\n await parallelize(\n allTasks,\n (task) => task(),\n nbSimultaneousFileProcessed ?? 3\n );\n};\n"],"mappings":"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","names":["fg"]}
|