@intlayer/cli 9.5.3 → 9.5.4-canary.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 (54) hide show
  1. package/README.md +8 -8
  2. package/dist/cjs/editor.cjs +1 -1
  3. package/dist/cjs/extract.cjs +2 -2
  4. package/dist/cjs/extract.cjs.map +1 -1
  5. package/dist/cjs/fill/formatAutoFilledFilePath.cjs +1 -1
  6. package/dist/cjs/fill/listTranslationsTasks.cjs +2 -2
  7. package/dist/cjs/fill/listTranslationsTasks.cjs.map +1 -1
  8. package/dist/cjs/fill/translateDictionary.cjs +4 -4
  9. package/dist/cjs/fill/translateDictionary.cjs.map +1 -1
  10. package/dist/cjs/getTargetDictionary.cjs +2 -2
  11. package/dist/cjs/getTargetDictionary.cjs.map +1 -1
  12. package/dist/cjs/index.cjs +9 -9
  13. package/dist/cjs/init.cjs +1 -1
  14. package/dist/cjs/listContentDeclaration.cjs +2 -2
  15. package/dist/cjs/listContentDeclaration.cjs.map +1 -1
  16. package/dist/cjs/liveSync.cjs +2 -2
  17. package/dist/cjs/liveSync.cjs.map +1 -1
  18. package/dist/cjs/pull.cjs +4 -4
  19. package/dist/cjs/pull.cjs.map +1 -1
  20. package/dist/cjs/push/push.cjs +3 -3
  21. package/dist/cjs/push/push.cjs.map +1 -1
  22. package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs +1 -1
  23. package/dist/cjs/test/listMissingTranslations.cjs +2 -2
  24. package/dist/cjs/test/listMissingTranslations.cjs.map +1 -1
  25. package/dist/cjs/translateDoc/translateFile.cjs +1 -1
  26. package/dist/cjs/utils/checkAccess.cjs +1 -1
  27. package/dist/cjs/utils/getOutputFilePath.cjs +1 -1
  28. package/dist/esm/editor.mjs +1 -1
  29. package/dist/esm/extract.mjs +1 -1
  30. package/dist/esm/extract.mjs.map +1 -1
  31. package/dist/esm/fill/formatAutoFilledFilePath.mjs +1 -1
  32. package/dist/esm/fill/listTranslationsTasks.mjs +1 -1
  33. package/dist/esm/fill/listTranslationsTasks.mjs.map +1 -1
  34. package/dist/esm/fill/translateDictionary.mjs +3 -3
  35. package/dist/esm/fill/translateDictionary.mjs.map +1 -1
  36. package/dist/esm/getTargetDictionary.mjs +1 -1
  37. package/dist/esm/getTargetDictionary.mjs.map +1 -1
  38. package/dist/esm/index.mjs +9 -9
  39. package/dist/esm/init.mjs +1 -1
  40. package/dist/esm/listContentDeclaration.mjs +1 -1
  41. package/dist/esm/listContentDeclaration.mjs.map +1 -1
  42. package/dist/esm/liveSync.mjs +1 -1
  43. package/dist/esm/liveSync.mjs.map +1 -1
  44. package/dist/esm/pull.mjs +3 -3
  45. package/dist/esm/pull.mjs.map +1 -1
  46. package/dist/esm/push/push.mjs +2 -2
  47. package/dist/esm/push/push.mjs.map +1 -1
  48. package/dist/esm/reviewDoc/reviewDocBlockAware.mjs +1 -1
  49. package/dist/esm/test/listMissingTranslations.mjs +1 -1
  50. package/dist/esm/test/listMissingTranslations.mjs.map +1 -1
  51. package/dist/esm/translateDoc/translateFile.mjs +1 -1
  52. package/dist/esm/utils/checkAccess.mjs +1 -1
  53. package/dist/esm/utils/getOutputFilePath.mjs +1 -1
  54. package/package.json +12 -13
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <p align="center">
2
2
  <a href="https://intlayer.org" rel="">
3
- <img src="https://raw.githubusercontent.com/aymericzip/intlayer/main/docs/assets/cover.png" width="60%" alt="Intlayer Logo" />
3
+ <img src="https://raw.githubusercontent.com/aymericzip/intlayer/main/docs/assets/cover.webp" width="60%" alt="Intlayer Logo" />
4
4
  </a>
5
5
  </p>
6
6
 
@@ -49,10 +49,10 @@ With **per-locale content files**, **TypeScript autocompletion**, **tree-shakabl
49
49
 
50
50
  | Feature | Description |
51
51
  | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/frameworks.png?raw=true" alt="Feature" width="700"> | **Cross-Frameworks Support**<br><br>Intlayer is compatible with all major frameworks and libraries, including Next.js, React, Vite, Vue.js, Nuxt, Preact, Express, and more. |
52
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/frameworks.webp?raw=true" alt="Feature" width="700"> | **Cross-Frameworks Support**<br><br>Intlayer is compatible with all major frameworks and libraries, including Next.js, React, Vite, Vue.js, Nuxt, Preact, Express, and more. |
53
53
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/javascript_content_management.jpg?raw=true" alt="Feature" width="700"> | **JavaScript-Powered Content Management**<br><br>Harness the flexibility of JavaScript to define and manage your content efficiently. <br><br> - [Content declaration](https://intlayer.org/doc/concept/content) |
54
54
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/per_locale_content_declaration_file.png?raw=true" alt="Feature" width="700"> | **Per-Locale Content Declaration File**<br><br>Speed up your development by declaring your content once, before auto generation.<br><br> - [Per-Locale Content Declaration File](https://intlayer.org/doc/concept/per-locale-file) |
55
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/compiler.jpg?raw=true" alt="Feature" width="700"> | **Compiler**<br><br>The Intlayer Compiler extract automatically the content from the components and generate the dictionary files.<br><br> - [Compiler](https://intlayer.org/doc/compiler) |
55
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/compiler.webp?raw=true" alt="Feature" width="700"> | **Compiler**<br><br>The Intlayer Compiler extract automatically the content from the components and generate the dictionary files.<br><br> - [Compiler](https://intlayer.org/doc/compiler) |
56
56
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true" alt="Feature" width="700"> | **Type-Safe Environment**<br><br>Leverage TypeScript to ensure your content definitions and code are error-free, while also benefiting from IDE autocompletion.<br><br> - [TypeScript configuration](https://intlayer.org/doc/environment/vite-and-react#configure-typescript) |
57
57
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/config_file.png?raw=true" alt="Feature" width="700"> | **Simplified Setup**<br><br>Get up and running quickly with minimal configuration. Adjust settings for internationalization, routing, AI, build, and content handling with ease. <br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
58
58
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/content_retrieval.png?raw=true" alt="Feature" width="700"> | **Simplified Content Retrieval**<br><br>No need to call your `t` function for each piece of content. Retrieve all your content directly using a single hook.<br><br> - [React integration](https://intlayer.org/doc/environment/create-react-app) |
@@ -60,12 +60,12 @@ With **per-locale content files**, **TypeScript autocompletion**, **tree-shakabl
60
60
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/file_tree.png?raw=true" alt="Feature" width="700"> | **Organized Codebase**<br><br>Keep your codebase more organized: 1 component = 1 dictionary in the same folder. Translations close to their respective components, enhance maintainability and clarity. <br><br> - [How Intlayer works](https://intlayer.org/doc/concept/how-works-intlayer) |
61
61
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/url_routing.png?raw=true" alt="Feature" width="700"> | **Enhanced Routing**<br><br>Full support of app routing, adapting seamlessly to complex application structures, for Next.js, React, Vite, Vue.js, etc.<br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
62
62
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/markdown.png?raw=true" alt="Feature" width="700"> | **Markdown Support**<br><br>Import and interpret, locale files and remote Markdown for multilingual content like privacy policies, documentation, etc. Interpret and make Markdown metadata accessible in your code.<br><br> - [Content files](https://intlayer.org/doc/concept/content/file) |
63
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/visual_editor.png?raw=true" alt="Feature" width="700"> | **Free Visual Editor & CMS**<br><br>A free visual editor and CMS are available for content writers, removing the need for a localization platform. Keep your content synchronized using Git, or externalize it totally or partially with the CMS.<br><br> - [Intlayer Editor](https://intlayer.org/doc/concept/editor) <br> - [Intlayer CMS](https://intlayer.org/doc/concept/cms) |
64
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png?raw=true" alt="Feature" width="700"> | **Tree-shakable Content**<br><br>Tree-shakable content, reducing the size of the final bundle. Loads content per component, excluding any unused content from your bundle. Supports lazy loading to enhance app loading efficiency. <br><br> - [App build optimization](https://intlayer.org/doc/concept/how-works-intlayer#app-build-optimization) |
65
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/static_rendering.png?raw=true" alt="Feature" width="700"> | **Static Rendering**<br><br>Doesn't block Static Rendering. <br><br> - [Next.js integration](https://intlayer.org/doc/environment/nextjs) |
63
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/visual_editor.webp?raw=true" alt="Feature" width="700"> | **Free Visual Editor & CMS**<br><br>A free visual editor and CMS are available for content writers, removing the need for a localization platform. Keep your content synchronized using Git, or externalize it totally or partially with the CMS.<br><br> - [Intlayer Editor](https://intlayer.org/doc/concept/editor) <br> - [Intlayer CMS](https://intlayer.org/doc/concept/cms) |
64
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.webp?raw=true" alt="Feature" width="700"> | **Tree-shakable Content**<br><br>Tree-shakable content, reducing the size of the final bundle. Loads content per component, excluding any unused content from your bundle. Supports lazy loading to enhance app loading efficiency. <br><br> - [App build optimization](https://intlayer.org/doc/concept/how-works-intlayer#app-build-optimization) |
65
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/static_rendering.webp?raw=true" alt="Feature" width="700"> | **Static Rendering**<br><br>Doesn't block Static Rendering. <br><br> - [Next.js integration](https://intlayer.org/doc/environment/nextjs) |
66
66
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/AI_translation.png?raw=true" alt="Feature" width="700"> | **AI-Powered Translation**<br><br>Transform your website into 231 languages with just one click using Intlayer's advanced AI-powered translation tools using your own AI provider / API key. <br><br> - [CI/CD integration](https://intlayer.org/doc/concept/ci-cd) <br> - [Intlayer CLI](https://intlayer.org/doc/concept/cli) <br> - [Auto fill](https://intlayer.org/doc/concept/auto-fill) |
67
67
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/mcp.png?raw=true" alt="Feature" width="700"> | **MCP Server Integration**<br><br>Provides an MCP (Model Context Protocol) server for IDE automation, enabling seamless content management and i18n workflows directly within your development environment. <br><br> - [MCP Server](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/mcp_server.md) |
68
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/vscode_extension.png?raw=true" alt="Feature" width="700"> | **VSCode Extension**<br><br>Intlayer provides a VSCode extension to help you manage your content and translations, building your dictionaries, translating your content, and more. <br><br> - [VSCode Extension](https://intlayer.org/doc/vs-code-extension) |
68
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/vscode_extension.webp?raw=true" alt="Feature" width="700"> | **VSCode Extension**<br><br>Intlayer provides a VSCode extension to help you manage your content and translations, building your dictionaries, translating your content, and more. <br><br> - [VSCode Extension](https://intlayer.org/doc/vs-code-extension) |
69
69
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/interoperability.png?raw=true" alt="Feature" width="700"> | **Interoperability**<br><br>Allow interoperability with react-i18next, next-i18next, next-intl, react-intl, vue-i18n. <br><br> - [Intlayer and react-intl](https://intlayer.org/blog/intlayer-with-react-intl) <br> - [Intlayer and next-intl](https://intlayer.org/blog/intlayer-with-next-intl) <br> - [Intlayer and next-i18next](https://intlayer.org/blog/intlayer-with-next-i18next) <br> - [Intlayer and vue-i18n](https://intlayer.org/blog/intlayer-with-vue-i18n) <br> - [Intlayer compat adapters](https://intlayer.org/doc/compatibility) |
70
70
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/benchmark.png?raw=true" alt="Feature" width="700"> | **Performances & Benchmark**<br><br>Uses advanced tree-shaking and dynamic loading to boost performances and keep the solution as light as possible. <br><br> - [Performances & Benchmark](https://intlayer.org/doc/benchmark) |
71
71
 
@@ -262,7 +262,7 @@ Intlayer connects **developers**, **copywriters**, and **AI agents** in one work
262
262
  - Feature flags
263
263
  - Headless CMSs (e.g. Contentful, Strapi, Sanity)
264
264
 
265
- ![CMS Preview](https://github.com/aymericzip/intlayer/blob/main/docs/assets/CMS.png?raw=true)
265
+ ![CMS Preview](https://github.com/aymericzip/intlayer/blob/main/docs/assets/CMS.webp?raw=true)
266
266
 
267
267
  ## 🌐 Readme in other languages
268
268
 
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  let node_path = require("node:path");
3
+ let _intlayer_config_utils = require("@intlayer/config/utils");
3
4
  let node_child_process = require("node:child_process");
4
5
  let node_module = require("node:module");
5
- let _intlayer_config_utils = require("@intlayer/config/utils");
6
6
 
7
7
  //#region src/editor.ts
8
8
  const startEditor = (options) => {
@@ -6,10 +6,10 @@ let _intlayer_config_colors = require("@intlayer/config/colors");
6
6
  _intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
7
7
  let _intlayer_config_logger = require("@intlayer/config/logger");
8
8
  let _intlayer_config_node = require("@intlayer/config/node");
9
+ let _intlayer_dictionaries_entry_unmerged = require("@intlayer/dictionaries-entry/unmerged");
9
10
  let _intlayer_engine_build = require("@intlayer/engine/build");
10
11
  let _intlayer_engine_cli = require("@intlayer/engine/cli");
11
12
  let _intlayer_engine_utils = require("@intlayer/engine/utils");
12
- let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
13
13
  let enquirer = require("enquirer");
14
14
  enquirer = require_runtime.__toESM(enquirer);
15
15
 
@@ -88,7 +88,7 @@ const extract = async (options) => {
88
88
  return true;
89
89
  });
90
90
  if (absoluteFiles.length === 0) return;
91
- const unmergedDictionaries = (0, _intlayer_unmerged_dictionaries_entry.getUnmergedDictionaries)(configuration);
91
+ const unmergedDictionaries = (0, _intlayer_dictionaries_entry_unmerged.getUnmergedDictionaries)(configuration);
92
92
  for (const filePath of absoluteFiles) try {
93
93
  await extractContent(filePath, packageName, {
94
94
  unmergedDictionaries,
@@ -1 +1 @@
1
- {"version":3,"file":"extract.cjs","names":["getConfiguration","getAppLogger","x","colorize","ANSIColors","buildComponentFilesList","relative","resolve","existsSync","formatPath","getUnmergedDictionaries","prepareIntlayer"],"sources":["../../src/extract.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport type { PackageName } from '@intlayer/babel';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger, x } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { buildComponentFilesList, formatPath } from '@intlayer/engine/utils';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport enquirer from 'enquirer';\n\ntype ExtractOptions = {\n files?: string[];\n output?: FilePathPattern;\n configOptions?: GetConfigurationOptions;\n codeOnly?: boolean;\n declarationOnly?: boolean;\n};\n\nexport const extract = async (options: ExtractOptions) => {\n const configuration = getConfiguration(options.configOptions);\n\n logConfigDetails(options?.configOptions);\n\n const appLogger = getAppLogger(configuration);\n\n const { baseDir } = configuration.system;\n const { output } = configuration.compiler;\n\n if (!output) {\n appLogger(\n `${x} No output configuration found. Add a ${colorize('compiler.output', ANSIColors.BLUE)} in your configuration.`,\n {\n level: 'error',\n }\n );\n return;\n }\n\n const { detectPackageName, extractContent } = await import('@intlayer/babel');\n\n // Detect package\n const packageName: PackageName = detectPackageName(baseDir);\n\n let filesToExtract = options.files ?? [];\n\n if (filesToExtract.length === 0) {\n // Await all promises simultaneously\n const fileList = buildComponentFilesList(configuration);\n\n // Flatten the nested arrays and remove duplicates\n // Relative paths for selection\n const choices = fileList.map((file) => {\n const relPath = relative(baseDir, file);\n\n return {\n value: file,\n label: relPath,\n };\n });\n\n if (choices.length === 0) {\n appLogger('No extractable files found in the project.');\n return;\n }\n\n const SELECT_ALL = '__select_all__';\n\n type PromptChoice = {\n name: string;\n enabled: boolean;\n disabled?: boolean | string;\n };\n\n type PromptContext = {\n choices: PromptChoice[];\n render(): void | Promise<void>;\n state: { submitted: boolean };\n selected: PromptChoice[];\n input: string;\n options: { multiple?: boolean };\n };\n\n let selectedFiles: string[] | symbol;\n try {\n const maxLen = Math.max((process.stdout.columns || 80) - 15, 20);\n const truncatePath = (path: string) =>\n path.length > maxLen ? `...${path.slice(-(maxLen - 3))}` : path;\n\n const { files: enquirerSelectedFiles } = await enquirer.prompt<{\n files: string[];\n }>({\n type: 'autocomplete',\n name: 'files',\n message: 'Select files to extract (Type to search):',\n multiple: true,\n // @ts-ignore limit exist but is not typed\n limit: 40,\n choices: [\n { name: SELECT_ALL, message: '────── Select all ──────' },\n ...choices.map((choice) => ({\n name: choice.value,\n message: truncatePath(choice.label),\n })),\n ],\n async toggle(\n this: PromptContext,\n choice: PromptChoice,\n enabled?: boolean\n ) {\n if (!choice || choice.disabled) return;\n choice.enabled = enabled == null ? !choice.enabled : enabled;\n\n if (choice.name === SELECT_ALL) {\n this.choices\n .filter((choiceEl) => choiceEl.name !== SELECT_ALL)\n .forEach((choiceEl) => {\n choiceEl.enabled = choice.enabled;\n });\n }\n\n return this.render();\n },\n format(this: PromptContext) {\n if (this.state?.submitted && this.options?.multiple) {\n return `${this.selected.filter((s) => s.name !== SELECT_ALL).length} file(s) selected`;\n }\n return this.input ?? '';\n },\n });\n\n selectedFiles = enquirerSelectedFiles.filter(\n (file) => file !== SELECT_ALL\n );\n } catch {\n selectedFiles = Symbol('cancel');\n }\n\n if (typeof selectedFiles === 'symbol') {\n // User cancelled\n process.exit(0);\n }\n\n filesToExtract = selectedFiles as string[];\n }\n\n if (filesToExtract.length === 0) {\n appLogger('No files selected for extraction.');\n return;\n }\n\n const absoluteFiles = filesToExtract\n .map((file) => resolve(baseDir, file))\n .filter((file) => {\n if (!existsSync(file)) {\n appLogger(`File not found: ${formatPath(file)}`);\n return false;\n }\n return true;\n });\n\n if (absoluteFiles.length === 0) {\n return;\n }\n\n const unmergedDictionaries = getUnmergedDictionaries(configuration);\n\n for (const filePath of absoluteFiles) {\n try {\n await extractContent(filePath, packageName, {\n unmergedDictionaries,\n configuration,\n codeOnly: options.codeOnly,\n declarationOnly: options.declarationOnly,\n });\n } catch (error) {\n appLogger(`Failed to transform ${filePath}: ${(error as Error).message}`);\n }\n }\n\n await prepareIntlayer(configuration); // Prepare Intlayer to apply the changes\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAwBA,MAAa,UAAU,OAAO,YAA4B;CACxD,MAAM,oBAAgBA,wCAAiB,QAAQ,aAAa;CAE5D,2CAAiB,SAAS,aAAa;CAEvC,MAAM,gBAAYC,sCAAa,aAAa;CAE5C,MAAM,EAAE,YAAY,cAAc;CAClC,MAAM,EAAE,WAAW,cAAc;CAEjC,IAAI,CAAC,QAAQ;EACX,UACE,GAAGC,0BAAE,4CAAwCC,kCAAS,mBAAmBC,wBAAW,IAAI,EAAE,0BAC1F,EACE,OAAO,QACT,CACF;EACA;CACF;CAEA,MAAM,EAAE,mBAAmB,mBAAmB,MAAM,OAAO;CAG3D,MAAM,cAA2B,kBAAkB,OAAO;CAE1D,IAAI,iBAAiB,QAAQ,SAAS,CAAC;CAEvC,IAAI,eAAe,WAAW,GAAG;EAM/B,MAAM,cAJWC,gDAAwB,aAIlB,CAAC,CAAC,KAAK,SAAS;GAGrC,OAAO;IACL,OAAO;IACP,WAJcC,oBAAS,SAAS,IAInB;GACf;EACF,CAAC;EAED,IAAI,QAAQ,WAAW,GAAG;GACxB,UAAU,4CAA4C;GACtD;EACF;EAEA,MAAM,aAAa;EAiBnB,IAAI;EACJ,IAAI;GACF,MAAM,SAAS,KAAK,KAAK,QAAQ,OAAO,WAAW,MAAM,IAAI,EAAE;GAC/D,MAAM,gBAAgB,SACpB,KAAK,SAAS,SAAS,MAAM,KAAK,MAAM,EAAE,SAAS,EAAE,MAAM;GAE7D,MAAM,EAAE,OAAO,0BAA0B,MAAM,iBAAS,OAErD;IACD,MAAM;IACN,MAAM;IACN,SAAS;IACT,UAAU;IAEV,OAAO;IACP,SAAS,CACP;KAAE,MAAM;KAAY,SAAS;IAA2B,GACxD,GAAG,QAAQ,KAAK,YAAY;KAC1B,MAAM,OAAO;KACb,SAAS,aAAa,OAAO,KAAK;IACpC,EAAE,CACJ;IACA,MAAM,OAEJ,QACA,SACA;KACA,IAAI,CAAC,UAAU,OAAO,UAAU;KAChC,OAAO,UAAU,WAAW,OAAO,CAAC,OAAO,UAAU;KAErD,IAAI,OAAO,SAAS,YAClB,KAAK,QACF,QAAQ,aAAa,SAAS,SAAS,UAAU,CAAC,CAClD,SAAS,aAAa;MACrB,SAAS,UAAU,OAAO;KAC5B,CAAC;KAGL,OAAO,KAAK,OAAO;IACrB;IACA,SAA4B;KAC1B,IAAI,KAAK,OAAO,aAAa,KAAK,SAAS,UACzC,OAAO,GAAG,KAAK,SAAS,QAAQ,MAAM,EAAE,SAAS,UAAU,CAAC,CAAC,OAAO;KAEtE,OAAO,KAAK,SAAS;IACvB;GACF,CAAC;GAED,gBAAgB,sBAAsB,QACnC,SAAS,SAAS,UACrB;EACF,QAAQ;GACN,gBAAgB,OAAO,QAAQ;EACjC;EAEA,IAAI,OAAO,kBAAkB,UAE3B,QAAQ,KAAK,CAAC;EAGhB,iBAAiB;CACnB;CAEA,IAAI,eAAe,WAAW,GAAG;EAC/B,UAAU,mCAAmC;EAC7C;CACF;CAEA,MAAM,gBAAgB,eACnB,KAAK,aAASC,mBAAQ,SAAS,IAAI,CAAC,CAAC,CACrC,QAAQ,SAAS;EAChB,IAAI,KAACC,oBAAW,IAAI,GAAG;GACrB,UAAU,uBAAmBC,mCAAW,IAAI,GAAG;GAC/C,OAAO;EACT;EACA,OAAO;CACT,CAAC;CAEH,IAAI,cAAc,WAAW,GAC3B;CAGF,MAAM,2BAAuBC,+DAAwB,aAAa;CAElE,KAAK,MAAM,YAAY,eACrB,IAAI;EACF,MAAM,eAAe,UAAU,aAAa;GAC1C;GACA;GACA,UAAU,QAAQ;GAClB,iBAAiB,QAAQ;EAC3B,CAAC;CACH,SAAS,OAAO;EACd,UAAU,uBAAuB,SAAS,IAAK,MAAgB,SAAS;CAC1E;CAGF,UAAMC,wCAAgB,aAAa;AACrC"}
1
+ {"version":3,"file":"extract.cjs","names":["getConfiguration","getAppLogger","x","colorize","ANSIColors","buildComponentFilesList","relative","resolve","existsSync","formatPath","getUnmergedDictionaries","prepareIntlayer"],"sources":["../../src/extract.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport type { PackageName } from '@intlayer/babel';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger, x } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getUnmergedDictionaries } from '@intlayer/dictionaries-entry/unmerged';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { buildComponentFilesList, formatPath } from '@intlayer/engine/utils';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport enquirer from 'enquirer';\n\ntype ExtractOptions = {\n files?: string[];\n output?: FilePathPattern;\n configOptions?: GetConfigurationOptions;\n codeOnly?: boolean;\n declarationOnly?: boolean;\n};\n\nexport const extract = async (options: ExtractOptions) => {\n const configuration = getConfiguration(options.configOptions);\n\n logConfigDetails(options?.configOptions);\n\n const appLogger = getAppLogger(configuration);\n\n const { baseDir } = configuration.system;\n const { output } = configuration.compiler;\n\n if (!output) {\n appLogger(\n `${x} No output configuration found. Add a ${colorize('compiler.output', ANSIColors.BLUE)} in your configuration.`,\n {\n level: 'error',\n }\n );\n return;\n }\n\n const { detectPackageName, extractContent } = await import('@intlayer/babel');\n\n // Detect package\n const packageName: PackageName = detectPackageName(baseDir);\n\n let filesToExtract = options.files ?? [];\n\n if (filesToExtract.length === 0) {\n // Await all promises simultaneously\n const fileList = buildComponentFilesList(configuration);\n\n // Flatten the nested arrays and remove duplicates\n // Relative paths for selection\n const choices = fileList.map((file) => {\n const relPath = relative(baseDir, file);\n\n return {\n value: file,\n label: relPath,\n };\n });\n\n if (choices.length === 0) {\n appLogger('No extractable files found in the project.');\n return;\n }\n\n const SELECT_ALL = '__select_all__';\n\n type PromptChoice = {\n name: string;\n enabled: boolean;\n disabled?: boolean | string;\n };\n\n type PromptContext = {\n choices: PromptChoice[];\n render(): void | Promise<void>;\n state: { submitted: boolean };\n selected: PromptChoice[];\n input: string;\n options: { multiple?: boolean };\n };\n\n let selectedFiles: string[] | symbol;\n try {\n const maxLen = Math.max((process.stdout.columns || 80) - 15, 20);\n const truncatePath = (path: string) =>\n path.length > maxLen ? `...${path.slice(-(maxLen - 3))}` : path;\n\n const { files: enquirerSelectedFiles } = await enquirer.prompt<{\n files: string[];\n }>({\n type: 'autocomplete',\n name: 'files',\n message: 'Select files to extract (Type to search):',\n multiple: true,\n // @ts-ignore limit exist but is not typed\n limit: 40,\n choices: [\n { name: SELECT_ALL, message: '────── Select all ──────' },\n ...choices.map((choice) => ({\n name: choice.value,\n message: truncatePath(choice.label),\n })),\n ],\n async toggle(\n this: PromptContext,\n choice: PromptChoice,\n enabled?: boolean\n ) {\n if (!choice || choice.disabled) return;\n choice.enabled = enabled == null ? !choice.enabled : enabled;\n\n if (choice.name === SELECT_ALL) {\n this.choices\n .filter((choiceEl) => choiceEl.name !== SELECT_ALL)\n .forEach((choiceEl) => {\n choiceEl.enabled = choice.enabled;\n });\n }\n\n return this.render();\n },\n format(this: PromptContext) {\n if (this.state?.submitted && this.options?.multiple) {\n return `${this.selected.filter((s) => s.name !== SELECT_ALL).length} file(s) selected`;\n }\n return this.input ?? '';\n },\n });\n\n selectedFiles = enquirerSelectedFiles.filter(\n (file) => file !== SELECT_ALL\n );\n } catch {\n selectedFiles = Symbol('cancel');\n }\n\n if (typeof selectedFiles === 'symbol') {\n // User cancelled\n process.exit(0);\n }\n\n filesToExtract = selectedFiles as string[];\n }\n\n if (filesToExtract.length === 0) {\n appLogger('No files selected for extraction.');\n return;\n }\n\n const absoluteFiles = filesToExtract\n .map((file) => resolve(baseDir, file))\n .filter((file) => {\n if (!existsSync(file)) {\n appLogger(`File not found: ${formatPath(file)}`);\n return false;\n }\n return true;\n });\n\n if (absoluteFiles.length === 0) {\n return;\n }\n\n const unmergedDictionaries = getUnmergedDictionaries(configuration);\n\n for (const filePath of absoluteFiles) {\n try {\n await extractContent(filePath, packageName, {\n unmergedDictionaries,\n configuration,\n codeOnly: options.codeOnly,\n declarationOnly: options.declarationOnly,\n });\n } catch (error) {\n appLogger(`Failed to transform ${filePath}: ${(error as Error).message}`);\n }\n }\n\n await prepareIntlayer(configuration); // Prepare Intlayer to apply the changes\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAwBA,MAAa,UAAU,OAAO,YAA4B;CACxD,MAAM,oBAAgBA,wCAAiB,QAAQ,aAAa;CAE5D,2CAAiB,SAAS,aAAa;CAEvC,MAAM,gBAAYC,sCAAa,aAAa;CAE5C,MAAM,EAAE,YAAY,cAAc;CAClC,MAAM,EAAE,WAAW,cAAc;CAEjC,IAAI,CAAC,QAAQ;EACX,UACE,GAAGC,0BAAE,4CAAwCC,kCAAS,mBAAmBC,wBAAW,IAAI,EAAE,0BAC1F,EACE,OAAO,QACT,CACF;EACA;CACF;CAEA,MAAM,EAAE,mBAAmB,mBAAmB,MAAM,OAAO;CAG3D,MAAM,cAA2B,kBAAkB,OAAO;CAE1D,IAAI,iBAAiB,QAAQ,SAAS,CAAC;CAEvC,IAAI,eAAe,WAAW,GAAG;EAM/B,MAAM,cAJWC,gDAAwB,aAIlB,CAAC,CAAC,KAAK,SAAS;GAGrC,OAAO;IACL,OAAO;IACP,WAJcC,oBAAS,SAAS,IAInB;GACf;EACF,CAAC;EAED,IAAI,QAAQ,WAAW,GAAG;GACxB,UAAU,4CAA4C;GACtD;EACF;EAEA,MAAM,aAAa;EAiBnB,IAAI;EACJ,IAAI;GACF,MAAM,SAAS,KAAK,KAAK,QAAQ,OAAO,WAAW,MAAM,IAAI,EAAE;GAC/D,MAAM,gBAAgB,SACpB,KAAK,SAAS,SAAS,MAAM,KAAK,MAAM,EAAE,SAAS,EAAE,MAAM;GAE7D,MAAM,EAAE,OAAO,0BAA0B,MAAM,iBAAS,OAErD;IACD,MAAM;IACN,MAAM;IACN,SAAS;IACT,UAAU;IAEV,OAAO;IACP,SAAS,CACP;KAAE,MAAM;KAAY,SAAS;IAA2B,GACxD,GAAG,QAAQ,KAAK,YAAY;KAC1B,MAAM,OAAO;KACb,SAAS,aAAa,OAAO,KAAK;IACpC,EAAE,CACJ;IACA,MAAM,OAEJ,QACA,SACA;KACA,IAAI,CAAC,UAAU,OAAO,UAAU;KAChC,OAAO,UAAU,WAAW,OAAO,CAAC,OAAO,UAAU;KAErD,IAAI,OAAO,SAAS,YAClB,KAAK,QACF,QAAQ,aAAa,SAAS,SAAS,UAAU,CAAC,CAClD,SAAS,aAAa;MACrB,SAAS,UAAU,OAAO;KAC5B,CAAC;KAGL,OAAO,KAAK,OAAO;IACrB;IACA,SAA4B;KAC1B,IAAI,KAAK,OAAO,aAAa,KAAK,SAAS,UACzC,OAAO,GAAG,KAAK,SAAS,QAAQ,MAAM,EAAE,SAAS,UAAU,CAAC,CAAC,OAAO;KAEtE,OAAO,KAAK,SAAS;IACvB;GACF,CAAC;GAED,gBAAgB,sBAAsB,QACnC,SAAS,SAAS,UACrB;EACF,QAAQ;GACN,gBAAgB,OAAO,QAAQ;EACjC;EAEA,IAAI,OAAO,kBAAkB,UAE3B,QAAQ,KAAK,CAAC;EAGhB,iBAAiB;CACnB;CAEA,IAAI,eAAe,WAAW,GAAG;EAC/B,UAAU,mCAAmC;EAC7C;CACF;CAEA,MAAM,gBAAgB,eACnB,KAAK,aAASC,mBAAQ,SAAS,IAAI,CAAC,CAAC,CACrC,QAAQ,SAAS;EAChB,IAAI,KAACC,oBAAW,IAAI,GAAG;GACrB,UAAU,uBAAmBC,mCAAW,IAAI,GAAG;GAC/C,OAAO;EACT;EACA,OAAO;CACT,CAAC;CAEH,IAAI,cAAc,WAAW,GAC3B;CAGF,MAAM,2BAAuBC,+DAAwB,aAAa;CAElE,KAAK,MAAM,YAAY,eACrB,IAAI;EACF,MAAM,eAAe,UAAU,aAAa;GAC1C;GACA;GACA,UAAU,QAAQ;GAClB,iBAAiB,QAAQ;EAC3B,CAAC;CACH,SAAS,OAAO;EACd,UAAU,uBAAuB,SAAS,IAAK,MAAgB,SAAS;CAC1E;CAGF,UAAMC,wCAAgB,aAAa;AACrC"}
@@ -2,8 +2,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  let node_path = require("node:path");
3
3
  let _intlayer_config_colors = require("@intlayer/config/colors");
4
4
  let _intlayer_config_logger = require("@intlayer/config/logger");
5
- let _intlayer_engine_utils = require("@intlayer/engine/utils");
6
5
  let _intlayer_config_utils = require("@intlayer/config/utils");
6
+ let _intlayer_engine_utils = require("@intlayer/engine/utils");
7
7
 
8
8
  //#region src/fill/formatAutoFilledFilePath.ts
9
9
  const formatAutoFilledFilePath = async (autoFillField, dictionaryKey, dictionaryFilePath, baseDir, configuration, locale) => {
@@ -5,8 +5,8 @@ let node_path = require("node:path");
5
5
  let _intlayer_config_colors = require("@intlayer/config/colors");
6
6
  _intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
7
7
  let _intlayer_config_logger = require("@intlayer/config/logger");
8
+ let _intlayer_dictionaries_entry_unmerged = require("@intlayer/dictionaries-entry/unmerged");
8
9
  let _intlayer_engine_utils = require("@intlayer/engine/utils");
9
- let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
10
10
  let _intlayer_core_plugins = require("@intlayer/core/plugins");
11
11
  let _intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
12
12
 
@@ -14,7 +14,7 @@ let _intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
14
14
  const listTranslationsTasks = (localIds, outputLocales, mode, baseLocale, configuration) => {
15
15
  const appLogger = (0, _intlayer_config_logger.getAppLogger)(configuration);
16
16
  const mergedDictionariesRecord = (0, _intlayer_dictionaries_entry.getDictionaries)(configuration);
17
- const unmergedDictionariesRecord = (0, _intlayer_unmerged_dictionaries_entry.getUnmergedDictionaries)(configuration);
17
+ const unmergedDictionariesRecord = (0, _intlayer_dictionaries_entry_unmerged.getUnmergedDictionaries)(configuration);
18
18
  const dictionariesToProcess = Object.values(unmergedDictionariesRecord).flat().filter((dictionary) => localIds.includes(dictionary.localId));
19
19
  const { missingTranslations } = require_test_listMissingTranslations.listMissingTranslationsWithConfig(configuration);
20
20
  const maxKeyLength = Math.max(...dictionariesToProcess.map((dictionary) => dictionary.key.length));
@@ -1 +1 @@
1
- {"version":3,"file":"listTranslationsTasks.cjs","names":["getAppLogger","getDictionaries","getUnmergedDictionaries","listMissingTranslationsWithConfig","colon","colorize","ANSIColors","colorizeKey","getFilterTranslationsOnlyDictionary","formatLocale","colorizePath","basename"],"sources":["../../../src/fill/listTranslationsTasks.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport {\n colon,\n colorize,\n colorizeKey,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport { getFilterTranslationsOnlyDictionary } from '@intlayer/core/plugins';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { formatLocale } from '@intlayer/engine/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary, LocalDictionaryId } from '@intlayer/types/dictionary';\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} ${colorize('No locales to fill, Skipping', ANSIColors.GREY_DARK)} ${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":";;;;;;;;;;;;;AA2BA,MAAa,yBACX,UACA,eACA,MACA,YACA,kBACsB;CACtB,MAAM,gBAAYA,sCAAa,aAAa;CAE5C,MAAM,+BAA2BC,8CAAgB,aAAa;CAC9D,MAAM,iCAA6BC,+DAAwB,aAAa;CAGxE,MAAM,wBADsB,OAAO,OAAO,0BAA0B,CAAC,CAAC,KACtB,CAAC,CAAC,QAAQ,eACxD,SAAS,SAAS,WAAW,OAAQ,CACvC;CAEA,MAAM,EAAE,wBACNC,uEAAkC,aAAa;CAEjD,MAAM,eAAe,KAAK,IACxB,GAAG,sBAAsB,KAAK,eAAe,WAAW,IAAI,MAAM,CACpE;CAEA,MAAM,mBAAsC,CAAC;CAE7C,KAAK,MAAM,4BAA4B,uBAAuB;EAC5D,MAAM,uBAAmBC,+BACvB;GACE;OACAC,kCAAS,KAAKC,wBAAW,SAAS;OAClCC,qCAAY,yBAAyB,GAAG;OACxCF,kCAAS,KAAKC,wBAAW,SAAS;EACpC,CAAC,CAAC,KAAK,EAAE,GACT,EAAE,SAAS,eAAe,EAAE,CAC9B;EAEA,MAAM,gBAAgB,yBAAyB;EAC/C,MAAM,oBAAoB,yBAAyB;EACnD,MAAM,0BACJ,yBAAyB;EAG3B,KAFyB,yBAAyB,UAAU,WAEnC,MACvB;EAMF,KAFE,yBAAyB,QAAQ,cAAc,YAAY,QAAQ,WAE9C,OAAO;EAE9B,MAAM,eAAwB,yBAAyB,UACrD;EAEF,IAAI,CAAC,yBAAyB;GAC5B,UACE,GAAG,iBAAiB,yDACpB,EACE,OAAO,OACT,CACF;GACA;EACF;EAEA,IAAI,CAAC,yBAAyB,UAAU;GACtC,UAAU,GAAG,iBAAiB,0CAA0C,EACtE,OAAO,OACT,CAAC;GACD;EACF;EAEA,MAAM,0BAAsBE,4DAC1B,yBACA,YACF;EAEA,IACE,OAAO,KAAK,mBAA8C,CAAC,CAAC,WAAW,GACvE;GACA,UACE,GAAG,iBAAiB,wDAAoDC,qCAAa,YAAY,EAAE,8CACnG,EACE,OAAO,OACT,CACF;GACA;EACF;;;;;;EAOA,IAAI,oBAA8B;EAElC,IAAI,SAAS,YACX,oBACE,oBACG,MACE,uBAAuB,mBAAmB,QAAQ,aACrD,CAAC,EACC,QAAQ,QAAQ,WAAW,cAAc,SAAS,MAAM,CAAC,KAAK,CAAC;EAGvE,IAAI,kBAAkB,WAAW,GAAG;GAClC,UACE,GAAG,iBAAiB,OAAGJ,kCAAS,gCAAgCC,wBAAW,SAAS,EAAE,OAAGI,0CAAaC,oBAAS,yBAAyB,QAAQ,CAAC,KACjJ,EACE,OAAO,OACT,CACF;GACA;EACF;EAEA,iBAAiB,KAAK;GACpB;GACA;GACA;GACA,eAAe;GACf;GACA,oBAAoB,yBAAyB;EAC/C,CAAC;CACH;CAGA,OAAO;AACT"}
1
+ {"version":3,"file":"listTranslationsTasks.cjs","names":["getAppLogger","getDictionaries","getUnmergedDictionaries","listMissingTranslationsWithConfig","colon","colorize","ANSIColors","colorizeKey","getFilterTranslationsOnlyDictionary","formatLocale","colorizePath","basename"],"sources":["../../../src/fill/listTranslationsTasks.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport {\n colon,\n colorize,\n colorizeKey,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport { getFilterTranslationsOnlyDictionary } from '@intlayer/core/plugins';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { getUnmergedDictionaries } from '@intlayer/dictionaries-entry/unmerged';\nimport { formatLocale } from '@intlayer/engine/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary, LocalDictionaryId } from '@intlayer/types/dictionary';\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 | undefined =\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} ${colorize('No locales to fill, Skipping', ANSIColors.GREY_DARK)} ${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":";;;;;;;;;;;;;AA2BA,MAAa,yBACX,UACA,eACA,MACA,YACA,kBACsB;CACtB,MAAM,gBAAYA,sCAAa,aAAa;CAE5C,MAAM,+BAA2BC,8CAAgB,aAAa;CAC9D,MAAM,iCAA6BC,+DAAwB,aAAa;CAGxE,MAAM,wBADsB,OAAO,OAAO,0BAA0B,CAAC,CAAC,KACtB,CAAC,CAAC,QAAQ,eACxD,SAAS,SAAS,WAAW,OAAQ,CACvC;CAEA,MAAM,EAAE,wBACNC,uEAAkC,aAAa;CAEjD,MAAM,eAAe,KAAK,IACxB,GAAG,sBAAsB,KAAK,eAAe,WAAW,IAAI,MAAM,CACpE;CAEA,MAAM,mBAAsC,CAAC;CAE7C,KAAK,MAAM,4BAA4B,uBAAuB;EAC5D,MAAM,uBAAmBC,+BACvB;GACE;OACAC,kCAAS,KAAKC,wBAAW,SAAS;OAClCC,qCAAY,yBAAyB,GAAG;OACxCF,kCAAS,KAAKC,wBAAW,SAAS;EACpC,CAAC,CAAC,KAAK,EAAE,GACT,EAAE,SAAS,eAAe,EAAE,CAC9B;EAEA,MAAM,gBAAgB,yBAAyB;EAC/C,MAAM,oBAAoB,yBAAyB;EACnD,MAAM,0BACJ,yBAAyB;EAG3B,KAFyB,yBAAyB,UAAU,WAEnC,MACvB;EAMF,KAFE,yBAAyB,QAAQ,cAAc,YAAY,QAAQ,WAE9C,OAAO;EAE9B,MAAM,eAAwB,yBAAyB,UACrD;EAEF,IAAI,CAAC,yBAAyB;GAC5B,UACE,GAAG,iBAAiB,yDACpB,EACE,OAAO,OACT,CACF;GACA;EACF;EAEA,IAAI,CAAC,yBAAyB,UAAU;GACtC,UAAU,GAAG,iBAAiB,0CAA0C,EACtE,OAAO,OACT,CAAC;GACD;EACF;EAEA,MAAM,0BAAsBE,4DAC1B,yBACA,YACF;EAEA,IACE,OAAO,KAAK,mBAA8C,CAAC,CAAC,WAAW,GACvE;GACA,UACE,GAAG,iBAAiB,wDAAoDC,qCAAa,YAAY,EAAE,8CACnG,EACE,OAAO,OACT,CACF;GACA;EACF;;;;;;EAOA,IAAI,oBAA8B;EAElC,IAAI,SAAS,YACX,oBACE,oBACG,MACE,uBAAuB,mBAAmB,QAAQ,aACrD,CAAC,EACC,QAAQ,QAAQ,WAAW,cAAc,SAAS,MAAM,CAAC,KAAK,CAAC;EAGvE,IAAI,kBAAkB,WAAW,GAAG;GAClC,UACE,GAAG,iBAAiB,OAAGJ,kCAAS,gCAAgCC,wBAAW,SAAS,EAAE,OAAGI,0CAAaC,oBAAS,yBAAyB,QAAQ,CAAC,KACjJ,EACE,OAAO,OACT,CACF;GACA;EACF;EAEA,iBAAiB,KAAK;GACpB;GACA;GACA;GACA,eAAe;GACf;GACA,oBAAoB,yBAAyB;EAC/C,CAAC;CACH;CAGA,OAAO;AACT"}
@@ -7,10 +7,10 @@ let node_path = require("node:path");
7
7
  let _intlayer_config_colors = require("@intlayer/config/colors");
8
8
  _intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
9
9
  let _intlayer_config_logger = require("@intlayer/config/logger");
10
+ let _intlayer_config_utils = require("@intlayer/config/utils");
11
+ let _intlayer_dictionaries_entry_unmerged = require("@intlayer/dictionaries-entry/unmerged");
10
12
  let _intlayer_engine_utils = require("@intlayer/engine/utils");
11
- let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
12
13
  let _intlayer_core_plugins = require("@intlayer/core/plugins");
13
- let _intlayer_config_utils = require("@intlayer/config/utils");
14
14
 
15
15
  //#region src/fill/translateDictionary.ts
16
16
  const createChunkPreset = (chunkIndex, totalChunks) => {
@@ -51,8 +51,8 @@ const translateDictionary = async (task, configuration, options) => {
51
51
  options?.onSuccess?.();
52
52
  };
53
53
  return await (0, _intlayer_config_utils.retryManager)(async () => {
54
- const unmergedDictionariesRecord = (0, _intlayer_unmerged_dictionaries_entry.getUnmergedDictionaries)(configuration);
55
- const baseUnmergedDictionary = unmergedDictionariesRecord[task.dictionaryKey].find((dict) => dict.localId === task.dictionaryLocalId);
54
+ const unmergedDictionariesRecord = (0, _intlayer_dictionaries_entry_unmerged.getUnmergedDictionaries)(configuration);
55
+ const baseUnmergedDictionary = unmergedDictionariesRecord[task.dictionaryKey]?.find((dict) => dict.localId === task.dictionaryLocalId);
56
56
  if (!baseUnmergedDictionary) {
57
57
  appLogger(`${task.dictionaryPreset}Dictionary not found in unmergedDictionariesRecord. Skipping.`, { level: "warn" });
58
58
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"translateDictionary.cjs","names":["colon","colorize","ANSIColors","colorizeNumber","getAppLogger","getAuthenticatedAPI","retryManager","getUnmergedDictionaries","getPerLocaleDictionary","colorizePath","basename","getFilterMissingTranslationsDictionary","excludeObjectFormat","formatLocale","chunkJSON","reconstructFromSingleChunk","extractTranslatableContent","verifyIdenticObjectFormat","reinsertTranslatedContent","mergeChunks","deepMergeContent","getMultilingualDictionary","insertContentInDictionary"],"sources":["../../../src/fill/translateDictionary.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport type { AIConfig } from '@intlayer/ai';\nimport type { AIOptions } from '@intlayer/api';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport {\n colon,\n colorize,\n colorizeNumber,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport { retryManager } from '@intlayer/config/utils';\nimport {\n getFilterMissingTranslationsDictionary,\n getMultilingualDictionary,\n getPerLocaleDictionary,\n insertContentInDictionary,\n} from '@intlayer/core/plugins';\nimport {\n chunkJSON,\n excludeObjectFormat,\n formatLocale,\n type JsonChunk,\n mergeChunks,\n reconstructFromSingleChunk,\n verifyIdenticObjectFormat,\n} from '@intlayer/engine/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { getAuthenticatedAPI } from '../utils/checkAccess';\nimport type { AIClient } from '../utils/setupAI';\nimport { deepMergeContent } from './deepMergeContent';\nimport {\n extractTranslatableContent,\n reinsertTranslatedContent,\n} from './extractTranslatableContent';\nimport type { TranslationTask } from './listTranslationsTasks';\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<\n typeof import('@intlayer/engine/utils').getGlobalLimiter\n >;\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n getAbortError?: () => Error | null;\n aiClient?: AIClient;\n aiConfig?: AIConfig;\n};\n\nconst createChunkPreset = (chunkIndex: number, totalChunks: number) => {\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\nconst hasMissingMetadata = (dictionary: Dictionary) =>\n !dictionary.description || !dictionary.title || !dictionary.tags;\n\nconst serializeError = (error: unknown): string => {\n if (error instanceof Error) {\n return error.cause\n ? `${error.message} (cause: ${String(error.cause)})`\n : error.message;\n }\n if (typeof error === 'string') return error;\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n};\n\nconst CHUNK_SIZE = 4000;\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 = await getAuthenticatedAPI(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 // Look up the target locale dictionary by its locale property.\n // This handles both directory-based paths (/en/file.json → /es/file.json)\n // AND filename-based paths (messages_ICU/en.json → messages_ICU/es.json).\n // Plugins like syncJSON set `dict.locale` correctly, so matching by locale\n // is the only reliable strategy — path string-replacement fails when the\n // locale appears in the filename rather than a directory segment.\n const targetUnmergedDictionary = unmergedDictionariesRecord[\n task.dictionaryKey\n ]?.find(\n (dict) =>\n dict.locale === targetLocale &&\n dict.filePath !== baseUnmergedDictionary.filePath\n );\n\n // Derive the target file path for the fallback (when the file doesn't exist yet).\n // Try directory-style first (/en/ → /es/), then filename-style (en.json → es.json).\n const sourceFilePath = baseUnmergedDictionary.filePath ?? '';\n const derivedTargetFilePath = sourceFilePath.includes(\n `/${task.sourceLocale}/`\n )\n ? sourceFilePath.replace(\n new RegExp(`/${task.sourceLocale}/`, 'g'),\n `/${targetLocale}/`\n )\n : sourceFilePath.replace(\n new RegExp(`(^|/)${task.sourceLocale}(\\\\.[^/]+)$`),\n `$1${targetLocale}$2`\n );\n\n targetLocaleDictionary = targetUnmergedDictionary ?? {\n key: baseUnmergedDictionary.key,\n content: {},\n filePath: derivedTargetFilePath || undefined,\n locale: targetLocale,\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 // Filter to only untranslated fields, preserving explicit null values as\n // default-locale fallback markers. Applied after both paths converge so\n // the same logic covers per-locale and multilingual dictionaries.\n if (mode === 'complete') {\n dictionaryToProcess = {\n ...dictionaryToProcess,\n content:\n excludeObjectFormat(\n dictionaryToProcess.content,\n targetLocaleDictionary.content\n ) ?? {},\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 appLogger(\n `${task.dictionaryPreset}${localePreset} Preparing ${colorizePath(basename(targetLocaleDictionary.filePath!))}`,\n {\n level: 'info',\n }\n );\n\n const chunkedJsonContent: JsonChunk[] = chunkJSON(\n dictionaryToProcess.content 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(async (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 const reconstructedChunk = reconstructFromSingleChunk(chunk);\n const {\n extractedContent: chunkExtractedContent,\n translatableDictionary: chunkTranslatableDictionary,\n } = extractTranslatableContent(reconstructedChunk);\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:\n chunkTranslatableDictionary as unknown as JSON,\n presetOutputContent: chunkTranslatableDictionary,\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:\n chunkTranslatableDictionary as unknown as JSON,\n presetOutputContent: chunkTranslatableDictionary,\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, error } = verifyIdenticObjectFormat(\n translationResult.fileContent,\n chunkTranslatableDictionary\n );\n\n if (!isIdentic) {\n throw new Error(\n `Translation result does not match expected format: ${error}`\n );\n }\n\n notifySuccess();\n return reinsertTranslatedContent(\n reconstructedChunk,\n chunkExtractedContent,\n translationResult.fileContent as Record<number, string>\n );\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(serializeError(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 translated chunk contents back into a single content object\n const reinsertedContent = mergeChunks(chunkResult);\n\n const merged = {\n ...dictionaryToProcess,\n content: reinsertedContent,\n };\n\n // Merge newly translated content (including explicit null fallbacks) back\n // into the existing target locale content. Applies to both per-locale and\n // multilingual paths so the target always retains previously translated\n // fields and receives null markers where the source has no translation.\n const finalContent = deepMergeContent(\n targetLocaleDictionary.content ?? {},\n merged.content\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 // The dict-level `fill` value may have been lost during JSON serialisation\n // (functions can't be serialised to JSON). Fall back to the config-level\n // fill so that an explicit fill in intlayer.config.ts is honoured.\n const effectiveFillForCheck =\n baseUnmergedDictionary.fill ?? configuration.dictionary?.fill;\n\n if (\n baseUnmergedDictionary.locale &&\n (effectiveFillForCheck === true ||\n effectiveFillForCheck === 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:', ANSIColors.RED)} ${colorize(serializeError(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(serializeError(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":["colon","colorize","ANSIColors","colorizeNumber","getAppLogger","getAuthenticatedAPI","retryManager","getUnmergedDictionaries","getPerLocaleDictionary","colorizePath","basename","getFilterMissingTranslationsDictionary","excludeObjectFormat","formatLocale","chunkJSON","reconstructFromSingleChunk","extractTranslatableContent","verifyIdenticObjectFormat","reinsertTranslatedContent","mergeChunks","deepMergeContent","getMultilingualDictionary","insertContentInDictionary"],"sources":["../../../src/fill/translateDictionary.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport type { AIConfig } from '@intlayer/ai';\nimport type { AIOptions } from '@intlayer/api';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport {\n colon,\n colorize,\n colorizeNumber,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport { retryManager } from '@intlayer/config/utils';\nimport {\n getFilterMissingTranslationsDictionary,\n getMultilingualDictionary,\n getPerLocaleDictionary,\n insertContentInDictionary,\n} from '@intlayer/core/plugins';\nimport { getUnmergedDictionaries } from '@intlayer/dictionaries-entry/unmerged';\nimport {\n chunkJSON,\n excludeObjectFormat,\n formatLocale,\n type JsonChunk,\n mergeChunks,\n reconstructFromSingleChunk,\n verifyIdenticObjectFormat,\n} from '@intlayer/engine/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { getAuthenticatedAPI } from '../utils/checkAccess';\nimport type { AIClient } from '../utils/setupAI';\nimport { deepMergeContent } from './deepMergeContent';\nimport {\n extractTranslatableContent,\n reinsertTranslatedContent,\n} from './extractTranslatableContent';\nimport type { TranslationTask } from './listTranslationsTasks';\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<\n typeof import('@intlayer/engine/utils').getGlobalLimiter\n >;\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n getAbortError?: () => Error | null;\n aiClient?: AIClient;\n aiConfig?: AIConfig;\n};\n\nconst createChunkPreset = (chunkIndex: number, totalChunks: number) => {\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\nconst hasMissingMetadata = (dictionary: Dictionary) =>\n !dictionary.description || !dictionary.title || !dictionary.tags;\n\nconst serializeError = (error: unknown): string => {\n if (error instanceof Error) {\n return error.cause\n ? `${error.message} (cause: ${String(error.cause)})`\n : error.message;\n }\n if (typeof error === 'string') return error;\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n};\n\nconst CHUNK_SIZE = 4000;\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 = await getAuthenticatedAPI(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 // Look up the target locale dictionary by its locale property.\n // This handles both directory-based paths (/en/file.json → /es/file.json)\n // AND filename-based paths (messages_ICU/en.json → messages_ICU/es.json).\n // Plugins like syncJSON set `dict.locale` correctly, so matching by locale\n // is the only reliable strategy — path string-replacement fails when the\n // locale appears in the filename rather than a directory segment.\n const targetUnmergedDictionary = unmergedDictionariesRecord[\n task.dictionaryKey\n ]?.find(\n (dict) =>\n dict.locale === targetLocale &&\n dict.filePath !== baseUnmergedDictionary.filePath\n );\n\n // Derive the target file path for the fallback (when the file doesn't exist yet).\n // Try directory-style first (/en/ → /es/), then filename-style (en.json → es.json).\n const sourceFilePath = baseUnmergedDictionary.filePath ?? '';\n const derivedTargetFilePath = sourceFilePath.includes(\n `/${task.sourceLocale}/`\n )\n ? sourceFilePath.replace(\n new RegExp(`/${task.sourceLocale}/`, 'g'),\n `/${targetLocale}/`\n )\n : sourceFilePath.replace(\n new RegExp(`(^|/)${task.sourceLocale}(\\\\.[^/]+)$`),\n `$1${targetLocale}$2`\n );\n\n targetLocaleDictionary = targetUnmergedDictionary ?? {\n key: baseUnmergedDictionary.key,\n content: {},\n filePath: derivedTargetFilePath || undefined,\n locale: targetLocale,\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 // Filter to only untranslated fields, preserving explicit null values as\n // default-locale fallback markers. Applied after both paths converge so\n // the same logic covers per-locale and multilingual dictionaries.\n if (mode === 'complete') {\n dictionaryToProcess = {\n ...dictionaryToProcess,\n content:\n excludeObjectFormat(\n dictionaryToProcess.content,\n targetLocaleDictionary.content\n ) ?? {},\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 appLogger(\n `${task.dictionaryPreset}${localePreset} Preparing ${colorizePath(basename(targetLocaleDictionary.filePath!))}`,\n {\n level: 'info',\n }\n );\n\n const chunkedJsonContent: JsonChunk[] = chunkJSON(\n dictionaryToProcess.content 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(async (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 const reconstructedChunk = reconstructFromSingleChunk(chunk);\n const {\n extractedContent: chunkExtractedContent,\n translatableDictionary: chunkTranslatableDictionary,\n } = extractTranslatableContent(reconstructedChunk);\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:\n chunkTranslatableDictionary as unknown as JSON,\n presetOutputContent: chunkTranslatableDictionary,\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:\n chunkTranslatableDictionary as unknown as JSON,\n presetOutputContent: chunkTranslatableDictionary,\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, error } = verifyIdenticObjectFormat(\n translationResult.fileContent,\n chunkTranslatableDictionary\n );\n\n if (!isIdentic) {\n throw new Error(\n `Translation result does not match expected format: ${error}`\n );\n }\n\n notifySuccess();\n return reinsertTranslatedContent(\n reconstructedChunk,\n chunkExtractedContent,\n translationResult.fileContent as Record<number, string>\n );\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(serializeError(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 translated chunk contents back into a single content object\n const reinsertedContent = mergeChunks(chunkResult);\n\n const merged = {\n ...dictionaryToProcess,\n content: reinsertedContent,\n };\n\n // Merge newly translated content (including explicit null fallbacks) back\n // into the existing target locale content. Applies to both per-locale and\n // multilingual paths so the target always retains previously translated\n // fields and receives null markers where the source has no translation.\n const finalContent = deepMergeContent(\n targetLocaleDictionary.content ?? {},\n merged.content\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 // The dict-level `fill` value may have been lost during JSON serialisation\n // (functions can't be serialised to JSON). Fall back to the config-level\n // fill so that an explicit fill in intlayer.config.ts is honoured.\n const effectiveFillForCheck =\n baseUnmergedDictionary.fill ?? configuration.dictionary?.fill;\n\n if (\n baseUnmergedDictionary.locale &&\n (effectiveFillForCheck === true ||\n effectiveFillForCheck === 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:', ANSIColors.RED)} ${colorize(serializeError(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(serializeError(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
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  let node_path = require("node:path");
3
3
  let _intlayer_config_node = require("@intlayer/config/node");
4
+ let _intlayer_dictionaries_entry_unmerged = require("@intlayer/dictionaries-entry/unmerged");
4
5
  let _intlayer_engine_cli = require("@intlayer/engine/cli");
5
- let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
6
6
 
7
7
  //#region src/getTargetDictionary.ts
8
8
  const ensureArray = (value) => [value].flat();
9
9
  const getTargetUnmergedDictionaries = async (options) => {
10
10
  const configuration = (0, _intlayer_config_node.getConfiguration)(options?.configOptions);
11
11
  const { baseDir } = configuration.system;
12
- const unmergedDictionariesRecord = (0, _intlayer_unmerged_dictionaries_entry.getUnmergedDictionaries)(configuration);
12
+ const unmergedDictionariesRecord = (0, _intlayer_dictionaries_entry_unmerged.getUnmergedDictionaries)(configuration);
13
13
  let result = Object.values(unmergedDictionariesRecord).flat();
14
14
  if (typeof options?.file !== "undefined") {
15
15
  const relativeFilePaths = ensureArray(options?.file).map((file) => file.startsWith("/") ? (0, node_path.relative)(baseDir, file) : (0, node_path.join)("./", file));
@@ -1 +1 @@
1
- {"version":3,"file":"getTargetDictionary.cjs","names":["getConfiguration","getUnmergedDictionaries","relative","join","listGitFiles"],"sources":["../../src/getTargetDictionary.ts"],"sourcesContent":["import { join, relative } from 'node:path';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { type ListGitFilesOptions, listGitFiles } from '@intlayer/engine/cli';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\n\nexport const ensureArray = <T>(value: T | T[]): T[] => [value].flat() as T[];\n\n// Arguments for the fill function\nexport type GetTargetDictionaryOptions = {\n file?: string | string[];\n keys?: string | string[];\n excludedKeys?: string | string[];\n filter?: (entry: Dictionary) => boolean; // DictionaryEntry needs to be defined\n pathFilter?: string | string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n};\n\nexport const getTargetUnmergedDictionaries = async (\n options?: GetTargetDictionaryOptions\n): Promise<Dictionary[]> => {\n const configuration = getConfiguration(options?.configOptions);\n\n const { baseDir } = configuration.system;\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);\n let result = Object.values(unmergedDictionariesRecord).flat();\n\n // 1. if filePath not defined, list all content declaration files based on unmerged dictionaries list\n if (typeof options?.file !== 'undefined') {\n const fileArray = ensureArray(options?.file);\n const relativeFilePaths = fileArray.map((file) =>\n file.startsWith('/') ? relative(baseDir, file) : join('./', file)\n );\n\n result = result.filter(\n (dict) =>\n dict.filePath &&\n // Check for absolute path\n relativeFilePaths.includes(dict.filePath)\n );\n }\n\n if (typeof options?.keys !== 'undefined') {\n result = result.filter((dict) =>\n ensureArray(options?.keys)?.includes(dict.key)\n );\n }\n\n if (typeof options?.excludedKeys !== 'undefined') {\n result = result.filter(\n (dict) => !ensureArray(options?.excludedKeys)?.includes(dict.key)\n );\n }\n\n if (typeof options?.pathFilter !== 'undefined') {\n result = result.filter((dict) =>\n ensureArray(options?.pathFilter)?.includes(dict.filePath ?? '')\n );\n }\n\n if (typeof options?.filter !== 'undefined') {\n result = result.filter(options?.filter);\n }\n\n const gitOptions = options?.gitOptions;\n if (gitOptions) {\n const gitChangedFiles = await listGitFiles(gitOptions);\n\n if (gitChangedFiles) {\n // Convert dictionary file paths to be relative to git root for comparison\n\n // Filter dictionaries based on git changed files\n result = result.filter((dict) => {\n if (!dict.filePath) return false;\n\n return gitChangedFiles.some((gitFile) => dict.filePath === gitFile);\n });\n }\n }\n\n return result;\n};\n"],"mappings":";;;;;;;AASA,MAAa,eAAkB,UAAwB,CAAC,KAAK,CAAC,CAAC,KAAK;AAapE,MAAa,gCAAgC,OAC3C,YAC0B;CAC1B,MAAM,oBAAgBA,wCAAiB,SAAS,aAAa;CAE7D,MAAM,EAAE,YAAY,cAAc;CAElC,MAAM,iCAA6BC,+DAAwB,aAAa;CACxE,IAAI,SAAS,OAAO,OAAO,0BAA0B,CAAC,CAAC,KAAK;CAG5D,IAAI,OAAO,SAAS,SAAS,aAAa;EAExC,MAAM,oBADY,YAAY,SAAS,IACL,CAAC,CAAC,KAAK,SACvC,KAAK,WAAW,GAAG,QAAIC,oBAAS,SAAS,IAAI,QAAIC,gBAAK,MAAM,IAAI,CAClE;EAEA,SAAS,OAAO,QACb,SACC,KAAK,YAEL,kBAAkB,SAAS,KAAK,QAAQ,CAC5C;CACF;CAEA,IAAI,OAAO,SAAS,SAAS,aAC3B,SAAS,OAAO,QAAQ,SACtB,YAAY,SAAS,IAAI,CAAC,EAAE,SAAS,KAAK,GAAG,CAC/C;CAGF,IAAI,OAAO,SAAS,iBAAiB,aACnC,SAAS,OAAO,QACb,SAAS,CAAC,YAAY,SAAS,YAAY,CAAC,EAAE,SAAS,KAAK,GAAG,CAClE;CAGF,IAAI,OAAO,SAAS,eAAe,aACjC,SAAS,OAAO,QAAQ,SACtB,YAAY,SAAS,UAAU,CAAC,EAAE,SAAS,KAAK,YAAY,EAAE,CAChE;CAGF,IAAI,OAAO,SAAS,WAAW,aAC7B,SAAS,OAAO,OAAO,SAAS,MAAM;CAGxC,MAAM,aAAa,SAAS;CAC5B,IAAI,YAAY;EACd,MAAM,kBAAkB,UAAMC,mCAAa,UAAU;EAErD,IAAI,iBAIF,SAAS,OAAO,QAAQ,SAAS;GAC/B,IAAI,CAAC,KAAK,UAAU,OAAO;GAE3B,OAAO,gBAAgB,MAAM,YAAY,KAAK,aAAa,OAAO;EACpE,CAAC;CAEL;CAEA,OAAO;AACT"}
1
+ {"version":3,"file":"getTargetDictionary.cjs","names":["getConfiguration","getUnmergedDictionaries","relative","join","listGitFiles"],"sources":["../../src/getTargetDictionary.ts"],"sourcesContent":["import { join, relative } from 'node:path';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getUnmergedDictionaries } from '@intlayer/dictionaries-entry/unmerged';\nimport { type ListGitFilesOptions, listGitFiles } from '@intlayer/engine/cli';\nimport type { Dictionary } from '@intlayer/types/dictionary';\n\nexport const ensureArray = <T>(value: T | T[]): T[] => [value].flat() as T[];\n\n// Arguments for the fill function\nexport type GetTargetDictionaryOptions = {\n file?: string | string[];\n keys?: string | string[];\n excludedKeys?: string | string[];\n filter?: (entry: Dictionary) => boolean; // DictionaryEntry needs to be defined\n pathFilter?: string | string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n};\n\nexport const getTargetUnmergedDictionaries = async (\n options?: GetTargetDictionaryOptions\n): Promise<Dictionary[]> => {\n const configuration = getConfiguration(options?.configOptions);\n\n const { baseDir } = configuration.system;\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);\n let result = Object.values(unmergedDictionariesRecord).flat();\n\n // 1. if filePath not defined, list all content declaration files based on unmerged dictionaries list\n if (typeof options?.file !== 'undefined') {\n const fileArray = ensureArray(options?.file);\n const relativeFilePaths = fileArray.map((file) =>\n file.startsWith('/') ? relative(baseDir, file) : join('./', file)\n );\n\n result = result.filter(\n (dict) =>\n dict.filePath &&\n // Check for absolute path\n relativeFilePaths.includes(dict.filePath)\n );\n }\n\n if (typeof options?.keys !== 'undefined') {\n result = result.filter((dict) =>\n ensureArray(options?.keys)?.includes(dict.key)\n );\n }\n\n if (typeof options?.excludedKeys !== 'undefined') {\n result = result.filter(\n (dict) => !ensureArray(options?.excludedKeys)?.includes(dict.key)\n );\n }\n\n if (typeof options?.pathFilter !== 'undefined') {\n result = result.filter((dict) =>\n ensureArray(options?.pathFilter)?.includes(dict.filePath ?? '')\n );\n }\n\n if (typeof options?.filter !== 'undefined') {\n result = result.filter(options?.filter);\n }\n\n const gitOptions = options?.gitOptions;\n if (gitOptions) {\n const gitChangedFiles = await listGitFiles(gitOptions);\n\n if (gitChangedFiles) {\n // Convert dictionary file paths to be relative to git root for comparison\n\n // Filter dictionaries based on git changed files\n result = result.filter((dict) => {\n if (!dict.filePath) return false;\n\n return gitChangedFiles.some((gitFile) => dict.filePath === gitFile);\n });\n }\n }\n\n return result;\n};\n"],"mappings":";;;;;;;AASA,MAAa,eAAkB,UAAwB,CAAC,KAAK,CAAC,CAAC,KAAK;AAapE,MAAa,gCAAgC,OAC3C,YAC0B;CAC1B,MAAM,oBAAgBA,wCAAiB,SAAS,aAAa;CAE7D,MAAM,EAAE,YAAY,cAAc;CAElC,MAAM,iCAA6BC,+DAAwB,aAAa;CACxE,IAAI,SAAS,OAAO,OAAO,0BAA0B,CAAC,CAAC,KAAK;CAG5D,IAAI,OAAO,SAAS,SAAS,aAAa;EAExC,MAAM,oBADY,YAAY,SAAS,IACL,CAAC,CAAC,KAAK,SACvC,KAAK,WAAW,GAAG,QAAIC,oBAAS,SAAS,IAAI,QAAIC,gBAAK,MAAM,IAAI,CAClE;EAEA,SAAS,OAAO,QACb,SACC,KAAK,YAEL,kBAAkB,SAAS,KAAK,QAAQ,CAC5C;CACF;CAEA,IAAI,OAAO,SAAS,SAAS,aAC3B,SAAS,OAAO,QAAQ,SACtB,YAAY,SAAS,IAAI,CAAC,EAAE,SAAS,KAAK,GAAG,CAC/C;CAGF,IAAI,OAAO,SAAS,iBAAiB,aACnC,SAAS,OAAO,QACb,SAAS,CAAC,YAAY,SAAS,YAAY,CAAC,EAAE,SAAS,KAAK,GAAG,CAClE;CAGF,IAAI,OAAO,SAAS,eAAe,aACjC,SAAS,OAAO,QAAQ,SACtB,YAAY,SAAS,UAAU,CAAC,EAAE,SAAS,KAAK,YAAY,EAAE,CAChE;CAGF,IAAI,OAAO,SAAS,WAAW,aAC7B,SAAS,OAAO,OAAO,SAAS,MAAM;CAGxC,MAAM,aAAa,SAAS;CAC5B,IAAI,YAAY;EACd,MAAM,kBAAkB,UAAMC,mCAAa,UAAU;EAErD,IAAI,iBAIF,SAAS,OAAO,QAAQ,SAAS;GAC/B,IAAI,CAAC,KAAK,UAAU,OAAO;GAE3B,OAAO,gBAAgB,MAAM,YAAY,KAAK,aAAa,OAAO;EACpE,CAAC;CAEL;CAEA,OAAO;AACT"}
@@ -1,23 +1,23 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_extract = require('./extract.cjs');
3
- const require_listProjects = require('./listProjects.cjs');
4
- const require_liveSync = require('./liveSync.cjs');
5
- const require_listContentDeclaration = require('./listContentDeclaration.cjs');
2
+ const require_pull = require('./pull.cjs');
6
3
  const require_initSkills = require('./initSkills.cjs');
7
4
  const require_init = require('./init.cjs');
5
+ const require_extract = require('./extract.cjs');
8
6
  const require_editor = require('./editor.cjs');
9
- const require_scan = require('./scan.cjs');
10
- const require_cli = require('./cli.cjs');
11
- const require_searchDoc = require('./searchDoc.cjs');
12
- const require_pushConfig = require('./pushConfig.cjs');
7
+ const require_liveSync = require('./liveSync.cjs');
13
8
  const require_build = require('./build.cjs');
14
9
  const require_bundle = require('./bundle.cjs');
10
+ const require_cli = require('./cli.cjs');
15
11
  const require_test_listMissingTranslations = require('./test/listMissingTranslations.cjs');
16
12
  const require_test_test = require('./test/test.cjs');
17
13
  const require_fill_fill = require('./fill/fill.cjs');
18
- const require_pull = require('./pull.cjs');
14
+ const require_listContentDeclaration = require('./listContentDeclaration.cjs');
15
+ const require_listProjects = require('./listProjects.cjs');
19
16
  const require_push_push = require('./push/push.cjs');
17
+ const require_pushConfig = require('./pushConfig.cjs');
20
18
  const require_reviewDoc_reviewDoc = require('./reviewDoc/reviewDoc.cjs');
19
+ const require_scan = require('./scan.cjs');
20
+ const require_searchDoc = require('./searchDoc.cjs');
21
21
  const require_translateDoc_translateDoc = require('./translateDoc/translateDoc.cjs');
22
22
 
23
23
  exports.PLATFORM_OPTIONS = require_initSkills.PLATFORM_OPTIONS;
package/dist/cjs/init.cjs CHANGED
@@ -3,9 +3,9 @@ const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
3
3
  const require_auth_login = require('./auth/login.cjs');
4
4
  const require_loadPrompts = require('./loadPrompts.cjs');
5
5
  const require_initBuildOptimization = require('./initBuildOptimization.cjs');
6
- const require_initCompiler = require('./initCompiler.cjs');
7
6
  const require_initSkills = require('./initSkills.cjs');
8
7
  const require_initMCP = require('./initMCP.cjs');
8
+ const require_initCompiler = require('./initCompiler.cjs');
9
9
  let node_fs = require("node:fs");
10
10
  let node_path = require("node:path");
11
11
  let _intlayer_engine_cli = require("@intlayer/engine/cli");
@@ -2,15 +2,15 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  let node_path = require("node:path");
3
3
  let _intlayer_config_logger = require("@intlayer/config/logger");
4
4
  let _intlayer_config_node = require("@intlayer/config/node");
5
+ let _intlayer_dictionaries_entry_unmerged = require("@intlayer/dictionaries-entry/unmerged");
5
6
  let _intlayer_engine_cli = require("@intlayer/engine/cli");
6
7
  let _intlayer_engine_utils = require("@intlayer/engine/utils");
7
- let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
8
8
 
9
9
  //#region src/listContentDeclaration.ts
10
10
  const listContentDeclarationRows = async (options) => {
11
11
  const config = (0, _intlayer_config_node.getConfiguration)(options?.configOptions);
12
12
  await (0, _intlayer_engine_cli.prepareIntlayer)(config);
13
- const unmergedDictionariesRecord = (0, _intlayer_unmerged_dictionaries_entry.getUnmergedDictionaries)(config);
13
+ const unmergedDictionariesRecord = (0, _intlayer_dictionaries_entry_unmerged.getUnmergedDictionaries)(config);
14
14
  return Object.values(unmergedDictionariesRecord).flat().map((dictionary) => ({
15
15
  key: dictionary.key ?? "",
16
16
  path: options?.absolute ? dictionary.filePath ?? "Remote" : (0, node_path.relative)(config.system.baseDir, dictionary.filePath ?? "Remote")
@@ -1 +1 @@
1
- {"version":3,"file":"listContentDeclaration.cjs","names":["getConfiguration","prepareIntlayer","getUnmergedDictionaries","relative","getAppLogger","colon","colorizeKey","formatPath","colorizeNumber"],"sources":["../../src/listContentDeclaration.ts"],"sourcesContent":["import { relative } from 'node:path';\nimport {\n colon,\n colorizeKey,\n colorizeNumber,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { prepareIntlayer } from '@intlayer/engine/cli';\nimport { formatPath } from '@intlayer/engine/utils';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\n\ntype ListContentDeclarationOptions = {\n configOptions?: GetConfigurationOptions;\n json?: boolean;\n absolute?: boolean;\n};\n\nexport const listContentDeclarationRows = async (\n options?: ListContentDeclarationOptions\n) => {\n const config = getConfiguration(options?.configOptions);\n\n await prepareIntlayer(config);\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n\n const rows = Object.values(unmergedDictionariesRecord)\n .flat()\n .map((dictionary) => ({\n key: dictionary.key ?? '',\n path: options?.absolute\n ? (dictionary.filePath ?? 'Remote')\n : relative(config.system.baseDir, dictionary.filePath ?? 'Remote'),\n }));\n return rows;\n};\n\nexport const listContentDeclaration = async (\n options?: ListContentDeclarationOptions\n) => {\n const rows = await listContentDeclarationRows(options);\n\n if (options?.json) {\n console.log(JSON.stringify(rows));\n return;\n }\n\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n const lines = rows.map((row) =>\n [\n colon(` - ${colorizeKey(row.key)}`, {\n colSize: rows.map((row) => row.key.length),\n maxSize: 60,\n }),\n ' - ',\n formatPath(row.path),\n ].join('')\n );\n\n appLogger(`Content declaration files:`);\n\n lines.forEach((line) => {\n appLogger(line, {\n level: 'info',\n });\n });\n\n appLogger(`Total content declaration files: ${colorizeNumber(rows.length)}`);\n};\n"],"mappings":";;;;;;;;;AAqBA,MAAa,6BAA6B,OACxC,YACG;CACH,MAAM,aAASA,wCAAiB,SAAS,aAAa;CAEtD,UAAMC,sCAAgB,MAAM;CAE5B,MAAM,iCAA6BC,+DAAwB,MAAM;CAUjE,OARa,OAAO,OAAO,0BAA0B,CAAC,CACnD,KAAK,CAAC,CACN,KAAK,gBAAgB;EACpB,KAAK,WAAW,OAAO;EACvB,MAAM,SAAS,WACV,WAAW,YAAY,eACxBC,oBAAS,OAAO,OAAO,SAAS,WAAW,YAAY,QAAQ;CACrE,EACQ;AACZ;AAEA,MAAa,yBAAyB,OACpC,YACG;CACH,MAAM,OAAO,MAAM,2BAA2B,OAAO;CAErD,IAAI,SAAS,MAAM;EACjB,QAAQ,IAAI,KAAK,UAAU,IAAI,CAAC;EAChC;CACF;CAEA,MAAM,aAASH,wCAAiB,SAAS,aAAa;CACtD,MAAM,gBAAYI,sCAAa,MAAM;CAErC,MAAM,QAAQ,KAAK,KAAK,QACtB;MACEC,+BAAM,UAAMC,qCAAY,IAAI,GAAG,KAAK;GAClC,SAAS,KAAK,KAAK,QAAQ,IAAI,IAAI,MAAM;GACzC,SAAS;EACX,CAAC;EACD;MACAC,mCAAW,IAAI,IAAI;CACrB,CAAC,CAAC,KAAK,EAAE,CACX;CAEA,UAAU,4BAA4B;CAEtC,MAAM,SAAS,SAAS;EACtB,UAAU,MAAM,EACd,OAAO,OACT,CAAC;CACH,CAAC;CAED,UAAU,wCAAoCC,wCAAe,KAAK,MAAM,GAAG;AAC7E"}
1
+ {"version":3,"file":"listContentDeclaration.cjs","names":["getConfiguration","prepareIntlayer","getUnmergedDictionaries","relative","getAppLogger","colon","colorizeKey","formatPath","colorizeNumber"],"sources":["../../src/listContentDeclaration.ts"],"sourcesContent":["import { relative } from 'node:path';\nimport {\n colon,\n colorizeKey,\n colorizeNumber,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getUnmergedDictionaries } from '@intlayer/dictionaries-entry/unmerged';\nimport { prepareIntlayer } from '@intlayer/engine/cli';\nimport { formatPath } from '@intlayer/engine/utils';\n\ntype ListContentDeclarationOptions = {\n configOptions?: GetConfigurationOptions;\n json?: boolean;\n absolute?: boolean;\n};\n\nexport const listContentDeclarationRows = async (\n options?: ListContentDeclarationOptions\n) => {\n const config = getConfiguration(options?.configOptions);\n\n await prepareIntlayer(config);\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n\n const rows = Object.values(unmergedDictionariesRecord)\n .flat()\n .map((dictionary) => ({\n key: dictionary.key ?? '',\n path: options?.absolute\n ? (dictionary.filePath ?? 'Remote')\n : relative(config.system.baseDir, dictionary.filePath ?? 'Remote'),\n }));\n return rows;\n};\n\nexport const listContentDeclaration = async (\n options?: ListContentDeclarationOptions\n) => {\n const rows = await listContentDeclarationRows(options);\n\n if (options?.json) {\n console.log(JSON.stringify(rows));\n return;\n }\n\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n const lines = rows.map((row) =>\n [\n colon(` - ${colorizeKey(row.key)}`, {\n colSize: rows.map((row) => row.key.length),\n maxSize: 60,\n }),\n ' - ',\n formatPath(row.path),\n ].join('')\n );\n\n appLogger(`Content declaration files:`);\n\n lines.forEach((line) => {\n appLogger(line, {\n level: 'info',\n });\n });\n\n appLogger(`Total content declaration files: ${colorizeNumber(rows.length)}`);\n};\n"],"mappings":";;;;;;;;;AAqBA,MAAa,6BAA6B,OACxC,YACG;CACH,MAAM,aAASA,wCAAiB,SAAS,aAAa;CAEtD,UAAMC,sCAAgB,MAAM;CAE5B,MAAM,iCAA6BC,+DAAwB,MAAM;CAUjE,OARa,OAAO,OAAO,0BAA0B,CAAC,CACnD,KAAK,CAAC,CACN,KAAK,gBAAgB;EACpB,KAAK,WAAW,OAAO;EACvB,MAAM,SAAS,WACV,WAAW,YAAY,eACxBC,oBAAS,OAAO,OAAO,SAAS,WAAW,YAAY,QAAQ;CACrE,EACQ;AACZ;AAEA,MAAa,yBAAyB,OACpC,YACG;CACH,MAAM,OAAO,MAAM,2BAA2B,OAAO;CAErD,IAAI,SAAS,MAAM;EACjB,QAAQ,IAAI,KAAK,UAAU,IAAI,CAAC;EAChC;CACF;CAEA,MAAM,aAASH,wCAAiB,SAAS,aAAa;CACtD,MAAM,gBAAYI,sCAAa,MAAM;CAErC,MAAM,QAAQ,KAAK,KAAK,QACtB;MACEC,+BAAM,UAAMC,qCAAY,IAAI,GAAG,KAAK;GAClC,SAAS,KAAK,KAAK,QAAQ,IAAI,IAAI,MAAM;GACzC,SAAS;EACX,CAAC;EACD;MACAC,mCAAW,IAAI,IAAI;CACrB,CAAC,CAAC,KAAK,EAAE,CACX;CAEA,UAAU,4BAA4B;CAEtC,MAAM,SAAS,SAAS;EACtB,UAAU,MAAM,EACd,OAAO,OACT,CAAC;CACH,CAAC;CAED,UAAU,wCAAoCC,wCAAe,KAAK,MAAM,GAAG;AAC7E"}
@@ -5,9 +5,9 @@ let _intlayer_config_colors = require("@intlayer/config/colors");
5
5
  _intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
6
6
  let _intlayer_config_logger = require("@intlayer/config/logger");
7
7
  let _intlayer_config_node = require("@intlayer/config/node");
8
+ let _intlayer_dictionaries_entry_unmerged = require("@intlayer/dictionaries-entry/unmerged");
8
9
  let _intlayer_engine_build = require("@intlayer/engine/build");
9
10
  let _intlayer_engine_utils = require("@intlayer/engine/utils");
10
- let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
11
11
  let node_http = require("node:http");
12
12
  let _intlayer_config_package_json = require("@intlayer/config/package.json");
13
13
  _intlayer_config_package_json = require_runtime.__toESM(_intlayer_config_package_json);
@@ -104,7 +104,7 @@ const liveSync = async (options) => {
104
104
  "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
105
105
  "Access-Control-Allow-Headers": "Content-Type, Authorization"
106
106
  });
107
- const unmergedDictionaries = (0, _intlayer_unmerged_dictionaries_entry.getUnmergedDictionaries)(configuration);
107
+ const unmergedDictionaries = (0, _intlayer_dictionaries_entry_unmerged.getUnmergedDictionaries)(configuration);
108
108
  if (req.url.startsWith("/unmerged_dictionaries/")) {
109
109
  const one = unmergedDictionaries[decodeURIComponent(req.url.slice(23))] ?? null;
110
110
  res.end(JSON.stringify(one));