@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.
Files changed (134) hide show
  1. package/dist/cjs/IntlayerEventListener.cjs +241 -0
  2. package/dist/cjs/IntlayerEventListener.cjs.map +1 -0
  3. package/dist/cjs/cli.cjs +29 -7
  4. package/dist/cjs/cli.cjs.map +1 -1
  5. package/dist/cjs/config.cjs +5 -1
  6. package/dist/cjs/config.cjs.map +1 -1
  7. package/dist/cjs/fill/autoFill.cjs +105 -0
  8. package/dist/cjs/fill/autoFill.cjs.map +1 -0
  9. package/dist/cjs/fill/formatAutoFillData.cjs +108 -0
  10. package/dist/cjs/fill/formatAutoFillData.cjs.map +1 -0
  11. package/dist/cjs/fill/formatAutoFilledFilePath.cjs +46 -0
  12. package/dist/cjs/fill/formatAutoFilledFilePath.cjs.map +1 -0
  13. package/dist/cjs/fill/getTargetDictionary.cjs +86 -0
  14. package/dist/cjs/fill/getTargetDictionary.cjs.map +1 -0
  15. package/dist/cjs/fill/index.cjs +257 -0
  16. package/dist/cjs/fill/index.cjs.map +1 -0
  17. package/dist/cjs/index.cjs +4 -2
  18. package/dist/cjs/index.cjs.map +1 -1
  19. package/dist/cjs/listContentDeclaration.cjs +37 -19
  20. package/dist/cjs/listContentDeclaration.cjs.map +1 -1
  21. package/dist/cjs/liveSync.cjs +254 -0
  22. package/dist/cjs/liveSync.cjs.map +1 -0
  23. package/dist/cjs/pull.cjs +119 -117
  24. package/dist/cjs/pull.cjs.map +1 -1
  25. package/dist/cjs/pullLog.cjs +146 -0
  26. package/dist/cjs/pullLog.cjs.map +1 -0
  27. package/dist/cjs/push.cjs +74 -88
  28. package/dist/cjs/push.cjs.map +1 -1
  29. package/dist/cjs/pushConfig.cjs +10 -25
  30. package/dist/cjs/pushConfig.cjs.map +1 -1
  31. package/dist/cjs/pushLog.cjs +130 -0
  32. package/dist/cjs/pushLog.cjs.map +1 -0
  33. package/dist/cjs/reviewDoc.cjs +45 -36
  34. package/dist/cjs/reviewDoc.cjs.map +1 -1
  35. package/dist/cjs/test/index.cjs +91 -0
  36. package/dist/cjs/test/index.cjs.map +1 -0
  37. package/dist/cjs/test/listMissingTranslations.cjs +73 -0
  38. package/dist/cjs/test/listMissingTranslations.cjs.map +1 -0
  39. package/dist/cjs/translateDoc.cjs +42 -34
  40. package/dist/cjs/translateDoc.cjs.map +1 -1
  41. package/dist/cjs/utils/checkAIAccess.cjs +5 -1
  42. package/dist/cjs/utils/checkAIAccess.cjs.map +1 -1
  43. package/dist/cjs/utils/chunkInference.cjs +7 -14
  44. package/dist/cjs/utils/chunkInference.cjs.map +1 -1
  45. package/dist/esm/IntlayerEventListener.mjs +207 -0
  46. package/dist/esm/IntlayerEventListener.mjs.map +1 -0
  47. package/dist/esm/cli.mjs +26 -4
  48. package/dist/esm/cli.mjs.map +1 -1
  49. package/dist/esm/config.mjs +5 -1
  50. package/dist/esm/config.mjs.map +1 -1
  51. package/dist/esm/fill/autoFill.mjs +92 -0
  52. package/dist/esm/fill/autoFill.mjs.map +1 -0
  53. package/dist/esm/fill/formatAutoFillData.mjs +84 -0
  54. package/dist/esm/fill/formatAutoFillData.mjs.map +1 -0
  55. package/dist/esm/fill/formatAutoFilledFilePath.mjs +22 -0
  56. package/dist/esm/fill/formatAutoFilledFilePath.mjs.map +1 -0
  57. package/dist/esm/fill/getTargetDictionary.mjs +51 -0
  58. package/dist/esm/fill/getTargetDictionary.mjs.map +1 -0
  59. package/dist/esm/fill/index.mjs +240 -0
  60. package/dist/esm/fill/index.mjs.map +1 -0
  61. package/dist/esm/index.mjs +2 -1
  62. package/dist/esm/index.mjs.map +1 -1
  63. package/dist/esm/listContentDeclaration.mjs +38 -17
  64. package/dist/esm/listContentDeclaration.mjs.map +1 -1
  65. package/dist/esm/liveSync.mjs +220 -0
  66. package/dist/esm/liveSync.mjs.map +1 -0
  67. package/dist/esm/pull.mjs +123 -108
  68. package/dist/esm/pull.mjs.map +1 -1
  69. package/dist/esm/pullLog.mjs +127 -0
  70. package/dist/esm/pullLog.mjs.map +1 -0
  71. package/dist/esm/push.mjs +81 -90
  72. package/dist/esm/push.mjs.map +1 -1
  73. package/dist/esm/pushConfig.mjs +11 -26
  74. package/dist/esm/pushConfig.mjs.map +1 -1
  75. package/dist/esm/pushLog.mjs +111 -0
  76. package/dist/esm/pushLog.mjs.map +1 -0
  77. package/dist/esm/reviewDoc.mjs +55 -38
  78. package/dist/esm/reviewDoc.mjs.map +1 -1
  79. package/dist/esm/test/index.mjs +74 -0
  80. package/dist/esm/test/index.mjs.map +1 -0
  81. package/dist/esm/test/listMissingTranslations.mjs +41 -0
  82. package/dist/esm/test/listMissingTranslations.mjs.map +1 -0
  83. package/dist/esm/translateDoc.mjs +52 -37
  84. package/dist/esm/translateDoc.mjs.map +1 -1
  85. package/dist/esm/utils/checkAIAccess.mjs +5 -1
  86. package/dist/esm/utils/checkAIAccess.mjs.map +1 -1
  87. package/dist/esm/utils/chunkInference.mjs +14 -16
  88. package/dist/esm/utils/chunkInference.mjs.map +1 -1
  89. package/dist/types/IntlayerEventListener.d.ts +85 -0
  90. package/dist/types/IntlayerEventListener.d.ts.map +1 -0
  91. package/dist/types/cli.d.ts.map +1 -1
  92. package/dist/types/config.d.ts.map +1 -1
  93. package/dist/types/fill/autoFill.d.ts +4 -0
  94. package/dist/types/fill/autoFill.d.ts.map +1 -0
  95. package/dist/types/fill/formatAutoFillData.d.ts +9 -0
  96. package/dist/types/fill/formatAutoFillData.d.ts.map +1 -0
  97. package/dist/types/fill/formatAutoFilledFilePath.d.ts +3 -0
  98. package/dist/types/fill/formatAutoFilledFilePath.d.ts.map +1 -0
  99. package/dist/types/fill/getTargetDictionary.d.ts +4 -0
  100. package/dist/types/fill/getTargetDictionary.d.ts.map +1 -0
  101. package/dist/types/{fill.d.ts → fill/index.d.ts} +2 -5
  102. package/dist/types/fill/index.d.ts.map +1 -0
  103. package/dist/types/index.d.ts +1 -0
  104. package/dist/types/index.d.ts.map +1 -1
  105. package/dist/types/listContentDeclaration.d.ts +4 -5
  106. package/dist/types/listContentDeclaration.d.ts.map +1 -1
  107. package/dist/types/liveSync.d.ts +6 -0
  108. package/dist/types/liveSync.d.ts.map +1 -0
  109. package/dist/types/pull.d.ts.map +1 -1
  110. package/dist/types/pullLog.d.ts +24 -0
  111. package/dist/types/pullLog.d.ts.map +1 -0
  112. package/dist/types/push.d.ts +1 -1
  113. package/dist/types/push.d.ts.map +1 -1
  114. package/dist/types/pushConfig.d.ts +0 -1
  115. package/dist/types/pushConfig.d.ts.map +1 -1
  116. package/dist/types/pushLog.d.ts +23 -0
  117. package/dist/types/pushLog.d.ts.map +1 -0
  118. package/dist/types/reviewDoc.d.ts +1 -1
  119. package/dist/types/reviewDoc.d.ts.map +1 -1
  120. package/dist/types/test/index.d.ts +8 -0
  121. package/dist/types/test/index.d.ts.map +1 -0
  122. package/dist/types/test/listMissingTranslations.d.ts +12 -0
  123. package/dist/types/test/listMissingTranslations.d.ts.map +1 -0
  124. package/dist/types/translateDoc.d.ts +1 -1
  125. package/dist/types/translateDoc.d.ts.map +1 -1
  126. package/dist/types/utils/checkAIAccess.d.ts.map +1 -1
  127. package/dist/types/utils/chunkInference.d.ts +2 -1
  128. package/dist/types/utils/chunkInference.d.ts.map +1 -1
  129. package/package.json +19 -15
  130. package/dist/cjs/fill.cjs +0 -405
  131. package/dist/cjs/fill.cjs.map +0 -1
  132. package/dist/esm/fill.mjs +0 -385
  133. package/dist/esm/fill.mjs.map +0 -1
  134. package/dist/types/fill.d.ts.map +0 -1
@@ -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, oAuth2AccessToken, customInstructions, changedLines) => {
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
- appLogger(` Base file splitted into ${baseChunks.length} chunks`);
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(`No git changed lines found for chunk ${i + 1}`);
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, import_core.getLocaleName)(baseLocale, import_config.Locales.ENGLISH)} (${baseLocale}) as reference.
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, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale}) as reference.
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
- oAuth2AccessToken
119
+ configOptions
109
120
  );
110
121
  appLogger(
111
- ` -> ${result.tokenUsed} tokens used - CHUNK ${i + 1} of ${baseChunks.length}`
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
- appLogger(` File ${outputFilePath} created/updated successfully.`);
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
- let oAuth2AccessToken;
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: [ ${locales.map((locale) => `${(0, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale})`).join(", ")} ]`
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, import_core.getLocaleName)(
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, oAuth2AccessToken, customInstructions) => {
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
- "{{localeName}}",
63
- `${(0, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale})`
64
- ).replaceAll(
65
- "{{baseLocaleName}}",
66
- `${(0, import_core.getLocaleName)(baseLocale, import_config.Locales.ENGLISH)} (${baseLocale})`
67
- ).replace("{{applicationContext}}", aiOptions?.applicationContext ?? "-").replace("{{customInstructions}}", customInstructions ?? "-");
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(`Base file splitted into ${chunks.length} chunks`);
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, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale}):
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, import_core.getLocaleName)(baseLocale, import_config.Locales.ENGLISH)} (${baseLocale}) as reference.
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, import_core.getLocaleName)(baseLocale, import_config.Locales.ENGLISH)} (${baseLocale}) to translate in ${(0, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale}):`
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
- oAuth2AccessToken
98
+ configOptions
91
99
  );
92
100
  appLogger(
93
- ` -> ${result.tokenUsed} tokens used - CHUNK ${i + 1} of ${chunks.length}`
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
- appLogger(`File ${outputFilePath} created/updated successfully.`);
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
- let oAuth2AccessToken;
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: [ ${locales.map((locale) => `${(0, import_core.getLocaleName)(locale, baseLocale)} (${locale})`).join(", ")} ]`
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, import_core.getLocaleName)(
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
  })