@intlayer/cli 6.1.6 → 7.0.0-canary.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/dist/cjs/IntlayerEventListener.cjs +187 -239
- package/dist/cjs/IntlayerEventListener.cjs.map +1 -1
- package/dist/cjs/_virtual/_utils_asset.cjs +104 -0
- package/dist/cjs/_virtual/rolldown_runtime.cjs +25 -0
- package/dist/cjs/build.cjs +23 -42
- package/dist/cjs/build.cjs.map +1 -1
- package/dist/cjs/cli.cjs +370 -431
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/config.cjs +10 -35
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/editor.cjs +51 -66
- package/dist/cjs/editor.cjs.map +1 -1
- package/dist/cjs/fill/fill.cjs +73 -301
- package/dist/cjs/fill/fill.cjs.map +1 -1
- package/dist/cjs/fill/formatAutoFillData.cjs +48 -106
- package/dist/cjs/fill/formatAutoFillData.cjs.map +1 -1
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs +27 -43
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs.map +1 -1
- package/dist/cjs/fill/formatFillData.cjs +50 -0
- package/dist/cjs/fill/formatFillData.cjs.map +1 -0
- package/dist/cjs/fill/groupLimiter.cjs +42 -0
- package/dist/cjs/fill/groupLimiter.cjs.map +1 -0
- package/dist/cjs/fill/index.cjs +5 -25
- package/dist/cjs/fill/listTranslationsTasks.cjs +77 -0
- package/dist/cjs/fill/listTranslationsTasks.cjs.map +1 -0
- package/dist/cjs/fill/test-original-case.cjs +10 -0
- package/dist/cjs/fill/test-original-case.cjs.map +1 -0
- package/dist/cjs/fill/translateDictionary.cjs +148 -0
- package/dist/cjs/fill/translateDictionary.cjs.map +1 -0
- package/dist/cjs/fill/writeAutoFill.cjs +48 -0
- package/dist/cjs/fill/writeAutoFill.cjs.map +1 -0
- package/dist/cjs/fill/writeFill.cjs +50 -0
- package/dist/cjs/fill/writeFill.cjs.map +1 -0
- package/dist/cjs/getTargetDictionary.cjs +36 -76
- package/dist/cjs/getTargetDictionary.cjs.map +1 -1
- package/dist/cjs/index.cjs +31 -45
- package/dist/cjs/listContentDeclaration.cjs +36 -64
- package/dist/cjs/listContentDeclaration.cjs.map +1 -1
- package/dist/cjs/liveSync.cjs +146 -221
- package/dist/cjs/liveSync.cjs.map +1 -1
- package/dist/cjs/pull.cjs +132 -195
- package/dist/cjs/pull.cjs.map +1 -1
- package/dist/cjs/push/pullLog.cjs +101 -144
- package/dist/cjs/push/pullLog.cjs.map +1 -1
- package/dist/cjs/push/push.cjs +159 -249
- package/dist/cjs/push/push.cjs.map +1 -1
- package/dist/cjs/pushConfig.cjs +18 -45
- package/dist/cjs/pushConfig.cjs.map +1 -1
- package/dist/cjs/pushLog.cjs +87 -128
- package/dist/cjs/pushLog.cjs.map +1 -1
- package/dist/cjs/reviewDoc.cjs +183 -291
- package/dist/cjs/reviewDoc.cjs.map +1 -1
- package/dist/cjs/test/index.cjs +52 -91
- package/dist/cjs/test/index.cjs.map +1 -1
- package/dist/cjs/test/listMissingTranslations.cjs +35 -62
- package/dist/cjs/test/listMissingTranslations.cjs.map +1 -1
- package/dist/cjs/translateDoc.cjs +127 -221
- package/dist/cjs/translateDoc.cjs.map +1 -1
- package/dist/cjs/utils/calculateChunks.cjs +85 -115
- package/dist/cjs/utils/calculateChunks.cjs.map +1 -1
- package/dist/cjs/utils/checkAccess.cjs +33 -72
- package/dist/cjs/utils/checkAccess.cjs.map +1 -1
- package/dist/cjs/utils/checkFileModifiedRange.cjs +75 -91
- package/dist/cjs/utils/checkFileModifiedRange.cjs.map +1 -1
- package/dist/cjs/utils/checkLastUpdateTime.cjs +17 -30
- package/dist/cjs/utils/checkLastUpdateTime.cjs.map +1 -1
- package/dist/cjs/utils/chunkInference.cjs +28 -47
- package/dist/cjs/utils/chunkInference.cjs.map +1 -1
- package/dist/cjs/utils/fixChunkStartEndChars.cjs +23 -42
- package/dist/cjs/utils/fixChunkStartEndChars.cjs.map +1 -1
- package/dist/cjs/utils/formatTimeDiff.cjs +17 -43
- package/dist/cjs/utils/formatTimeDiff.cjs.map +1 -1
- package/dist/cjs/utils/getIsFileUpdatedRecently.cjs +13 -32
- package/dist/cjs/utils/getIsFileUpdatedRecently.cjs.map +1 -1
- package/dist/cjs/utils/getOutputFilePath.cjs +71 -86
- package/dist/cjs/utils/getOutputFilePath.cjs.map +1 -1
- package/dist/cjs/utils/getParentPackageJSON.cjs +19 -44
- package/dist/cjs/utils/getParentPackageJSON.cjs.map +1 -1
- package/dist/cjs/utils/listSpecialChars.cjs +49 -73
- package/dist/cjs/utils/listSpecialChars.cjs.map +1 -1
- package/dist/cjs/utils/mapChunksBetweenFiles.cjs +90 -132
- package/dist/cjs/utils/mapChunksBetweenFiles.cjs.map +1 -1
- package/dist/cjs/utils/reorderParagraphs.cjs +86 -118
- package/dist/cjs/utils/reorderParagraphs.cjs.map +1 -1
- package/dist/cjs/watch.cjs +21 -39
- package/dist/cjs/watch.cjs.map +1 -1
- package/dist/esm/IntlayerEventListener.mjs +178 -201
- package/dist/esm/IntlayerEventListener.mjs.map +1 -1
- package/dist/esm/_virtual/_utils_asset.mjs +100 -0
- package/dist/esm/_virtual/rolldown_runtime.mjs +8 -0
- package/dist/esm/build.mjs +20 -23
- package/dist/esm/build.mjs.map +1 -1
- package/dist/esm/cli.mjs +349 -380
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/config.mjs +8 -14
- package/dist/esm/config.mjs.map +1 -1
- package/dist/esm/editor.mjs +47 -41
- package/dist/esm/editor.mjs.map +1 -1
- package/dist/esm/fill/fill.mjs +68 -300
- package/dist/esm/fill/fill.mjs.map +1 -1
- package/dist/esm/fill/formatAutoFillData.mjs +47 -81
- package/dist/esm/fill/formatAutoFillData.mjs.map +1 -1
- package/dist/esm/fill/formatAutoFilledFilePath.mjs +25 -19
- package/dist/esm/fill/formatAutoFilledFilePath.mjs.map +1 -1
- package/dist/esm/fill/formatFillData.mjs +50 -0
- package/dist/esm/fill/formatFillData.mjs.map +1 -0
- package/dist/esm/fill/groupLimiter.mjs +40 -0
- package/dist/esm/fill/groupLimiter.mjs.map +1 -0
- package/dist/esm/fill/index.mjs +4 -3
- package/dist/esm/fill/listTranslationsTasks.mjs +70 -0
- package/dist/esm/fill/listTranslationsTasks.mjs.map +1 -0
- package/dist/esm/fill/test-original-case.mjs +10 -0
- package/dist/esm/fill/test-original-case.mjs.map +1 -0
- package/dist/esm/fill/translateDictionary.mjs +141 -0
- package/dist/esm/fill/translateDictionary.mjs.map +1 -0
- package/dist/esm/fill/writeAutoFill.mjs +44 -0
- package/dist/esm/fill/writeAutoFill.mjs.map +1 -0
- package/dist/esm/fill/writeFill.mjs +45 -0
- package/dist/esm/fill/writeFill.mjs.map +1 -0
- package/dist/esm/getTargetDictionary.mjs +27 -48
- package/dist/esm/getTargetDictionary.mjs.map +1 -1
- package/dist/esm/index.mjs +15 -13
- package/dist/esm/listContentDeclaration.mjs +28 -43
- package/dist/esm/listContentDeclaration.mjs.map +1 -1
- package/dist/esm/liveSync.mjs +135 -187
- package/dist/esm/liveSync.mjs.map +1 -1
- package/dist/esm/pull.mjs +125 -178
- package/dist/esm/pull.mjs.map +1 -1
- package/dist/esm/push/pullLog.mjs +99 -125
- package/dist/esm/push/pullLog.mjs.map +1 -1
- package/dist/esm/push/push.mjs +149 -221
- package/dist/esm/push/push.mjs.map +1 -1
- package/dist/esm/pushConfig.mjs +14 -23
- package/dist/esm/pushConfig.mjs.map +1 -1
- package/dist/esm/pushLog.mjs +85 -109
- package/dist/esm/pushLog.mjs.map +1 -1
- package/dist/esm/reviewDoc.mjs +167 -264
- package/dist/esm/reviewDoc.mjs.map +1 -1
- package/dist/esm/test/index.mjs +47 -73
- package/dist/esm/test/index.mjs.map +1 -1
- package/dist/esm/test/listMissingTranslations.mjs +30 -41
- package/dist/esm/test/listMissingTranslations.mjs.map +1 -1
- package/dist/esm/translateDoc.mjs +114 -193
- package/dist/esm/translateDoc.mjs.map +1 -1
- package/dist/esm/utils/calculateChunks.mjs +83 -91
- package/dist/esm/utils/calculateChunks.mjs.map +1 -1
- package/dist/esm/utils/checkAccess.mjs +28 -46
- package/dist/esm/utils/checkAccess.mjs.map +1 -1
- package/dist/esm/utils/checkFileModifiedRange.mjs +73 -65
- package/dist/esm/utils/checkFileModifiedRange.mjs.map +1 -1
- package/dist/esm/utils/checkLastUpdateTime.mjs +15 -6
- package/dist/esm/utils/checkLastUpdateTime.mjs.map +1 -1
- package/dist/esm/utils/chunkInference.mjs +24 -24
- package/dist/esm/utils/chunkInference.mjs.map +1 -1
- package/dist/esm/utils/fixChunkStartEndChars.mjs +22 -18
- package/dist/esm/utils/fixChunkStartEndChars.mjs.map +1 -1
- package/dist/esm/utils/formatTimeDiff.mjs +16 -19
- package/dist/esm/utils/formatTimeDiff.mjs.map +1 -1
- package/dist/esm/utils/getIsFileUpdatedRecently.mjs +11 -8
- package/dist/esm/utils/getIsFileUpdatedRecently.mjs.map +1 -1
- package/dist/esm/utils/getOutputFilePath.mjs +70 -62
- package/dist/esm/utils/getOutputFilePath.mjs.map +1 -1
- package/dist/esm/utils/getParentPackageJSON.mjs +16 -20
- package/dist/esm/utils/getParentPackageJSON.mjs.map +1 -1
- package/dist/esm/utils/listSpecialChars.mjs +48 -49
- package/dist/esm/utils/listSpecialChars.mjs.map +1 -1
- package/dist/esm/utils/mapChunksBetweenFiles.mjs +87 -107
- package/dist/esm/utils/mapChunksBetweenFiles.mjs.map +1 -1
- package/dist/esm/utils/reorderParagraphs.mjs +85 -93
- package/dist/esm/utils/reorderParagraphs.mjs.map +1 -1
- package/dist/esm/watch.mjs +17 -17
- package/dist/esm/watch.mjs.map +1 -1
- package/dist/types/IntlayerEventListener.d.ts +63 -59
- package/dist/types/IntlayerEventListener.d.ts.map +1 -1
- package/dist/types/build.d.ts +10 -7
- package/dist/types/build.d.ts.map +1 -1
- package/dist/types/cli.d.ts +13 -10
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts +7 -4
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/editor.d.ts +6 -4
- package/dist/types/editor.d.ts.map +1 -1
- package/dist/types/fill/fill.d.ts +20 -14
- package/dist/types/fill/fill.d.ts.map +1 -1
- package/dist/types/fill/formatAutoFillData.d.ts +10 -7
- package/dist/types/fill/formatAutoFillData.d.ts.map +1 -1
- package/dist/types/fill/formatAutoFilledFilePath.d.ts +6 -2
- package/dist/types/fill/formatAutoFilledFilePath.d.ts.map +1 -1
- package/dist/types/fill/formatFillData.d.ts +12 -0
- package/dist/types/fill/formatFillData.d.ts.map +1 -0
- package/dist/types/fill/groupLimiter.d.ts +15 -0
- package/dist/types/fill/groupLimiter.d.ts.map +1 -0
- package/dist/types/fill/index.d.ts +3 -3
- package/dist/types/fill/listTranslationsTasks.d.ts +15 -0
- package/dist/types/fill/listTranslationsTasks.d.ts.map +1 -0
- package/dist/types/fill/test-original-case.d.ts +1 -0
- package/dist/types/fill/translateDictionary.d.ts +19 -0
- package/dist/types/fill/translateDictionary.d.ts.map +1 -0
- package/dist/types/fill/writeAutoFill.d.ts +7 -0
- package/dist/types/fill/writeAutoFill.d.ts.map +1 -0
- package/dist/types/fill/writeFill.d.ts +7 -0
- package/dist/types/fill/writeFill.d.ts.map +1 -0
- package/dist/types/getTargetDictionary.d.ts +17 -13
- package/dist/types/getTargetDictionary.d.ts.map +1 -1
- package/dist/types/index.d.ts +15 -14
- package/dist/types/listContentDeclaration.d.ts +10 -7
- package/dist/types/listContentDeclaration.d.ts.map +1 -1
- package/dist/types/liveSync.d.ts +8 -3
- package/dist/types/liveSync.d.ts.map +1 -1
- package/dist/types/pull.d.ts +9 -6
- package/dist/types/pull.d.ts.map +1 -1
- package/dist/types/push/pullLog.d.ts +25 -21
- package/dist/types/push/pullLog.d.ts.map +1 -1
- package/dist/types/push/push.d.ts +13 -9
- package/dist/types/push/push.d.ts.map +1 -1
- package/dist/types/pushConfig.d.ts +7 -4
- package/dist/types/pushConfig.d.ts.map +1 -1
- package/dist/types/pushLog.d.ts +23 -20
- package/dist/types/pushLog.d.ts.map +1 -1
- package/dist/types/reviewDoc.d.ts +34 -17
- package/dist/types/reviewDoc.d.ts.map +1 -1
- package/dist/types/test/index.d.ts +9 -5
- package/dist/types/test/index.d.ts.map +1 -1
- package/dist/types/test/listMissingTranslations.d.ts +14 -10
- package/dist/types/test/listMissingTranslations.d.ts.map +1 -1
- package/dist/types/translateDoc.d.ts +34 -17
- package/dist/types/translateDoc.d.ts.map +1 -1
- package/dist/types/utils/calculateChunks.d.ts +10 -7
- package/dist/types/utils/calculateChunks.d.ts.map +1 -1
- package/dist/types/utils/checkAccess.d.ts +8 -4
- package/dist/types/utils/checkAccess.d.ts.map +1 -1
- package/dist/types/utils/checkFileModifiedRange.d.ts +8 -6
- package/dist/types/utils/checkFileModifiedRange.d.ts.map +1 -1
- package/dist/types/utils/checkLastUpdateTime.d.ts +4 -1
- package/dist/types/utils/checkLastUpdateTime.d.ts.map +1 -1
- package/dist/types/utils/chunkInference.d.ts +9 -6
- package/dist/types/utils/chunkInference.d.ts.map +1 -1
- package/dist/types/utils/fixChunkStartEndChars.d.ts +4 -1
- package/dist/types/utils/fixChunkStartEndChars.d.ts.map +1 -1
- package/dist/types/utils/formatTimeDiff.d.ts +4 -1
- package/dist/types/utils/formatTimeDiff.d.ts.map +1 -1
- package/dist/types/utils/getIsFileUpdatedRecently.d.ts +4 -1
- package/dist/types/utils/getIsFileUpdatedRecently.d.ts.map +1 -1
- package/dist/types/utils/getOutputFilePath.d.ts +7 -2
- package/dist/types/utils/getOutputFilePath.d.ts.map +1 -1
- package/dist/types/utils/getParentPackageJSON.d.ts +30 -28
- package/dist/types/utils/getParentPackageJSON.d.ts.map +1 -1
- package/dist/types/utils/listSpecialChars.d.ts +9 -7
- package/dist/types/utils/listSpecialChars.d.ts.map +1 -1
- package/dist/types/utils/mapChunksBetweenFiles.d.ts +10 -6
- package/dist/types/utils/mapChunksBetweenFiles.d.ts.map +1 -1
- package/dist/types/utils/reorderParagraphs.d.ts +4 -1
- package/dist/types/utils/reorderParagraphs.d.ts.map +1 -1
- package/dist/types/watch.d.ts +9 -6
- package/dist/types/watch.d.ts.map +1 -1
- package/package.json +42 -47
- package/LICENSE +0 -202
- package/dist/cjs/fill/autoFill.cjs +0 -105
- package/dist/cjs/fill/autoFill.cjs.map +0 -1
- package/dist/cjs/fill/index.cjs.map +0 -1
- package/dist/cjs/index.cjs.map +0 -1
- package/dist/cjs/utils/getChunk.cjs +0 -77
- package/dist/cjs/utils/getChunk.cjs.map +0 -1
- package/dist/cjs/utils/splitTextByLine.cjs +0 -35
- package/dist/cjs/utils/splitTextByLine.cjs.map +0 -1
- package/dist/esm/fill/autoFill.mjs +0 -92
- package/dist/esm/fill/autoFill.mjs.map +0 -1
- package/dist/esm/fill/index.mjs.map +0 -1
- package/dist/esm/index.mjs.map +0 -1
- package/dist/esm/prompts/REVIEW_PROMPT.md +0 -37
- package/dist/esm/prompts/TRANSLATE_PROMPT.md +0 -38
- package/dist/esm/utils/calculrateChunkTest.md +0 -9
- package/dist/esm/utils/getChunk.mjs +0 -53
- package/dist/esm/utils/getChunk.mjs.map +0 -1
- package/dist/esm/utils/splitTextByLine.mjs +0 -11
- package/dist/esm/utils/splitTextByLine.mjs.map +0 -1
- package/dist/types/fill/autoFill.d.ts +0 -4
- package/dist/types/fill/autoFill.d.ts.map +0 -1
- package/dist/types/fill/index.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/utils/getChunk.d.ts +0 -9
- package/dist/types/utils/getChunk.d.ts.map +0 -1
- package/dist/types/utils/splitTextByLine.d.ts +0 -2
- package/dist/types/utils/splitTextByLine.d.ts.map +0 -1
- /package/dist/{cjs → assets}/prompts/REVIEW_PROMPT.md +0 -0
- /package/dist/{cjs → assets}/prompts/TRANSLATE_PROMPT.md +0 -0
- /package/dist/{cjs/utils/calculrateChunkTest.md → assets/utils/_calculateChunkTest.md} +0 -0
package/dist/esm/reviewDoc.mjs
CHANGED
|
@@ -1,274 +1,177 @@
|
|
|
1
|
-
import {
|
|
2
|
-
formatLocale,
|
|
3
|
-
formatPath,
|
|
4
|
-
listGitFiles,
|
|
5
|
-
listGitLines,
|
|
6
|
-
parallelize
|
|
7
|
-
} from "@intlayer/chokidar";
|
|
8
|
-
import {
|
|
9
|
-
ANSIColors,
|
|
10
|
-
colon,
|
|
11
|
-
colorize,
|
|
12
|
-
colorizeNumber,
|
|
13
|
-
getAppLogger,
|
|
14
|
-
getConfiguration,
|
|
15
|
-
Locales,
|
|
16
|
-
retryManager
|
|
17
|
-
} from "@intlayer/config";
|
|
18
|
-
import { getLocaleName } from "@intlayer/core";
|
|
19
|
-
import fg from "fast-glob";
|
|
20
|
-
import { mkdirSync, writeFileSync } from "fs";
|
|
21
|
-
import { readFile } from "fs/promises";
|
|
22
|
-
import { dirname, join, relative } from "path";
|
|
23
|
-
import { fileURLToPath } from "url";
|
|
24
|
-
import { chunkText } from "./utils/calculateChunks.mjs";
|
|
25
1
|
import { checkAIAccess } from "./utils/checkAccess.mjs";
|
|
2
|
+
import { readAsset } from "./_virtual/_utils_asset.mjs";
|
|
3
|
+
import { chunkText } from "./utils/calculateChunks.mjs";
|
|
26
4
|
import { checkFileModifiedRange } from "./utils/checkFileModifiedRange.mjs";
|
|
27
5
|
import { chunkInference } from "./utils/chunkInference.mjs";
|
|
28
6
|
import { fixChunkStartEndChars } from "./utils/fixChunkStartEndChars.mjs";
|
|
29
|
-
import { getChunk } from "./utils/getChunk.mjs";
|
|
30
7
|
import { getOutputFilePath } from "./utils/getOutputFilePath.mjs";
|
|
31
8
|
import { mapChunksBetweenFiles } from "./utils/mapChunksBetweenFiles.mjs";
|
|
32
|
-
|
|
33
|
-
|
|
9
|
+
import { formatLocale, formatPath, getChunk, listGitFiles, listGitLines, parallelize } from "@intlayer/chokidar";
|
|
10
|
+
import { ANSIColors, colon, colorize, colorizeNumber, getAppLogger, getConfiguration, retryManager } from "@intlayer/config";
|
|
11
|
+
import { dirname, join, relative } from "node:path";
|
|
12
|
+
import { getLocaleName } from "@intlayer/core";
|
|
13
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
14
|
+
import { readFile } from "node:fs/promises";
|
|
15
|
+
import { Locales } from "@intlayer/types";
|
|
16
|
+
import fg from "fast-glob";
|
|
17
|
+
|
|
18
|
+
//#region src/reviewDoc.ts
|
|
19
|
+
/**
|
|
20
|
+
* Translate a single file for a given locale
|
|
21
|
+
*/
|
|
34
22
|
const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions, configOptions, customInstructions, changedLines) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
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}).`
|
|
144
|
-
},
|
|
145
|
-
{ role: "user", content: baseChunkContext.content }
|
|
146
|
-
],
|
|
147
|
-
aiOptions,
|
|
148
|
-
configuration
|
|
149
|
-
);
|
|
150
|
-
appLogger(
|
|
151
|
-
`${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}`
|
|
152
|
-
);
|
|
153
|
-
const fixedReviewedChunkResult = fixChunkStartEndChars(
|
|
154
|
-
result?.fileContent,
|
|
155
|
-
baseChunkContext.content
|
|
156
|
-
);
|
|
157
|
-
return fixedReviewedChunkResult;
|
|
158
|
-
})();
|
|
159
|
-
updatedFileContent = updatedFileContent.replace(
|
|
160
|
-
baseChunkContext.content,
|
|
161
|
-
reviewedChunkResult
|
|
162
|
-
);
|
|
163
|
-
fileResultContent += reviewedChunkResult;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
mkdirSync(dirname(outputFilePath), { recursive: true });
|
|
167
|
-
writeFileSync(outputFilePath, fileResultContent);
|
|
168
|
-
const relativePath = relative(
|
|
169
|
-
configuration.content.baseDir,
|
|
170
|
-
outputFilePath
|
|
171
|
-
);
|
|
172
|
-
appLogger(
|
|
173
|
-
`${colorize("\u2714", ANSIColors.GREEN)} File ${formatPath(relativePath)} created/updated successfully.`
|
|
174
|
-
);
|
|
175
|
-
} catch (error) {
|
|
176
|
-
console.error(error);
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
const reviewDoc = async ({
|
|
180
|
-
docPattern,
|
|
181
|
-
locales,
|
|
182
|
-
excludedGlobPattern,
|
|
183
|
-
baseLocale,
|
|
184
|
-
aiOptions,
|
|
185
|
-
nbSimultaneousFileProcessed,
|
|
186
|
-
configOptions,
|
|
187
|
-
customInstructions,
|
|
188
|
-
skipIfModifiedBefore,
|
|
189
|
-
skipIfModifiedAfter,
|
|
190
|
-
gitOptions
|
|
191
|
-
}) => {
|
|
192
|
-
const configuration = getConfiguration(configOptions);
|
|
193
|
-
const appLogger = getAppLogger(configuration, {
|
|
194
|
-
config: {
|
|
195
|
-
prefix: ""
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
const hasCMSAuth = await checkAIAccess(configuration, aiOptions);
|
|
199
|
-
if (!hasCMSAuth) return;
|
|
200
|
-
if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {
|
|
201
|
-
appLogger(
|
|
202
|
-
`Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`
|
|
203
|
-
);
|
|
204
|
-
nbSimultaneousFileProcessed = 10;
|
|
205
|
-
}
|
|
206
|
-
let docList = fg.sync(docPattern, {
|
|
207
|
-
ignore: excludedGlobPattern
|
|
208
|
-
});
|
|
209
|
-
if (gitOptions) {
|
|
210
|
-
const gitChangedFiles = await listGitFiles(gitOptions);
|
|
211
|
-
if (gitChangedFiles) {
|
|
212
|
-
docList = docList.filter(
|
|
213
|
-
(path) => gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile)
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
appLogger(`Base locale is ${formatLocale(baseLocale)}`);
|
|
218
|
-
appLogger(
|
|
219
|
-
`Reviewing ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`
|
|
220
|
-
);
|
|
221
|
-
appLogger(`Reviewing ${colorizeNumber(docList.length)} files:`);
|
|
222
|
-
appLogger(docList.map((path) => ` - ${formatPath(path)}
|
|
223
|
-
`));
|
|
224
|
-
const allTasks = docList.flatMap(
|
|
225
|
-
(docPath) => locales.map((locale) => async () => {
|
|
226
|
-
appLogger(
|
|
227
|
-
`Reviewing file: ${formatPath(docPath)} to ${formatLocale(locale)}`
|
|
228
|
-
);
|
|
229
|
-
const absoluteBaseFilePath = join(configuration.content.baseDir, docPath);
|
|
230
|
-
const outputFilePath = getOutputFilePath(
|
|
231
|
-
absoluteBaseFilePath,
|
|
232
|
-
locale,
|
|
233
|
-
baseLocale
|
|
234
|
-
);
|
|
235
|
-
const fileModificationData = checkFileModifiedRange(outputFilePath, {
|
|
236
|
-
skipIfModifiedBefore,
|
|
237
|
-
skipIfModifiedAfter
|
|
238
|
-
});
|
|
239
|
-
if (fileModificationData.isSkipped) {
|
|
240
|
-
appLogger(fileModificationData.message);
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
let changedLines = void 0;
|
|
244
|
-
if (gitOptions) {
|
|
245
|
-
const gitChangedLines = await listGitLines(
|
|
246
|
-
absoluteBaseFilePath,
|
|
247
|
-
gitOptions
|
|
248
|
-
);
|
|
249
|
-
appLogger(`Git changed lines: ${gitChangedLines.join(", ")}`);
|
|
250
|
-
changedLines = gitChangedLines;
|
|
251
|
-
}
|
|
252
|
-
await reviewFile(
|
|
253
|
-
absoluteBaseFilePath,
|
|
254
|
-
outputFilePath,
|
|
255
|
-
locale,
|
|
256
|
-
baseLocale,
|
|
257
|
-
aiOptions,
|
|
258
|
-
configOptions,
|
|
259
|
-
customInstructions,
|
|
260
|
-
changedLines
|
|
261
|
-
);
|
|
262
|
-
})
|
|
263
|
-
);
|
|
264
|
-
await parallelize(
|
|
265
|
-
allTasks,
|
|
266
|
-
(task) => task(),
|
|
267
|
-
nbSimultaneousFileProcessed ?? 3
|
|
268
|
-
);
|
|
23
|
+
try {
|
|
24
|
+
const configuration = getConfiguration(configOptions);
|
|
25
|
+
const appLogger = getAppLogger(configuration);
|
|
26
|
+
const basedFileContent = await readFile(baseFilePath, "utf-8");
|
|
27
|
+
const fileToReviewContent = await readFile(outputFilePath, "utf-8");
|
|
28
|
+
let updatedFileContent = fileToReviewContent;
|
|
29
|
+
let fileResultContent = "";
|
|
30
|
+
const basePrompt = readAsset("./prompts/REVIEW_PROMPT.md", "utf-8").replaceAll("{{localeName}}", `${formatLocale(locale, false)}`).replaceAll("{{baseLocaleName}}", `${formatLocale(baseLocale, false)}`).replace("{{applicationContext}}", aiOptions?.applicationContext ?? "-").replace("{{customInstructions}}", customInstructions ?? "-");
|
|
31
|
+
const filePrefix = [colon(`${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}] `, { colSize: 40 }), `→ ${ANSIColors.RESET}`].join("");
|
|
32
|
+
const prefix = [colon(`${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `, { colSize: 40 }), `→ ${ANSIColors.RESET}`].join("");
|
|
33
|
+
if (changedLines && changedLines.length > 0) {
|
|
34
|
+
appLogger(`${filePrefix}Using optimization with ${colorizeNumber(changedLines.length)} changed lines`);
|
|
35
|
+
const chunkMappings = mapChunksBetweenFiles(basedFileContent, updatedFileContent, 800, changedLines);
|
|
36
|
+
appLogger(`${filePrefix}Base file mapped to ${colorizeNumber(chunkMappings.length)} chunk mappings`);
|
|
37
|
+
for await (const [i, mapping] of chunkMappings.entries()) {
|
|
38
|
+
const { baseChunk, updatedChunk, hasChanges } = mapping;
|
|
39
|
+
if (!hasChanges && updatedChunk) {
|
|
40
|
+
appLogger(`${prefix}No changes found for chunk ${colorizeNumber(i + 1)}, preserving existing translation`);
|
|
41
|
+
const existingChunk = getChunk(fileToReviewContent, {
|
|
42
|
+
lineStart: updatedChunk.lineStart,
|
|
43
|
+
lineLength: updatedChunk.lineLength
|
|
44
|
+
});
|
|
45
|
+
fileResultContent += existingChunk;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (!updatedChunk) {
|
|
49
|
+
appLogger(`${prefix}Chunk ${colorizeNumber(i + 1)} was deleted, skipping`);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const baseChunkContext = baseChunk;
|
|
53
|
+
const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} of ${chunkMappings.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\n///chunksStart///` + baseChunkContext.content + `///chunksEnd///`;
|
|
54
|
+
const getChunkToReviewPrompt = () => `**CHUNK ${i + 1} of ${chunkMappings.length}** is the current chunk to review in ${formatLocale(locale, false)}.\n///chunksStart///` + updatedChunk.content + `///chunksEnd///`;
|
|
55
|
+
const reviewedChunkResult = await retryManager(async () => {
|
|
56
|
+
const result = await chunkInference([
|
|
57
|
+
{
|
|
58
|
+
role: "system",
|
|
59
|
+
content: basePrompt
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
role: "system",
|
|
63
|
+
content: getBaseChunkContextPrompt()
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
role: "system",
|
|
67
|
+
content: getChunkToReviewPrompt()
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
role: "system",
|
|
71
|
+
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}).`
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
role: "user",
|
|
75
|
+
content: baseChunkContext.content
|
|
76
|
+
}
|
|
77
|
+
], aiOptions, configuration);
|
|
78
|
+
appLogger(`${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(chunkMappings.length)}`);
|
|
79
|
+
return fixChunkStartEndChars(result?.fileContent, baseChunkContext.content);
|
|
80
|
+
})();
|
|
81
|
+
fileResultContent += reviewedChunkResult;
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
appLogger(`${filePrefix}Processing all chunks (no optimization)`);
|
|
85
|
+
const baseChunks = chunkText(basedFileContent, 800, 0);
|
|
86
|
+
appLogger(`${filePrefix}Base file splitted into ${colorizeNumber(baseChunks.length)} chunks`);
|
|
87
|
+
for await (const [i, baseChunk] of baseChunks.entries()) {
|
|
88
|
+
const baseChunkContext = baseChunk;
|
|
89
|
+
const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\n///chunksStart///` + (baseChunks[i - 1]?.content ?? "") + baseChunkContext.content + (baseChunks[i + 1]?.content ?? "") + `///chunksEnd///`;
|
|
90
|
+
const getChunkToReviewPrompt = () => `**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///chunksStart///` + getChunk(updatedFileContent, {
|
|
91
|
+
lineStart: baseChunks[i - 1]?.lineStart ?? 0,
|
|
92
|
+
lineLength: (baseChunks[i - 1]?.lineLength ?? 0) + baseChunkContext.lineLength + (baseChunks[i + 1]?.lineLength ?? 0)
|
|
93
|
+
}) + `///chunksEnd///`;
|
|
94
|
+
const reviewedChunkResult = await retryManager(async () => {
|
|
95
|
+
const result = await chunkInference([
|
|
96
|
+
{
|
|
97
|
+
role: "system",
|
|
98
|
+
content: basePrompt
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
role: "system",
|
|
102
|
+
content: getBaseChunkContextPrompt()
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
role: "system",
|
|
106
|
+
content: getChunkToReviewPrompt()
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
role: "system",
|
|
110
|
+
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}).`
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
role: "user",
|
|
114
|
+
content: baseChunkContext.content
|
|
115
|
+
}
|
|
116
|
+
], aiOptions, configuration);
|
|
117
|
+
appLogger(`${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}`);
|
|
118
|
+
return fixChunkStartEndChars(result?.fileContent, baseChunkContext.content);
|
|
119
|
+
})();
|
|
120
|
+
updatedFileContent = updatedFileContent.replace(baseChunkContext.content, reviewedChunkResult);
|
|
121
|
+
fileResultContent += reviewedChunkResult;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
mkdirSync(dirname(outputFilePath), { recursive: true });
|
|
125
|
+
writeFileSync(outputFilePath, fileResultContent);
|
|
126
|
+
const relativePath = relative(configuration.content.baseDir, outputFilePath);
|
|
127
|
+
appLogger(`${colorize("✔", ANSIColors.GREEN)} File ${formatPath(relativePath)} created/updated successfully.`);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error(error);
|
|
130
|
+
}
|
|
269
131
|
};
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
132
|
+
/**
|
|
133
|
+
* Main audit function: scans all .md files in "en/" (unless you specified DOC_LIST),
|
|
134
|
+
* then audits them to each locale in LOCALE_LIST.
|
|
135
|
+
*/
|
|
136
|
+
const reviewDoc = async ({ docPattern, locales, excludedGlobPattern, baseLocale, aiOptions, nbSimultaneousFileProcessed, configOptions, customInstructions, skipIfModifiedBefore, skipIfModifiedAfter, gitOptions }) => {
|
|
137
|
+
const configuration = getConfiguration(configOptions);
|
|
138
|
+
const appLogger = getAppLogger(configuration);
|
|
139
|
+
if (!await checkAIAccess(configuration, aiOptions)) return;
|
|
140
|
+
if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {
|
|
141
|
+
appLogger(`Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`);
|
|
142
|
+
nbSimultaneousFileProcessed = 10;
|
|
143
|
+
}
|
|
144
|
+
let docList = await fg(docPattern, { ignore: excludedGlobPattern });
|
|
145
|
+
if (gitOptions) {
|
|
146
|
+
const gitChangedFiles = await listGitFiles(gitOptions);
|
|
147
|
+
if (gitChangedFiles) docList = docList.filter((path) => gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile));
|
|
148
|
+
}
|
|
149
|
+
appLogger(`Base locale is ${formatLocale(baseLocale)}`);
|
|
150
|
+
appLogger(`Reviewing ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`);
|
|
151
|
+
appLogger(`Reviewing ${colorizeNumber(docList.length)} files:`);
|
|
152
|
+
appLogger(docList.map((path) => ` - ${formatPath(path)}\n`));
|
|
153
|
+
await parallelize(docList.flatMap((docPath) => locales.map((locale) => async () => {
|
|
154
|
+
appLogger(`Reviewing file: ${formatPath(docPath)} to ${formatLocale(locale)}`);
|
|
155
|
+
const absoluteBaseFilePath = join(configuration.content.baseDir, docPath);
|
|
156
|
+
const outputFilePath = getOutputFilePath(absoluteBaseFilePath, locale, baseLocale);
|
|
157
|
+
const fileModificationData = checkFileModifiedRange(outputFilePath, {
|
|
158
|
+
skipIfModifiedBefore,
|
|
159
|
+
skipIfModifiedAfter
|
|
160
|
+
});
|
|
161
|
+
if (fileModificationData.isSkipped) {
|
|
162
|
+
appLogger(fileModificationData.message);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
let changedLines;
|
|
166
|
+
if (gitOptions) {
|
|
167
|
+
const gitChangedLines = await listGitLines(absoluteBaseFilePath, gitOptions);
|
|
168
|
+
appLogger(`Git changed lines: ${gitChangedLines.join(", ")}`);
|
|
169
|
+
changedLines = gitChangedLines;
|
|
170
|
+
}
|
|
171
|
+
await reviewFile(absoluteBaseFilePath, outputFilePath, locale, baseLocale, aiOptions, configOptions, customInstructions, changedLines);
|
|
172
|
+
})), (task) => task(), nbSimultaneousFileProcessed ?? 3);
|
|
273
173
|
};
|
|
174
|
+
|
|
175
|
+
//#endregion
|
|
176
|
+
export { reviewDoc, reviewFile };
|
|
274
177
|
//# sourceMappingURL=reviewDoc.mjs.map
|
|
@@ -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 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":[]}
|
|
1
|
+
{"version":3,"file":"reviewDoc.mjs","names":["docList: string[]","changedLines: number[] | undefined"],"sources":["../../src/reviewDoc.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport type { AIOptions } from '@intlayer/api'; // OAuth handled by API proxy\nimport {\n formatLocale,\n formatPath,\n getChunk,\n type ListGitFilesOptions,\n listGitFiles,\n listGitLines,\n parallelize,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeNumber,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n retryManager,\n} from '@intlayer/config';\nimport { getLocaleName } from '@intlayer/core';\nimport { type Locale, Locales } from '@intlayer/types';\nimport fg from 'fast-glob';\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 { getOutputFilePath } from './utils/getOutputFilePath';\nimport { mapChunksBetweenFiles } from './utils/mapChunksBetweenFiles';\n\n/**\n * Translate a single file for a given locale\n */\nexport const reviewFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locale,\n baseLocale: Locale,\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\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 = readAsset('./prompts/REVIEW_PROMPT.md', 'utf-8')\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 const 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 const 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: Locale[];\n excludedGlobPattern: string[];\n baseLocale: Locale;\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\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[] = await fg(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;\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 Locale,\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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"}
|