@intlayer/cli 7.5.0-canary.0 → 7.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/cjs/IntlayerEventListener.cjs +8 -8
  2. package/dist/cjs/IntlayerEventListener.cjs.map +1 -1
  3. package/dist/cjs/auth/login.cjs +156 -0
  4. package/dist/cjs/auth/login.cjs.map +1 -0
  5. package/dist/cjs/build.cjs +5 -5
  6. package/dist/cjs/build.cjs.map +1 -1
  7. package/dist/cjs/cli.cjs +19 -3
  8. package/dist/cjs/cli.cjs.map +1 -1
  9. package/dist/cjs/config.cjs +3 -3
  10. package/dist/cjs/config.cjs.map +1 -1
  11. package/dist/cjs/editor.cjs +2 -2
  12. package/dist/cjs/editor.cjs.map +1 -1
  13. package/dist/cjs/fill/fill.cjs +12 -12
  14. package/dist/cjs/fill/fill.cjs.map +1 -1
  15. package/dist/cjs/fill/listTranslationsTasks.cjs +15 -15
  16. package/dist/cjs/fill/listTranslationsTasks.cjs.map +1 -1
  17. package/dist/cjs/fill/translateDictionary.cjs +36 -36
  18. package/dist/cjs/fill/translateDictionary.cjs.map +1 -1
  19. package/dist/cjs/fill/writeFill.cjs +11 -11
  20. package/dist/cjs/fill/writeFill.cjs.map +1 -1
  21. package/dist/cjs/getTargetDictionary.cjs +6 -6
  22. package/dist/cjs/getTargetDictionary.cjs.map +1 -1
  23. package/dist/cjs/listContentDeclaration.cjs +9 -9
  24. package/dist/cjs/listContentDeclaration.cjs.map +1 -1
  25. package/dist/cjs/liveSync.cjs +16 -16
  26. package/dist/cjs/liveSync.cjs.map +1 -1
  27. package/dist/cjs/pull.cjs +14 -14
  28. package/dist/cjs/pull.cjs.map +1 -1
  29. package/dist/cjs/push/pullLog.cjs +6 -6
  30. package/dist/cjs/push/pullLog.cjs.map +1 -1
  31. package/dist/cjs/push/push.cjs +23 -23
  32. package/dist/cjs/push/push.cjs.map +1 -1
  33. package/dist/cjs/pushConfig.cjs +5 -5
  34. package/dist/cjs/pushConfig.cjs.map +1 -1
  35. package/dist/cjs/pushLog.cjs +6 -6
  36. package/dist/cjs/pushLog.cjs.map +1 -1
  37. package/dist/cjs/reviewDoc.cjs +13 -13
  38. package/dist/cjs/reviewDoc.cjs.map +1 -1
  39. package/dist/cjs/reviewDocBlockAware.cjs +19 -19
  40. package/dist/cjs/reviewDocBlockAware.cjs.map +1 -1
  41. package/dist/cjs/test/listMissingTranslations.cjs +9 -9
  42. package/dist/cjs/test/listMissingTranslations.cjs.map +1 -1
  43. package/dist/cjs/test/test.cjs +22 -22
  44. package/dist/cjs/test/test.cjs.map +1 -1
  45. package/dist/cjs/transform.cjs +8 -8
  46. package/dist/cjs/transform.cjs.map +1 -1
  47. package/dist/cjs/translateDoc.cjs +29 -29
  48. package/dist/cjs/translateDoc.cjs.map +1 -1
  49. package/dist/cjs/utils/calculateChunks.cjs +4 -4
  50. package/dist/cjs/utils/calculateChunks.cjs.map +1 -1
  51. package/dist/cjs/utils/checkAccess.cjs +13 -13
  52. package/dist/cjs/utils/checkAccess.cjs.map +1 -1
  53. package/dist/cjs/utils/chunkInference.cjs +4 -4
  54. package/dist/cjs/utils/chunkInference.cjs.map +1 -1
  55. package/dist/cjs/utils/mapChunksBetweenFiles.cjs +4 -4
  56. package/dist/cjs/utils/mapChunksBetweenFiles.cjs.map +1 -1
  57. package/dist/cjs/utils/openBrowser.cjs +19 -0
  58. package/dist/cjs/utils/openBrowser.cjs.map +1 -0
  59. package/dist/cjs/utils/setupAI.cjs +5 -5
  60. package/dist/cjs/utils/setupAI.cjs.map +1 -1
  61. package/dist/cjs/watch.cjs +26 -5
  62. package/dist/cjs/watch.cjs.map +1 -1
  63. package/dist/esm/auth/login.mjs +154 -0
  64. package/dist/esm/auth/login.mjs.map +1 -0
  65. package/dist/esm/cli.mjs +16 -0
  66. package/dist/esm/cli.mjs.map +1 -1
  67. package/dist/esm/liveSync.mjs +1 -1
  68. package/dist/esm/translateDoc.mjs +1 -1
  69. package/dist/esm/translateDoc.mjs.map +1 -1
  70. package/dist/esm/utils/openBrowser.mjs +18 -0
  71. package/dist/esm/utils/openBrowser.mjs.map +1 -0
  72. package/dist/esm/watch.mjs +23 -2
  73. package/dist/esm/watch.mjs.map +1 -1
  74. package/dist/types/auth/login.d.ts +11 -0
  75. package/dist/types/auth/login.d.ts.map +1 -0
  76. package/dist/types/cli.d.ts.map +1 -1
  77. package/dist/types/config.d.ts.map +1 -1
  78. package/dist/types/pull.d.ts.map +1 -1
  79. package/dist/types/utils/openBrowser.d.ts +5 -0
  80. package/dist/types/utils/openBrowser.d.ts.map +1 -0
  81. package/package.json +13 -13
@@ -4,8 +4,8 @@ const require_utils_setupAI = require('../utils/setupAI.cjs');
4
4
  const require_fill_listTranslationsTasks = require('./listTranslationsTasks.cjs');
5
5
  const require_fill_translateDictionary = require('./translateDictionary.cjs');
6
6
  const require_fill_writeFill = require('./writeFill.cjs');
7
- let __intlayer_chokidar = require("@intlayer/chokidar");
8
- let __intlayer_config = require("@intlayer/config");
7
+ let _intlayer_chokidar = require("@intlayer/chokidar");
8
+ let _intlayer_config = require("@intlayer/config");
9
9
  let node_path = require("node:path");
10
10
 
11
11
  //#region src/fill/fill.ts
@@ -14,10 +14,10 @@ const NB_CONCURRENT_TRANSLATIONS = 7;
14
14
  * Fill translations based on the provided options.
15
15
  */
16
16
  const fill = async (options) => {
17
- const configuration = (0, __intlayer_config.getConfiguration)(options?.configOptions);
18
- const appLogger = (0, __intlayer_config.getAppLogger)(configuration);
19
- if (options?.build === true) await (0, __intlayer_chokidar.prepareIntlayer)(configuration, { forceRun: true });
20
- else if (typeof options?.build === "undefined") await (0, __intlayer_chokidar.prepareIntlayer)(configuration);
17
+ const configuration = (0, _intlayer_config.getConfiguration)(options?.configOptions);
18
+ const appLogger = (0, _intlayer_config.getAppLogger)(configuration);
19
+ if (options?.build === true) await (0, _intlayer_chokidar.prepareIntlayer)(configuration, { forceRun: true });
20
+ else if (typeof options?.build === "undefined") await (0, _intlayer_chokidar.prepareIntlayer)(configuration);
21
21
  const { defaultLocale, locales } = configuration.internationalization;
22
22
  const mode = options?.mode ?? "complete";
23
23
  const baseLocale = options?.sourceLocale ?? defaultLocale;
@@ -31,7 +31,7 @@ const fill = async (options) => {
31
31
  affectedDictionaryKeys.add(dict.key);
32
32
  });
33
33
  const keysToProcess = Array.from(affectedDictionaryKeys);
34
- appLogger(["Affected dictionary keys for processing:", keysToProcess.length > 0 ? keysToProcess.map((key) => (0, __intlayer_config.colorizeKey)(key)).join(", ") : (0, __intlayer_config.colorize)("No keys found", __intlayer_config.ANSIColors.YELLOW)]);
34
+ appLogger(["Affected dictionary keys for processing:", keysToProcess.length > 0 ? keysToProcess.map((key) => (0, _intlayer_config.colorizeKey)(key)).join(", ") : (0, _intlayer_config.colorize)("No keys found", _intlayer_config.ANSIColors.YELLOW)]);
35
35
  if (keysToProcess.length === 0) return;
36
36
  /**
37
37
  * List the translations tasks
@@ -42,11 +42,11 @@ const fill = async (options) => {
42
42
  */
43
43
  const translationTasks = require_fill_listTranslationsTasks.listTranslationsTasks(targetUnmergedDictionaries.map((dictionary) => dictionary.localId), outputLocales, mode, baseLocale, configuration);
44
44
  const nbConcurrentTranslations = options?.nbConcurrentTranslations ?? NB_CONCURRENT_TRANSLATIONS;
45
- const globalLimiter = (0, __intlayer_chokidar.getGlobalLimiter)(nbConcurrentTranslations);
46
- const taskLimiter = (0, __intlayer_chokidar.getTaskLimiter)(Math.max(1, Math.min(options?.nbConcurrentTasks ?? nbConcurrentTranslations, translationTasks.length)));
45
+ const globalLimiter = (0, _intlayer_chokidar.getGlobalLimiter)(nbConcurrentTranslations);
46
+ const taskLimiter = (0, _intlayer_chokidar.getTaskLimiter)(Math.max(1, Math.min(options?.nbConcurrentTasks ?? nbConcurrentTranslations, translationTasks.length)));
47
47
  const runners = translationTasks.map((task) => taskLimiter(async () => {
48
48
  const relativePath = (0, node_path.relative)(configuration?.content?.baseDir ?? process.cwd(), task?.dictionaryFilePath ?? "");
49
- appLogger(`${task.dictionaryPreset} Processing ${(0, __intlayer_config.colorizePath)((0, node_path.basename)(relativePath))}`, { level: "info" });
49
+ appLogger(`${task.dictionaryPreset} Processing ${(0, _intlayer_config.colorizePath)((0, node_path.basename)(relativePath))}`, { level: "info" });
50
50
  const translationTaskResult = await require_fill_translateDictionary.translateDictionary(task, configuration, {
51
51
  mode,
52
52
  aiOptions: options?.aiOptions,
@@ -65,8 +65,8 @@ const fill = async (options) => {
65
65
  fill: effectiveFill
66
66
  }, outputLocales, [sourceLocale], configuration);
67
67
  else {
68
- await (0, __intlayer_chokidar.writeContentDeclaration)(dictionaryOutput, configuration);
69
- if (dictionaryOutput.filePath) appLogger(`${task.dictionaryPreset} Content declaration written to ${(0, __intlayer_chokidar.formatPath)((0, node_path.basename)(dictionaryOutput.filePath))}`, { level: "info" });
68
+ await (0, _intlayer_chokidar.writeContentDeclaration)(dictionaryOutput, configuration);
69
+ if (dictionaryOutput.filePath) appLogger(`${task.dictionaryPreset} Content declaration written to ${(0, _intlayer_chokidar.formatPath)((0, node_path.basename)(dictionaryOutput.filePath))}`, { level: "info" });
70
70
  }
71
71
  }));
72
72
  await Promise.all(runners);
@@ -1 +1 @@
1
- {"version":3,"file":"fill.cjs","names":["ensureArray","setupAI","getTargetUnmergedDictionaries","ANSIColors","translationTasks: TranslationTask[]","listTranslationsTasks","translateDictionary","writeFill"],"sources":["../../../src/fill/fill.ts"],"sourcesContent":["import { basename, relative } from 'node:path';\nimport type { AIOptions } from '@intlayer/api';\nimport {\n formatPath,\n getGlobalLimiter,\n getTaskLimiter,\n type ListGitFilesOptions,\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colorize,\n colorizeKey,\n colorizePath,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport type { Locale } from '@intlayer/types';\nimport {\n ensureArray,\n type GetTargetDictionaryOptions,\n getTargetUnmergedDictionaries,\n} from '../getTargetDictionary';\nimport { setupAI } from '../utils/setupAI';\nimport {\n listTranslationsTasks,\n type TranslationTask,\n} from './listTranslationsTasks';\nimport { translateDictionary } from './translateDictionary';\nimport { writeFill } from './writeFill';\n\nconst NB_CONCURRENT_TRANSLATIONS = 7;\n\n// Arguments for the fill function\nexport type FillOptions = {\n sourceLocale?: Locale;\n outputLocales?: Locale | Locale[];\n mode?: 'complete' | 'review';\n gitOptions?: ListGitFilesOptions;\n aiOptions?: AIOptions; // Added aiOptions to be passed to translateJSON\n verbose?: boolean;\n nbConcurrentTranslations?: number;\n nbConcurrentTasks?: number; // NEW: number of tasks that may run at once\n build?: boolean;\n skipMetadata?: boolean;\n} & GetTargetDictionaryOptions;\n\n/**\n * Fill translations based on the provided options.\n */\nexport const fill = async (options?: FillOptions): Promise<void> => {\n const configuration = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(configuration);\n\n if (options?.build === true) {\n await prepareIntlayer(configuration, { forceRun: true });\n } else if (typeof options?.build === 'undefined') {\n await prepareIntlayer(configuration);\n }\n\n const { defaultLocale, locales } = configuration.internationalization;\n const mode = options?.mode ?? 'complete';\n const baseLocale = options?.sourceLocale ?? defaultLocale;\n\n const outputLocales = options?.outputLocales\n ? ensureArray(options.outputLocales)\n : locales;\n\n const aiResult = await setupAI(configuration, options?.aiOptions);\n\n if (!aiResult?.hasAIAccess) return;\n\n const { aiClient, aiConfig } = aiResult;\n\n const targetUnmergedDictionaries =\n await getTargetUnmergedDictionaries(options);\n\n const affectedDictionaryKeys = new Set<string>();\n targetUnmergedDictionaries.forEach((dict) => {\n affectedDictionaryKeys.add(dict.key);\n });\n\n const keysToProcess = Array.from(affectedDictionaryKeys);\n\n appLogger([\n 'Affected dictionary keys for processing:',\n keysToProcess.length > 0\n ? keysToProcess.map((key) => colorizeKey(key)).join(', ')\n : colorize('No keys found', ANSIColors.YELLOW),\n ]);\n\n if (keysToProcess.length === 0) return;\n\n /**\n * List the translations tasks\n *\n * Create a list of per-locale dictionaries to translate\n *\n * In 'complete' mode, filter only the missing locales to translate\n */\n const translationTasks: TranslationTask[] = listTranslationsTasks(\n targetUnmergedDictionaries.map((dictionary) => dictionary.localId!),\n outputLocales,\n mode,\n baseLocale,\n configuration\n );\n\n // AI calls in flight at once (translateJSON + metadata audit)\n const nbConcurrentTranslations =\n options?.nbConcurrentTranslations ?? NB_CONCURRENT_TRANSLATIONS;\n const globalLimiter = getGlobalLimiter(nbConcurrentTranslations);\n\n // NEW: number of *tasks* that may run at once (start/prepare/log/write)\n const nbConcurrentTasks = Math.max(\n 1,\n Math.min(\n options?.nbConcurrentTasks ?? nbConcurrentTranslations,\n translationTasks.length\n )\n );\n\n const taskLimiter = getTaskLimiter(nbConcurrentTasks);\n\n const runners = translationTasks.map((task) =>\n taskLimiter(async () => {\n const relativePath = relative(\n configuration?.content?.baseDir ?? process.cwd(),\n task?.dictionaryFilePath ?? ''\n );\n\n // log AFTER acquiring a task slot\n appLogger(\n `${task.dictionaryPreset} Processing ${colorizePath(basename(relativePath))}`,\n { level: 'info' }\n );\n\n const translationTaskResult = await translateDictionary(\n task,\n configuration,\n {\n mode,\n aiOptions: options?.aiOptions,\n fillMetadata: !options?.skipMetadata,\n onHandle: globalLimiter, // <= AI calls go through here\n aiClient,\n aiConfig,\n }\n );\n\n if (!translationTaskResult?.dictionaryOutput) return;\n\n const { dictionaryOutput, sourceLocale } = translationTaskResult;\n\n // Determine if we should write to separate files\n // - If dictionary has explicit fill setting (string or object), use it\n // - If dictionary is per-locale AND has no explicit fill=false, use global fill config\n // - If dictionary is multilingual (no locale property), always write to same file\n const hasDictionaryLevelFill =\n typeof dictionaryOutput.fill === 'string' ||\n typeof dictionaryOutput.fill === 'object';\n\n const isPerLocale = typeof dictionaryOutput.locale === 'string';\n\n const effectiveFill = hasDictionaryLevelFill\n ? dictionaryOutput.fill\n : isPerLocale\n ? (configuration.dictionary?.fill ?? true)\n : false; // Multilingual dictionaries don't use fill by default\n\n const isFillOtherFile =\n typeof effectiveFill === 'string' || typeof effectiveFill === 'object';\n\n if (isFillOtherFile) {\n await writeFill(\n {\n ...dictionaryOutput,\n // Ensure fill is set on the dictionary for writeFill to use\n fill: effectiveFill,\n },\n outputLocales,\n [sourceLocale],\n configuration\n );\n } else {\n await writeContentDeclaration(dictionaryOutput, configuration);\n\n if (dictionaryOutput.filePath) {\n appLogger(\n `${task.dictionaryPreset} Content declaration written to ${formatPath(basename(dictionaryOutput.filePath))}`,\n { level: 'info' }\n );\n }\n }\n })\n );\n\n await Promise.all(runners);\n await (globalLimiter as any).onIdle();\n};\n"],"mappings":";;;;;;;;;;;AAgCA,MAAM,6BAA6B;;;;AAmBnC,MAAa,OAAO,OAAO,YAAyC;CAClE,MAAM,wDAAiC,SAAS,cAAc;CAC9D,MAAM,gDAAyB,cAAc;AAE7C,KAAI,SAAS,UAAU,KACrB,gDAAsB,eAAe,EAAE,UAAU,MAAM,CAAC;UAC/C,OAAO,SAAS,UAAU,YACnC,gDAAsB,cAAc;CAGtC,MAAM,EAAE,eAAe,YAAY,cAAc;CACjD,MAAM,OAAO,SAAS,QAAQ;CAC9B,MAAM,aAAa,SAAS,gBAAgB;CAE5C,MAAM,gBAAgB,SAAS,gBAC3BA,wCAAY,QAAQ,cAAc,GAClC;CAEJ,MAAM,WAAW,MAAMC,8BAAQ,eAAe,SAAS,UAAU;AAEjE,KAAI,CAAC,UAAU,YAAa;CAE5B,MAAM,EAAE,UAAU,aAAa;CAE/B,MAAM,6BACJ,MAAMC,0DAA8B,QAAQ;CAE9C,MAAM,yCAAyB,IAAI,KAAa;AAChD,4BAA2B,SAAS,SAAS;AAC3C,yBAAuB,IAAI,KAAK,IAAI;GACpC;CAEF,MAAM,gBAAgB,MAAM,KAAK,uBAAuB;AAExD,WAAU,CACR,4CACA,cAAc,SAAS,IACnB,cAAc,KAAK,2CAAoB,IAAI,CAAC,CAAC,KAAK,KAAK,mCAC9C,iBAAiBC,6BAAW,OAAO,CACjD,CAAC;AAEF,KAAI,cAAc,WAAW,EAAG;;;;;;;;CAShC,MAAMC,mBAAsCC,yDAC1C,2BAA2B,KAAK,eAAe,WAAW,QAAS,EACnE,eACA,MACA,YACA,cACD;CAGD,MAAM,2BACJ,SAAS,4BAA4B;CACvC,MAAM,0DAAiC,yBAAyB;CAWhE,MAAM,sDARoB,KAAK,IAC7B,GACA,KAAK,IACH,SAAS,qBAAqB,0BAC9B,iBAAiB,OAClB,CACF,CAEoD;CAErD,MAAM,UAAU,iBAAiB,KAAK,SACpC,YAAY,YAAY;EACtB,MAAM,uCACJ,eAAe,SAAS,WAAW,QAAQ,KAAK,EAChD,MAAM,sBAAsB,GAC7B;AAGD,YACE,GAAG,KAAK,iBAAiB,0EAAoC,aAAa,CAAC,IAC3E,EAAE,OAAO,QAAQ,CAClB;EAED,MAAM,wBAAwB,MAAMC,qDAClC,MACA,eACA;GACE;GACA,WAAW,SAAS;GACpB,cAAc,CAAC,SAAS;GACxB,UAAU;GACV;GACA;GACD,CACF;AAED,MAAI,CAAC,uBAAuB,iBAAkB;EAE9C,MAAM,EAAE,kBAAkB,iBAAiB;EAM3C,MAAM,yBACJ,OAAO,iBAAiB,SAAS,YACjC,OAAO,iBAAiB,SAAS;EAEnC,MAAM,cAAc,OAAO,iBAAiB,WAAW;EAEvD,MAAM,gBAAgB,yBAClB,iBAAiB,OACjB,cACG,cAAc,YAAY,QAAQ,OACnC;AAKN,MAFE,OAAO,kBAAkB,YAAY,OAAO,kBAAkB,SAG9D,OAAMC,iCACJ;GACE,GAAG;GAEH,MAAM;GACP,EACD,eACA,CAAC,aAAa,EACd,cACD;OACI;AACL,0DAA8B,kBAAkB,cAAc;AAE9D,OAAI,iBAAiB,SACnB,WACE,GAAG,KAAK,iBAAiB,8FAAsD,iBAAiB,SAAS,CAAC,IAC1G,EAAE,OAAO,QAAQ,CAClB;;GAGL,CACH;AAED,OAAM,QAAQ,IAAI,QAAQ;AAC1B,OAAO,cAAsB,QAAQ"}
1
+ {"version":3,"file":"fill.cjs","names":["ensureArray","setupAI","getTargetUnmergedDictionaries","ANSIColors","translationTasks: TranslationTask[]","listTranslationsTasks","translateDictionary","writeFill"],"sources":["../../../src/fill/fill.ts"],"sourcesContent":["import { basename, relative } from 'node:path';\nimport type { AIOptions } from '@intlayer/api';\nimport {\n formatPath,\n getGlobalLimiter,\n getTaskLimiter,\n type ListGitFilesOptions,\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colorize,\n colorizeKey,\n colorizePath,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport type { Locale } from '@intlayer/types';\nimport {\n ensureArray,\n type GetTargetDictionaryOptions,\n getTargetUnmergedDictionaries,\n} from '../getTargetDictionary';\nimport { setupAI } from '../utils/setupAI';\nimport {\n listTranslationsTasks,\n type TranslationTask,\n} from './listTranslationsTasks';\nimport { translateDictionary } from './translateDictionary';\nimport { writeFill } from './writeFill';\n\nconst NB_CONCURRENT_TRANSLATIONS = 7;\n\n// Arguments for the fill function\nexport type FillOptions = {\n sourceLocale?: Locale;\n outputLocales?: Locale | Locale[];\n mode?: 'complete' | 'review';\n gitOptions?: ListGitFilesOptions;\n aiOptions?: AIOptions; // Added aiOptions to be passed to translateJSON\n verbose?: boolean;\n nbConcurrentTranslations?: number;\n nbConcurrentTasks?: number; // NEW: number of tasks that may run at once\n build?: boolean;\n skipMetadata?: boolean;\n} & GetTargetDictionaryOptions;\n\n/**\n * Fill translations based on the provided options.\n */\nexport const fill = async (options?: FillOptions): Promise<void> => {\n const configuration = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(configuration);\n\n if (options?.build === true) {\n await prepareIntlayer(configuration, { forceRun: true });\n } else if (typeof options?.build === 'undefined') {\n await prepareIntlayer(configuration);\n }\n\n const { defaultLocale, locales } = configuration.internationalization;\n const mode = options?.mode ?? 'complete';\n const baseLocale = options?.sourceLocale ?? defaultLocale;\n\n const outputLocales = options?.outputLocales\n ? ensureArray(options.outputLocales)\n : locales;\n\n const aiResult = await setupAI(configuration, options?.aiOptions);\n\n if (!aiResult?.hasAIAccess) return;\n\n const { aiClient, aiConfig } = aiResult;\n\n const targetUnmergedDictionaries =\n await getTargetUnmergedDictionaries(options);\n\n const affectedDictionaryKeys = new Set<string>();\n targetUnmergedDictionaries.forEach((dict) => {\n affectedDictionaryKeys.add(dict.key);\n });\n\n const keysToProcess = Array.from(affectedDictionaryKeys);\n\n appLogger([\n 'Affected dictionary keys for processing:',\n keysToProcess.length > 0\n ? keysToProcess.map((key) => colorizeKey(key)).join(', ')\n : colorize('No keys found', ANSIColors.YELLOW),\n ]);\n\n if (keysToProcess.length === 0) return;\n\n /**\n * List the translations tasks\n *\n * Create a list of per-locale dictionaries to translate\n *\n * In 'complete' mode, filter only the missing locales to translate\n */\n const translationTasks: TranslationTask[] = listTranslationsTasks(\n targetUnmergedDictionaries.map((dictionary) => dictionary.localId!),\n outputLocales,\n mode,\n baseLocale,\n configuration\n );\n\n // AI calls in flight at once (translateJSON + metadata audit)\n const nbConcurrentTranslations =\n options?.nbConcurrentTranslations ?? NB_CONCURRENT_TRANSLATIONS;\n const globalLimiter = getGlobalLimiter(nbConcurrentTranslations);\n\n // NEW: number of *tasks* that may run at once (start/prepare/log/write)\n const nbConcurrentTasks = Math.max(\n 1,\n Math.min(\n options?.nbConcurrentTasks ?? nbConcurrentTranslations,\n translationTasks.length\n )\n );\n\n const taskLimiter = getTaskLimiter(nbConcurrentTasks);\n\n const runners = translationTasks.map((task) =>\n taskLimiter(async () => {\n const relativePath = relative(\n configuration?.content?.baseDir ?? process.cwd(),\n task?.dictionaryFilePath ?? ''\n );\n\n // log AFTER acquiring a task slot\n appLogger(\n `${task.dictionaryPreset} Processing ${colorizePath(basename(relativePath))}`,\n { level: 'info' }\n );\n\n const translationTaskResult = await translateDictionary(\n task,\n configuration,\n {\n mode,\n aiOptions: options?.aiOptions,\n fillMetadata: !options?.skipMetadata,\n onHandle: globalLimiter, // <= AI calls go through here\n aiClient,\n aiConfig,\n }\n );\n\n if (!translationTaskResult?.dictionaryOutput) return;\n\n const { dictionaryOutput, sourceLocale } = translationTaskResult;\n\n // Determine if we should write to separate files\n // - If dictionary has explicit fill setting (string or object), use it\n // - If dictionary is per-locale AND has no explicit fill=false, use global fill config\n // - If dictionary is multilingual (no locale property), always write to same file\n const hasDictionaryLevelFill =\n typeof dictionaryOutput.fill === 'string' ||\n typeof dictionaryOutput.fill === 'object';\n\n const isPerLocale = typeof dictionaryOutput.locale === 'string';\n\n const effectiveFill = hasDictionaryLevelFill\n ? dictionaryOutput.fill\n : isPerLocale\n ? (configuration.dictionary?.fill ?? true)\n : false; // Multilingual dictionaries don't use fill by default\n\n const isFillOtherFile =\n typeof effectiveFill === 'string' || typeof effectiveFill === 'object';\n\n if (isFillOtherFile) {\n await writeFill(\n {\n ...dictionaryOutput,\n // Ensure fill is set on the dictionary for writeFill to use\n fill: effectiveFill,\n },\n outputLocales,\n [sourceLocale],\n configuration\n );\n } else {\n await writeContentDeclaration(dictionaryOutput, configuration);\n\n if (dictionaryOutput.filePath) {\n appLogger(\n `${task.dictionaryPreset} Content declaration written to ${formatPath(basename(dictionaryOutput.filePath))}`,\n { level: 'info' }\n );\n }\n }\n })\n );\n\n await Promise.all(runners);\n await (globalLimiter as any).onIdle();\n};\n"],"mappings":";;;;;;;;;;;AAgCA,MAAM,6BAA6B;;;;AAmBnC,MAAa,OAAO,OAAO,YAAyC;CAClE,MAAM,uDAAiC,SAAS,cAAc;CAC9D,MAAM,+CAAyB,cAAc;AAE7C,KAAI,SAAS,UAAU,KACrB,+CAAsB,eAAe,EAAE,UAAU,MAAM,CAAC;UAC/C,OAAO,SAAS,UAAU,YACnC,+CAAsB,cAAc;CAGtC,MAAM,EAAE,eAAe,YAAY,cAAc;CACjD,MAAM,OAAO,SAAS,QAAQ;CAC9B,MAAM,aAAa,SAAS,gBAAgB;CAE5C,MAAM,gBAAgB,SAAS,gBAC3BA,wCAAY,QAAQ,cAAc,GAClC;CAEJ,MAAM,WAAW,MAAMC,8BAAQ,eAAe,SAAS,UAAU;AAEjE,KAAI,CAAC,UAAU,YAAa;CAE5B,MAAM,EAAE,UAAU,aAAa;CAE/B,MAAM,6BACJ,MAAMC,0DAA8B,QAAQ;CAE9C,MAAM,yCAAyB,IAAI,KAAa;AAChD,4BAA2B,SAAS,SAAS;AAC3C,yBAAuB,IAAI,KAAK,IAAI;GACpC;CAEF,MAAM,gBAAgB,MAAM,KAAK,uBAAuB;AAExD,WAAU,CACR,4CACA,cAAc,SAAS,IACnB,cAAc,KAAK,0CAAoB,IAAI,CAAC,CAAC,KAAK,KAAK,kCAC9C,iBAAiBC,4BAAW,OAAO,CACjD,CAAC;AAEF,KAAI,cAAc,WAAW,EAAG;;;;;;;;CAShC,MAAMC,mBAAsCC,yDAC1C,2BAA2B,KAAK,eAAe,WAAW,QAAS,EACnE,eACA,MACA,YACA,cACD;CAGD,MAAM,2BACJ,SAAS,4BAA4B;CACvC,MAAM,yDAAiC,yBAAyB;CAWhE,MAAM,qDARoB,KAAK,IAC7B,GACA,KAAK,IACH,SAAS,qBAAqB,0BAC9B,iBAAiB,OAClB,CACF,CAEoD;CAErD,MAAM,UAAU,iBAAiB,KAAK,SACpC,YAAY,YAAY;EACtB,MAAM,uCACJ,eAAe,SAAS,WAAW,QAAQ,KAAK,EAChD,MAAM,sBAAsB,GAC7B;AAGD,YACE,GAAG,KAAK,iBAAiB,yEAAoC,aAAa,CAAC,IAC3E,EAAE,OAAO,QAAQ,CAClB;EAED,MAAM,wBAAwB,MAAMC,qDAClC,MACA,eACA;GACE;GACA,WAAW,SAAS;GACpB,cAAc,CAAC,SAAS;GACxB,UAAU;GACV;GACA;GACD,CACF;AAED,MAAI,CAAC,uBAAuB,iBAAkB;EAE9C,MAAM,EAAE,kBAAkB,iBAAiB;EAM3C,MAAM,yBACJ,OAAO,iBAAiB,SAAS,YACjC,OAAO,iBAAiB,SAAS;EAEnC,MAAM,cAAc,OAAO,iBAAiB,WAAW;EAEvD,MAAM,gBAAgB,yBAClB,iBAAiB,OACjB,cACG,cAAc,YAAY,QAAQ,OACnC;AAKN,MAFE,OAAO,kBAAkB,YAAY,OAAO,kBAAkB,SAG9D,OAAMC,iCACJ;GACE,GAAG;GAEH,MAAM;GACP,EACD,eACA,CAAC,aAAa,EACd,cACD;OACI;AACL,yDAA8B,kBAAkB,cAAc;AAE9D,OAAI,iBAAiB,SACnB,WACE,GAAG,KAAK,iBAAiB,6FAAsD,iBAAiB,SAAS,CAAC,IAC1G,EAAE,OAAO,QAAQ,CAClB;;GAGL,CACH;AAED,OAAM,QAAQ,IAAI,QAAQ;AAC1B,OAAO,cAAsB,QAAQ"}
@@ -1,27 +1,27 @@
1
1
  const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
2
  const require_test_listMissingTranslations = require('../test/listMissingTranslations.cjs');
3
- let __intlayer_chokidar = require("@intlayer/chokidar");
4
- let __intlayer_config = require("@intlayer/config");
3
+ let _intlayer_chokidar = require("@intlayer/chokidar");
4
+ let _intlayer_config = require("@intlayer/config");
5
5
  let node_path = require("node:path");
6
- let __intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
7
- let __intlayer_core = require("@intlayer/core");
8
- let __intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
6
+ let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
7
+ let _intlayer_core = require("@intlayer/core");
8
+ let _intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
9
9
 
10
10
  //#region src/fill/listTranslationsTasks.ts
11
11
  const listTranslationsTasks = (localIds, outputLocales, mode, baseLocale, configuration) => {
12
- const appLogger = (0, __intlayer_config.getAppLogger)(configuration);
13
- const mergedDictionariesRecord = (0, __intlayer_dictionaries_entry.getDictionaries)(configuration);
14
- const unmergedDictionariesRecord = (0, __intlayer_unmerged_dictionaries_entry.getUnmergedDictionaries)(configuration);
12
+ const appLogger = (0, _intlayer_config.getAppLogger)(configuration);
13
+ const mergedDictionariesRecord = (0, _intlayer_dictionaries_entry.getDictionaries)(configuration);
14
+ const unmergedDictionariesRecord = (0, _intlayer_unmerged_dictionaries_entry.getUnmergedDictionaries)(configuration);
15
15
  const dictionariesToProcess = Object.values(unmergedDictionariesRecord).flat().filter((dictionary) => localIds.includes(dictionary.localId));
16
16
  const { missingTranslations } = require_test_listMissingTranslations.listMissingTranslationsWithConfig(configuration);
17
17
  const maxKeyLength = Math.max(...dictionariesToProcess.map((dictionary) => dictionary.key.length));
18
18
  const translationTasks = [];
19
19
  for (const targetUnmergedDictionary of dictionariesToProcess) {
20
- const dictionaryPreset = (0, __intlayer_config.colon)([
20
+ const dictionaryPreset = (0, _intlayer_config.colon)([
21
21
  " - ",
22
- (0, __intlayer_config.colorize)("[", __intlayer_config.ANSIColors.GREY_DARK),
23
- (0, __intlayer_config.colorizeKey)(targetUnmergedDictionary.key),
24
- (0, __intlayer_config.colorize)("]", __intlayer_config.ANSIColors.GREY_DARK)
22
+ (0, _intlayer_config.colorize)("[", _intlayer_config.ANSIColors.GREY_DARK),
23
+ (0, _intlayer_config.colorizeKey)(targetUnmergedDictionary.key),
24
+ (0, _intlayer_config.colorize)("]", _intlayer_config.ANSIColors.GREY_DARK)
25
25
  ].join(""), { colSize: maxKeyLength + 6 });
26
26
  const dictionaryKey = targetUnmergedDictionary.key;
27
27
  const dictionaryLocalId = targetUnmergedDictionary.localId;
@@ -37,9 +37,9 @@ const listTranslationsTasks = (localIds, outputLocales, mode, baseLocale, config
37
37
  appLogger(`${dictionaryPreset} Dictionary has no file path. Skipping.`, { level: "warn" });
38
38
  continue;
39
39
  }
40
- const sourceLocaleContent = (0, __intlayer_core.getFilterTranslationsOnlyDictionary)(mainDictionaryToProcess, sourceLocale);
40
+ const sourceLocaleContent = (0, _intlayer_core.getFilterTranslationsOnlyDictionary)(mainDictionaryToProcess, sourceLocale);
41
41
  if (Object.keys(sourceLocaleContent).length === 0) {
42
- appLogger(`${dictionaryPreset} No content found for dictionary in source locale ${(0, __intlayer_chokidar.formatLocale)(sourceLocale)}. Skipping translation for this dictionary.`, { level: "warn" });
42
+ appLogger(`${dictionaryPreset} No content found for dictionary in source locale ${(0, _intlayer_chokidar.formatLocale)(sourceLocale)}. Skipping translation for this dictionary.`, { level: "warn" });
43
43
  continue;
44
44
  }
45
45
  /**
@@ -50,7 +50,7 @@ const listTranslationsTasks = (localIds, outputLocales, mode, baseLocale, config
50
50
  let outputLocalesList = outputLocales;
51
51
  if (mode === "complete") outputLocalesList = missingTranslations.find((missingTranslation) => missingTranslation.key === dictionaryKey)?.locales.filter((locale) => outputLocales.includes(locale)) ?? [];
52
52
  if (outputLocalesList.length === 0) {
53
- appLogger(`${dictionaryPreset} No locales to fill, Skipping ${(0, __intlayer_config.colorizePath)((0, node_path.basename)(targetUnmergedDictionary.filePath))}`, { level: "warn" });
53
+ appLogger(`${dictionaryPreset} No locales to fill, Skipping ${(0, _intlayer_config.colorizePath)((0, node_path.basename)(targetUnmergedDictionary.filePath))}`, { level: "warn" });
54
54
  continue;
55
55
  }
56
56
  translationTasks.push({
@@ -1 +1 @@
1
- {"version":3,"file":"listTranslationsTasks.cjs","names":["listMissingTranslationsWithConfig","translationTasks: TranslationTask[]","ANSIColors","mainDictionaryToProcess: Dictionary","sourceLocale: Locale","outputLocalesList: Locale[]"],"sources":["../../../src/fill/listTranslationsTasks.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport { formatLocale } from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeKey,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config';\nimport { getFilterTranslationsOnlyDictionary } from '@intlayer/core';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type {\n Dictionary,\n IntlayerConfig,\n LocalDictionaryId,\n Locale,\n} from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { listMissingTranslationsWithConfig } from '../test';\n\nexport type TranslationTask = {\n dictionaryKey: string;\n dictionaryLocalId: LocalDictionaryId;\n sourceLocale: Locale;\n targetLocales: Locale[];\n dictionaryPreset: string;\n dictionaryFilePath: string;\n};\n\nexport const listTranslationsTasks = (\n localIds: LocalDictionaryId[],\n outputLocales: Locale[],\n mode: 'complete' | 'review',\n baseLocale: Locale,\n configuration: IntlayerConfig\n): TranslationTask[] => {\n const appLogger = getAppLogger(configuration);\n\n const mergedDictionariesRecord = getDictionaries(configuration);\n const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);\n\n const allFlatDictionaries = Object.values(unmergedDictionariesRecord).flat();\n const dictionariesToProcess = allFlatDictionaries.filter((dictionary) =>\n localIds.includes(dictionary.localId!)\n );\n\n const { missingTranslations } =\n listMissingTranslationsWithConfig(configuration);\n\n const maxKeyLength = Math.max(\n ...dictionariesToProcess.map((dictionary) => dictionary.key.length)\n );\n\n const translationTasks: TranslationTask[] = [];\n\n for (const targetUnmergedDictionary of dictionariesToProcess) {\n const dictionaryPreset = colon(\n [\n ' - ',\n colorize('[', ANSIColors.GREY_DARK),\n colorizeKey(targetUnmergedDictionary.key),\n colorize(']', ANSIColors.GREY_DARK),\n ].join(''),\n { colSize: maxKeyLength + 6 }\n );\n\n const dictionaryKey = targetUnmergedDictionary.key;\n const dictionaryLocalId = targetUnmergedDictionary.localId!;\n const mainDictionaryToProcess: Dictionary =\n mergedDictionariesRecord[dictionaryKey];\n const dictionaryFilled = targetUnmergedDictionary.filled ?? false;\n\n if (dictionaryFilled === true) {\n continue;\n }\n\n const dictionaryFill =\n targetUnmergedDictionary.fill ?? configuration.dictionary?.fill ?? false;\n\n if (dictionaryFill === false) continue;\n\n const sourceLocale: Locale = (targetUnmergedDictionary.locale ??\n baseLocale) as Locale;\n\n if (!mainDictionaryToProcess) {\n appLogger(\n `${dictionaryPreset} Dictionary not found in dictionariesRecord. Skipping.`,\n {\n level: 'warn',\n }\n );\n continue;\n }\n\n if (!targetUnmergedDictionary.filePath) {\n appLogger(`${dictionaryPreset} Dictionary has no file path. Skipping.`, {\n level: 'warn',\n });\n continue;\n }\n\n const sourceLocaleContent = getFilterTranslationsOnlyDictionary(\n mainDictionaryToProcess,\n sourceLocale\n );\n\n if (\n Object.keys(sourceLocaleContent as Record<string, unknown>).length === 0\n ) {\n appLogger(\n `${dictionaryPreset} No content found for dictionary in source locale ${formatLocale(sourceLocale)}. Skipping translation for this dictionary.`,\n {\n level: 'warn',\n }\n );\n continue;\n }\n\n /**\n * In 'complete' mode, filter only the missing locales to translate\n *\n * Skip the dictionary if there are no missing locales to translate\n */\n let outputLocalesList: Locale[] = outputLocales as Locale[];\n\n if (mode === 'complete') {\n outputLocalesList =\n missingTranslations\n .find(\n (missingTranslation) => missingTranslation.key === dictionaryKey\n )\n ?.locales.filter((locale) => outputLocales.includes(locale)) ?? [];\n }\n\n if (outputLocalesList.length === 0) {\n appLogger(\n `${dictionaryPreset} No locales to fill, Skipping ${colorizePath(basename(targetUnmergedDictionary.filePath))}`,\n {\n level: 'warn',\n }\n );\n continue;\n }\n\n translationTasks.push({\n dictionaryKey,\n dictionaryLocalId,\n sourceLocale,\n targetLocales: outputLocalesList,\n dictionaryPreset,\n dictionaryFilePath: targetUnmergedDictionary.filePath,\n });\n }\n\n // Return the list of tasks to execute\n return translationTasks;\n};\n"],"mappings":";;;;;;;;;;AA8BA,MAAa,yBACX,UACA,eACA,MACA,YACA,kBACsB;CACtB,MAAM,gDAAyB,cAAc;CAE7C,MAAM,8EAA2C,cAAc;CAC/D,MAAM,iGAAqD,cAAc;CAGzE,MAAM,wBADsB,OAAO,OAAO,2BAA2B,CAAC,MAAM,CAC1B,QAAQ,eACxD,SAAS,SAAS,WAAW,QAAS,CACvC;CAED,MAAM,EAAE,wBACNA,uEAAkC,cAAc;CAElD,MAAM,eAAe,KAAK,IACxB,GAAG,sBAAsB,KAAK,eAAe,WAAW,IAAI,OAAO,CACpE;CAED,MAAMC,mBAAsC,EAAE;AAE9C,MAAK,MAAM,4BAA4B,uBAAuB;EAC5D,MAAM,gDACJ;GACE;mCACS,KAAKC,6BAAW,UAAU;sCACvB,yBAAyB,IAAI;mCAChC,KAAKA,6BAAW,UAAU;GACpC,CAAC,KAAK,GAAG,EACV,EAAE,SAAS,eAAe,GAAG,CAC9B;EAED,MAAM,gBAAgB,yBAAyB;EAC/C,MAAM,oBAAoB,yBAAyB;EACnD,MAAMC,0BACJ,yBAAyB;AAG3B,OAFyB,yBAAyB,UAAU,WAEnC,KACvB;AAMF,OAFE,yBAAyB,QAAQ,cAAc,YAAY,QAAQ,WAE9C,MAAO;EAE9B,MAAMC,eAAwB,yBAAyB,UACrD;AAEF,MAAI,CAAC,yBAAyB;AAC5B,aACE,GAAG,iBAAiB,yDACpB,EACE,OAAO,QACR,CACF;AACD;;AAGF,MAAI,CAAC,yBAAyB,UAAU;AACtC,aAAU,GAAG,iBAAiB,0CAA0C,EACtE,OAAO,QACR,CAAC;AACF;;EAGF,MAAM,+EACJ,yBACA,aACD;AAED,MACE,OAAO,KAAK,oBAA+C,CAAC,WAAW,GACvE;AACA,aACE,GAAG,iBAAiB,0FAAiE,aAAa,CAAC,8CACnG,EACE,OAAO,QACR,CACF;AACD;;;;;;;EAQF,IAAIC,oBAA8B;AAElC,MAAI,SAAS,WACX,qBACE,oBACG,MACE,uBAAuB,mBAAmB,QAAQ,cACpD,EACC,QAAQ,QAAQ,WAAW,cAAc,SAAS,OAAO,CAAC,IAAI,EAAE;AAGxE,MAAI,kBAAkB,WAAW,GAAG;AAClC,aACE,GAAG,iBAAiB,4FAAsD,yBAAyB,SAAS,CAAC,IAC7G,EACE,OAAO,QACR,CACF;AACD;;AAGF,mBAAiB,KAAK;GACpB;GACA;GACA;GACA,eAAe;GACf;GACA,oBAAoB,yBAAyB;GAC9C,CAAC;;AAIJ,QAAO"}
1
+ {"version":3,"file":"listTranslationsTasks.cjs","names":["listMissingTranslationsWithConfig","translationTasks: TranslationTask[]","ANSIColors","mainDictionaryToProcess: Dictionary","sourceLocale: Locale","outputLocalesList: Locale[]"],"sources":["../../../src/fill/listTranslationsTasks.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport { formatLocale } from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeKey,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config';\nimport { getFilterTranslationsOnlyDictionary } from '@intlayer/core';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type {\n Dictionary,\n IntlayerConfig,\n LocalDictionaryId,\n Locale,\n} from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { listMissingTranslationsWithConfig } from '../test';\n\nexport type TranslationTask = {\n dictionaryKey: string;\n dictionaryLocalId: LocalDictionaryId;\n sourceLocale: Locale;\n targetLocales: Locale[];\n dictionaryPreset: string;\n dictionaryFilePath: string;\n};\n\nexport const listTranslationsTasks = (\n localIds: LocalDictionaryId[],\n outputLocales: Locale[],\n mode: 'complete' | 'review',\n baseLocale: Locale,\n configuration: IntlayerConfig\n): TranslationTask[] => {\n const appLogger = getAppLogger(configuration);\n\n const mergedDictionariesRecord = getDictionaries(configuration);\n const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);\n\n const allFlatDictionaries = Object.values(unmergedDictionariesRecord).flat();\n const dictionariesToProcess = allFlatDictionaries.filter((dictionary) =>\n localIds.includes(dictionary.localId!)\n );\n\n const { missingTranslations } =\n listMissingTranslationsWithConfig(configuration);\n\n const maxKeyLength = Math.max(\n ...dictionariesToProcess.map((dictionary) => dictionary.key.length)\n );\n\n const translationTasks: TranslationTask[] = [];\n\n for (const targetUnmergedDictionary of dictionariesToProcess) {\n const dictionaryPreset = colon(\n [\n ' - ',\n colorize('[', ANSIColors.GREY_DARK),\n colorizeKey(targetUnmergedDictionary.key),\n colorize(']', ANSIColors.GREY_DARK),\n ].join(''),\n { colSize: maxKeyLength + 6 }\n );\n\n const dictionaryKey = targetUnmergedDictionary.key;\n const dictionaryLocalId = targetUnmergedDictionary.localId!;\n const mainDictionaryToProcess: Dictionary =\n mergedDictionariesRecord[dictionaryKey];\n const dictionaryFilled = targetUnmergedDictionary.filled ?? false;\n\n if (dictionaryFilled === true) {\n continue;\n }\n\n const dictionaryFill =\n targetUnmergedDictionary.fill ?? configuration.dictionary?.fill ?? false;\n\n if (dictionaryFill === false) continue;\n\n const sourceLocale: Locale = (targetUnmergedDictionary.locale ??\n baseLocale) as Locale;\n\n if (!mainDictionaryToProcess) {\n appLogger(\n `${dictionaryPreset} Dictionary not found in dictionariesRecord. Skipping.`,\n {\n level: 'warn',\n }\n );\n continue;\n }\n\n if (!targetUnmergedDictionary.filePath) {\n appLogger(`${dictionaryPreset} Dictionary has no file path. Skipping.`, {\n level: 'warn',\n });\n continue;\n }\n\n const sourceLocaleContent = getFilterTranslationsOnlyDictionary(\n mainDictionaryToProcess,\n sourceLocale\n );\n\n if (\n Object.keys(sourceLocaleContent as Record<string, unknown>).length === 0\n ) {\n appLogger(\n `${dictionaryPreset} No content found for dictionary in source locale ${formatLocale(sourceLocale)}. Skipping translation for this dictionary.`,\n {\n level: 'warn',\n }\n );\n continue;\n }\n\n /**\n * In 'complete' mode, filter only the missing locales to translate\n *\n * Skip the dictionary if there are no missing locales to translate\n */\n let outputLocalesList: Locale[] = outputLocales as Locale[];\n\n if (mode === 'complete') {\n outputLocalesList =\n missingTranslations\n .find(\n (missingTranslation) => missingTranslation.key === dictionaryKey\n )\n ?.locales.filter((locale) => outputLocales.includes(locale)) ?? [];\n }\n\n if (outputLocalesList.length === 0) {\n appLogger(\n `${dictionaryPreset} No locales to fill, Skipping ${colorizePath(basename(targetUnmergedDictionary.filePath))}`,\n {\n level: 'warn',\n }\n );\n continue;\n }\n\n translationTasks.push({\n dictionaryKey,\n dictionaryLocalId,\n sourceLocale,\n targetLocales: outputLocalesList,\n dictionaryPreset,\n dictionaryFilePath: targetUnmergedDictionary.filePath,\n });\n }\n\n // Return the list of tasks to execute\n return translationTasks;\n};\n"],"mappings":";;;;;;;;;;AA8BA,MAAa,yBACX,UACA,eACA,MACA,YACA,kBACsB;CACtB,MAAM,+CAAyB,cAAc;CAE7C,MAAM,6EAA2C,cAAc;CAC/D,MAAM,gGAAqD,cAAc;CAGzE,MAAM,wBADsB,OAAO,OAAO,2BAA2B,CAAC,MAAM,CAC1B,QAAQ,eACxD,SAAS,SAAS,WAAW,QAAS,CACvC;CAED,MAAM,EAAE,wBACNA,uEAAkC,cAAc;CAElD,MAAM,eAAe,KAAK,IACxB,GAAG,sBAAsB,KAAK,eAAe,WAAW,IAAI,OAAO,CACpE;CAED,MAAMC,mBAAsC,EAAE;AAE9C,MAAK,MAAM,4BAA4B,uBAAuB;EAC5D,MAAM,+CACJ;GACE;kCACS,KAAKC,4BAAW,UAAU;qCACvB,yBAAyB,IAAI;kCAChC,KAAKA,4BAAW,UAAU;GACpC,CAAC,KAAK,GAAG,EACV,EAAE,SAAS,eAAe,GAAG,CAC9B;EAED,MAAM,gBAAgB,yBAAyB;EAC/C,MAAM,oBAAoB,yBAAyB;EACnD,MAAMC,0BACJ,yBAAyB;AAG3B,OAFyB,yBAAyB,UAAU,WAEnC,KACvB;AAMF,OAFE,yBAAyB,QAAQ,cAAc,YAAY,QAAQ,WAE9C,MAAO;EAE9B,MAAMC,eAAwB,yBAAyB,UACrD;AAEF,MAAI,CAAC,yBAAyB;AAC5B,aACE,GAAG,iBAAiB,yDACpB,EACE,OAAO,QACR,CACF;AACD;;AAGF,MAAI,CAAC,yBAAyB,UAAU;AACtC,aAAU,GAAG,iBAAiB,0CAA0C,EACtE,OAAO,QACR,CAAC;AACF;;EAGF,MAAM,8EACJ,yBACA,aACD;AAED,MACE,OAAO,KAAK,oBAA+C,CAAC,WAAW,GACvE;AACA,aACE,GAAG,iBAAiB,yFAAiE,aAAa,CAAC,8CACnG,EACE,OAAO,QACR,CACF;AACD;;;;;;;EAQF,IAAIC,oBAA8B;AAElC,MAAI,SAAS,WACX,qBACE,oBACG,MACE,uBAAuB,mBAAmB,QAAQ,cACpD,EACC,QAAQ,QAAQ,WAAW,cAAc,SAAS,OAAO,CAAC,IAAI,EAAE;AAGxE,MAAI,kBAAkB,WAAW,GAAG;AAClC,aACE,GAAG,iBAAiB,2FAAsD,yBAAyB,SAAS,CAAC,IAC7G,EACE,OAAO,QACR,CACF;AACD;;AAGF,mBAAiB,KAAK;GACpB;GACA;GACA;GACA,eAAe;GACf;GACA,oBAAoB,yBAAyB;GAC9C,CAAC;;AAIJ,QAAO"}
@@ -2,12 +2,12 @@ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
2
  const require_fill_deepMergeContent = require('./deepMergeContent.cjs');
3
3
  const require_fill_getFilterMissingContentPerLocale = require('./getFilterMissingContentPerLocale.cjs');
4
4
  const require_fill_mergeChunks = require('./mergeChunks.cjs');
5
- let __intlayer_api = require("@intlayer/api");
6
- let __intlayer_chokidar = require("@intlayer/chokidar");
7
- let __intlayer_config = require("@intlayer/config");
5
+ let _intlayer_api = require("@intlayer/api");
6
+ let _intlayer_chokidar = require("@intlayer/chokidar");
7
+ let _intlayer_config = require("@intlayer/config");
8
8
  let node_path = require("node:path");
9
- let __intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
10
- let __intlayer_core = require("@intlayer/core");
9
+ let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
10
+ let _intlayer_core = require("@intlayer/core");
11
11
 
12
12
  //#region src/fill/translateDictionary.ts
13
13
  const hasMissingMetadata = (dictionary) => !dictionary.description || !dictionary.title || !dictionary.tags;
@@ -18,8 +18,8 @@ const RETRY_DELAY = 1e3 * 10;
18
18
  const MAX_FOLLOWING_ERRORS = 10;
19
19
  let followingErrors = 0;
20
20
  const translateDictionary = async (task, configuration, options) => {
21
- const appLogger = (0, __intlayer_config.getAppLogger)(configuration);
22
- const intlayerAPI = (0, __intlayer_api.getIntlayerAPIProxy)(void 0, configuration);
21
+ const appLogger = (0, _intlayer_config.getAppLogger)(configuration);
22
+ const intlayerAPI = (0, _intlayer_api.getIntlayerAPIProxy)(void 0, configuration);
23
23
  const { mode, aiOptions, fillMetadata, aiClient, aiConfig } = {
24
24
  mode: "complete",
25
25
  fillMetadata: true,
@@ -29,8 +29,8 @@ const translateDictionary = async (task, configuration, options) => {
29
29
  followingErrors = 0;
30
30
  options?.onSuccess?.();
31
31
  };
32
- return await (0, __intlayer_config.retryManager)(async () => {
33
- const unmergedDictionariesRecord = (0, __intlayer_unmerged_dictionaries_entry.getUnmergedDictionaries)(configuration);
32
+ return await (0, _intlayer_config.retryManager)(async () => {
33
+ const unmergedDictionariesRecord = (0, _intlayer_unmerged_dictionaries_entry.getUnmergedDictionaries)(configuration);
34
34
  const baseUnmergedDictionary = unmergedDictionariesRecord[task.dictionaryKey].find((dict) => dict.localId === task.dictionaryLocalId);
35
35
  if (!baseUnmergedDictionary) {
36
36
  appLogger(`${task.dictionaryPreset}Dictionary not found in unmergedDictionariesRecord. Skipping.`, { level: "warn" });
@@ -41,8 +41,8 @@ const translateDictionary = async (task, configuration, options) => {
41
41
  }
42
42
  let metadata;
43
43
  if (fillMetadata && (hasMissingMetadata(baseUnmergedDictionary) || mode === "review")) {
44
- const defaultLocaleDictionary = (0, __intlayer_core.getPerLocaleDictionary)(baseUnmergedDictionary, configuration.internationalization.defaultLocale);
45
- appLogger(`${task.dictionaryPreset} Filling missing metadata for ${(0, __intlayer_config.colorizePath)((0, node_path.basename)(baseUnmergedDictionary.filePath))}`, { level: "info" });
44
+ const defaultLocaleDictionary = (0, _intlayer_core.getPerLocaleDictionary)(baseUnmergedDictionary, configuration.internationalization.defaultLocale);
45
+ appLogger(`${task.dictionaryPreset} Filling missing metadata for ${(0, _intlayer_config.colorizePath)((0, node_path.basename)(baseUnmergedDictionary.filePath))}`, { level: "info" });
46
46
  const runAudit = async () => {
47
47
  if (aiClient && aiConfig) return { data: await aiClient.auditDictionaryMetadata({
48
48
  fileContent: JSON.stringify(defaultLocaleDictionary),
@@ -78,37 +78,37 @@ const translateDictionary = async (task, configuration, options) => {
78
78
  };
79
79
  if (mode === "complete") dictionaryToProcess = require_fill_getFilterMissingContentPerLocale.getFilterMissingContentPerLocale(dictionaryToProcess, targetUnmergedDictionary);
80
80
  } else {
81
- if (mode === "complete") dictionaryToProcess = (0, __intlayer_core.getFilterMissingTranslationsDictionary)(dictionaryToProcess, targetLocale);
82
- dictionaryToProcess = (0, __intlayer_core.getPerLocaleDictionary)(dictionaryToProcess, task.sourceLocale);
83
- targetLocaleDictionary = (0, __intlayer_core.getPerLocaleDictionary)(baseUnmergedDictionary, targetLocale);
81
+ if (mode === "complete") dictionaryToProcess = (0, _intlayer_core.getFilterMissingTranslationsDictionary)(dictionaryToProcess, targetLocale);
82
+ dictionaryToProcess = (0, _intlayer_core.getPerLocaleDictionary)(dictionaryToProcess, task.sourceLocale);
83
+ targetLocaleDictionary = (0, _intlayer_core.getPerLocaleDictionary)(baseUnmergedDictionary, targetLocale);
84
84
  }
85
- const localePreset = (0, __intlayer_config.colon)([
86
- (0, __intlayer_config.colorize)("[", __intlayer_config.ANSIColors.GREY_DARK),
87
- (0, __intlayer_chokidar.formatLocale)(targetLocale),
88
- (0, __intlayer_config.colorize)("]", __intlayer_config.ANSIColors.GREY_DARK)
85
+ const localePreset = (0, _intlayer_config.colon)([
86
+ (0, _intlayer_config.colorize)("[", _intlayer_config.ANSIColors.GREY_DARK),
87
+ (0, _intlayer_chokidar.formatLocale)(targetLocale),
88
+ (0, _intlayer_config.colorize)("]", _intlayer_config.ANSIColors.GREY_DARK)
89
89
  ].join(""), { colSize: 18 });
90
90
  const createChunkPreset = (chunkIndex, totalChunks) => {
91
91
  if (totalChunks <= 1) return "";
92
- return (0, __intlayer_config.colon)([
93
- (0, __intlayer_config.colorize)("[", __intlayer_config.ANSIColors.GREY_DARK),
94
- (0, __intlayer_config.colorizeNumber)(chunkIndex + 1),
95
- (0, __intlayer_config.colorize)(`/${totalChunks}`, __intlayer_config.ANSIColors.GREY_DARK),
96
- (0, __intlayer_config.colorize)("]", __intlayer_config.ANSIColors.GREY_DARK)
92
+ return (0, _intlayer_config.colon)([
93
+ (0, _intlayer_config.colorize)("[", _intlayer_config.ANSIColors.GREY_DARK),
94
+ (0, _intlayer_config.colorizeNumber)(chunkIndex + 1),
95
+ (0, _intlayer_config.colorize)(`/${totalChunks}`, _intlayer_config.ANSIColors.GREY_DARK),
96
+ (0, _intlayer_config.colorize)("]", _intlayer_config.ANSIColors.GREY_DARK)
97
97
  ].join(""), { colSize: 5 });
98
98
  };
99
- appLogger(`${task.dictionaryPreset}${localePreset} Preparing ${(0, __intlayer_config.colorizePath)((0, node_path.basename)(targetLocaleDictionary.filePath))}`, { level: "info" });
99
+ appLogger(`${task.dictionaryPreset}${localePreset} Preparing ${(0, _intlayer_config.colorizePath)((0, node_path.basename)(targetLocaleDictionary.filePath))}`, { level: "info" });
100
100
  const isContentStructured = typeof dictionaryToProcess.content === "object" && dictionaryToProcess.content !== null || Array.isArray(dictionaryToProcess.content);
101
- const chunkedJsonContent = (0, __intlayer_chokidar.chunkJSON)(isContentStructured ? dictionaryToProcess.content : { __INTLAYER_ROOT_PRIMITIVE_CONTENT__: dictionaryToProcess.content }, CHUNK_SIZE);
101
+ const chunkedJsonContent = (0, _intlayer_chokidar.chunkJSON)(isContentStructured ? dictionaryToProcess.content : { __INTLAYER_ROOT_PRIMITIVE_CONTENT__: dictionaryToProcess.content }, CHUNK_SIZE);
102
102
  const nbOfChunks = chunkedJsonContent.length;
103
- if (nbOfChunks > 1) appLogger(`${task.dictionaryPreset}${localePreset} Split into ${(0, __intlayer_config.colorizeNumber)(nbOfChunks)} chunks for translation`, { level: "info" });
103
+ if (nbOfChunks > 1) appLogger(`${task.dictionaryPreset}${localePreset} Split into ${(0, _intlayer_config.colorizeNumber)(nbOfChunks)} chunks for translation`, { level: "info" });
104
104
  const chunkResult = [];
105
105
  const chunkPromises = chunkedJsonContent.map((chunk) => {
106
106
  const chunkPreset = createChunkPreset(chunk.index, chunk.total);
107
107
  if (nbOfChunks > 1) appLogger(`${task.dictionaryPreset}${localePreset}${chunkPreset} Translating chunk`, { level: "info" });
108
- const chunkContent = (0, __intlayer_chokidar.reconstructFromSingleChunk)(chunk);
109
- const presetOutputContent = (0, __intlayer_chokidar.reduceObjectFormat)(isContentStructured ? targetLocaleDictionary.content : { __INTLAYER_ROOT_PRIMITIVE_CONTENT__: targetLocaleDictionary.content }, chunkContent);
108
+ const chunkContent = (0, _intlayer_chokidar.reconstructFromSingleChunk)(chunk);
109
+ const presetOutputContent = (0, _intlayer_chokidar.reduceObjectFormat)(isContentStructured ? targetLocaleDictionary.content : { __INTLAYER_ROOT_PRIMITIVE_CONTENT__: targetLocaleDictionary.content }, chunkContent);
110
110
  const executeTranslation = async () => {
111
- return await (0, __intlayer_config.retryManager)(async () => {
111
+ return await (0, _intlayer_config.retryManager)(async () => {
112
112
  let translationResult;
113
113
  if (aiClient && aiConfig) translationResult = await aiClient.translateJSON({
114
114
  entryFileContent: chunkContent,
@@ -129,7 +129,7 @@ const translateDictionary = async (task, configuration, options) => {
129
129
  aiOptions
130
130
  }).then((result) => result.data);
131
131
  if (!translationResult?.fileContent) throw new Error("No content result");
132
- const { isIdentic } = (0, __intlayer_chokidar.verifyIdenticObjectFormat)(translationResult.fileContent, chunkContent);
132
+ const { isIdentic } = (0, _intlayer_chokidar.verifyIdenticObjectFormat)(translationResult.fileContent, chunkContent);
133
133
  if (!isIdentic) throw new Error("Translation result does not match expected format");
134
134
  notifySuccess();
135
135
  return translationResult.fileContent;
@@ -138,7 +138,7 @@ const translateDictionary = async (task, configuration, options) => {
138
138
  delay: RETRY_DELAY,
139
139
  onError: ({ error, attempt, maxRetry }) => {
140
140
  const chunkPreset$1 = createChunkPreset(chunk.index, chunk.total);
141
- appLogger(`${task.dictionaryPreset}${localePreset}${chunkPreset$1} ${(0, __intlayer_config.colorize)("Error filling:", __intlayer_config.ANSIColors.RED)} ${(0, __intlayer_config.colorize)(typeof error === "string" ? error : JSON.stringify(error), __intlayer_config.ANSIColors.GREY_DARK)} - Attempt ${(0, __intlayer_config.colorizeNumber)(attempt + 1)} of ${(0, __intlayer_config.colorizeNumber)(maxRetry)}`, { level: "error" });
141
+ appLogger(`${task.dictionaryPreset}${localePreset}${chunkPreset$1} ${(0, _intlayer_config.colorize)("Error filling:", _intlayer_config.ANSIColors.RED)} ${(0, _intlayer_config.colorize)(typeof error === "string" ? error : JSON.stringify(error), _intlayer_config.ANSIColors.GREY_DARK)} - Attempt ${(0, _intlayer_config.colorizeNumber)(attempt + 1)} of ${(0, _intlayer_config.colorizeNumber)(maxRetry)}`, { level: "error" });
142
142
  followingErrors += 1;
143
143
  if (followingErrors >= MAX_FOLLOWING_ERRORS) {
144
144
  appLogger(`There is something wrong.`, { level: "error" });
@@ -166,7 +166,7 @@ const translateDictionary = async (task, configuration, options) => {
166
166
  }));
167
167
  const translatedContent = Object.fromEntries(translatedContentResults);
168
168
  let dictionaryOutput = {
169
- ...(0, __intlayer_core.getMultilingualDictionary)(baseUnmergedDictionary.locale ? {
169
+ ...(0, _intlayer_core.getMultilingualDictionary)(baseUnmergedDictionary.locale ? {
170
170
  ...baseUnmergedDictionary,
171
171
  key: baseUnmergedDictionary.key,
172
172
  content: {}
@@ -174,8 +174,8 @@ const translateDictionary = async (task, configuration, options) => {
174
174
  locale: void 0,
175
175
  ...metadata
176
176
  };
177
- for (const targetLocale of task.targetLocales) if (translatedContent[targetLocale]) dictionaryOutput = (0, __intlayer_core.insertContentInDictionary)(dictionaryOutput, translatedContent[targetLocale], targetLocale);
178
- appLogger(`${task.dictionaryPreset} ${(0, __intlayer_config.colorize)("Translation completed successfully", __intlayer_config.ANSIColors.GREEN)} for ${(0, __intlayer_config.colorizePath)((0, node_path.basename)(dictionaryOutput.filePath))}`, { level: "info" });
177
+ for (const targetLocale of task.targetLocales) if (translatedContent[targetLocale]) dictionaryOutput = (0, _intlayer_core.insertContentInDictionary)(dictionaryOutput, translatedContent[targetLocale], targetLocale);
178
+ appLogger(`${task.dictionaryPreset} ${(0, _intlayer_config.colorize)("Translation completed successfully", _intlayer_config.ANSIColors.GREEN)} for ${(0, _intlayer_config.colorizePath)((0, node_path.basename)(dictionaryOutput.filePath))}`, { level: "info" });
179
179
  if (baseUnmergedDictionary.locale && (baseUnmergedDictionary.fill === true || baseUnmergedDictionary.fill === void 0) && baseUnmergedDictionary.location === "local") {
180
180
  const dictionaryFilePath = baseUnmergedDictionary.filePath.split(".").slice(0, -1);
181
181
  const contentIndex = dictionaryFilePath[dictionaryFilePath.length - 1];
@@ -195,8 +195,8 @@ const translateDictionary = async (task, configuration, options) => {
195
195
  }, {
196
196
  maxRetry: GROUP_MAX_RETRY,
197
197
  delay: RETRY_DELAY,
198
- onError: ({ error, attempt, maxRetry }) => appLogger(`${task.dictionaryPreset} ${(0, __intlayer_config.colorize)("Error fill command:", __intlayer_config.ANSIColors.RED)} ${(0, __intlayer_config.colorize)(typeof error === "string" ? error : JSON.stringify(error), __intlayer_config.ANSIColors.GREY_DARK)} - Attempt ${(0, __intlayer_config.colorizeNumber)(attempt + 1)} of ${(0, __intlayer_config.colorizeNumber)(maxRetry)}`, { level: "error" }),
199
- onMaxTryReached: ({ error }) => appLogger(`${task.dictionaryPreset} ${(0, __intlayer_config.colorize)("Maximum number of retries reached:", __intlayer_config.ANSIColors.RED)} ${(0, __intlayer_config.colorize)(typeof error === "string" ? error : JSON.stringify(error), __intlayer_config.ANSIColors.GREY_DARK)}`, { level: "error" })
198
+ onError: ({ error, attempt, maxRetry }) => appLogger(`${task.dictionaryPreset} ${(0, _intlayer_config.colorize)("Error fill command:", _intlayer_config.ANSIColors.RED)} ${(0, _intlayer_config.colorize)(typeof error === "string" ? error : JSON.stringify(error), _intlayer_config.ANSIColors.GREY_DARK)} - Attempt ${(0, _intlayer_config.colorizeNumber)(attempt + 1)} of ${(0, _intlayer_config.colorizeNumber)(maxRetry)}`, { level: "error" }),
199
+ onMaxTryReached: ({ error }) => appLogger(`${task.dictionaryPreset} ${(0, _intlayer_config.colorize)("Maximum number of retries reached:", _intlayer_config.ANSIColors.RED)} ${(0, _intlayer_config.colorize)(typeof error === "string" ? error : JSON.stringify(error), _intlayer_config.ANSIColors.GREY_DARK)}`, { level: "error" })
200
200
  })();
201
201
  };
202
202
 
@@ -1 +1 @@
1
- {"version":3,"file":"translateDictionary.cjs","names":["baseUnmergedDictionary: Dictionary | undefined","metadata:\n | Pick<Dictionary, 'description' | 'title' | 'tags'>\n | undefined","targetLocaleDictionary: Dictionary","getFilterMissingContentPerLocale","ANSIColors","chunkedJsonContent: JsonChunk[]","chunkResult: JsonChunk[]","translationResult: any","chunkPreset","mergeChunks","deepMergeContent","translatedContent: Partial<Record<Locale, Dictionary['content']>>","dictionaryOutput: Dictionary"],"sources":["../../../src/fill/translateDictionary.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport type { AIConfig } from '@intlayer/ai';\nimport { type AIOptions, getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n chunkJSON,\n formatLocale,\n type JsonChunk,\n reconstructFromSingleChunk,\n reduceObjectFormat,\n verifyIdenticObjectFormat,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeNumber,\n colorizePath,\n getAppLogger,\n retryManager,\n} from '@intlayer/config';\nimport {\n getFilterMissingTranslationsDictionary,\n getMultilingualDictionary,\n getPerLocaleDictionary,\n insertContentInDictionary,\n} from '@intlayer/core';\nimport type { Dictionary, IntlayerConfig, Locale } from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport type { AIClient } from '../utils/setupAI';\nimport { deepMergeContent } from './deepMergeContent';\nimport { getFilterMissingContentPerLocale } from './getFilterMissingContentPerLocale';\nimport type { TranslationTask } from './listTranslationsTasks';\nimport { mergeChunks } from './mergeChunks';\n\ntype TranslateDictionaryResult = TranslationTask & {\n dictionaryOutput: Dictionary | null;\n};\n\ntype TranslateDictionaryOptions = {\n mode: 'complete' | 'review';\n aiOptions?: AIOptions;\n fillMetadata?: boolean;\n onHandle?: ReturnType<typeof import('@intlayer/chokidar').getGlobalLimiter>;\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n getAbortError?: () => Error | null;\n aiClient?: AIClient;\n aiConfig?: AIConfig;\n};\n\nconst hasMissingMetadata = (dictionary: Dictionary) =>\n !dictionary.description || !dictionary.title || !dictionary.tags;\n\nconst CHUNK_SIZE = 7000; // GPT-5 Mini safe input size\nconst GROUP_MAX_RETRY = 2;\nconst MAX_RETRY = 3;\nconst RETRY_DELAY = 1000 * 10; // 10 seconds\n\nconst MAX_FOLLOWING_ERRORS = 10; // 10 errors in a row, hard exit the process\nlet followingErrors = 0;\n\nexport const translateDictionary = async (\n task: TranslationTask,\n configuration: IntlayerConfig,\n options?: TranslateDictionaryOptions\n): Promise<TranslateDictionaryResult> => {\n const appLogger = getAppLogger(configuration);\n const intlayerAPI = getIntlayerAPIProxy(undefined, configuration);\n\n const { mode, aiOptions, fillMetadata, aiClient, aiConfig } = {\n mode: 'complete',\n fillMetadata: true,\n ...options,\n } as const;\n\n const notifySuccess = () => {\n followingErrors = 0;\n options?.onSuccess?.();\n };\n\n const result = await retryManager(\n async () => {\n const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);\n\n const baseUnmergedDictionary: Dictionary | undefined =\n unmergedDictionariesRecord[task.dictionaryKey].find(\n (dict) => dict.localId === task.dictionaryLocalId\n );\n\n if (!baseUnmergedDictionary) {\n appLogger(\n `${task.dictionaryPreset}Dictionary not found in unmergedDictionariesRecord. Skipping.`,\n {\n level: 'warn',\n }\n );\n return { ...task, dictionaryOutput: null };\n }\n\n let metadata:\n | Pick<Dictionary, 'description' | 'title' | 'tags'>\n | undefined;\n\n if (\n fillMetadata &&\n (hasMissingMetadata(baseUnmergedDictionary) || mode === 'review')\n ) {\n const defaultLocaleDictionary = getPerLocaleDictionary(\n baseUnmergedDictionary,\n configuration.internationalization.defaultLocale\n );\n\n appLogger(\n `${task.dictionaryPreset} Filling missing metadata for ${colorizePath(basename(baseUnmergedDictionary.filePath!))}`,\n {\n level: 'info',\n }\n );\n\n const runAudit = async () => {\n if (aiClient && aiConfig) {\n const result = await aiClient.auditDictionaryMetadata({\n fileContent: JSON.stringify(defaultLocaleDictionary),\n aiConfig,\n });\n\n return {\n data: result,\n };\n }\n\n return await intlayerAPI.ai.auditContentDeclarationMetadata({\n fileContent: JSON.stringify(defaultLocaleDictionary),\n aiOptions,\n });\n };\n\n const metadataResult = options?.onHandle\n ? await options.onHandle(runAudit)\n : await runAudit();\n\n metadata = metadataResult.data?.fileContent;\n }\n\n const translatedContentResults = await Promise.all(\n task.targetLocales.map(async (targetLocale) => {\n /**\n * In complete mode, for large dictionaries, we want to filter all content that is already translated\n *\n * targetLocale: fr\n *\n * { test1: t({ ar: 'Hello', en: 'Hello', fr: 'Bonjour' } }) -> {}\n * { test2: t({ ar: 'Hello', en: 'Hello' }) } -> { test2: t({ ar: 'Hello', en: 'Hello' }) }\n *\n */\n // Reset to base dictionary for each locale to ensure we filter from the original\n let dictionaryToProcess = structuredClone(baseUnmergedDictionary);\n\n let targetLocaleDictionary: Dictionary;\n\n if (typeof baseUnmergedDictionary.locale === 'string') {\n // For per-locale files, the content is already in simple JSON format (not translation nodes)\n // The base dictionary is already the source locale content\n\n // Load the existing target locale dictionary\n const targetLocaleFilePath =\n baseUnmergedDictionary.filePath?.replace(\n new RegExp(`/${task.sourceLocale}/`, 'g'),\n `/${targetLocale}/`\n );\n\n // Find the target locale dictionary in unmerged dictionaries\n const targetUnmergedDictionary = targetLocaleFilePath\n ? unmergedDictionariesRecord[task.dictionaryKey]?.find(\n (dict) =>\n dict.filePath === targetLocaleFilePath &&\n dict.locale === targetLocale\n )\n : undefined;\n\n targetLocaleDictionary = targetUnmergedDictionary ?? {\n key: baseUnmergedDictionary.key,\n content: {},\n filePath: targetLocaleFilePath,\n locale: targetLocale,\n };\n\n // In complete mode, filter out already translated content\n if (mode === 'complete') {\n dictionaryToProcess = getFilterMissingContentPerLocale(\n dictionaryToProcess,\n targetUnmergedDictionary\n );\n }\n } else {\n // For multilingual dictionaries\n if (mode === 'complete') {\n // Remove all nodes that don't have any content to translate\n dictionaryToProcess = getFilterMissingTranslationsDictionary(\n dictionaryToProcess,\n targetLocale\n );\n }\n\n dictionaryToProcess = getPerLocaleDictionary(\n dictionaryToProcess,\n task.sourceLocale\n );\n\n targetLocaleDictionary = getPerLocaleDictionary(\n baseUnmergedDictionary,\n targetLocale\n );\n }\n\n const localePreset = colon(\n [\n colorize('[', ANSIColors.GREY_DARK),\n formatLocale(targetLocale),\n colorize(']', ANSIColors.GREY_DARK),\n ].join(''),\n { colSize: 18 }\n );\n\n const createChunkPreset = (\n chunkIndex: number,\n totalChunks: number\n ) => {\n if (totalChunks <= 1) return '';\n return colon(\n [\n colorize('[', ANSIColors.GREY_DARK),\n colorizeNumber(chunkIndex + 1),\n colorize(`/${totalChunks}`, ANSIColors.GREY_DARK),\n colorize(']', ANSIColors.GREY_DARK),\n ].join(''),\n { colSize: 5 }\n );\n };\n\n appLogger(\n `${task.dictionaryPreset}${localePreset} Preparing ${colorizePath(basename(targetLocaleDictionary.filePath!))}`,\n {\n level: 'info',\n }\n );\n\n const isContentStructured =\n (typeof dictionaryToProcess.content === 'object' &&\n dictionaryToProcess.content !== null) ||\n Array.isArray(dictionaryToProcess.content);\n\n const contentToProcess = isContentStructured\n ? dictionaryToProcess.content\n : {\n __INTLAYER_ROOT_PRIMITIVE_CONTENT__:\n dictionaryToProcess.content,\n };\n\n const chunkedJsonContent: JsonChunk[] = chunkJSON(\n contentToProcess as unknown as Record<string, any>,\n CHUNK_SIZE\n );\n\n const nbOfChunks = chunkedJsonContent.length;\n\n if (nbOfChunks > 1) {\n appLogger(\n `${task.dictionaryPreset}${localePreset} Split into ${colorizeNumber(nbOfChunks)} chunks for translation`,\n {\n level: 'info',\n }\n );\n }\n\n const chunkResult: JsonChunk[] = [];\n\n // Process chunks in parallel (globally throttled) to allow concurrent translation\n const chunkPromises = chunkedJsonContent.map((chunk) => {\n const chunkPreset = createChunkPreset(chunk.index, chunk.total);\n\n if (nbOfChunks > 1) {\n appLogger(\n `${task.dictionaryPreset}${localePreset}${chunkPreset} Translating chunk`,\n {\n level: 'info',\n }\n );\n }\n\n // Reconstruct partial JSON content from this chunk's patches\n const chunkContent = reconstructFromSingleChunk(chunk);\n const presetOutputContent = reduceObjectFormat(\n isContentStructured\n ? targetLocaleDictionary.content\n : {\n __INTLAYER_ROOT_PRIMITIVE_CONTENT__:\n targetLocaleDictionary.content,\n },\n chunkContent\n ) as unknown as JSON;\n\n const executeTranslation = async () => {\n return await retryManager(\n async () => {\n let translationResult: any;\n\n if (aiClient && aiConfig) {\n translationResult = await aiClient.translateJSON({\n entryFileContent: chunkContent as unknown as JSON,\n presetOutputContent,\n dictionaryDescription:\n dictionaryToProcess.description ??\n metadata?.description ??\n '',\n entryLocale: task.sourceLocale,\n outputLocale: targetLocale,\n mode,\n aiConfig,\n });\n } else {\n translationResult = await intlayerAPI.ai\n .translateJSON({\n entryFileContent: chunkContent as unknown as JSON,\n presetOutputContent,\n dictionaryDescription:\n dictionaryToProcess.description ??\n metadata?.description ??\n '',\n entryLocale: task.sourceLocale,\n outputLocale: targetLocale,\n mode,\n aiOptions,\n })\n .then((result) => result.data);\n }\n\n if (!translationResult?.fileContent) {\n throw new Error('No content result');\n }\n\n const { isIdentic } = verifyIdenticObjectFormat(\n translationResult.fileContent,\n chunkContent\n );\n if (!isIdentic) {\n throw new Error(\n 'Translation result does not match expected format'\n );\n }\n\n notifySuccess();\n return translationResult.fileContent;\n },\n {\n maxRetry: MAX_RETRY,\n delay: RETRY_DELAY,\n onError: ({ error, attempt, maxRetry }) => {\n const chunkPreset = createChunkPreset(\n chunk.index,\n chunk.total\n );\n appLogger(\n `${task.dictionaryPreset}${localePreset}${chunkPreset} ${colorize('Error filling:', ANSIColors.RED)} ${colorize(typeof error === 'string' ? error : JSON.stringify(error), ANSIColors.GREY_DARK)} - Attempt ${colorizeNumber(attempt + 1)} of ${colorizeNumber(maxRetry)}`,\n {\n level: 'error',\n }\n );\n\n followingErrors += 1;\n\n if (followingErrors >= MAX_FOLLOWING_ERRORS) {\n appLogger(`There is something wrong.`, {\n level: 'error',\n });\n process.exit(1); // 1 for error\n }\n },\n }\n )();\n };\n\n const wrapped = options?.onHandle\n ? options.onHandle(executeTranslation) // queued in global limiter\n : executeTranslation(); // no global limiter\n\n return wrapped.then((result) => ({ chunk, result }));\n });\n\n // Wait for all chunks for this locale in parallel (still capped by global limiter)\n const chunkResults = await Promise.all(chunkPromises);\n\n // Maintain order\n chunkResults\n .sort((chunkA, chunkB) => chunkA.chunk.index - chunkB.chunk.index)\n .forEach(({ result }) => {\n chunkResult.push(result);\n });\n\n // Merge partial JSON objects produced from each chunk into a single object\n const mergedContent = mergeChunks(chunkResult);\n\n const merged = {\n ...dictionaryToProcess,\n content: mergedContent,\n };\n\n // For per-locale files, merge the newly translated content with existing target content\n let finalContent = merged.content;\n\n if (!isContentStructured) {\n finalContent = (finalContent as any)\n ?.__INTLAYER_ROOT_PRIMITIVE_CONTENT__;\n }\n\n if (typeof baseUnmergedDictionary.locale === 'string') {\n // Deep merge: existing content + newly translated content\n finalContent = deepMergeContent(\n targetLocaleDictionary.content ?? {},\n finalContent\n );\n }\n\n return [targetLocale, finalContent] as const;\n })\n );\n\n const translatedContent: Partial<Record<Locale, Dictionary['content']>> =\n Object.fromEntries(translatedContentResults);\n\n const baseDictionary = baseUnmergedDictionary.locale\n ? {\n ...baseUnmergedDictionary,\n key: baseUnmergedDictionary.key!,\n content: {},\n }\n : baseUnmergedDictionary;\n\n let dictionaryOutput: Dictionary = {\n ...getMultilingualDictionary(baseDictionary),\n locale: undefined, // Ensure the dictionary is multilingual\n ...metadata,\n };\n\n for (const targetLocale of task.targetLocales) {\n if (translatedContent[targetLocale]) {\n dictionaryOutput = insertContentInDictionary(\n dictionaryOutput,\n translatedContent[targetLocale],\n targetLocale\n );\n }\n }\n\n appLogger(\n `${task.dictionaryPreset} ${colorize('Translation completed successfully', ANSIColors.GREEN)} for ${colorizePath(basename(dictionaryOutput.filePath!))}`,\n {\n level: 'info',\n }\n );\n\n if (\n baseUnmergedDictionary.locale &&\n (baseUnmergedDictionary.fill === true ||\n baseUnmergedDictionary.fill === undefined) &&\n baseUnmergedDictionary.location === 'local'\n ) {\n const dictionaryFilePath = baseUnmergedDictionary\n .filePath!.split('.')\n .slice(0, -1);\n\n const contentIndex = dictionaryFilePath[dictionaryFilePath.length - 1];\n\n return JSON.parse(\n JSON.stringify({\n ...task,\n dictionaryOutput: {\n ...dictionaryOutput,\n fill: undefined,\n filled: true,\n },\n }).replaceAll(\n new RegExp(`\\\\.${contentIndex}\\\\.[a-zA-Z0-9]+`, 'g'),\n `.filled.${contentIndex}.json`\n )\n );\n }\n\n return {\n ...task,\n dictionaryOutput,\n };\n },\n {\n maxRetry: GROUP_MAX_RETRY,\n delay: RETRY_DELAY,\n onError: ({ error, attempt, maxRetry }) =>\n appLogger(\n `${task.dictionaryPreset} ${colorize('Error fill command:', ANSIColors.RED)} ${colorize(typeof error === 'string' ? error : JSON.stringify(error), ANSIColors.GREY_DARK)} - Attempt ${colorizeNumber(attempt + 1)} of ${colorizeNumber(maxRetry)}`,\n {\n level: 'error',\n }\n ),\n onMaxTryReached: ({ error }) =>\n appLogger(\n `${task.dictionaryPreset} ${colorize('Maximum number of retries reached:', ANSIColors.RED)} ${colorize(typeof error === 'string' ? error : JSON.stringify(error), ANSIColors.GREY_DARK)}`,\n {\n level: 'error',\n }\n ),\n }\n )();\n\n return result as TranslateDictionaryResult;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"translateDictionary.cjs","names":["baseUnmergedDictionary: Dictionary | undefined","metadata:\n | Pick<Dictionary, 'description' | 'title' | 'tags'>\n | undefined","targetLocaleDictionary: Dictionary","getFilterMissingContentPerLocale","ANSIColors","chunkedJsonContent: JsonChunk[]","chunkResult: JsonChunk[]","translationResult: any","chunkPreset","mergeChunks","deepMergeContent","translatedContent: Partial<Record<Locale, Dictionary['content']>>","dictionaryOutput: Dictionary"],"sources":["../../../src/fill/translateDictionary.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport type { AIConfig } from '@intlayer/ai';\nimport { type AIOptions, getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n chunkJSON,\n formatLocale,\n type JsonChunk,\n reconstructFromSingleChunk,\n reduceObjectFormat,\n verifyIdenticObjectFormat,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeNumber,\n colorizePath,\n getAppLogger,\n retryManager,\n} from '@intlayer/config';\nimport {\n getFilterMissingTranslationsDictionary,\n getMultilingualDictionary,\n getPerLocaleDictionary,\n insertContentInDictionary,\n} from '@intlayer/core';\nimport type { Dictionary, IntlayerConfig, Locale } from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport type { AIClient } from '../utils/setupAI';\nimport { deepMergeContent } from './deepMergeContent';\nimport { getFilterMissingContentPerLocale } from './getFilterMissingContentPerLocale';\nimport type { TranslationTask } from './listTranslationsTasks';\nimport { mergeChunks } from './mergeChunks';\n\ntype TranslateDictionaryResult = TranslationTask & {\n dictionaryOutput: Dictionary | null;\n};\n\ntype TranslateDictionaryOptions = {\n mode: 'complete' | 'review';\n aiOptions?: AIOptions;\n fillMetadata?: boolean;\n onHandle?: ReturnType<typeof import('@intlayer/chokidar').getGlobalLimiter>;\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n getAbortError?: () => Error | null;\n aiClient?: AIClient;\n aiConfig?: AIConfig;\n};\n\nconst hasMissingMetadata = (dictionary: Dictionary) =>\n !dictionary.description || !dictionary.title || !dictionary.tags;\n\nconst CHUNK_SIZE = 7000; // GPT-5 Mini safe input size\nconst GROUP_MAX_RETRY = 2;\nconst MAX_RETRY = 3;\nconst RETRY_DELAY = 1000 * 10; // 10 seconds\n\nconst MAX_FOLLOWING_ERRORS = 10; // 10 errors in a row, hard exit the process\nlet followingErrors = 0;\n\nexport const translateDictionary = async (\n task: TranslationTask,\n configuration: IntlayerConfig,\n options?: TranslateDictionaryOptions\n): Promise<TranslateDictionaryResult> => {\n const appLogger = getAppLogger(configuration);\n const intlayerAPI = getIntlayerAPIProxy(undefined, configuration);\n\n const { mode, aiOptions, fillMetadata, aiClient, aiConfig } = {\n mode: 'complete',\n fillMetadata: true,\n ...options,\n } as const;\n\n const notifySuccess = () => {\n followingErrors = 0;\n options?.onSuccess?.();\n };\n\n const result = await retryManager(\n async () => {\n const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);\n\n const baseUnmergedDictionary: Dictionary | undefined =\n unmergedDictionariesRecord[task.dictionaryKey].find(\n (dict) => dict.localId === task.dictionaryLocalId\n );\n\n if (!baseUnmergedDictionary) {\n appLogger(\n `${task.dictionaryPreset}Dictionary not found in unmergedDictionariesRecord. Skipping.`,\n {\n level: 'warn',\n }\n );\n return { ...task, dictionaryOutput: null };\n }\n\n let metadata:\n | Pick<Dictionary, 'description' | 'title' | 'tags'>\n | undefined;\n\n if (\n fillMetadata &&\n (hasMissingMetadata(baseUnmergedDictionary) || mode === 'review')\n ) {\n const defaultLocaleDictionary = getPerLocaleDictionary(\n baseUnmergedDictionary,\n configuration.internationalization.defaultLocale\n );\n\n appLogger(\n `${task.dictionaryPreset} Filling missing metadata for ${colorizePath(basename(baseUnmergedDictionary.filePath!))}`,\n {\n level: 'info',\n }\n );\n\n const runAudit = async () => {\n if (aiClient && aiConfig) {\n const result = await aiClient.auditDictionaryMetadata({\n fileContent: JSON.stringify(defaultLocaleDictionary),\n aiConfig,\n });\n\n return {\n data: result,\n };\n }\n\n return await intlayerAPI.ai.auditContentDeclarationMetadata({\n fileContent: JSON.stringify(defaultLocaleDictionary),\n aiOptions,\n });\n };\n\n const metadataResult = options?.onHandle\n ? await options.onHandle(runAudit)\n : await runAudit();\n\n metadata = metadataResult.data?.fileContent;\n }\n\n const translatedContentResults = await Promise.all(\n task.targetLocales.map(async (targetLocale) => {\n /**\n * In complete mode, for large dictionaries, we want to filter all content that is already translated\n *\n * targetLocale: fr\n *\n * { test1: t({ ar: 'Hello', en: 'Hello', fr: 'Bonjour' } }) -> {}\n * { test2: t({ ar: 'Hello', en: 'Hello' }) } -> { test2: t({ ar: 'Hello', en: 'Hello' }) }\n *\n */\n // Reset to base dictionary for each locale to ensure we filter from the original\n let dictionaryToProcess = structuredClone(baseUnmergedDictionary);\n\n let targetLocaleDictionary: Dictionary;\n\n if (typeof baseUnmergedDictionary.locale === 'string') {\n // For per-locale files, the content is already in simple JSON format (not translation nodes)\n // The base dictionary is already the source locale content\n\n // Load the existing target locale dictionary\n const targetLocaleFilePath =\n baseUnmergedDictionary.filePath?.replace(\n new RegExp(`/${task.sourceLocale}/`, 'g'),\n `/${targetLocale}/`\n );\n\n // Find the target locale dictionary in unmerged dictionaries\n const targetUnmergedDictionary = targetLocaleFilePath\n ? unmergedDictionariesRecord[task.dictionaryKey]?.find(\n (dict) =>\n dict.filePath === targetLocaleFilePath &&\n dict.locale === targetLocale\n )\n : undefined;\n\n targetLocaleDictionary = targetUnmergedDictionary ?? {\n key: baseUnmergedDictionary.key,\n content: {},\n filePath: targetLocaleFilePath,\n locale: targetLocale,\n };\n\n // In complete mode, filter out already translated content\n if (mode === 'complete') {\n dictionaryToProcess = getFilterMissingContentPerLocale(\n dictionaryToProcess,\n targetUnmergedDictionary\n );\n }\n } else {\n // For multilingual dictionaries\n if (mode === 'complete') {\n // Remove all nodes that don't have any content to translate\n dictionaryToProcess = getFilterMissingTranslationsDictionary(\n dictionaryToProcess,\n targetLocale\n );\n }\n\n dictionaryToProcess = getPerLocaleDictionary(\n dictionaryToProcess,\n task.sourceLocale\n );\n\n targetLocaleDictionary = getPerLocaleDictionary(\n baseUnmergedDictionary,\n targetLocale\n );\n }\n\n const localePreset = colon(\n [\n colorize('[', ANSIColors.GREY_DARK),\n formatLocale(targetLocale),\n colorize(']', ANSIColors.GREY_DARK),\n ].join(''),\n { colSize: 18 }\n );\n\n const createChunkPreset = (\n chunkIndex: number,\n totalChunks: number\n ) => {\n if (totalChunks <= 1) return '';\n return colon(\n [\n colorize('[', ANSIColors.GREY_DARK),\n colorizeNumber(chunkIndex + 1),\n colorize(`/${totalChunks}`, ANSIColors.GREY_DARK),\n colorize(']', ANSIColors.GREY_DARK),\n ].join(''),\n { colSize: 5 }\n );\n };\n\n appLogger(\n `${task.dictionaryPreset}${localePreset} Preparing ${colorizePath(basename(targetLocaleDictionary.filePath!))}`,\n {\n level: 'info',\n }\n );\n\n const isContentStructured =\n (typeof dictionaryToProcess.content === 'object' &&\n dictionaryToProcess.content !== null) ||\n Array.isArray(dictionaryToProcess.content);\n\n const contentToProcess = isContentStructured\n ? dictionaryToProcess.content\n : {\n __INTLAYER_ROOT_PRIMITIVE_CONTENT__:\n dictionaryToProcess.content,\n };\n\n const chunkedJsonContent: JsonChunk[] = chunkJSON(\n contentToProcess as unknown as Record<string, any>,\n CHUNK_SIZE\n );\n\n const nbOfChunks = chunkedJsonContent.length;\n\n if (nbOfChunks > 1) {\n appLogger(\n `${task.dictionaryPreset}${localePreset} Split into ${colorizeNumber(nbOfChunks)} chunks for translation`,\n {\n level: 'info',\n }\n );\n }\n\n const chunkResult: JsonChunk[] = [];\n\n // Process chunks in parallel (globally throttled) to allow concurrent translation\n const chunkPromises = chunkedJsonContent.map((chunk) => {\n const chunkPreset = createChunkPreset(chunk.index, chunk.total);\n\n if (nbOfChunks > 1) {\n appLogger(\n `${task.dictionaryPreset}${localePreset}${chunkPreset} Translating chunk`,\n {\n level: 'info',\n }\n );\n }\n\n // Reconstruct partial JSON content from this chunk's patches\n const chunkContent = reconstructFromSingleChunk(chunk);\n const presetOutputContent = reduceObjectFormat(\n isContentStructured\n ? targetLocaleDictionary.content\n : {\n __INTLAYER_ROOT_PRIMITIVE_CONTENT__:\n targetLocaleDictionary.content,\n },\n chunkContent\n ) as unknown as JSON;\n\n const executeTranslation = async () => {\n return await retryManager(\n async () => {\n let translationResult: any;\n\n if (aiClient && aiConfig) {\n translationResult = await aiClient.translateJSON({\n entryFileContent: chunkContent as unknown as JSON,\n presetOutputContent,\n dictionaryDescription:\n dictionaryToProcess.description ??\n metadata?.description ??\n '',\n entryLocale: task.sourceLocale,\n outputLocale: targetLocale,\n mode,\n aiConfig,\n });\n } else {\n translationResult = await intlayerAPI.ai\n .translateJSON({\n entryFileContent: chunkContent as unknown as JSON,\n presetOutputContent,\n dictionaryDescription:\n dictionaryToProcess.description ??\n metadata?.description ??\n '',\n entryLocale: task.sourceLocale,\n outputLocale: targetLocale,\n mode,\n aiOptions,\n })\n .then((result) => result.data);\n }\n\n if (!translationResult?.fileContent) {\n throw new Error('No content result');\n }\n\n const { isIdentic } = verifyIdenticObjectFormat(\n translationResult.fileContent,\n chunkContent\n );\n if (!isIdentic) {\n throw new Error(\n 'Translation result does not match expected format'\n );\n }\n\n notifySuccess();\n return translationResult.fileContent;\n },\n {\n maxRetry: MAX_RETRY,\n delay: RETRY_DELAY,\n onError: ({ error, attempt, maxRetry }) => {\n const chunkPreset = createChunkPreset(\n chunk.index,\n chunk.total\n );\n appLogger(\n `${task.dictionaryPreset}${localePreset}${chunkPreset} ${colorize('Error filling:', ANSIColors.RED)} ${colorize(typeof error === 'string' ? error : JSON.stringify(error), ANSIColors.GREY_DARK)} - Attempt ${colorizeNumber(attempt + 1)} of ${colorizeNumber(maxRetry)}`,\n {\n level: 'error',\n }\n );\n\n followingErrors += 1;\n\n if (followingErrors >= MAX_FOLLOWING_ERRORS) {\n appLogger(`There is something wrong.`, {\n level: 'error',\n });\n process.exit(1); // 1 for error\n }\n },\n }\n )();\n };\n\n const wrapped = options?.onHandle\n ? options.onHandle(executeTranslation) // queued in global limiter\n : executeTranslation(); // no global limiter\n\n return wrapped.then((result) => ({ chunk, result }));\n });\n\n // Wait for all chunks for this locale in parallel (still capped by global limiter)\n const chunkResults = await Promise.all(chunkPromises);\n\n // Maintain order\n chunkResults\n .sort((chunkA, chunkB) => chunkA.chunk.index - chunkB.chunk.index)\n .forEach(({ result }) => {\n chunkResult.push(result);\n });\n\n // Merge partial JSON objects produced from each chunk into a single object\n const mergedContent = mergeChunks(chunkResult);\n\n const merged = {\n ...dictionaryToProcess,\n content: mergedContent,\n };\n\n // For per-locale files, merge the newly translated content with existing target content\n let finalContent = merged.content;\n\n if (!isContentStructured) {\n finalContent = (finalContent as any)\n ?.__INTLAYER_ROOT_PRIMITIVE_CONTENT__;\n }\n\n if (typeof baseUnmergedDictionary.locale === 'string') {\n // Deep merge: existing content + newly translated content\n finalContent = deepMergeContent(\n targetLocaleDictionary.content ?? {},\n finalContent\n );\n }\n\n return [targetLocale, finalContent] as const;\n })\n );\n\n const translatedContent: Partial<Record<Locale, Dictionary['content']>> =\n Object.fromEntries(translatedContentResults);\n\n const baseDictionary = baseUnmergedDictionary.locale\n ? {\n ...baseUnmergedDictionary,\n key: baseUnmergedDictionary.key!,\n content: {},\n }\n : baseUnmergedDictionary;\n\n let dictionaryOutput: Dictionary = {\n ...getMultilingualDictionary(baseDictionary),\n locale: undefined, // Ensure the dictionary is multilingual\n ...metadata,\n };\n\n for (const targetLocale of task.targetLocales) {\n if (translatedContent[targetLocale]) {\n dictionaryOutput = insertContentInDictionary(\n dictionaryOutput,\n translatedContent[targetLocale],\n targetLocale\n );\n }\n }\n\n appLogger(\n `${task.dictionaryPreset} ${colorize('Translation completed successfully', ANSIColors.GREEN)} for ${colorizePath(basename(dictionaryOutput.filePath!))}`,\n {\n level: 'info',\n }\n );\n\n if (\n baseUnmergedDictionary.locale &&\n (baseUnmergedDictionary.fill === true ||\n baseUnmergedDictionary.fill === undefined) &&\n baseUnmergedDictionary.location === 'local'\n ) {\n const dictionaryFilePath = baseUnmergedDictionary\n .filePath!.split('.')\n .slice(0, -1);\n\n const contentIndex = dictionaryFilePath[dictionaryFilePath.length - 1];\n\n return JSON.parse(\n JSON.stringify({\n ...task,\n dictionaryOutput: {\n ...dictionaryOutput,\n fill: undefined,\n filled: true,\n },\n }).replaceAll(\n new RegExp(`\\\\.${contentIndex}\\\\.[a-zA-Z0-9]+`, 'g'),\n `.filled.${contentIndex}.json`\n )\n );\n }\n\n return {\n ...task,\n dictionaryOutput,\n };\n },\n {\n maxRetry: GROUP_MAX_RETRY,\n delay: RETRY_DELAY,\n onError: ({ error, attempt, maxRetry }) =>\n appLogger(\n `${task.dictionaryPreset} ${colorize('Error fill command:', ANSIColors.RED)} ${colorize(typeof error === 'string' ? error : JSON.stringify(error), ANSIColors.GREY_DARK)} - Attempt ${colorizeNumber(attempt + 1)} of ${colorizeNumber(maxRetry)}`,\n {\n level: 'error',\n }\n ),\n onMaxTryReached: ({ error }) =>\n appLogger(\n `${task.dictionaryPreset} ${colorize('Maximum number of retries reached:', ANSIColors.RED)} ${colorize(typeof error === 'string' ? error : JSON.stringify(error), ANSIColors.GREY_DARK)}`,\n {\n level: 'error',\n }\n ),\n }\n )();\n\n return result as TranslateDictionaryResult;\n};\n"],"mappings":"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"}
@@ -1,15 +1,15 @@
1
1
  const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
2
  const require_fill_formatFillData = require('./formatFillData.cjs');
3
3
  const require_fill_getAvailableLocalesInDictionary = require('./getAvailableLocalesInDictionary.cjs');
4
- let __intlayer_chokidar = require("@intlayer/chokidar");
5
- let __intlayer_config = require("@intlayer/config");
4
+ let _intlayer_chokidar = require("@intlayer/chokidar");
5
+ let _intlayer_config = require("@intlayer/config");
6
6
  let node_path = require("node:path");
7
- let __intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
7
+ let _intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
8
8
 
9
9
  //#region src/fill/writeFill.ts
10
10
  const writeFill = async (contentDeclarationFile, outputLocales, parentLocales, configuration) => {
11
- const appLogger = (0, __intlayer_config.getAppLogger)(configuration);
12
- const fullDictionary = (0, __intlayer_dictionaries_entry.getDictionaries)(configuration)[contentDeclarationFile.key];
11
+ const appLogger = (0, _intlayer_config.getAppLogger)(configuration);
12
+ const fullDictionary = (0, _intlayer_dictionaries_entry.getDictionaries)(configuration)[contentDeclarationFile.key];
13
13
  const { filePath } = contentDeclarationFile;
14
14
  if (!filePath) {
15
15
  appLogger("No file path found for dictionary", { level: "error" });
@@ -17,25 +17,25 @@ const writeFill = async (contentDeclarationFile, outputLocales, parentLocales, c
17
17
  }
18
18
  const fillOptions = contentDeclarationFile.fill ?? configuration.dictionary?.fill ?? true;
19
19
  if (fillOptions === false) {
20
- appLogger(`Auto fill is disabled for '${(0, __intlayer_config.colorizeKey)(fullDictionary.key)}'`, { level: "info" });
20
+ appLogger(`Auto fill is disabled for '${(0, _intlayer_config.colorizeKey)(fullDictionary.key)}'`, { level: "info" });
21
21
  return;
22
22
  }
23
23
  const requestedLocales = (outputLocales ?? configuration.internationalization.locales).filter((locale) => !parentLocales?.includes(locale));
24
24
  const availableLocales = require_fill_getAvailableLocalesInDictionary.getAvailableLocalesInDictionary(contentDeclarationFile);
25
25
  const localeList = requestedLocales.filter((locale) => availableLocales.includes(locale));
26
26
  if (localeList.length === 0) {
27
- appLogger(`No translations available for dictionary '${(0, __intlayer_config.colorizeKey)(fullDictionary.key)}'`, { level: "info" });
27
+ appLogger(`No translations available for dictionary '${(0, _intlayer_config.colorizeKey)(fullDictionary.key)}'`, { level: "info" });
28
28
  return;
29
29
  }
30
30
  const fillData = require_fill_formatFillData.formatFillData(fillOptions, localeList, filePath, fullDictionary.key, configuration);
31
31
  for await (const output of fillData) {
32
32
  if (!output.filePath) {
33
- appLogger(`No file path found for auto filled content declaration for '${(0, __intlayer_config.colorizeKey)(fullDictionary.key)}'`, { level: "error" });
33
+ appLogger(`No file path found for auto filled content declaration for '${(0, _intlayer_config.colorizeKey)(fullDictionary.key)}'`, { level: "error" });
34
34
  continue;
35
35
  }
36
36
  const { fill, ...rest } = contentDeclarationFile;
37
37
  const relativeFilePath = (0, node_path.relative)(configuration.content.baseDir, output.filePath);
38
- await (0, __intlayer_chokidar.writeContentDeclaration)({
38
+ await (0, _intlayer_chokidar.writeContentDeclaration)({
39
39
  ...rest,
40
40
  filled: true,
41
41
  locale: output.isPerLocale ? output.localeList[0] : void 0,
@@ -44,8 +44,8 @@ const writeFill = async (contentDeclarationFile, outputLocales, parentLocales, c
44
44
  }, configuration, { localeList: output.localeList });
45
45
  if (output.isPerLocale) {
46
46
  const sourceLocale = output.localeList[0];
47
- appLogger(`Auto filled per-locale content declaration for '${(0, __intlayer_config.colorizeKey)(fullDictionary.key)}' written to ${(0, __intlayer_chokidar.formatPath)(output.filePath)} for locale ${(0, __intlayer_chokidar.formatLocale)(sourceLocale)}`, { level: "info" });
48
- } else appLogger(`Auto filled content declaration for '${(0, __intlayer_config.colorizeKey)(fullDictionary.key)}' written to ${(0, __intlayer_chokidar.formatPath)(output.filePath)}`, { level: "info" });
47
+ appLogger(`Auto filled per-locale content declaration for '${(0, _intlayer_config.colorizeKey)(fullDictionary.key)}' written to ${(0, _intlayer_chokidar.formatPath)(output.filePath)} for locale ${(0, _intlayer_chokidar.formatLocale)(sourceLocale)}`, { level: "info" });
48
+ } else appLogger(`Auto filled content declaration for '${(0, _intlayer_config.colorizeKey)(fullDictionary.key)}' written to ${(0, _intlayer_chokidar.formatPath)(output.filePath)}`, { level: "info" });
49
49
  }
50
50
  };
51
51
 
@@ -1 +1 @@
1
- {"version":3,"file":"writeFill.cjs","names":["fillOptions: Fill | undefined","requestedLocales: Locale[]","getAvailableLocalesInDictionary","fillData: FillData[]","formatFillData"],"sources":["../../../src/fill/writeFill.ts"],"sourcesContent":["import { relative } from 'node:path';\nimport {\n formatLocale,\n formatPath,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport { colorizeKey, getAppLogger } from '@intlayer/config';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type { Dictionary, Fill, IntlayerConfig, Locale } from '@intlayer/types';\nimport { type FillData, formatFillData } from './formatFillData';\nimport { getAvailableLocalesInDictionary } from './getAvailableLocalesInDictionary';\n\nexport const writeFill = async (\n contentDeclarationFile: Dictionary,\n outputLocales: Locale[],\n parentLocales: Locale[],\n configuration: IntlayerConfig\n) => {\n const appLogger = getAppLogger(configuration);\n const dictionaries = getDictionaries(configuration);\n\n const fullDictionary = dictionaries[contentDeclarationFile.key];\n\n const { filePath } = contentDeclarationFile;\n\n if (!filePath) {\n appLogger('No file path found for dictionary', {\n level: 'error',\n });\n return;\n }\n\n const fillOptions: Fill | undefined =\n contentDeclarationFile.fill ?? configuration.dictionary?.fill ?? true;\n\n if ((fillOptions as boolean) === false) {\n appLogger(\n `Auto fill is disabled for '${colorizeKey(fullDictionary.key)}'`,\n {\n level: 'info',\n }\n );\n return;\n }\n\n const requestedLocales: Locale[] = (\n outputLocales ?? configuration.internationalization.locales\n ).filter((locale) => !parentLocales?.includes(locale));\n\n // Get locales that actually have translations in the content\n const availableLocales = getAvailableLocalesInDictionary(\n contentDeclarationFile\n );\n\n // Only write files for locales that have actual translations\n const localeList = requestedLocales.filter((locale) =>\n availableLocales.includes(locale)\n );\n\n if (localeList.length === 0) {\n appLogger(\n `No translations available for dictionary '${colorizeKey(fullDictionary.key)}'`,\n {\n level: 'info',\n }\n );\n return;\n }\n\n const fillData: FillData[] = formatFillData(\n fillOptions as Fill,\n localeList,\n filePath,\n fullDictionary.key,\n configuration\n );\n\n for await (const output of fillData) {\n if (!output.filePath) {\n appLogger(\n `No file path found for auto filled content declaration for '${colorizeKey(fullDictionary.key)}'`,\n {\n level: 'error',\n }\n );\n continue;\n }\n\n // biome-ignore lint/correctness/noUnusedVariables: Just filtering out the fill property\n const { fill, ...rest } = contentDeclarationFile;\n\n const relativeFilePath = relative(\n configuration.content.baseDir,\n output.filePath\n );\n\n // write file\n await writeContentDeclaration(\n {\n ...rest,\n filled: true,\n locale: output.isPerLocale ? output.localeList[0] : undefined,\n localId: `${contentDeclarationFile.key}::local::${relativeFilePath}`,\n filePath: relativeFilePath,\n },\n configuration,\n {\n localeList: output.localeList,\n }\n );\n\n if (output.isPerLocale) {\n const sourceLocale = output.localeList[0];\n\n appLogger(\n `Auto filled per-locale content declaration for '${colorizeKey(fullDictionary.key)}' written to ${formatPath(output.filePath)} for locale ${formatLocale(sourceLocale)}`,\n {\n level: 'info',\n }\n );\n } else {\n appLogger(\n `Auto filled content declaration for '${colorizeKey(fullDictionary.key)}' written to ${formatPath(output.filePath)}`,\n {\n level: 'info',\n }\n );\n }\n }\n};\n"],"mappings":";;;;;;;;;AAYA,MAAa,YAAY,OACvB,wBACA,eACA,eACA,kBACG;CACH,MAAM,gDAAyB,cAAc;CAG7C,MAAM,oEAF+B,cAAc,CAEf,uBAAuB;CAE3D,MAAM,EAAE,aAAa;AAErB,KAAI,CAAC,UAAU;AACb,YAAU,qCAAqC,EAC7C,OAAO,SACR,CAAC;AACF;;CAGF,MAAMA,cACJ,uBAAuB,QAAQ,cAAc,YAAY,QAAQ;AAEnE,KAAK,gBAA4B,OAAO;AACtC,YACE,iEAA0C,eAAe,IAAI,CAAC,IAC9D,EACE,OAAO,QACR,CACF;AACD;;CAGF,MAAMC,oBACJ,iBAAiB,cAAc,qBAAqB,SACpD,QAAQ,WAAW,CAAC,eAAe,SAAS,OAAO,CAAC;CAGtD,MAAM,mBAAmBC,6EACvB,uBACD;CAGD,MAAM,aAAa,iBAAiB,QAAQ,WAC1C,iBAAiB,SAAS,OAAO,CAClC;AAED,KAAI,WAAW,WAAW,GAAG;AAC3B,YACE,gFAAyD,eAAe,IAAI,CAAC,IAC7E,EACE,OAAO,QACR,CACF;AACD;;CAGF,MAAMC,WAAuBC,2CAC3B,aACA,YACA,UACA,eAAe,KACf,cACD;AAED,YAAW,MAAM,UAAU,UAAU;AACnC,MAAI,CAAC,OAAO,UAAU;AACpB,aACE,kGAA2E,eAAe,IAAI,CAAC,IAC/F,EACE,OAAO,SACR,CACF;AACD;;EAIF,MAAM,EAAE,MAAM,GAAG,SAAS;EAE1B,MAAM,2CACJ,cAAc,QAAQ,SACtB,OAAO,SACR;AAGD,yDACE;GACE,GAAG;GACH,QAAQ;GACR,QAAQ,OAAO,cAAc,OAAO,WAAW,KAAK;GACpD,SAAS,GAAG,uBAAuB,IAAI,WAAW;GAClD,UAAU;GACX,EACD,eACA,EACE,YAAY,OAAO,YACpB,CACF;AAED,MAAI,OAAO,aAAa;GACtB,MAAM,eAAe,OAAO,WAAW;AAEvC,aACE,sFAA+D,eAAe,IAAI,CAAC,mDAA0B,OAAO,SAAS,CAAC,oDAA2B,aAAa,IACtK,EACE,OAAO,QACR,CACF;QAED,WACE,2EAAoD,eAAe,IAAI,CAAC,mDAA0B,OAAO,SAAS,IAClH,EACE,OAAO,QACR,CACF"}
1
+ {"version":3,"file":"writeFill.cjs","names":["fillOptions: Fill | undefined","requestedLocales: Locale[]","getAvailableLocalesInDictionary","fillData: FillData[]","formatFillData"],"sources":["../../../src/fill/writeFill.ts"],"sourcesContent":["import { relative } from 'node:path';\nimport {\n formatLocale,\n formatPath,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport { colorizeKey, getAppLogger } from '@intlayer/config';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type { Dictionary, Fill, IntlayerConfig, Locale } from '@intlayer/types';\nimport { type FillData, formatFillData } from './formatFillData';\nimport { getAvailableLocalesInDictionary } from './getAvailableLocalesInDictionary';\n\nexport const writeFill = async (\n contentDeclarationFile: Dictionary,\n outputLocales: Locale[],\n parentLocales: Locale[],\n configuration: IntlayerConfig\n) => {\n const appLogger = getAppLogger(configuration);\n const dictionaries = getDictionaries(configuration);\n\n const fullDictionary = dictionaries[contentDeclarationFile.key];\n\n const { filePath } = contentDeclarationFile;\n\n if (!filePath) {\n appLogger('No file path found for dictionary', {\n level: 'error',\n });\n return;\n }\n\n const fillOptions: Fill | undefined =\n contentDeclarationFile.fill ?? configuration.dictionary?.fill ?? true;\n\n if ((fillOptions as boolean) === false) {\n appLogger(\n `Auto fill is disabled for '${colorizeKey(fullDictionary.key)}'`,\n {\n level: 'info',\n }\n );\n return;\n }\n\n const requestedLocales: Locale[] = (\n outputLocales ?? configuration.internationalization.locales\n ).filter((locale) => !parentLocales?.includes(locale));\n\n // Get locales that actually have translations in the content\n const availableLocales = getAvailableLocalesInDictionary(\n contentDeclarationFile\n );\n\n // Only write files for locales that have actual translations\n const localeList = requestedLocales.filter((locale) =>\n availableLocales.includes(locale)\n );\n\n if (localeList.length === 0) {\n appLogger(\n `No translations available for dictionary '${colorizeKey(fullDictionary.key)}'`,\n {\n level: 'info',\n }\n );\n return;\n }\n\n const fillData: FillData[] = formatFillData(\n fillOptions as Fill,\n localeList,\n filePath,\n fullDictionary.key,\n configuration\n );\n\n for await (const output of fillData) {\n if (!output.filePath) {\n appLogger(\n `No file path found for auto filled content declaration for '${colorizeKey(fullDictionary.key)}'`,\n {\n level: 'error',\n }\n );\n continue;\n }\n\n // biome-ignore lint/correctness/noUnusedVariables: Just filtering out the fill property\n const { fill, ...rest } = contentDeclarationFile;\n\n const relativeFilePath = relative(\n configuration.content.baseDir,\n output.filePath\n );\n\n // write file\n await writeContentDeclaration(\n {\n ...rest,\n filled: true,\n locale: output.isPerLocale ? output.localeList[0] : undefined,\n localId: `${contentDeclarationFile.key}::local::${relativeFilePath}`,\n filePath: relativeFilePath,\n },\n configuration,\n {\n localeList: output.localeList,\n }\n );\n\n if (output.isPerLocale) {\n const sourceLocale = output.localeList[0];\n\n appLogger(\n `Auto filled per-locale content declaration for '${colorizeKey(fullDictionary.key)}' written to ${formatPath(output.filePath)} for locale ${formatLocale(sourceLocale)}`,\n {\n level: 'info',\n }\n );\n } else {\n appLogger(\n `Auto filled content declaration for '${colorizeKey(fullDictionary.key)}' written to ${formatPath(output.filePath)}`,\n {\n level: 'info',\n }\n );\n }\n }\n};\n"],"mappings":";;;;;;;;;AAYA,MAAa,YAAY,OACvB,wBACA,eACA,eACA,kBACG;CACH,MAAM,+CAAyB,cAAc;CAG7C,MAAM,mEAF+B,cAAc,CAEf,uBAAuB;CAE3D,MAAM,EAAE,aAAa;AAErB,KAAI,CAAC,UAAU;AACb,YAAU,qCAAqC,EAC7C,OAAO,SACR,CAAC;AACF;;CAGF,MAAMA,cACJ,uBAAuB,QAAQ,cAAc,YAAY,QAAQ;AAEnE,KAAK,gBAA4B,OAAO;AACtC,YACE,gEAA0C,eAAe,IAAI,CAAC,IAC9D,EACE,OAAO,QACR,CACF;AACD;;CAGF,MAAMC,oBACJ,iBAAiB,cAAc,qBAAqB,SACpD,QAAQ,WAAW,CAAC,eAAe,SAAS,OAAO,CAAC;CAGtD,MAAM,mBAAmBC,6EACvB,uBACD;CAGD,MAAM,aAAa,iBAAiB,QAAQ,WAC1C,iBAAiB,SAAS,OAAO,CAClC;AAED,KAAI,WAAW,WAAW,GAAG;AAC3B,YACE,+EAAyD,eAAe,IAAI,CAAC,IAC7E,EACE,OAAO,QACR,CACF;AACD;;CAGF,MAAMC,WAAuBC,2CAC3B,aACA,YACA,UACA,eAAe,KACf,cACD;AAED,YAAW,MAAM,UAAU,UAAU;AACnC,MAAI,CAAC,OAAO,UAAU;AACpB,aACE,iGAA2E,eAAe,IAAI,CAAC,IAC/F,EACE,OAAO,SACR,CACF;AACD;;EAIF,MAAM,EAAE,MAAM,GAAG,SAAS;EAE1B,MAAM,2CACJ,cAAc,QAAQ,SACtB,OAAO,SACR;AAGD,wDACE;GACE,GAAG;GACH,QAAQ;GACR,QAAQ,OAAO,cAAc,OAAO,WAAW,KAAK;GACpD,SAAS,GAAG,uBAAuB,IAAI,WAAW;GAClD,UAAU;GACX,EACD,eACA,EACE,YAAY,OAAO,YACpB,CACF;AAED,MAAI,OAAO,aAAa;GACtB,MAAM,eAAe,OAAO,WAAW;AAEvC,aACE,qFAA+D,eAAe,IAAI,CAAC,kDAA0B,OAAO,SAAS,CAAC,mDAA2B,aAAa,IACtK,EACE,OAAO,QACR,CACF;QAED,WACE,0EAAoD,eAAe,IAAI,CAAC,kDAA0B,OAAO,SAAS,IAClH,EACE,OAAO,QACR,CACF"}