@intlayer/cli 5.8.1 → 6.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 +241 -0
- package/dist/cjs/IntlayerEventListener.cjs.map +1 -0
- package/dist/cjs/cli.cjs +29 -7
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/config.cjs +5 -1
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/fill/autoFill.cjs +105 -0
- package/dist/cjs/fill/autoFill.cjs.map +1 -0
- package/dist/cjs/fill/formatAutoFillData.cjs +108 -0
- package/dist/cjs/fill/formatAutoFillData.cjs.map +1 -0
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs +46 -0
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs.map +1 -0
- package/dist/cjs/fill/getTargetDictionary.cjs +86 -0
- package/dist/cjs/fill/getTargetDictionary.cjs.map +1 -0
- package/dist/cjs/fill/index.cjs +257 -0
- package/dist/cjs/fill/index.cjs.map +1 -0
- package/dist/cjs/index.cjs +4 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/listContentDeclaration.cjs +37 -19
- package/dist/cjs/listContentDeclaration.cjs.map +1 -1
- package/dist/cjs/liveSync.cjs +254 -0
- package/dist/cjs/liveSync.cjs.map +1 -0
- package/dist/cjs/pull.cjs +119 -117
- package/dist/cjs/pull.cjs.map +1 -1
- package/dist/cjs/pullLog.cjs +146 -0
- package/dist/cjs/pullLog.cjs.map +1 -0
- package/dist/cjs/push.cjs +74 -88
- package/dist/cjs/push.cjs.map +1 -1
- package/dist/cjs/pushConfig.cjs +10 -25
- package/dist/cjs/pushConfig.cjs.map +1 -1
- package/dist/cjs/pushLog.cjs +130 -0
- package/dist/cjs/pushLog.cjs.map +1 -0
- package/dist/cjs/reviewDoc.cjs +45 -36
- package/dist/cjs/reviewDoc.cjs.map +1 -1
- package/dist/cjs/test/index.cjs +91 -0
- package/dist/cjs/test/index.cjs.map +1 -0
- package/dist/cjs/test/listMissingTranslations.cjs +73 -0
- package/dist/cjs/test/listMissingTranslations.cjs.map +1 -0
- package/dist/cjs/translateDoc.cjs +42 -34
- package/dist/cjs/translateDoc.cjs.map +1 -1
- package/dist/cjs/utils/checkAIAccess.cjs +5 -1
- package/dist/cjs/utils/checkAIAccess.cjs.map +1 -1
- package/dist/cjs/utils/chunkInference.cjs +7 -14
- package/dist/cjs/utils/chunkInference.cjs.map +1 -1
- package/dist/esm/IntlayerEventListener.mjs +207 -0
- package/dist/esm/IntlayerEventListener.mjs.map +1 -0
- package/dist/esm/cli.mjs +26 -4
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/config.mjs +5 -1
- package/dist/esm/config.mjs.map +1 -1
- package/dist/esm/fill/autoFill.mjs +92 -0
- package/dist/esm/fill/autoFill.mjs.map +1 -0
- package/dist/esm/fill/formatAutoFillData.mjs +84 -0
- package/dist/esm/fill/formatAutoFillData.mjs.map +1 -0
- package/dist/esm/fill/formatAutoFilledFilePath.mjs +22 -0
- package/dist/esm/fill/formatAutoFilledFilePath.mjs.map +1 -0
- package/dist/esm/fill/getTargetDictionary.mjs +51 -0
- package/dist/esm/fill/getTargetDictionary.mjs.map +1 -0
- package/dist/esm/fill/index.mjs +240 -0
- package/dist/esm/fill/index.mjs.map +1 -0
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/listContentDeclaration.mjs +38 -17
- package/dist/esm/listContentDeclaration.mjs.map +1 -1
- package/dist/esm/liveSync.mjs +220 -0
- package/dist/esm/liveSync.mjs.map +1 -0
- package/dist/esm/pull.mjs +123 -108
- package/dist/esm/pull.mjs.map +1 -1
- package/dist/esm/pullLog.mjs +127 -0
- package/dist/esm/pullLog.mjs.map +1 -0
- package/dist/esm/push.mjs +81 -90
- package/dist/esm/push.mjs.map +1 -1
- package/dist/esm/pushConfig.mjs +11 -26
- package/dist/esm/pushConfig.mjs.map +1 -1
- package/dist/esm/pushLog.mjs +111 -0
- package/dist/esm/pushLog.mjs.map +1 -0
- package/dist/esm/reviewDoc.mjs +55 -38
- package/dist/esm/reviewDoc.mjs.map +1 -1
- package/dist/esm/test/index.mjs +74 -0
- package/dist/esm/test/index.mjs.map +1 -0
- package/dist/esm/test/listMissingTranslations.mjs +41 -0
- package/dist/esm/test/listMissingTranslations.mjs.map +1 -0
- package/dist/esm/translateDoc.mjs +52 -37
- package/dist/esm/translateDoc.mjs.map +1 -1
- package/dist/esm/utils/checkAIAccess.mjs +5 -1
- package/dist/esm/utils/checkAIAccess.mjs.map +1 -1
- package/dist/esm/utils/chunkInference.mjs +14 -16
- package/dist/esm/utils/chunkInference.mjs.map +1 -1
- package/dist/types/IntlayerEventListener.d.ts +85 -0
- package/dist/types/IntlayerEventListener.d.ts.map +1 -0
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/fill/autoFill.d.ts +4 -0
- package/dist/types/fill/autoFill.d.ts.map +1 -0
- package/dist/types/fill/formatAutoFillData.d.ts +9 -0
- package/dist/types/fill/formatAutoFillData.d.ts.map +1 -0
- package/dist/types/fill/formatAutoFilledFilePath.d.ts +3 -0
- package/dist/types/fill/formatAutoFilledFilePath.d.ts.map +1 -0
- package/dist/types/fill/getTargetDictionary.d.ts +4 -0
- package/dist/types/fill/getTargetDictionary.d.ts.map +1 -0
- package/dist/types/{fill.d.ts → fill/index.d.ts} +2 -5
- package/dist/types/fill/index.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/listContentDeclaration.d.ts +4 -5
- package/dist/types/listContentDeclaration.d.ts.map +1 -1
- package/dist/types/liveSync.d.ts +6 -0
- package/dist/types/liveSync.d.ts.map +1 -0
- package/dist/types/pull.d.ts.map +1 -1
- package/dist/types/pullLog.d.ts +24 -0
- package/dist/types/pullLog.d.ts.map +1 -0
- package/dist/types/push.d.ts +1 -1
- package/dist/types/push.d.ts.map +1 -1
- package/dist/types/pushConfig.d.ts +0 -1
- package/dist/types/pushConfig.d.ts.map +1 -1
- package/dist/types/pushLog.d.ts +23 -0
- package/dist/types/pushLog.d.ts.map +1 -0
- package/dist/types/reviewDoc.d.ts +1 -1
- package/dist/types/reviewDoc.d.ts.map +1 -1
- package/dist/types/test/index.d.ts +8 -0
- package/dist/types/test/index.d.ts.map +1 -0
- package/dist/types/test/listMissingTranslations.d.ts +12 -0
- package/dist/types/test/listMissingTranslations.d.ts.map +1 -0
- package/dist/types/translateDoc.d.ts +1 -1
- package/dist/types/translateDoc.d.ts.map +1 -1
- package/dist/types/utils/checkAIAccess.d.ts.map +1 -1
- package/dist/types/utils/chunkInference.d.ts +2 -1
- package/dist/types/utils/chunkInference.d.ts.map +1 -1
- package/package.json +19 -15
- package/dist/cjs/fill.cjs +0 -405
- package/dist/cjs/fill.cjs.map +0 -1
- package/dist/esm/fill.mjs +0 -385
- package/dist/esm/fill.mjs.map +0 -1
- package/dist/types/fill.d.ts.map +0 -1
package/dist/cjs/reviewDoc.cjs
CHANGED
|
@@ -32,7 +32,6 @@ __export(reviewDoc_exports, {
|
|
|
32
32
|
reviewFile: () => reviewFile
|
|
33
33
|
});
|
|
34
34
|
module.exports = __toCommonJS(reviewDoc_exports);
|
|
35
|
-
var import_api = require("@intlayer/api");
|
|
36
35
|
var import_chokidar = require("@intlayer/chokidar");
|
|
37
36
|
var import_config = require("@intlayer/config");
|
|
38
37
|
var import_core = require("@intlayer/core");
|
|
@@ -52,23 +51,33 @@ var import_getOutputFilePath = require('./utils/getOutputFilePath.cjs');
|
|
|
52
51
|
const import_meta = {};
|
|
53
52
|
const isESModule = typeof import_meta.url === "string";
|
|
54
53
|
const dir = isESModule ? (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url)) : __dirname;
|
|
55
|
-
const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions, configOptions,
|
|
54
|
+
const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions, configOptions, customInstructions, changedLines) => {
|
|
56
55
|
try {
|
|
57
56
|
const configuration = (0, import_config.getConfiguration)(configOptions);
|
|
58
|
-
const appLogger = (0, import_config.getAppLogger)(configuration
|
|
57
|
+
const appLogger = (0, import_config.getAppLogger)(configuration, {
|
|
58
|
+
config: {
|
|
59
|
+
prefix: ""
|
|
60
|
+
}
|
|
61
|
+
});
|
|
59
62
|
const basedFileContent = await (0, import_promises.readFile)(baseFilePath, "utf-8");
|
|
60
63
|
const fileToReviewContent = await (0, import_promises.readFile)(outputFilePath, "utf-8");
|
|
61
64
|
let updatedFileContent = fileToReviewContent;
|
|
62
65
|
let fileResultContent = "";
|
|
63
|
-
const basePrompt = (await (0, import_promises.readFile)((0, import_path.join)(dir, "./prompts/REVIEW_PROMPT.md"), "utf-8")).replaceAll(
|
|
64
|
-
"{{localeName}}",
|
|
65
|
-
`${(0, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale})`
|
|
66
|
-
).replaceAll(
|
|
67
|
-
"{{baseLocaleName}}",
|
|
68
|
-
`${(0, import_core.getLocaleName)(baseLocale, import_config.Locales.ENGLISH)} (${baseLocale})`
|
|
69
|
-
).replace("{{applicationContext}}", aiOptions?.applicationContext ?? "-").replace("{{customInstructions}}", customInstructions ?? "-");
|
|
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 ?? "-");
|
|
70
67
|
const baseChunks = (0, import_calculateChunks.chunkText)(basedFileContent, 800, 0);
|
|
71
|
-
|
|
68
|
+
const filePrexixText = `${import_config.ANSIColors.GREY_DARK}[${(0, import_chokidar.formatPath)(baseFilePath)}${import_config.ANSIColors.GREY_DARK}] `;
|
|
69
|
+
const filePrefix = [
|
|
70
|
+
(0, import_config.colon)(filePrexixText, { colSize: 40 }),
|
|
71
|
+
`\u2192 ${import_config.ANSIColors.RESET}`
|
|
72
|
+
].join("");
|
|
73
|
+
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}] `;
|
|
74
|
+
const prefix = [
|
|
75
|
+
(0, import_config.colon)(prefixText, { colSize: 40 }),
|
|
76
|
+
`\u2192 ${import_config.ANSIColors.RESET}`
|
|
77
|
+
].join("");
|
|
78
|
+
appLogger(
|
|
79
|
+
`${filePrefix}Base file splitted into ${(0, import_config.colorizeNumber)(baseChunks.length)} chunks`
|
|
80
|
+
);
|
|
72
81
|
for await (const [i, baseChunk] of baseChunks.entries()) {
|
|
73
82
|
const baseChunkContext = baseChunk;
|
|
74
83
|
if (changedLines) {
|
|
@@ -76,7 +85,9 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
76
85
|
(line) => line > baseChunkContext.lineStart && line < baseChunkContext.lineStart + baseChunkContext.lineLength
|
|
77
86
|
);
|
|
78
87
|
if (!hasChangedLinesInChunk) {
|
|
79
|
-
appLogger(
|
|
88
|
+
appLogger(
|
|
89
|
+
`No git changed lines found for chunk ${(0, import_config.colorizeNumber)(i + 1)}`
|
|
90
|
+
);
|
|
80
91
|
const chunkWithNoChange = (0, import_getChunk.getChunk)(updatedFileContent, {
|
|
81
92
|
lineStart: baseChunkContext.lineStart,
|
|
82
93
|
lineLength: baseChunkContext.lineLength
|
|
@@ -85,9 +96,9 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
85
96
|
continue;
|
|
86
97
|
}
|
|
87
98
|
}
|
|
88
|
-
const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${(0,
|
|
99
|
+
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.
|
|
89
100
|
///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 ${(0,
|
|
101
|
+
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.
|
|
91
102
|
///chunksStart///` + (0, import_getChunk.getChunk)(updatedFileContent, {
|
|
92
103
|
lineStart: baseChunks[i - 1]?.lineStart ?? 0,
|
|
93
104
|
lineLength: (baseChunks[i - 1]?.lineLength ?? 0) + baseChunkContext.lineLength + (baseChunks[i + 1]?.lineLength ?? 0)
|
|
@@ -100,15 +111,15 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
100
111
|
{ role: "system", content: getChunkToReviewPrompt() },
|
|
101
112
|
{
|
|
102
113
|
role: "system",
|
|
103
|
-
content: `The next user message will be the **CHUNK ${i + 1} of ${baseChunks.length}** that should be translated in ${(0, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale}).`
|
|
114
|
+
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}).`
|
|
104
115
|
},
|
|
105
116
|
{ role: "user", content: baseChunkContext.content }
|
|
106
117
|
],
|
|
107
118
|
aiOptions,
|
|
108
|
-
|
|
119
|
+
configOptions
|
|
109
120
|
);
|
|
110
121
|
appLogger(
|
|
111
|
-
|
|
122
|
+
`${prefix}${(0, import_config.colorizeNumber)(result.tokenUsed)} tokens used - Chunk ${(0, import_config.colorizeNumber)(i + 1)} of ${(0, import_config.colorizeNumber)(baseChunks.length)}`
|
|
112
123
|
);
|
|
113
124
|
const fixedReviewedChunkResult = (0, import_fixChunkStartEndChars.fixChunkStartEndChars)(
|
|
114
125
|
result?.fileContent,
|
|
@@ -124,7 +135,13 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
124
135
|
}
|
|
125
136
|
(0, import_fs.mkdirSync)((0, import_path.dirname)(outputFilePath), { recursive: true });
|
|
126
137
|
(0, import_fs.writeFileSync)(outputFilePath, fileResultContent);
|
|
127
|
-
|
|
138
|
+
const relativePath = (0, import_path.relative)(
|
|
139
|
+
configuration.content.baseDir,
|
|
140
|
+
outputFilePath
|
|
141
|
+
);
|
|
142
|
+
appLogger(
|
|
143
|
+
`${(0, import_config.colorize)("\u2714", import_config.ANSIColors.GREEN)} File ${(0, import_chokidar.formatPath)(relativePath)} created/updated successfully.`
|
|
144
|
+
);
|
|
128
145
|
} catch (error) {
|
|
129
146
|
console.error(error);
|
|
130
147
|
}
|
|
@@ -143,7 +160,11 @@ const reviewDoc = async ({
|
|
|
143
160
|
gitOptions
|
|
144
161
|
}) => {
|
|
145
162
|
const configuration = (0, import_config.getConfiguration)(configOptions);
|
|
146
|
-
const appLogger = (0, import_config.getAppLogger)(configuration
|
|
163
|
+
const appLogger = (0, import_config.getAppLogger)(configuration, {
|
|
164
|
+
config: {
|
|
165
|
+
prefix: ""
|
|
166
|
+
}
|
|
167
|
+
});
|
|
147
168
|
if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {
|
|
148
169
|
appLogger(
|
|
149
170
|
`Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`
|
|
@@ -163,29 +184,18 @@ const reviewDoc = async ({
|
|
|
163
184
|
}
|
|
164
185
|
}
|
|
165
186
|
(0, import_checkAIAccess.checkAIAccess)(configuration, aiOptions);
|
|
166
|
-
|
|
167
|
-
if (configuration.editor.clientId) {
|
|
168
|
-
const intlayerAuthAPI = (0, import_api.getOAuthAPI)(configuration);
|
|
169
|
-
const oAuth2TokenResult = await intlayerAuthAPI.getOAuth2AccessToken();
|
|
170
|
-
oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;
|
|
171
|
-
}
|
|
172
|
-
appLogger(
|
|
173
|
-
`Base locale is ${(0, import_core.getLocaleName)(baseLocale, import_config.Locales.ENGLISH)} (${baseLocale})`
|
|
174
|
-
);
|
|
187
|
+
appLogger(`Base locale is ${(0, import_chokidar.formatLocale)(baseLocale)}`);
|
|
175
188
|
appLogger(
|
|
176
|
-
`Reviewing ${locales.length} locales: [ ${
|
|
189
|
+
`Reviewing ${(0, import_config.colorizeNumber)(locales.length)} locales: [ ${(0, import_chokidar.formatLocale)(locales)} ]`
|
|
177
190
|
);
|
|
178
|
-
appLogger(`Reviewing ${docList.length} files:`);
|
|
179
|
-
appLogger(docList.map((path) => ` - ${path}
|
|
191
|
+
appLogger(`Reviewing ${(0, import_config.colorizeNumber)(docList.length)} files:`);
|
|
192
|
+
appLogger(docList.map((path) => ` - ${(0, import_chokidar.formatPath)(path)}
|
|
180
193
|
`));
|
|
181
194
|
const tasks = docList.map(
|
|
182
195
|
(docPath) => locales.flatMap(
|
|
183
196
|
(locale) => limit(async () => {
|
|
184
197
|
appLogger(
|
|
185
|
-
`Reviewing file: ${docPath} to ${(0,
|
|
186
|
-
locale,
|
|
187
|
-
import_config.Locales.ENGLISH
|
|
188
|
-
)} (${locale})`
|
|
198
|
+
`Reviewing file: ${(0, import_chokidar.formatPath)(docPath)} to ${(0, import_chokidar.formatLocale)(locale)}`
|
|
189
199
|
);
|
|
190
200
|
const absoluteBaseFilePath = (0, import_path.join)(
|
|
191
201
|
configuration.content.baseDir,
|
|
@@ -212,7 +222,6 @@ const reviewDoc = async ({
|
|
|
212
222
|
baseLocale,
|
|
213
223
|
aiOptions,
|
|
214
224
|
configOptions,
|
|
215
|
-
oAuth2AccessToken,
|
|
216
225
|
customInstructions,
|
|
217
226
|
changedLines
|
|
218
227
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/reviewDoc.ts"],"sourcesContent":["import { AIOptions, getOAuthAPI } from '@intlayer/api'; // Importing only getAiAPI for now\nimport { listGitFiles, ListGitFilesOptions } from '@intlayer/chokidar';\nimport {\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 pLimit from 'p-limit';\nimport { dirname, join } from 'path';\nimport { fileURLToPath } from 'url';\nimport { chunkText } from './utils/calculateChunks';\nimport { checkAIAccess } from './utils/checkAIAccess';\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 configOptions?: GetConfigurationOptions,\n oAuth2AccessToken?: string,\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 = (\n await readFile(join(dir, './prompts/REVIEW_PROMPT.md'), 'utf-8')\n )\n .replaceAll(\n '{{localeName}}',\n `${getLocaleName(locale, Locales.ENGLISH)} (${locale})`\n )\n .replaceAll(\n '{{baseLocaleName}}',\n `${getLocaleName(baseLocale, Locales.ENGLISH)} (${baseLocale})`\n )\n .replace('{{applicationContext}}', aiOptions?.applicationContext ?? '-')\n .replace('{{customInstructions}}', customInstructions ?? '-');\n\n const baseChunks = chunkText(basedFileContent, 800, 0);\n\n appLogger(` Base file splitted into ${baseChunks.length} chunks`);\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(`No git changed lines found for chunk ${i + 1}`);\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 ${getLocaleName(baseLocale, Locales.ENGLISH)} (${baseLocale}) 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 ${getLocaleName(locale, Locales.ENGLISH)} (${locale}) 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 ${i + 1} of ${baseChunks.length}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`,\n },\n { role: 'user', content: baseChunkContext.content },\n ],\n aiOptions,\n oAuth2AccessToken\n );\n\n appLogger(\n ` -> ${result.tokenUsed} tokens used - CHUNK ${i + 1} of ${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 mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, fileResultContent);\n\n appLogger(` File ${outputFilePath} created/updated successfully.`);\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\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 checkAIAccess(configuration, aiOptions);\n\n let oAuth2AccessToken: string | undefined;\n if (configuration.editor.clientId) {\n const intlayerAuthAPI = getOAuthAPI(configuration);\n const oAuth2TokenResult = await intlayerAuthAPI.getOAuth2AccessToken();\n\n oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n }\n\n appLogger(\n `Base locale is ${getLocaleName(baseLocale, Locales.ENGLISH)} (${baseLocale})`\n );\n appLogger(\n `Reviewing ${locales.length} locales: [ ${locales\n .map((locale) => `${getLocaleName(locale, Locales.ENGLISH)} (${locale})`)\n .join(', ')} ]`\n );\n\n appLogger(`Reviewing ${docList.length} files:`);\n appLogger(docList.map((path) => ` - ${path}\\n`));\n\n const tasks = docList.map((docPath) =>\n locales.flatMap((locale) =>\n limit(async () => {\n appLogger(\n `Reviewing file: ${docPath} to ${getLocaleName(\n locale,\n Locales.ENGLISH\n )} (${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 configOptions,\n oAuth2AccessToken,\n customInstructions,\n changedLines\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/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 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/checkAIAccess';\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 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 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 = [\n colon(prefixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].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 configOptions\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 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 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 checkAIAccess(configuration, aiOptions);\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 configOptions,\n customInstructions,\n changedLines\n );\n })\n )\n );\n\n await Promise.all(tasks);\n};\n"],"mappings":"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","names":["pLimit","fg"]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var test_exports = {};
|
|
20
|
+
__export(test_exports, {
|
|
21
|
+
listMissingTranslations: () => import_listMissingTranslations.listMissingTranslations,
|
|
22
|
+
testMissingTranslations: () => testMissingTranslations
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(test_exports);
|
|
25
|
+
var import_chokidar = require("@intlayer/chokidar");
|
|
26
|
+
var import_config = require("@intlayer/config");
|
|
27
|
+
var import_listMissingTranslations = require('./listMissingTranslations.cjs');
|
|
28
|
+
const testMissingTranslations = (options) => {
|
|
29
|
+
const config = (0, import_config.getConfiguration)(options?.configOptions);
|
|
30
|
+
const { locales, requiredLocales } = config.internationalization;
|
|
31
|
+
const appLogger = (0, import_config.getAppLogger)(config, {
|
|
32
|
+
config: {
|
|
33
|
+
prefix: ""
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const result = (0, import_listMissingTranslations.listMissingTranslations)();
|
|
37
|
+
const maxKeyColSize = result.missingTranslations.map((t) => ` - ${t.key}`).reduce((max, t) => Math.max(max, t.length), 0);
|
|
38
|
+
const maxLocalesColSize = result.missingTranslations.map((t) => (0, import_chokidar.formatLocale)(t.locales, false)).reduce((max, t) => Math.max(max, t.length), 0);
|
|
39
|
+
const formattedMissingTranslations = result.missingTranslations.map(
|
|
40
|
+
(translation) => [
|
|
41
|
+
(0, import_config.colon)(` - ${(0, import_config.colorizeKey)(translation.key)}`, {
|
|
42
|
+
colSize: maxKeyColSize,
|
|
43
|
+
maxSize: 40
|
|
44
|
+
}),
|
|
45
|
+
" - ",
|
|
46
|
+
(0, import_config.colon)((0, import_chokidar.formatLocale)(translation.locales, import_config.ANSIColors.RED), {
|
|
47
|
+
colSize: maxLocalesColSize,
|
|
48
|
+
maxSize: 40
|
|
49
|
+
}),
|
|
50
|
+
" - ",
|
|
51
|
+
translation.filePath ? (0, import_chokidar.formatPath)(translation.filePath) : "Remote"
|
|
52
|
+
].join("")
|
|
53
|
+
);
|
|
54
|
+
appLogger(`Missing translations:`, {
|
|
55
|
+
level: "info"
|
|
56
|
+
});
|
|
57
|
+
formattedMissingTranslations.forEach((t) => {
|
|
58
|
+
appLogger(t, {
|
|
59
|
+
level: "info"
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
appLogger(`Locales: ${(0, import_chokidar.formatLocale)(locales)}`);
|
|
63
|
+
appLogger(`Required locales: ${(0, import_chokidar.formatLocale)(requiredLocales ?? locales)}`);
|
|
64
|
+
appLogger(
|
|
65
|
+
`Missing locales: ${result.missingLocales.length === 0 ? (0, import_config.colorize)("-", import_config.ANSIColors.GREEN) : (0, import_chokidar.formatLocale)(result.missingLocales, import_config.ANSIColors.RED)}`
|
|
66
|
+
);
|
|
67
|
+
appLogger(
|
|
68
|
+
`Missing required locales: ${result.missingRequiredLocales.length === 0 ? (0, import_config.colorize)("-", import_config.ANSIColors.GREEN) : (0, import_chokidar.formatLocale)(result.missingRequiredLocales, import_config.ANSIColors.RED)}`
|
|
69
|
+
);
|
|
70
|
+
appLogger(
|
|
71
|
+
`Total missing locales: ${(0, import_config.colorizeNumber)(result.missingLocales.length, {
|
|
72
|
+
other: import_config.ANSIColors.RED,
|
|
73
|
+
zero: import_config.ANSIColors.GREEN
|
|
74
|
+
})}`
|
|
75
|
+
);
|
|
76
|
+
appLogger(
|
|
77
|
+
`Total missing required locales: ${(0, import_config.colorizeNumber)(
|
|
78
|
+
result.missingRequiredLocales.length,
|
|
79
|
+
{
|
|
80
|
+
other: import_config.ANSIColors.RED,
|
|
81
|
+
zero: import_config.ANSIColors.GREEN
|
|
82
|
+
}
|
|
83
|
+
)}`
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
87
|
+
0 && (module.exports = {
|
|
88
|
+
listMissingTranslations,
|
|
89
|
+
testMissingTranslations
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +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();\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;AAEvC,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":[]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var listMissingTranslations_exports = {};
|
|
30
|
+
__export(listMissingTranslations_exports, {
|
|
31
|
+
listMissingTranslations: () => listMissingTranslations
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(listMissingTranslations_exports);
|
|
34
|
+
var import_built = __toESM(require("@intlayer/config/built"));
|
|
35
|
+
var import_core = require("@intlayer/core");
|
|
36
|
+
var import_unmerged_dictionaries_entry = __toESM(require("@intlayer/unmerged-dictionaries-entry"));
|
|
37
|
+
const listMissingTranslations = (dictionariesRecord = import_unmerged_dictionaries_entry.default) => {
|
|
38
|
+
const missingTranslations = [];
|
|
39
|
+
const { locales, requiredLocales } = import_built.default.internationalization;
|
|
40
|
+
for (const dictionaries of Object.values(dictionariesRecord)) {
|
|
41
|
+
for (const dictionary of dictionaries) {
|
|
42
|
+
const missingLocales2 = (0, import_core.getMissingLocalesContent)(
|
|
43
|
+
dictionary,
|
|
44
|
+
import_built.default.internationalization.locales,
|
|
45
|
+
{
|
|
46
|
+
dictionaryKey: dictionary.key,
|
|
47
|
+
keyPath: [],
|
|
48
|
+
plugins: []
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
if (missingLocales2.length > 0) {
|
|
52
|
+
missingTranslations.push({
|
|
53
|
+
key: dictionary.key,
|
|
54
|
+
filePath: dictionary.filePath,
|
|
55
|
+
locales: missingLocales2
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const missingLocalesSet = new Set(
|
|
61
|
+
missingTranslations.flatMap((t) => t.locales)
|
|
62
|
+
);
|
|
63
|
+
const missingLocales = Array.from(missingLocalesSet);
|
|
64
|
+
const missingRequiredLocales = missingLocales.filter(
|
|
65
|
+
(locale) => (requiredLocales ?? locales).includes(locale)
|
|
66
|
+
);
|
|
67
|
+
return { missingTranslations, missingLocales, missingRequiredLocales };
|
|
68
|
+
};
|
|
69
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
70
|
+
0 && (module.exports = {
|
|
71
|
+
listMissingTranslations
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=listMissingTranslations.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/test/listMissingTranslations.ts"],"sourcesContent":["import type { Locales } from '@intlayer/config';\nimport configuration from '@intlayer/config/built';\nimport {\n type ContentNode,\n type Dictionary,\n getMissingLocalesContent,\n} from '@intlayer/core';\nimport unmergedDictionariesRecord from '@intlayer/unmerged-dictionaries-entry';\n\nexport const listMissingTranslations = (\n dictionariesRecord: keyof typeof unmergedDictionariesRecord = unmergedDictionariesRecord\n) => {\n const missingTranslations: {\n key: keyof typeof unmergedDictionariesRecord;\n filePath?: string;\n locales: Locales[];\n }[] = [];\n\n const { locales, requiredLocales } = configuration.internationalization;\n\n for (const dictionaries of Object.values(dictionariesRecord)) {\n for (const dictionary of dictionaries as unknown as Dictionary[]) {\n const missingLocales = getMissingLocalesContent(\n dictionary as unknown as ContentNode,\n configuration.internationalization.locales,\n {\n dictionaryKey: dictionary.key,\n keyPath: [],\n plugins: [],\n }\n );\n\n if (missingLocales.length > 0) {\n missingTranslations.push({\n key: dictionary.key,\n filePath: dictionary.filePath,\n locales: missingLocales,\n });\n }\n }\n }\n\n const missingLocalesSet = new Set(\n missingTranslations.flatMap((t) => t.locales)\n );\n const missingLocales = Array.from(missingLocalesSet);\n\n const missingRequiredLocales = missingLocales.filter((locale) =>\n (requiredLocales ?? locales).includes(locale)\n );\n\n return { missingTranslations, missingLocales, missingRequiredLocales };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAA0B;AAC1B,kBAIO;AACP,yCAAuC;AAEhC,MAAM,0BAA0B,CACrC,qBAA8D,mCAAAA,YAC3D;AACH,QAAM,sBAIA,CAAC;AAEP,QAAM,EAAE,SAAS,gBAAgB,IAAI,aAAAC,QAAc;AAEnD,aAAW,gBAAgB,OAAO,OAAO,kBAAkB,GAAG;AAC5D,eAAW,cAAc,cAAyC;AAChE,YAAMC,sBAAiB;AAAA,QACrB;AAAA,QACA,aAAAD,QAAc,qBAAqB;AAAA,QACnC;AAAA,UACE,eAAe,WAAW;AAAA,UAC1B,SAAS,CAAC;AAAA,UACV,SAAS,CAAC;AAAA,QACZ;AAAA,MACF;AAEA,UAAIC,gBAAe,SAAS,GAAG;AAC7B,4BAAoB,KAAK;AAAA,UACvB,KAAK,WAAW;AAAA,UAChB,UAAU,WAAW;AAAA,UACrB,SAASA;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,QAAM,oBAAoB,IAAI;AAAA,IAC5B,oBAAoB,QAAQ,CAAC,MAAM,EAAE,OAAO;AAAA,EAC9C;AACA,QAAM,iBAAiB,MAAM,KAAK,iBAAiB;AAEnD,QAAM,yBAAyB,eAAe;AAAA,IAAO,CAAC,YACnD,mBAAmB,SAAS,SAAS,MAAM;AAAA,EAC9C;AAEA,SAAO,EAAE,qBAAqB,gBAAgB,uBAAuB;AACvE;","names":["unmergedDictionariesRecord","configuration","missingLocales"]}
|
|
@@ -32,10 +32,8 @@ __export(translateDoc_exports, {
|
|
|
32
32
|
translateFile: () => translateFile
|
|
33
33
|
});
|
|
34
34
|
module.exports = __toCommonJS(translateDoc_exports);
|
|
35
|
-
var import_api = require("@intlayer/api");
|
|
36
35
|
var import_chokidar = require("@intlayer/chokidar");
|
|
37
36
|
var import_config = require("@intlayer/config");
|
|
38
|
-
var import_core = require("@intlayer/core");
|
|
39
37
|
var import_fast_glob = __toESM(require("fast-glob"));
|
|
40
38
|
var import_fs = require("fs");
|
|
41
39
|
var import_promises = require("fs/promises");
|
|
@@ -52,26 +50,36 @@ var import_getOutputFilePath = require('./utils/getOutputFilePath.cjs');
|
|
|
52
50
|
const import_meta = {};
|
|
53
51
|
const isESModule = typeof import_meta.url === "string";
|
|
54
52
|
const dir = isESModule ? (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url)) : __dirname;
|
|
55
|
-
const translateFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions, configOptions,
|
|
53
|
+
const translateFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions, configOptions, customInstructions) => {
|
|
56
54
|
try {
|
|
57
55
|
const configuration = (0, import_config.getConfiguration)(configOptions);
|
|
58
|
-
const appLogger = (0, import_config.getAppLogger)(configuration
|
|
56
|
+
const appLogger = (0, import_config.getAppLogger)(configuration, {
|
|
57
|
+
config: {
|
|
58
|
+
prefix: ""
|
|
59
|
+
}
|
|
60
|
+
});
|
|
59
61
|
const fileContent = await (0, import_promises.readFile)(baseFilePath, "utf-8");
|
|
60
62
|
let fileResultContent = fileContent;
|
|
61
|
-
const basePrompt = (await (0, import_promises.readFile)((0, import_path.join)(dir, "./prompts/TRANSLATE_PROMPT.md"), "utf-8")).replaceAll(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
const basePrompt = (await (0, import_promises.readFile)((0, import_path.join)(dir, "./prompts/TRANSLATE_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 ?? "-");
|
|
64
|
+
const filePrexixText = `${import_config.ANSIColors.GREY_DARK}[${(0, import_chokidar.formatPath)(baseFilePath)}${import_config.ANSIColors.GREY_DARK}] `;
|
|
65
|
+
const filePrefix = [
|
|
66
|
+
(0, import_config.colon)(filePrexixText, { colSize: 40 }),
|
|
67
|
+
`\u2192 ${import_config.ANSIColors.RESET}`
|
|
68
|
+
].join("");
|
|
69
|
+
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}] `;
|
|
70
|
+
const prefix = [
|
|
71
|
+
(0, import_config.colon)(prefixText, { colSize: 40 }),
|
|
72
|
+
`\u2192 ${import_config.ANSIColors.RESET}`
|
|
73
|
+
].join("");
|
|
68
74
|
const chunks = (0, import_calculateChunks.chunkText)(fileContent);
|
|
69
|
-
appLogger(
|
|
75
|
+
appLogger(
|
|
76
|
+
`${filePrefix}Base file splitted into ${(0, import_config.colorizeNumber)(chunks.length)} chunks`
|
|
77
|
+
);
|
|
70
78
|
for await (const [i, chunk] of chunks.entries()) {
|
|
71
79
|
const isFirstChunk = i === 0;
|
|
72
|
-
const getPrevChunkPrompt = () => `**CHUNK ${i} of ${chunks.length}** that has been translated in ${(0,
|
|
80
|
+
const getPrevChunkPrompt = () => `**CHUNK ${i} of ${chunks.length}** that has been translated in ${(0, import_chokidar.formatLocale)(locale)}:
|
|
73
81
|
///chunkStart///` + (0, import_getChunk.getChunk)(fileResultContent, chunks[i - 1]) + `///chunkEnd///`;
|
|
74
|
-
const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, chunks.length)} of ${chunks.length}** is the base chunk in ${(0,
|
|
82
|
+
const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, chunks.length)} of ${chunks.length}** is the base chunk in ${(0, import_chokidar.formatLocale)(baseLocale, false)} as reference.
|
|
75
83
|
///chunksStart///` + (chunks[i - 1]?.content ?? "") + chunks[i].content + (chunks[i + 1]?.content ?? "") + `///chunksEnd///`;
|
|
76
84
|
const fileToTranslateCurrentChunk = chunk.content;
|
|
77
85
|
let chunkTranslation = await (0, import_config.retryManager)(async () => {
|
|
@@ -82,15 +90,15 @@ const translateFile = async (baseFilePath, outputFilePath, locale, baseLocale, a
|
|
|
82
90
|
...isFirstChunk ? [] : [{ role: "system", content: getPrevChunkPrompt() }],
|
|
83
91
|
{
|
|
84
92
|
role: "system",
|
|
85
|
-
content: `The next user message will be the **CHUNK ${i + 1} of ${chunks.length}** in ${(0,
|
|
93
|
+
content: `The next user message will be the **CHUNK ${(0, import_config.colorizeNumber)(i + 1)} of ${(0, import_config.colorizeNumber)(chunks.length)}** in ${(0, import_chokidar.formatLocale)(baseLocale, false)} to translate in ${(0, import_chokidar.formatLocale)(locale, false)}:`
|
|
86
94
|
},
|
|
87
95
|
{ role: "user", content: fileToTranslateCurrentChunk }
|
|
88
96
|
],
|
|
89
97
|
aiOptions,
|
|
90
|
-
|
|
98
|
+
configOptions
|
|
91
99
|
);
|
|
92
100
|
appLogger(
|
|
93
|
-
|
|
101
|
+
`${prefix}${(0, import_config.colorizeNumber)(result.tokenUsed)} tokens used - Chunk ${(0, import_config.colorizeNumber)(i + 1)} of ${(0, import_config.colorizeNumber)(chunks.length)}`
|
|
94
102
|
);
|
|
95
103
|
const fixedTranslatedChunkResult = (0, import_fixChunkStartEndChars.fixChunkStartEndChars)(
|
|
96
104
|
result?.fileContent,
|
|
@@ -105,7 +113,13 @@ const translateFile = async (baseFilePath, outputFilePath, locale, baseLocale, a
|
|
|
105
113
|
}
|
|
106
114
|
(0, import_fs.mkdirSync)((0, import_path.dirname)(outputFilePath), { recursive: true });
|
|
107
115
|
(0, import_fs.writeFileSync)(outputFilePath, fileResultContent);
|
|
108
|
-
|
|
116
|
+
const relativePath = (0, import_path.relative)(
|
|
117
|
+
configuration.content.baseDir,
|
|
118
|
+
outputFilePath
|
|
119
|
+
);
|
|
120
|
+
appLogger(
|
|
121
|
+
`${(0, import_config.colorize)("\u2714", import_config.ANSIColors.GREEN)} File ${(0, import_chokidar.formatPath)(relativePath)} created/updated successfully.`
|
|
122
|
+
);
|
|
109
123
|
} catch (error) {
|
|
110
124
|
console.error(error);
|
|
111
125
|
}
|
|
@@ -124,7 +138,11 @@ const translateDoc = async ({
|
|
|
124
138
|
gitOptions
|
|
125
139
|
}) => {
|
|
126
140
|
const configuration = (0, import_config.getConfiguration)(configOptions);
|
|
127
|
-
const appLogger = (0, import_config.getAppLogger)(configuration
|
|
141
|
+
const appLogger = (0, import_config.getAppLogger)(configuration, {
|
|
142
|
+
config: {
|
|
143
|
+
prefix: ""
|
|
144
|
+
}
|
|
145
|
+
});
|
|
128
146
|
if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {
|
|
129
147
|
appLogger(
|
|
130
148
|
`Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`
|
|
@@ -144,27 +162,18 @@ const translateDoc = async ({
|
|
|
144
162
|
);
|
|
145
163
|
}
|
|
146
164
|
}
|
|
147
|
-
|
|
148
|
-
if (configuration.editor.clientId) {
|
|
149
|
-
const intlayerAuthAPI = (0, import_api.getOAuthAPI)(configuration);
|
|
150
|
-
const oAuth2TokenResult = await intlayerAuthAPI.getOAuth2AccessToken();
|
|
151
|
-
oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;
|
|
152
|
-
}
|
|
153
|
-
appLogger(`Base locale is ${(0, import_core.getLocaleName)(baseLocale)} (${baseLocale})`);
|
|
165
|
+
appLogger(`Base locale is ${(0, import_chokidar.formatLocale)(baseLocale)}`);
|
|
154
166
|
appLogger(
|
|
155
|
-
`Translating ${locales.length} locales: [ ${
|
|
167
|
+
`Translating ${(0, import_config.colorizeNumber)(locales.length)} locales: [ ${(0, import_chokidar.formatLocale)(locales)} ]`
|
|
156
168
|
);
|
|
157
|
-
appLogger(`Translating ${docList.length} files:`);
|
|
158
|
-
appLogger(docList.map((path) => ` - ${path}
|
|
169
|
+
appLogger(`Translating ${(0, import_config.colorizeNumber)(docList.length)} files:`);
|
|
170
|
+
appLogger(docList.map((path) => ` - ${(0, import_chokidar.formatPath)(path)}
|
|
159
171
|
`));
|
|
160
172
|
const tasks = docList.map(
|
|
161
173
|
(docPath) => locales.flatMap(
|
|
162
174
|
(locale) => limit(async () => {
|
|
163
175
|
appLogger(
|
|
164
|
-
`Translating file: ${docPath} to ${(0,
|
|
165
|
-
locale,
|
|
166
|
-
import_config.Locales.ENGLISH
|
|
167
|
-
)} (${locale})`
|
|
176
|
+
`Translating file: ${(0, import_chokidar.formatPath)(docPath)} to ${(0, import_chokidar.formatLocale)(locale)}`
|
|
168
177
|
);
|
|
169
178
|
const absoluteBaseFilePath = (0, import_path.join)(
|
|
170
179
|
configuration.content.baseDir,
|
|
@@ -195,7 +204,6 @@ const translateDoc = async ({
|
|
|
195
204
|
baseLocale,
|
|
196
205
|
aiOptions,
|
|
197
206
|
configOptions,
|
|
198
|
-
oAuth2AccessToken,
|
|
199
207
|
customInstructions
|
|
200
208
|
);
|
|
201
209
|
})
|