@intlayer/cli 8.4.4 → 8.4.5

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 (301) hide show
  1. package/dist/cjs/IntlayerEventListener.cjs +186 -1
  2. package/dist/cjs/IntlayerEventListener.cjs.map +1 -1
  3. package/dist/cjs/_virtual/_rolldown/runtime.cjs +29 -0
  4. package/dist/cjs/_virtual/_utils_asset.cjs +98 -0
  5. package/dist/cjs/auth/login.cjs +90 -2
  6. package/dist/cjs/auth/login.cjs.map +1 -1
  7. package/dist/cjs/build.cjs +30 -1
  8. package/dist/cjs/build.cjs.map +1 -1
  9. package/dist/cjs/ci.cjs +76 -1
  10. package/dist/cjs/ci.cjs.map +1 -1
  11. package/dist/cjs/cli.cjs +485 -1
  12. package/dist/cjs/cli.cjs.map +1 -1
  13. package/dist/cjs/config.cjs +15 -1
  14. package/dist/cjs/config.cjs.map +1 -1
  15. package/dist/cjs/editor.cjs +50 -1
  16. package/dist/cjs/editor.cjs.map +1 -1
  17. package/dist/cjs/extract.cjs +108 -1
  18. package/dist/cjs/extract.cjs.map +1 -1
  19. package/dist/cjs/fill/deepMergeContent.cjs +27 -1
  20. package/dist/cjs/fill/deepMergeContent.cjs.map +1 -1
  21. package/dist/cjs/fill/fill.cjs +84 -1
  22. package/dist/cjs/fill/fill.cjs.map +1 -1
  23. package/dist/cjs/fill/formatAutoFilledFilePath.cjs +32 -1
  24. package/dist/cjs/fill/formatAutoFilledFilePath.cjs.map +1 -1
  25. package/dist/cjs/fill/formatFillData.cjs +87 -1
  26. package/dist/cjs/fill/formatFillData.cjs.map +1 -1
  27. package/dist/cjs/fill/getAvailableLocalesInDictionary.cjs +26 -1
  28. package/dist/cjs/fill/getAvailableLocalesInDictionary.cjs.map +1 -1
  29. package/dist/cjs/fill/getFilterMissingContentPerLocale.cjs +51 -1
  30. package/dist/cjs/fill/getFilterMissingContentPerLocale.cjs.map +1 -1
  31. package/dist/cjs/fill/index.cjs +6 -1
  32. package/dist/cjs/fill/listTranslationsTasks.cjs +72 -1
  33. package/dist/cjs/fill/listTranslationsTasks.cjs.map +1 -1
  34. package/dist/cjs/fill/translateDictionary.cjs +240 -1
  35. package/dist/cjs/fill/translateDictionary.cjs.map +1 -1
  36. package/dist/cjs/fill/writeFill.cjs +55 -1
  37. package/dist/cjs/fill/writeFill.cjs.map +1 -1
  38. package/dist/cjs/getTargetDictionary.cjs +36 -1
  39. package/dist/cjs/getTargetDictionary.cjs.map +1 -1
  40. package/dist/cjs/index.cjs +44 -1
  41. package/dist/cjs/init.cjs +22 -1
  42. package/dist/cjs/init.cjs.map +1 -1
  43. package/dist/cjs/initMCP.cjs +69 -1
  44. package/dist/cjs/initMCP.cjs.map +1 -1
  45. package/dist/cjs/initSkills.cjs +93 -1
  46. package/dist/cjs/initSkills.cjs.map +1 -1
  47. package/dist/cjs/listContentDeclaration.cjs +42 -1
  48. package/dist/cjs/listContentDeclaration.cjs.map +1 -1
  49. package/dist/cjs/listProjects.cjs +28 -1
  50. package/dist/cjs/listProjects.cjs.map +1 -1
  51. package/dist/cjs/liveSync.cjs +153 -8
  52. package/dist/cjs/liveSync.cjs.map +1 -1
  53. package/dist/cjs/pull.cjs +153 -1
  54. package/dist/cjs/pull.cjs.map +1 -1
  55. package/dist/cjs/push/pullLog.cjs +105 -3
  56. package/dist/cjs/push/pullLog.cjs.map +1 -1
  57. package/dist/cjs/push/push.cjs +212 -1
  58. package/dist/cjs/push/push.cjs.map +1 -1
  59. package/dist/cjs/pushConfig.cjs +22 -1
  60. package/dist/cjs/pushConfig.cjs.map +1 -1
  61. package/dist/cjs/pushLog.cjs +86 -3
  62. package/dist/cjs/pushLog.cjs.map +1 -1
  63. package/dist/cjs/reviewDoc/reviewDoc.cjs +73 -1
  64. package/dist/cjs/reviewDoc/reviewDoc.cjs.map +1 -1
  65. package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs +98 -1
  66. package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs.map +1 -1
  67. package/dist/cjs/searchDoc.cjs +41 -1
  68. package/dist/cjs/searchDoc.cjs.map +1 -1
  69. package/dist/cjs/test/index.cjs +7 -1
  70. package/dist/cjs/test/listMissingTranslations.cjs +52 -1
  71. package/dist/cjs/test/listMissingTranslations.cjs.map +1 -1
  72. package/dist/cjs/test/test.cjs +56 -1
  73. package/dist/cjs/test/test.cjs.map +1 -1
  74. package/dist/cjs/translateDoc/index.cjs +9 -1
  75. package/dist/cjs/translateDoc/translateDoc.cjs +79 -1
  76. package/dist/cjs/translateDoc/translateDoc.cjs.map +1 -1
  77. package/dist/cjs/translateDoc/translateFile.cjs +106 -2
  78. package/dist/cjs/translateDoc/translateFile.cjs.map +1 -1
  79. package/dist/cjs/translateDoc/validation.cjs +49 -5
  80. package/dist/cjs/translateDoc/validation.cjs.map +1 -1
  81. package/dist/cjs/translation-alignment/alignBlocks.cjs +67 -1
  82. package/dist/cjs/translation-alignment/alignBlocks.cjs.map +1 -1
  83. package/dist/cjs/translation-alignment/computeSimilarity.cjs +25 -1
  84. package/dist/cjs/translation-alignment/computeSimilarity.cjs.map +1 -1
  85. package/dist/cjs/translation-alignment/fingerprintBlock.cjs +23 -1
  86. package/dist/cjs/translation-alignment/fingerprintBlock.cjs.map +1 -1
  87. package/dist/cjs/translation-alignment/index.cjs +22 -1
  88. package/dist/cjs/translation-alignment/mapChangedLinesToBlocks.cjs +18 -1
  89. package/dist/cjs/translation-alignment/mapChangedLinesToBlocks.cjs.map +1 -1
  90. package/dist/cjs/translation-alignment/normalizeBlock.cjs +22 -1
  91. package/dist/cjs/translation-alignment/normalizeBlock.cjs.map +1 -1
  92. package/dist/cjs/translation-alignment/pipeline.cjs +37 -1
  93. package/dist/cjs/translation-alignment/pipeline.cjs.map +1 -1
  94. package/dist/cjs/translation-alignment/planActions.cjs +46 -1
  95. package/dist/cjs/translation-alignment/planActions.cjs.map +1 -1
  96. package/dist/cjs/translation-alignment/rebuildDocument.cjs +49 -2
  97. package/dist/cjs/translation-alignment/rebuildDocument.cjs.map +1 -1
  98. package/dist/cjs/translation-alignment/segmentDocument.cjs +66 -5
  99. package/dist/cjs/translation-alignment/segmentDocument.cjs.map +1 -1
  100. package/dist/cjs/utils/calculateChunks.cjs +89 -2
  101. package/dist/cjs/utils/calculateChunks.cjs.map +1 -1
  102. package/dist/cjs/utils/checkAccess.cjs +83 -1
  103. package/dist/cjs/utils/checkAccess.cjs.map +1 -1
  104. package/dist/cjs/utils/checkConfigConsistency.cjs +16 -1
  105. package/dist/cjs/utils/checkConfigConsistency.cjs.map +1 -1
  106. package/dist/cjs/utils/checkFileModifiedRange.cjs +81 -1
  107. package/dist/cjs/utils/checkFileModifiedRange.cjs.map +1 -1
  108. package/dist/cjs/utils/checkLastUpdateTime.cjs +19 -1
  109. package/dist/cjs/utils/checkLastUpdateTime.cjs.map +1 -1
  110. package/dist/cjs/utils/chunkInference.cjs +45 -1
  111. package/dist/cjs/utils/chunkInference.cjs.map +1 -1
  112. package/dist/cjs/utils/fixChunkStartEndChars.cjs +27 -3
  113. package/dist/cjs/utils/fixChunkStartEndChars.cjs.map +1 -1
  114. package/dist/cjs/utils/formatTimeDiff.cjs +20 -1
  115. package/dist/cjs/utils/formatTimeDiff.cjs.map +1 -1
  116. package/dist/cjs/utils/getIsFileUpdatedRecently.cjs +16 -1
  117. package/dist/cjs/utils/getIsFileUpdatedRecently.cjs.map +1 -1
  118. package/dist/cjs/utils/getOutputFilePath.cjs +74 -1
  119. package/dist/cjs/utils/getOutputFilePath.cjs.map +1 -1
  120. package/dist/cjs/utils/getParentPackageJSON.cjs +20 -1
  121. package/dist/cjs/utils/getParentPackageJSON.cjs.map +1 -1
  122. package/dist/cjs/utils/listSpecialChars.cjs +54 -2
  123. package/dist/cjs/utils/listSpecialChars.cjs.map +1 -1
  124. package/dist/cjs/utils/mapChunksBetweenFiles.cjs +102 -1
  125. package/dist/cjs/utils/mapChunksBetweenFiles.cjs.map +1 -1
  126. package/dist/cjs/utils/openBrowser.cjs +19 -1
  127. package/dist/cjs/utils/openBrowser.cjs.map +1 -1
  128. package/dist/cjs/utils/reorderParagraphs.cjs +91 -3
  129. package/dist/cjs/utils/reorderParagraphs.cjs.map +1 -1
  130. package/dist/cjs/utils/setupAI.cjs +66 -1
  131. package/dist/cjs/utils/setupAI.cjs.map +1 -1
  132. package/dist/cjs/watch.cjs +47 -1
  133. package/dist/cjs/watch.cjs.map +1 -1
  134. package/dist/esm/IntlayerEventListener.mjs +183 -1
  135. package/dist/esm/IntlayerEventListener.mjs.map +1 -1
  136. package/dist/esm/_virtual/_rolldown/runtime.mjs +8 -0
  137. package/dist/esm/_virtual/_utils_asset.mjs +97 -0
  138. package/dist/esm/auth/login.mjs +86 -2
  139. package/dist/esm/auth/login.mjs.map +1 -1
  140. package/dist/esm/build.mjs +28 -1
  141. package/dist/esm/build.mjs.map +1 -1
  142. package/dist/esm/ci.mjs +74 -1
  143. package/dist/esm/ci.mjs.map +1 -1
  144. package/dist/esm/cli.mjs +482 -1
  145. package/dist/esm/cli.mjs.map +1 -1
  146. package/dist/esm/config.mjs +13 -1
  147. package/dist/esm/config.mjs.map +1 -1
  148. package/dist/esm/editor.mjs +50 -1
  149. package/dist/esm/editor.mjs.map +1 -0
  150. package/dist/esm/extract.mjs +104 -1
  151. package/dist/esm/extract.mjs.map +1 -1
  152. package/dist/esm/fill/deepMergeContent.mjs +25 -1
  153. package/dist/esm/fill/deepMergeContent.mjs.map +1 -1
  154. package/dist/esm/fill/fill.mjs +81 -1
  155. package/dist/esm/fill/fill.mjs.map +1 -1
  156. package/dist/esm/fill/formatAutoFilledFilePath.mjs +30 -1
  157. package/dist/esm/fill/formatAutoFilledFilePath.mjs.map +1 -1
  158. package/dist/esm/fill/formatFillData.mjs +85 -1
  159. package/dist/esm/fill/formatFillData.mjs.map +1 -1
  160. package/dist/esm/fill/getAvailableLocalesInDictionary.mjs +24 -1
  161. package/dist/esm/fill/getAvailableLocalesInDictionary.mjs.map +1 -1
  162. package/dist/esm/fill/getFilterMissingContentPerLocale.mjs +49 -1
  163. package/dist/esm/fill/getFilterMissingContentPerLocale.mjs.map +1 -1
  164. package/dist/esm/fill/index.mjs +4 -1
  165. package/dist/esm/fill/listTranslationsTasks.mjs +69 -1
  166. package/dist/esm/fill/listTranslationsTasks.mjs.map +1 -1
  167. package/dist/esm/fill/translateDictionary.mjs +237 -1
  168. package/dist/esm/fill/translateDictionary.mjs.map +1 -1
  169. package/dist/esm/fill/writeFill.mjs +53 -1
  170. package/dist/esm/fill/writeFill.mjs.map +1 -1
  171. package/dist/esm/getTargetDictionary.mjs +33 -1
  172. package/dist/esm/getTargetDictionary.mjs.map +1 -1
  173. package/dist/esm/index.mjs +20 -1
  174. package/dist/esm/init.mjs +19 -1
  175. package/dist/esm/init.mjs.map +1 -1
  176. package/dist/esm/initMCP.mjs +65 -1
  177. package/dist/esm/initMCP.mjs.map +1 -1
  178. package/dist/esm/initSkills.mjs +87 -1
  179. package/dist/esm/initSkills.mjs.map +1 -1
  180. package/dist/esm/listContentDeclaration.mjs +39 -1
  181. package/dist/esm/listContentDeclaration.mjs.map +1 -1
  182. package/dist/esm/listProjects.mjs +26 -1
  183. package/dist/esm/listProjects.mjs.map +1 -1
  184. package/dist/esm/liveSync.mjs +150 -8
  185. package/dist/esm/liveSync.mjs.map +1 -1
  186. package/dist/esm/pull.mjs +150 -1
  187. package/dist/esm/pull.mjs.map +1 -1
  188. package/dist/esm/push/pullLog.mjs +102 -3
  189. package/dist/esm/push/pullLog.mjs.map +1 -1
  190. package/dist/esm/push/push.mjs +208 -1
  191. package/dist/esm/push/push.mjs.map +1 -1
  192. package/dist/esm/pushConfig.mjs +20 -1
  193. package/dist/esm/pushConfig.mjs.map +1 -1
  194. package/dist/esm/pushLog.mjs +83 -3
  195. package/dist/esm/pushLog.mjs.map +1 -1
  196. package/dist/esm/reviewDoc/reviewDoc.mjs +69 -1
  197. package/dist/esm/reviewDoc/reviewDoc.mjs.map +1 -1
  198. package/dist/esm/reviewDoc/reviewDocBlockAware.mjs +95 -1
  199. package/dist/esm/reviewDoc/reviewDocBlockAware.mjs.map +1 -1
  200. package/dist/esm/searchDoc.mjs +39 -1
  201. package/dist/esm/searchDoc.mjs.map +1 -1
  202. package/dist/esm/test/index.mjs +4 -1
  203. package/dist/esm/test/listMissingTranslations.mjs +49 -1
  204. package/dist/esm/test/listMissingTranslations.mjs.map +1 -1
  205. package/dist/esm/test/test.mjs +53 -1
  206. package/dist/esm/test/test.mjs.map +1 -1
  207. package/dist/esm/translateDoc/index.mjs +5 -1
  208. package/dist/esm/translateDoc/translateDoc.mjs +75 -1
  209. package/dist/esm/translateDoc/translateDoc.mjs.map +1 -1
  210. package/dist/esm/translateDoc/translateFile.mjs +103 -2
  211. package/dist/esm/translateDoc/translateFile.mjs.map +1 -1
  212. package/dist/esm/translateDoc/validation.mjs +46 -5
  213. package/dist/esm/translateDoc/validation.mjs.map +1 -1
  214. package/dist/esm/translation-alignment/alignBlocks.mjs +66 -1
  215. package/dist/esm/translation-alignment/alignBlocks.mjs.map +1 -1
  216. package/dist/esm/translation-alignment/computeSimilarity.mjs +22 -1
  217. package/dist/esm/translation-alignment/computeSimilarity.mjs.map +1 -1
  218. package/dist/esm/translation-alignment/fingerprintBlock.mjs +20 -1
  219. package/dist/esm/translation-alignment/fingerprintBlock.mjs.map +1 -1
  220. package/dist/esm/translation-alignment/index.mjs +11 -1
  221. package/dist/esm/translation-alignment/mapChangedLinesToBlocks.mjs +16 -1
  222. package/dist/esm/translation-alignment/mapChangedLinesToBlocks.mjs.map +1 -1
  223. package/dist/esm/translation-alignment/normalizeBlock.mjs +20 -1
  224. package/dist/esm/translation-alignment/normalizeBlock.mjs.map +1 -1
  225. package/dist/esm/translation-alignment/pipeline.mjs +35 -1
  226. package/dist/esm/translation-alignment/pipeline.mjs.map +1 -1
  227. package/dist/esm/translation-alignment/planActions.mjs +44 -1
  228. package/dist/esm/translation-alignment/planActions.mjs.map +1 -1
  229. package/dist/esm/translation-alignment/rebuildDocument.mjs +46 -2
  230. package/dist/esm/translation-alignment/rebuildDocument.mjs.map +1 -1
  231. package/dist/esm/translation-alignment/segmentDocument.mjs +64 -5
  232. package/dist/esm/translation-alignment/segmentDocument.mjs.map +1 -1
  233. package/dist/esm/utils/calculateChunks.mjs +87 -2
  234. package/dist/esm/utils/calculateChunks.mjs.map +1 -1
  235. package/dist/esm/utils/checkAccess.mjs +79 -1
  236. package/dist/esm/utils/checkAccess.mjs.map +1 -1
  237. package/dist/esm/utils/checkConfigConsistency.mjs +14 -1
  238. package/dist/esm/utils/checkConfigConsistency.mjs.map +1 -1
  239. package/dist/esm/utils/checkFileModifiedRange.mjs +80 -1
  240. package/dist/esm/utils/checkFileModifiedRange.mjs.map +1 -1
  241. package/dist/esm/utils/checkLastUpdateTime.mjs +17 -1
  242. package/dist/esm/utils/checkLastUpdateTime.mjs.map +1 -1
  243. package/dist/esm/utils/chunkInference.mjs +43 -1
  244. package/dist/esm/utils/chunkInference.mjs.map +1 -1
  245. package/dist/esm/utils/fixChunkStartEndChars.mjs +25 -3
  246. package/dist/esm/utils/fixChunkStartEndChars.mjs.map +1 -1
  247. package/dist/esm/utils/formatTimeDiff.mjs +18 -1
  248. package/dist/esm/utils/formatTimeDiff.mjs.map +1 -1
  249. package/dist/esm/utils/getIsFileUpdatedRecently.mjs +14 -1
  250. package/dist/esm/utils/getIsFileUpdatedRecently.mjs.map +1 -1
  251. package/dist/esm/utils/getOutputFilePath.mjs +72 -1
  252. package/dist/esm/utils/getOutputFilePath.mjs.map +1 -1
  253. package/dist/esm/utils/getParentPackageJSON.mjs +18 -1
  254. package/dist/esm/utils/getParentPackageJSON.mjs.map +1 -1
  255. package/dist/esm/utils/listSpecialChars.mjs +52 -2
  256. package/dist/esm/utils/listSpecialChars.mjs.map +1 -1
  257. package/dist/esm/utils/mapChunksBetweenFiles.mjs +100 -1
  258. package/dist/esm/utils/mapChunksBetweenFiles.mjs.map +1 -1
  259. package/dist/esm/utils/openBrowser.mjs +17 -1
  260. package/dist/esm/utils/openBrowser.mjs.map +1 -1
  261. package/dist/esm/utils/reorderParagraphs.mjs +90 -3
  262. package/dist/esm/utils/reorderParagraphs.mjs.map +1 -1
  263. package/dist/esm/utils/setupAI.mjs +63 -1
  264. package/dist/esm/utils/setupAI.mjs.map +1 -1
  265. package/dist/esm/watch.mjs +45 -1
  266. package/dist/esm/watch.mjs.map +1 -1
  267. package/dist/types/fill/fill.d.ts +1 -1
  268. package/dist/types/fill/translateDictionary.d.ts +1 -1
  269. package/dist/types/getTargetDictionary.d.ts +19 -2
  270. package/dist/types/getTargetDictionary.d.ts.map +1 -0
  271. package/dist/types/index.d.ts +2 -2
  272. package/dist/types/reviewDoc/reviewDocBlockAware.d.ts +1 -1
  273. package/dist/types/test/index.d.ts +2 -2
  274. package/dist/types/test/listMissingTranslations.d.ts +28 -2
  275. package/dist/types/test/listMissingTranslations.d.ts.map +1 -0
  276. package/dist/types/test/test.d.ts +11 -2
  277. package/dist/types/test/test.d.ts.map +1 -0
  278. package/dist/types/translateDoc/index.d.ts +1 -1
  279. package/dist/types/translateDoc/translateDoc.d.ts +1 -1
  280. package/dist/types/translateDoc/translateFile.d.ts +1 -1
  281. package/dist/types/translateDoc/types.d.ts +48 -2
  282. package/dist/types/translateDoc/types.d.ts.map +1 -0
  283. package/dist/types/utils/chunkInference.d.ts +1 -1
  284. package/dist/types/utils/setupAI.d.ts +21 -2
  285. package/dist/types/utils/setupAI.d.ts.map +1 -0
  286. package/package.json +12 -12
  287. package/dist/cjs/_utils_asset-ghp_Cjwk.cjs +0 -2
  288. package/dist/cjs/chunk-Bmb41Sf3.cjs +0 -1
  289. package/dist/esm/_utils_asset-B187VPMw.mjs +0 -2
  290. package/dist/esm/editor-D8BGlLzF.mjs +0 -2
  291. package/dist/esm/editor-D8BGlLzF.mjs.map +0 -1
  292. package/dist/types/getTargetDictionary-RBSRtaQj.d.ts +0 -19
  293. package/dist/types/getTargetDictionary-RBSRtaQj.d.ts.map +0 -1
  294. package/dist/types/listMissingTranslations-DxKw7nqI.d.ts +0 -28
  295. package/dist/types/listMissingTranslations-DxKw7nqI.d.ts.map +0 -1
  296. package/dist/types/setupAI-Bosjx7ah.d.ts +0 -21
  297. package/dist/types/setupAI-Bosjx7ah.d.ts.map +0 -1
  298. package/dist/types/test-DUTiJR5_.d.ts +0 -11
  299. package/dist/types/test-DUTiJR5_.d.ts.map +0 -1
  300. package/dist/types/types-BKvc3FmV.d.ts +0 -48
  301. package/dist/types/types-BKvc3FmV.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"fill.mjs","names":[],"sources":["../../../src/fill/fill.ts"],"sourcesContent":["import { basename, relative } from 'node:path';\nimport type { AIOptions } from '@intlayer/api';\nimport {\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/chokidar/build';\nimport {\n type ListGitFilesOptions,\n logConfigDetails,\n} from '@intlayer/chokidar/cli';\nimport {\n formatPath,\n getGlobalLimiter,\n getTaskLimiter,\n} from '@intlayer/chokidar/utils';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport {\n colorize,\n colorizeKey,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport {\n ensureArray,\n type GetTargetDictionaryOptions,\n getTargetUnmergedDictionaries,\n} from '../getTargetDictionary';\nimport { setupAI } from '../utils/setupAI';\nimport {\n listTranslationsTasks,\n type TranslationTask,\n} from './listTranslationsTasks';\nimport { translateDictionary } from './translateDictionary';\nimport { writeFill } from './writeFill';\n\nconst NB_CONCURRENT_TRANSLATIONS = 7;\n\n// Arguments for the fill function\nexport type FillOptions = {\n sourceLocale?: Locale;\n outputLocales?: Locale | Locale[];\n mode?: 'complete' | 'review';\n gitOptions?: ListGitFilesOptions;\n aiOptions?: AIOptions; // Added aiOptions to be passed to translateJSON\n verbose?: boolean;\n nbConcurrentTranslations?: number;\n nbConcurrentTasks?: number; // NEW: number of tasks that may run at once\n build?: boolean;\n skipMetadata?: boolean;\n} & GetTargetDictionaryOptions;\n\n/**\n * Fill translations based on the provided options.\n */\nexport const fill = async (options?: FillOptions): Promise<void> => {\n const configuration = getConfiguration(options?.configOptions);\n logConfigDetails(options?.configOptions);\n\n const appLogger = getAppLogger(configuration);\n\n if (options?.build === true) {\n await prepareIntlayer(configuration, { forceRun: true });\n } else if (typeof options?.build === 'undefined') {\n await prepareIntlayer(configuration);\n }\n\n const { defaultLocale, locales } = configuration.internationalization;\n const mode = options?.mode ?? 'complete';\n const baseLocale = options?.sourceLocale ?? defaultLocale;\n\n const outputLocales = options?.outputLocales\n ? ensureArray(options.outputLocales)\n : locales;\n\n const aiResult = await setupAI(configuration, options?.aiOptions);\n\n if (!aiResult?.hasAIAccess) return;\n\n const { aiClient, aiConfig } = aiResult;\n\n const targetUnmergedDictionaries =\n await getTargetUnmergedDictionaries(options);\n\n const affectedDictionaryKeys = new Set<string>();\n targetUnmergedDictionaries.forEach((dict) => {\n affectedDictionaryKeys.add(dict.key);\n });\n\n const keysToProcess = Array.from(affectedDictionaryKeys);\n\n appLogger([\n 'Affected dictionary keys for processing:',\n keysToProcess.length > 0\n ? keysToProcess.map((key) => colorizeKey(key)).join(', ')\n : colorize('No keys found', ANSIColors.YELLOW),\n ]);\n\n if (keysToProcess.length === 0) return;\n\n /**\n * List the translations tasks\n *\n * Create a list of per-locale dictionaries to translate\n *\n * In 'complete' mode, filter only the missing locales to translate\n */\n const translationTasks: TranslationTask[] = listTranslationsTasks(\n targetUnmergedDictionaries.map((dictionary) => dictionary.localId!),\n outputLocales,\n mode,\n baseLocale,\n configuration\n );\n\n // AI calls in flight at once (translateJSON + metadata audit)\n const nbConcurrentTranslations =\n options?.nbConcurrentTranslations ?? NB_CONCURRENT_TRANSLATIONS;\n const globalLimiter = getGlobalLimiter(nbConcurrentTranslations);\n\n // NEW: number of *tasks* that may run at once (start/prepare/log/write)\n const nbConcurrentTasks = Math.max(\n 1,\n Math.min(\n options?.nbConcurrentTasks ?? nbConcurrentTranslations,\n translationTasks.length\n )\n );\n\n const taskLimiter = getTaskLimiter(nbConcurrentTasks);\n\n const runners = translationTasks.map((task) =>\n taskLimiter(async () => {\n const relativePath = relative(\n configuration?.content?.baseDir ?? process.cwd(),\n task?.dictionaryFilePath ?? ''\n );\n\n // log AFTER acquiring a task slot\n appLogger(\n `${task.dictionaryPreset} Processing ${colorizePath(basename(relativePath))}`,\n { level: 'info' }\n );\n\n const translationTaskResult = await translateDictionary(\n task,\n configuration,\n {\n mode,\n aiOptions: options?.aiOptions,\n fillMetadata: !options?.skipMetadata,\n onHandle: globalLimiter, // <= AI calls go through here\n aiClient,\n aiConfig,\n }\n );\n\n if (!translationTaskResult?.dictionaryOutput) return;\n\n const { dictionaryOutput, sourceLocale } = translationTaskResult;\n\n // Determine if we should write to separate files\n // - If dictionary has explicit fill setting (string or object), use it\n // - If dictionary is per-locale AND has no explicit fill=false, use global fill config\n // - If dictionary is multilingual (no locale property), always write to same file\n const hasDictionaryLevelFill =\n typeof dictionaryOutput.fill === 'string' ||\n typeof dictionaryOutput.fill === 'object';\n\n const isPerLocale = typeof dictionaryOutput.locale === 'string';\n\n const effectiveFill = hasDictionaryLevelFill\n ? dictionaryOutput.fill\n : isPerLocale\n ? (configuration.dictionary?.fill ?? true)\n : false; // Multilingual dictionaries don't use fill by default\n\n const isFillOtherFile =\n typeof effectiveFill === 'string' || typeof effectiveFill === 'object';\n\n if (isFillOtherFile) {\n await writeFill(\n {\n ...dictionaryOutput,\n // Ensure fill is set on the dictionary for writeFill to use\n fill: effectiveFill,\n },\n outputLocales,\n [sourceLocale],\n configuration\n );\n } else {\n await writeContentDeclaration(dictionaryOutput, configuration);\n\n if (dictionaryOutput.filePath) {\n appLogger(\n `${task.dictionaryPreset} Content declaration written to ${formatPath(basename(dictionaryOutput.filePath))}`,\n { level: 'info' }\n );\n }\n }\n })\n );\n\n await Promise.all(runners);\n await (globalLimiter as any).onIdle();\n};\n"],"mappings":"2yBAqCA,MAmBa,EAAO,KAAO,IAAyC,CAClE,IAAM,EAAgB,EAAiB,GAAS,cAAc,CAC9D,EAAiB,GAAS,cAAc,CAExC,IAAM,EAAY,EAAa,EAAc,CAEzC,GAAS,QAAU,GACrB,MAAM,EAAgB,EAAe,CAAE,SAAU,GAAM,CAAC,CACxC,GAAS,QAAU,QACnC,MAAM,EAAgB,EAAc,CAGtC,GAAM,CAAE,gBAAe,WAAY,EAAc,qBAC3C,EAAO,GAAS,MAAQ,WACxB,EAAa,GAAS,cAAgB,EAEtC,EAAgB,GAAS,cAC3B,EAAY,EAAQ,cAAc,CAClC,EAEE,EAAW,MAAM,EAAQ,EAAe,GAAS,UAAU,CAEjE,GAAI,CAAC,GAAU,YAAa,OAE5B,GAAM,CAAE,WAAU,YAAa,EAEzB,EACJ,MAAM,EAA8B,EAAQ,CAExC,EAAyB,IAAI,IACnC,EAA2B,QAAS,GAAS,CAC3C,EAAuB,IAAI,EAAK,IAAI,EACpC,CAEF,IAAM,EAAgB,MAAM,KAAK,EAAuB,CASxD,GAPA,EAAU,CACR,2CACA,EAAc,OAAS,EACnB,EAAc,IAAK,GAAQ,EAAY,EAAI,CAAC,CAAC,KAAK,KAAK,CACvD,EAAS,gBAAiB,EAAW,OAAO,CACjD,CAAC,CAEE,EAAc,SAAW,EAAG,OAShC,IAAM,EAAsC,EAC1C,EAA2B,IAAK,GAAe,EAAW,QAAS,CACnE,EACA,EACA,EACA,EACD,CAGK,EACJ,GAAS,0BAA4B,EACjC,EAAgB,EAAiB,EAAyB,CAW1D,EAAc,EARM,KAAK,IAC7B,EACA,KAAK,IACH,GAAS,mBAAqB,EAC9B,EAAiB,OAClB,CACF,CAEoD,CAE/C,EAAU,EAAiB,IAAK,GACpC,EAAY,SAAY,CACtB,IAAM,EAAe,EACnB,GAAe,SAAS,SAAW,QAAQ,KAAK,CAChD,GAAM,oBAAsB,GAC7B,CAGD,EACE,GAAG,EAAK,iBAAiB,cAAc,EAAa,EAAS,EAAa,CAAC,GAC3E,CAAE,MAAO,OAAQ,CAClB,CAED,IAAM,EAAwB,MAAM,EAClC,EACA,EACA,CACE,OACA,UAAW,GAAS,UACpB,aAAc,CAAC,GAAS,aACxB,SAAU,EACV,WACA,WACD,CACF,CAED,GAAI,CAAC,GAAuB,iBAAkB,OAE9C,GAAM,CAAE,mBAAkB,gBAAiB,EAMrC,EACJ,OAAO,EAAiB,MAAS,UACjC,OAAO,EAAiB,MAAS,SAE7B,EAAc,OAAO,EAAiB,QAAW,SAEjD,EAAgB,EAClB,EAAiB,KACjB,EACG,EAAc,YAAY,MAAQ,GACnC,GAGJ,OAAO,GAAkB,UAAY,OAAO,GAAkB,SAG9D,MAAM,EACJ,CACE,GAAG,EAEH,KAAM,EACP,CACD,EACA,CAAC,EAAa,CACd,EACD,EAED,MAAM,EAAwB,EAAkB,EAAc,CAE1D,EAAiB,UACnB,EACE,GAAG,EAAK,iBAAiB,kCAAkC,EAAW,EAAS,EAAiB,SAAS,CAAC,GAC1G,CAAE,MAAO,OAAQ,CAClB,GAGL,CACH,CAED,MAAM,QAAQ,IAAI,EAAQ,CAC1B,MAAO,EAAsB,QAAQ"}
1
+ {"version":3,"file":"fill.mjs","names":[],"sources":["../../../src/fill/fill.ts"],"sourcesContent":["import { basename, relative } from 'node:path';\nimport type { AIOptions } from '@intlayer/api';\nimport {\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/chokidar/build';\nimport {\n type ListGitFilesOptions,\n logConfigDetails,\n} from '@intlayer/chokidar/cli';\nimport {\n formatPath,\n getGlobalLimiter,\n getTaskLimiter,\n} from '@intlayer/chokidar/utils';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport {\n colorize,\n colorizeKey,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport {\n ensureArray,\n type GetTargetDictionaryOptions,\n getTargetUnmergedDictionaries,\n} from '../getTargetDictionary';\nimport { setupAI } from '../utils/setupAI';\nimport {\n listTranslationsTasks,\n type TranslationTask,\n} from './listTranslationsTasks';\nimport { translateDictionary } from './translateDictionary';\nimport { writeFill } from './writeFill';\n\nconst NB_CONCURRENT_TRANSLATIONS = 7;\n\n// Arguments for the fill function\nexport type FillOptions = {\n sourceLocale?: Locale;\n outputLocales?: Locale | Locale[];\n mode?: 'complete' | 'review';\n gitOptions?: ListGitFilesOptions;\n aiOptions?: AIOptions; // Added aiOptions to be passed to translateJSON\n verbose?: boolean;\n nbConcurrentTranslations?: number;\n nbConcurrentTasks?: number; // NEW: number of tasks that may run at once\n build?: boolean;\n skipMetadata?: boolean;\n} & GetTargetDictionaryOptions;\n\n/**\n * Fill translations based on the provided options.\n */\nexport const fill = async (options?: FillOptions): Promise<void> => {\n const configuration = getConfiguration(options?.configOptions);\n logConfigDetails(options?.configOptions);\n\n const appLogger = getAppLogger(configuration);\n\n if (options?.build === true) {\n await prepareIntlayer(configuration, { forceRun: true });\n } else if (typeof options?.build === 'undefined') {\n await prepareIntlayer(configuration);\n }\n\n const { defaultLocale, locales } = configuration.internationalization;\n const mode = options?.mode ?? 'complete';\n const baseLocale = options?.sourceLocale ?? defaultLocale;\n\n const outputLocales = options?.outputLocales\n ? ensureArray(options.outputLocales)\n : locales;\n\n const aiResult = await setupAI(configuration, options?.aiOptions);\n\n if (!aiResult?.hasAIAccess) return;\n\n const { aiClient, aiConfig } = aiResult;\n\n const targetUnmergedDictionaries =\n await getTargetUnmergedDictionaries(options);\n\n const affectedDictionaryKeys = new Set<string>();\n targetUnmergedDictionaries.forEach((dict) => {\n affectedDictionaryKeys.add(dict.key);\n });\n\n const keysToProcess = Array.from(affectedDictionaryKeys);\n\n appLogger([\n 'Affected dictionary keys for processing:',\n keysToProcess.length > 0\n ? keysToProcess.map((key) => colorizeKey(key)).join(', ')\n : colorize('No keys found', ANSIColors.YELLOW),\n ]);\n\n if (keysToProcess.length === 0) return;\n\n /**\n * List the translations tasks\n *\n * Create a list of per-locale dictionaries to translate\n *\n * In 'complete' mode, filter only the missing locales to translate\n */\n const translationTasks: TranslationTask[] = listTranslationsTasks(\n targetUnmergedDictionaries.map((dictionary) => dictionary.localId!),\n outputLocales,\n mode,\n baseLocale,\n configuration\n );\n\n // AI calls in flight at once (translateJSON + metadata audit)\n const nbConcurrentTranslations =\n options?.nbConcurrentTranslations ?? NB_CONCURRENT_TRANSLATIONS;\n const globalLimiter = getGlobalLimiter(nbConcurrentTranslations);\n\n // NEW: number of *tasks* that may run at once (start/prepare/log/write)\n const nbConcurrentTasks = Math.max(\n 1,\n Math.min(\n options?.nbConcurrentTasks ?? nbConcurrentTranslations,\n translationTasks.length\n )\n );\n\n const taskLimiter = getTaskLimiter(nbConcurrentTasks);\n\n const runners = translationTasks.map((task) =>\n taskLimiter(async () => {\n const relativePath = relative(\n configuration?.content?.baseDir ?? process.cwd(),\n task?.dictionaryFilePath ?? ''\n );\n\n // log AFTER acquiring a task slot\n appLogger(\n `${task.dictionaryPreset} Processing ${colorizePath(basename(relativePath))}`,\n { level: 'info' }\n );\n\n const translationTaskResult = await translateDictionary(\n task,\n configuration,\n {\n mode,\n aiOptions: options?.aiOptions,\n fillMetadata: !options?.skipMetadata,\n onHandle: globalLimiter, // <= AI calls go through here\n aiClient,\n aiConfig,\n }\n );\n\n if (!translationTaskResult?.dictionaryOutput) return;\n\n const { dictionaryOutput, sourceLocale } = translationTaskResult;\n\n // Determine if we should write to separate files\n // - If dictionary has explicit fill setting (string or object), use it\n // - If dictionary is per-locale AND has no explicit fill=false, use global fill config\n // - If dictionary is multilingual (no locale property), always write to same file\n const hasDictionaryLevelFill =\n typeof dictionaryOutput.fill === 'string' ||\n typeof dictionaryOutput.fill === 'object';\n\n const isPerLocale = typeof dictionaryOutput.locale === 'string';\n\n const effectiveFill = hasDictionaryLevelFill\n ? dictionaryOutput.fill\n : isPerLocale\n ? (configuration.dictionary?.fill ?? true)\n : false; // Multilingual dictionaries don't use fill by default\n\n const isFillOtherFile =\n typeof effectiveFill === 'string' || typeof effectiveFill === 'object';\n\n if (isFillOtherFile) {\n await writeFill(\n {\n ...dictionaryOutput,\n // Ensure fill is set on the dictionary for writeFill to use\n fill: effectiveFill,\n },\n outputLocales,\n [sourceLocale],\n configuration\n );\n } else {\n await writeContentDeclaration(dictionaryOutput, configuration);\n\n if (dictionaryOutput.filePath) {\n appLogger(\n `${task.dictionaryPreset} Content declaration written to ${formatPath(basename(dictionaryOutput.filePath))}`,\n { level: 'info' }\n );\n }\n }\n })\n );\n\n await Promise.all(runners);\n await (globalLimiter as any).onIdle();\n};\n"],"mappings":";;;;;;;;;;;;;;AAqCA,MAAM,6BAA6B;;;;AAmBnC,MAAa,OAAO,OAAO,YAAyC;CAClE,MAAM,gBAAgB,iBAAiB,SAAS,cAAc;AAC9D,kBAAiB,SAAS,cAAc;CAExC,MAAM,YAAY,aAAa,cAAc;AAE7C,KAAI,SAAS,UAAU,KACrB,OAAM,gBAAgB,eAAe,EAAE,UAAU,MAAM,CAAC;UAC/C,OAAO,SAAS,UAAU,YACnC,OAAM,gBAAgB,cAAc;CAGtC,MAAM,EAAE,eAAe,YAAY,cAAc;CACjD,MAAM,OAAO,SAAS,QAAQ;CAC9B,MAAM,aAAa,SAAS,gBAAgB;CAE5C,MAAM,gBAAgB,SAAS,gBAC3B,YAAY,QAAQ,cAAc,GAClC;CAEJ,MAAM,WAAW,MAAM,QAAQ,eAAe,SAAS,UAAU;AAEjE,KAAI,CAAC,UAAU,YAAa;CAE5B,MAAM,EAAE,UAAU,aAAa;CAE/B,MAAM,6BACJ,MAAM,8BAA8B,QAAQ;CAE9C,MAAM,yCAAyB,IAAI,KAAa;AAChD,4BAA2B,SAAS,SAAS;AAC3C,yBAAuB,IAAI,KAAK,IAAI;GACpC;CAEF,MAAM,gBAAgB,MAAM,KAAK,uBAAuB;AAExD,WAAU,CACR,4CACA,cAAc,SAAS,IACnB,cAAc,KAAK,QAAQ,YAAY,IAAI,CAAC,CAAC,KAAK,KAAK,GACvD,SAAS,iBAAiB,WAAW,OAAO,CACjD,CAAC;AAEF,KAAI,cAAc,WAAW,EAAG;;;;;;;;CAShC,MAAM,mBAAsC,sBAC1C,2BAA2B,KAAK,eAAe,WAAW,QAAS,EACnE,eACA,MACA,YACA,cACD;CAGD,MAAM,2BACJ,SAAS,4BAA4B;CACvC,MAAM,gBAAgB,iBAAiB,yBAAyB;CAWhE,MAAM,cAAc,eARM,KAAK,IAC7B,GACA,KAAK,IACH,SAAS,qBAAqB,0BAC9B,iBAAiB,OAClB,CACF,CAEoD;CAErD,MAAM,UAAU,iBAAiB,KAAK,SACpC,YAAY,YAAY;EACtB,MAAM,eAAe,SACnB,eAAe,SAAS,WAAW,QAAQ,KAAK,EAChD,MAAM,sBAAsB,GAC7B;AAGD,YACE,GAAG,KAAK,iBAAiB,cAAc,aAAa,SAAS,aAAa,CAAC,IAC3E,EAAE,OAAO,QAAQ,CAClB;EAED,MAAM,wBAAwB,MAAM,oBAClC,MACA,eACA;GACE;GACA,WAAW,SAAS;GACpB,cAAc,CAAC,SAAS;GACxB,UAAU;GACV;GACA;GACD,CACF;AAED,MAAI,CAAC,uBAAuB,iBAAkB;EAE9C,MAAM,EAAE,kBAAkB,iBAAiB;EAM3C,MAAM,yBACJ,OAAO,iBAAiB,SAAS,YACjC,OAAO,iBAAiB,SAAS;EAEnC,MAAM,cAAc,OAAO,iBAAiB,WAAW;EAEvD,MAAM,gBAAgB,yBAClB,iBAAiB,OACjB,cACG,cAAc,YAAY,QAAQ,OACnC;AAKN,MAFE,OAAO,kBAAkB,YAAY,OAAO,kBAAkB,SAG9D,OAAM,UACJ;GACE,GAAG;GAEH,MAAM;GACP,EACD,eACA,CAAC,aAAa,EACd,cACD;OACI;AACL,SAAM,wBAAwB,kBAAkB,cAAc;AAE9D,OAAI,iBAAiB,SACnB,WACE,GAAG,KAAK,iBAAiB,kCAAkC,WAAW,SAAS,iBAAiB,SAAS,CAAC,IAC1G,EAAE,OAAO,QAAQ,CAClB;;GAGL,CACH;AAED,OAAM,QAAQ,IAAI,QAAQ;AAC1B,OAAO,cAAsB,QAAQ"}
@@ -1,2 +1,31 @@
1
- import{basename as e,dirname as t,isAbsolute as n,normalize as r,resolve as i}from"node:path";import{parseFilePathPattern as a}from"@intlayer/config/utils";const o=async(o,s,c,l,u)=>{if(!o)throw Error(`autoFillField must be provided`);if(!s||typeof s!=`string`)throw Error(`dictionaryKey must be a non-empty string`);if(!c||typeof c!=`string`)throw Error(`dictionaryFilePath must be a non-empty string`);if(!l||typeof l!=`string`)throw Error(`baseDir must be a non-empty string`);let d=await a(o,{key:s,fileName:e(c).split(`.`).slice(0,-2).join(`.`),locale:u}),f=n(c)?c:i(l,c);if(d.startsWith(`./`)||d.startsWith(`../`))return i(t(f),d);if(n(d)){let e=r(d),t=r(l);if(d.startsWith(`/`)&&!e.startsWith(t)){let e=i(l,d.substring(1));if(!d.startsWith(`/usr/`)&&!d.startsWith(`/etc/`)&&!d.startsWith(`/var/`)&&!d.startsWith(`/home/`)&&!d.startsWith(`/Users/`))return e}return e}return r(d)};export{o as formatAutoFilledFilePath};
1
+ import { basename, dirname, isAbsolute, normalize, resolve } from "node:path";
2
+ import { parseFilePathPattern } from "@intlayer/config/utils";
3
+
4
+ //#region src/fill/formatAutoFilledFilePath.ts
5
+ const formatAutoFilledFilePath = async (autoFillField, dictionaryKey, dictionaryFilePath, baseDir, locale) => {
6
+ if (!autoFillField) throw new Error("autoFillField must be provided");
7
+ if (!dictionaryKey || typeof dictionaryKey !== "string") throw new Error("dictionaryKey must be a non-empty string");
8
+ if (!dictionaryFilePath || typeof dictionaryFilePath !== "string") throw new Error("dictionaryFilePath must be a non-empty string");
9
+ if (!baseDir || typeof baseDir !== "string") throw new Error("baseDir must be a non-empty string");
10
+ const result = await parseFilePathPattern(autoFillField, {
11
+ key: dictionaryKey,
12
+ fileName: basename(dictionaryFilePath).split(".").slice(0, -2).join("."),
13
+ locale
14
+ });
15
+ const absoluteDictionaryPath = isAbsolute(dictionaryFilePath) ? dictionaryFilePath : resolve(baseDir, dictionaryFilePath);
16
+ if (result.startsWith("./") || result.startsWith("../")) return resolve(dirname(absoluteDictionaryPath), result);
17
+ if (isAbsolute(result)) {
18
+ const normalizedResult = normalize(result);
19
+ const normalizedBaseDir = normalize(baseDir);
20
+ if (result.startsWith("/") && !normalizedResult.startsWith(normalizedBaseDir)) {
21
+ const relativeToBase = resolve(baseDir, result.substring(1));
22
+ if (!result.startsWith("/usr/") && !result.startsWith("/etc/") && !result.startsWith("/var/") && !result.startsWith("/home/") && !result.startsWith("/Users/")) return relativeToBase;
23
+ }
24
+ return normalizedResult;
25
+ }
26
+ return normalize(result);
27
+ };
28
+
29
+ //#endregion
30
+ export { formatAutoFilledFilePath };
2
31
  //# sourceMappingURL=formatAutoFilledFilePath.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"formatAutoFilledFilePath.mjs","names":[],"sources":["../../../src/fill/formatAutoFilledFilePath.ts"],"sourcesContent":["import { basename, dirname, isAbsolute, normalize, resolve } from 'node:path';\nimport { parseFilePathPattern } from '@intlayer/config/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\n\nexport const formatAutoFilledFilePath = async (\n autoFillField: FilePathPattern,\n dictionaryKey: string,\n dictionaryFilePath: string,\n baseDir: string,\n locale?: Locale\n): Promise<string> => {\n // Validate inputs\n if (!autoFillField) {\n throw new Error('autoFillField must be provided');\n }\n if (!dictionaryKey || typeof dictionaryKey !== 'string') {\n throw new Error('dictionaryKey must be a non-empty string');\n }\n if (!dictionaryFilePath || typeof dictionaryFilePath !== 'string') {\n throw new Error('dictionaryFilePath must be a non-empty string');\n }\n if (!baseDir || typeof baseDir !== 'string') {\n throw new Error('baseDir must be a non-empty string');\n }\n\n // Extract the original filename without extensions (.content.ts -> dictionaryFieldEditor)\n const originalFileName = basename(dictionaryFilePath)\n .split('.')\n .slice(0, -2) // Remove last 2 extensions (.content.tsx)\n .join('.');\n\n // Replace placeholders in autoFillField\n const result: string = await parseFilePathPattern(autoFillField, {\n key: dictionaryKey,\n fileName: originalFileName,\n locale,\n });\n\n // Normalize the dictionary file path - if it's relative, make it absolute relative to baseDir\n const absoluteDictionaryPath = isAbsolute(dictionaryFilePath)\n ? dictionaryFilePath\n : resolve(baseDir, dictionaryFilePath);\n\n // Handle relative paths (starting with ./ or ../)\n if (result.startsWith('./') || result.startsWith('../')) {\n const fileDir = dirname(absoluteDictionaryPath);\n const resolvedPath = resolve(fileDir, result);\n\n return resolvedPath;\n }\n\n // Handle absolute paths\n if (isAbsolute(result)) {\n const normalizedResult = normalize(result);\n const normalizedBaseDir = normalize(baseDir);\n\n // Check if it's relative to baseDir (starts with /)\n // but not a system path (like /usr/local)\n if (\n result.startsWith('/') &&\n !normalizedResult.startsWith(normalizedBaseDir)\n ) {\n // Try to resolve it relative to baseDir first\n const relativeToBase = resolve(baseDir, result.substring(1));\n\n // If the path doesn't exist in common system directories, treat as relative to baseDir\n if (\n !result.startsWith('/usr/') &&\n !result.startsWith('/etc/') &&\n !result.startsWith('/var/') &&\n !result.startsWith('/home/') &&\n !result.startsWith('/Users/')\n ) {\n return relativeToBase;\n }\n }\n\n // It's a true system absolute path\n return normalizedResult;\n }\n\n // Default case: treat as relative to baseDir\n return normalize(result);\n};\n"],"mappings":"4JAKA,MAAa,EAA2B,MACtC,EACA,EACA,EACA,EACA,IACoB,CAEpB,GAAI,CAAC,EACH,MAAU,MAAM,iCAAiC,CAEnD,GAAI,CAAC,GAAiB,OAAO,GAAkB,SAC7C,MAAU,MAAM,2CAA2C,CAE7D,GAAI,CAAC,GAAsB,OAAO,GAAuB,SACvD,MAAU,MAAM,gDAAgD,CAElE,GAAI,CAAC,GAAW,OAAO,GAAY,SACjC,MAAU,MAAM,qCAAqC,CAUvD,IAAM,EAAiB,MAAM,EAAqB,EAAe,CAC/D,IAAK,EACL,SARuB,EAAS,EAAmB,CAClD,MAAM,IAAI,CACV,MAAM,EAAG,GAAG,CACZ,KAAK,IAAI,CAMV,SACD,CAAC,CAGI,EAAyB,EAAW,EAAmB,CACzD,EACA,EAAQ,EAAS,EAAmB,CAGxC,GAAI,EAAO,WAAW,KAAK,EAAI,EAAO,WAAW,MAAM,CAIrD,OAFqB,EADL,EAAQ,EAAuB,CACT,EAAO,CAM/C,GAAI,EAAW,EAAO,CAAE,CACtB,IAAM,EAAmB,EAAU,EAAO,CACpC,EAAoB,EAAU,EAAQ,CAI5C,GACE,EAAO,WAAW,IAAI,EACtB,CAAC,EAAiB,WAAW,EAAkB,CAC/C,CAEA,IAAM,EAAiB,EAAQ,EAAS,EAAO,UAAU,EAAE,CAAC,CAG5D,GACE,CAAC,EAAO,WAAW,QAAQ,EAC3B,CAAC,EAAO,WAAW,QAAQ,EAC3B,CAAC,EAAO,WAAW,QAAQ,EAC3B,CAAC,EAAO,WAAW,SAAS,EAC5B,CAAC,EAAO,WAAW,UAAU,CAE7B,OAAO,EAKX,OAAO,EAIT,OAAO,EAAU,EAAO"}
1
+ {"version":3,"file":"formatAutoFilledFilePath.mjs","names":[],"sources":["../../../src/fill/formatAutoFilledFilePath.ts"],"sourcesContent":["import { basename, dirname, isAbsolute, normalize, resolve } from 'node:path';\nimport { parseFilePathPattern } from '@intlayer/config/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\n\nexport const formatAutoFilledFilePath = async (\n autoFillField: FilePathPattern,\n dictionaryKey: string,\n dictionaryFilePath: string,\n baseDir: string,\n locale?: Locale\n): Promise<string> => {\n // Validate inputs\n if (!autoFillField) {\n throw new Error('autoFillField must be provided');\n }\n if (!dictionaryKey || typeof dictionaryKey !== 'string') {\n throw new Error('dictionaryKey must be a non-empty string');\n }\n if (!dictionaryFilePath || typeof dictionaryFilePath !== 'string') {\n throw new Error('dictionaryFilePath must be a non-empty string');\n }\n if (!baseDir || typeof baseDir !== 'string') {\n throw new Error('baseDir must be a non-empty string');\n }\n\n // Extract the original filename without extensions (.content.ts -> dictionaryFieldEditor)\n const originalFileName = basename(dictionaryFilePath)\n .split('.')\n .slice(0, -2) // Remove last 2 extensions (.content.tsx)\n .join('.');\n\n // Replace placeholders in autoFillField\n const result: string = await parseFilePathPattern(autoFillField, {\n key: dictionaryKey,\n fileName: originalFileName,\n locale,\n });\n\n // Normalize the dictionary file path - if it's relative, make it absolute relative to baseDir\n const absoluteDictionaryPath = isAbsolute(dictionaryFilePath)\n ? dictionaryFilePath\n : resolve(baseDir, dictionaryFilePath);\n\n // Handle relative paths (starting with ./ or ../)\n if (result.startsWith('./') || result.startsWith('../')) {\n const fileDir = dirname(absoluteDictionaryPath);\n const resolvedPath = resolve(fileDir, result);\n\n return resolvedPath;\n }\n\n // Handle absolute paths\n if (isAbsolute(result)) {\n const normalizedResult = normalize(result);\n const normalizedBaseDir = normalize(baseDir);\n\n // Check if it's relative to baseDir (starts with /)\n // but not a system path (like /usr/local)\n if (\n result.startsWith('/') &&\n !normalizedResult.startsWith(normalizedBaseDir)\n ) {\n // Try to resolve it relative to baseDir first\n const relativeToBase = resolve(baseDir, result.substring(1));\n\n // If the path doesn't exist in common system directories, treat as relative to baseDir\n if (\n !result.startsWith('/usr/') &&\n !result.startsWith('/etc/') &&\n !result.startsWith('/var/') &&\n !result.startsWith('/home/') &&\n !result.startsWith('/Users/')\n ) {\n return relativeToBase;\n }\n }\n\n // It's a true system absolute path\n return normalizedResult;\n }\n\n // Default case: treat as relative to baseDir\n return normalize(result);\n};\n"],"mappings":";;;;AAKA,MAAa,2BAA2B,OACtC,eACA,eACA,oBACA,SACA,WACoB;AAEpB,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,iCAAiC;AAEnD,KAAI,CAAC,iBAAiB,OAAO,kBAAkB,SAC7C,OAAM,IAAI,MAAM,2CAA2C;AAE7D,KAAI,CAAC,sBAAsB,OAAO,uBAAuB,SACvD,OAAM,IAAI,MAAM,gDAAgD;AAElE,KAAI,CAAC,WAAW,OAAO,YAAY,SACjC,OAAM,IAAI,MAAM,qCAAqC;CAUvD,MAAM,SAAiB,MAAM,qBAAqB,eAAe;EAC/D,KAAK;EACL,UARuB,SAAS,mBAAmB,CAClD,MAAM,IAAI,CACV,MAAM,GAAG,GAAG,CACZ,KAAK,IAAI;EAMV;EACD,CAAC;CAGF,MAAM,yBAAyB,WAAW,mBAAmB,GACzD,qBACA,QAAQ,SAAS,mBAAmB;AAGxC,KAAI,OAAO,WAAW,KAAK,IAAI,OAAO,WAAW,MAAM,CAIrD,QAFqB,QADL,QAAQ,uBAAuB,EACT,OAAO;AAM/C,KAAI,WAAW,OAAO,EAAE;EACtB,MAAM,mBAAmB,UAAU,OAAO;EAC1C,MAAM,oBAAoB,UAAU,QAAQ;AAI5C,MACE,OAAO,WAAW,IAAI,IACtB,CAAC,iBAAiB,WAAW,kBAAkB,EAC/C;GAEA,MAAM,iBAAiB,QAAQ,SAAS,OAAO,UAAU,EAAE,CAAC;AAG5D,OACE,CAAC,OAAO,WAAW,QAAQ,IAC3B,CAAC,OAAO,WAAW,QAAQ,IAC3B,CAAC,OAAO,WAAW,QAAQ,IAC3B,CAAC,OAAO,WAAW,SAAS,IAC5B,CAAC,OAAO,WAAW,UAAU,CAE7B,QAAO;;AAKX,SAAO;;AAIT,QAAO,UAAU,OAAO"}
@@ -1,2 +1,86 @@
1
- import{basename as e,dirname as t,extname as n,relative as r}from"node:path";import{getFormatFromExtension as i,resolveRelativePath as a}from"@intlayer/chokidar/utils";import{parseStringPattern as o}from"@intlayer/config/utils";const s=async(s,c,l,u,d)=>{if(!s||typeof s==`boolean`)return[];let{baseDir:f}=d.system,{defaultLocale:p}=d.internationalization,m=n(l),h=e(l),g=h.includes(`.content.`)?h.split(`.content.`)[0]:h.split(`.`)[0],_=g.charAt(0).toLowerCase()+g.slice(1),v=i(m),y=(e,a)=>{let o=`json`;if(typeof a==`string`){let e=i(n(a));e&&(o=e)}return{key:u,componentDirPath:r(f,t(l)),componentFileName:g,fileName:_,componentFormat:v,componentExtension:m,format:o,locale:e,extension:d.content.fileExtensions[0]}},b=async(e,t)=>{let n=`###########locale###########`,r=!1;if(typeof e==`string`?r=e.includes(`{{locale}}`):typeof e==`function`&&(r=(await e(y(n,e))).includes(n)),r){let n=[];for(let r of t){let t=a(typeof e==`string`?o(e,y(r,e)):await e(y(r,e)),l,f);n.push({filePath:t,localeList:[r],isPerLocale:!0})}return n.reduce((e,t)=>{let n=e.find(e=>e.filePath===t.filePath);return n?(n.localeList.includes(t.localeList[0])||n.localeList.push(...t.localeList),n.isPerLocale=!1):e.push(t),e},[])}else return[{filePath:a(typeof e==`string`?o(e,y(p,e)):await e(y(p,e)),l,f),localeList:t,isPerLocale:!1}]};if(typeof s==`object`&&s){let e=[];for(let t of c){let n=s[t];if(n&&typeof n!=`boolean`){let r=await b(n,[t]);e.push(...r)}}return e.reduce((e,t)=>{let n=e.find(e=>e.filePath===t.filePath);if(n){for(let e of t.localeList)n.localeList.includes(e)||n.localeList.push(e);n.isPerLocale=!1}else e.push(t);return e},[])}return typeof s==`string`||typeof s==`function`?b(s,c):[]};export{s as formatFillData};
1
+ import { basename, dirname, extname, relative } from "node:path";
2
+ import { getFormatFromExtension, resolveRelativePath } from "@intlayer/chokidar/utils";
3
+ import { parseStringPattern } from "@intlayer/config/utils";
4
+
5
+ //#region src/fill/formatFillData.ts
6
+ const formatFillData = async (fillField, localeList, filePath, dictionaryKey, configuration) => {
7
+ if (!fillField || typeof fillField === "boolean") return [];
8
+ const { baseDir } = configuration.system;
9
+ const { defaultLocale } = configuration.internationalization;
10
+ const extension = extname(filePath);
11
+ const base = basename(filePath);
12
+ const cleanComponentFileName = base.includes(".content.") ? base.split(".content.")[0] : base.split(".")[0];
13
+ const uncapitalizedName = cleanComponentFileName.charAt(0).toLowerCase() + cleanComponentFileName.slice(1);
14
+ const componentFormat = getFormatFromExtension(extension);
15
+ const getContext = (locale, patternType) => {
16
+ let format = "json";
17
+ if (typeof patternType === "string") {
18
+ const extFormat = getFormatFromExtension(extname(patternType));
19
+ if (extFormat) format = extFormat;
20
+ }
21
+ return {
22
+ key: dictionaryKey,
23
+ componentDirPath: relative(baseDir, dirname(filePath)),
24
+ componentFileName: cleanComponentFileName,
25
+ fileName: uncapitalizedName,
26
+ componentFormat,
27
+ componentExtension: extension,
28
+ format,
29
+ locale,
30
+ extension: configuration.content.fileExtensions[0]
31
+ };
32
+ };
33
+ const processPattern = async (pattern, locales) => {
34
+ const dummyLocale = "###########locale###########";
35
+ let isPatternPerLocale = false;
36
+ if (typeof pattern === "string") isPatternPerLocale = pattern.includes("{{locale}}");
37
+ else if (typeof pattern === "function") isPatternPerLocale = (await pattern(getContext(dummyLocale, pattern))).includes(dummyLocale);
38
+ if (isPatternPerLocale) {
39
+ const resolvedPaths = [];
40
+ for (const locale of locales) {
41
+ const absolutePath = resolveRelativePath(typeof pattern === "string" ? parseStringPattern(pattern, getContext(locale, pattern)) : await pattern(getContext(locale, pattern)), filePath, baseDir);
42
+ resolvedPaths.push({
43
+ filePath: absolutePath,
44
+ localeList: [locale],
45
+ isPerLocale: true
46
+ });
47
+ }
48
+ return resolvedPaths.reduce((acc, curr) => {
49
+ const existing = acc.find((item) => item.filePath === curr.filePath);
50
+ if (existing) {
51
+ if (!existing.localeList.includes(curr.localeList[0])) existing.localeList.push(...curr.localeList);
52
+ existing.isPerLocale = false;
53
+ } else acc.push(curr);
54
+ return acc;
55
+ }, []);
56
+ } else return [{
57
+ filePath: resolveRelativePath(typeof pattern === "string" ? parseStringPattern(pattern, getContext(defaultLocale, pattern)) : await pattern(getContext(defaultLocale, pattern)), filePath, baseDir),
58
+ localeList: locales,
59
+ isPerLocale: false
60
+ }];
61
+ };
62
+ if (typeof fillField === "object" && fillField !== null) {
63
+ const results = [];
64
+ for (const locale of localeList) {
65
+ const pattern = fillField[locale];
66
+ if (pattern && typeof pattern !== "boolean") {
67
+ const res = await processPattern(pattern, [locale]);
68
+ results.push(...res);
69
+ }
70
+ }
71
+ return results.reduce((acc, curr) => {
72
+ const existing = acc.find((item) => item.filePath === curr.filePath);
73
+ if (existing) {
74
+ for (const loc of curr.localeList) if (!existing.localeList.includes(loc)) existing.localeList.push(loc);
75
+ existing.isPerLocale = false;
76
+ } else acc.push(curr);
77
+ return acc;
78
+ }, []);
79
+ }
80
+ if (typeof fillField === "string" || typeof fillField === "function") return processPattern(fillField, localeList);
81
+ return [];
82
+ };
83
+
84
+ //#endregion
85
+ export { formatFillData };
2
86
  //# sourceMappingURL=formatFillData.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"formatFillData.mjs","names":[],"sources":["../../../src/fill/formatFillData.ts"],"sourcesContent":["import { basename, dirname, extname, relative } from 'node:path';\nimport {\n getFormatFromExtension,\n resolveRelativePath,\n} from '@intlayer/chokidar/utils';\nimport { parseStringPattern } from '@intlayer/config/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { DictionaryKey, Fill } from '@intlayer/types/dictionary';\nimport type {\n FilePathPattern,\n FilePathPatternContext,\n} from '@intlayer/types/filePathPattern';\n\nexport type FillData = {\n localeList: Locale[];\n filePath: string;\n isPerLocale: boolean;\n};\n\nexport const formatFillData = async (\n fillField: Fill,\n localeList: Locale[],\n filePath: string,\n dictionaryKey: DictionaryKey,\n configuration: IntlayerConfig\n): Promise<FillData[]> => {\n if (!fillField || typeof fillField === 'boolean') return [];\n\n const { baseDir } = configuration.system;\n const { defaultLocale } = configuration.internationalization;\n\n const extension = extname(filePath);\n const base = basename(filePath);\n\n // Extract the original filename without extensions\n const cleanComponentFileName = base.includes('.content.')\n ? base.split('.content.')[0]\n : base.split('.')[0];\n\n const uncapitalizedName =\n cleanComponentFileName.charAt(0).toLowerCase() +\n cleanComponentFileName.slice(1);\n\n const componentFormat = getFormatFromExtension(extension);\n\n const getContext = (\n locale: Locale,\n patternType?: FilePathPattern\n ): FilePathPatternContext => {\n let format: FilePathPatternContext['format'] = 'json';\n if (typeof patternType === 'string') {\n const extFormat = getFormatFromExtension(extname(patternType) as any);\n if (extFormat) {\n format = extFormat as any;\n }\n }\n\n return {\n key: dictionaryKey,\n componentDirPath: relative(baseDir, dirname(filePath)),\n componentFileName: cleanComponentFileName,\n fileName: uncapitalizedName,\n componentFormat:\n componentFormat as FilePathPatternContext['componentFormat'],\n componentExtension:\n extension as FilePathPatternContext['componentExtension'],\n format,\n locale,\n extension: configuration.content.fileExtensions[0],\n };\n };\n\n const processPattern = async (\n pattern: FilePathPattern,\n locales: Locale[]\n ): Promise<FillData[]> => {\n const dummyLocale = '###########locale###########' as Locale;\n let isPatternPerLocale = false;\n\n if (typeof pattern === 'string') {\n isPatternPerLocale = pattern.includes('{{locale}}');\n } else if (typeof pattern === 'function') {\n const pathWithDummy = await pattern(getContext(dummyLocale, pattern));\n isPatternPerLocale = pathWithDummy.includes(dummyLocale);\n }\n\n if (isPatternPerLocale) {\n const resolvedPaths: FillData[] = [];\n\n // Generate one path per locale\n for (const locale of locales) {\n const rawPath =\n typeof pattern === 'string'\n ? parseStringPattern(pattern, getContext(locale, pattern))\n : await pattern(getContext(locale, pattern));\n\n const absolutePath = resolveRelativePath(rawPath, filePath, baseDir);\n\n resolvedPaths.push({\n filePath: absolutePath,\n localeList: [locale],\n isPerLocale: true,\n });\n }\n\n // Group by filePath in case multiple locales resolve to the same path\n const groupedByFilePath = resolvedPaths.reduce((acc, curr) => {\n const existing = acc.find((item) => item.filePath === curr.filePath);\n if (existing) {\n if (!existing.localeList.includes(curr.localeList[0])) {\n existing.localeList.push(...curr.localeList);\n }\n // If multiple locales share a path, it's no longer strictly per-locale\n existing.isPerLocale = false;\n } else {\n acc.push(curr);\n }\n return acc;\n }, [] as FillData[]);\n\n return groupedByFilePath;\n } else {\n // Single multi-lingual path using default locale for pattern resolution\n const rawPath =\n typeof pattern === 'string'\n ? parseStringPattern(pattern, getContext(defaultLocale, pattern))\n : await pattern(getContext(defaultLocale, pattern));\n\n const absolutePath = resolveRelativePath(rawPath, filePath, baseDir);\n\n return [\n {\n filePath: absolutePath,\n localeList: locales,\n isPerLocale: false,\n },\n ];\n }\n };\n\n // Handle Record of Locales\n if (typeof fillField === 'object' && fillField !== null) {\n const results: FillData[] = [];\n\n for (const locale of localeList) {\n const pattern = (fillField as Record<string, any>)[locale];\n if (pattern && typeof pattern !== 'boolean') {\n const res = await processPattern(pattern as FilePathPattern, [locale]);\n results.push(...res);\n }\n }\n\n // Merge identical file paths if they stem from different locales having the same output path\n const grouped = results.reduce((acc, curr) => {\n const existing = acc.find((item) => item.filePath === curr.filePath);\n if (existing) {\n for (const loc of curr.localeList) {\n if (!existing.localeList.includes(loc)) {\n existing.localeList.push(loc);\n }\n }\n existing.isPerLocale = false;\n } else {\n acc.push(curr);\n }\n return acc;\n }, [] as FillData[]);\n\n return grouped;\n }\n\n // Handle static string or function patterns\n if (typeof fillField === 'string' || typeof fillField === 'function') {\n return processPattern(fillField as FilePathPattern, localeList);\n }\n\n return [];\n};\n"],"mappings":"oOAoBA,MAAa,EAAiB,MAC5B,EACA,EACA,EACA,EACA,IACwB,CACxB,GAAI,CAAC,GAAa,OAAO,GAAc,UAAW,MAAO,EAAE,CAE3D,GAAM,CAAE,WAAY,EAAc,OAC5B,CAAE,iBAAkB,EAAc,qBAElC,EAAY,EAAQ,EAAS,CAC7B,EAAO,EAAS,EAAS,CAGzB,EAAyB,EAAK,SAAS,YAAY,CACrD,EAAK,MAAM,YAAY,CAAC,GACxB,EAAK,MAAM,IAAI,CAAC,GAEd,EACJ,EAAuB,OAAO,EAAE,CAAC,aAAa,CAC9C,EAAuB,MAAM,EAAE,CAE3B,EAAkB,EAAuB,EAAU,CAEnD,GACJ,EACA,IAC2B,CAC3B,IAAI,EAA2C,OAC/C,GAAI,OAAO,GAAgB,SAAU,CACnC,IAAM,EAAY,EAAuB,EAAQ,EAAY,CAAQ,CACjE,IACF,EAAS,GAIb,MAAO,CACL,IAAK,EACL,iBAAkB,EAAS,EAAS,EAAQ,EAAS,CAAC,CACtD,kBAAmB,EACnB,SAAU,EAER,kBACF,mBACE,EACF,SACA,SACA,UAAW,EAAc,QAAQ,eAAe,GACjD,EAGG,EAAiB,MACrB,EACA,IACwB,CACxB,IAAM,EAAc,+BAChB,EAAqB,GASzB,GAPI,OAAO,GAAY,SACrB,EAAqB,EAAQ,SAAS,aAAa,CAC1C,OAAO,GAAY,aAE5B,GADsB,MAAM,EAAQ,EAAW,EAAa,EAAQ,CAAC,EAClC,SAAS,EAAY,EAGtD,EAAoB,CACtB,IAAM,EAA4B,EAAE,CAGpC,IAAK,IAAM,KAAU,EAAS,CAM5B,IAAM,EAAe,EAJnB,OAAO,GAAY,SACf,EAAmB,EAAS,EAAW,EAAQ,EAAQ,CAAC,CACxD,MAAM,EAAQ,EAAW,EAAQ,EAAQ,CAAC,CAEE,EAAU,EAAQ,CAEpE,EAAc,KAAK,CACjB,SAAU,EACV,WAAY,CAAC,EAAO,CACpB,YAAa,GACd,CAAC,CAkBJ,OAd0B,EAAc,QAAQ,EAAK,IAAS,CAC5D,IAAM,EAAW,EAAI,KAAM,GAAS,EAAK,WAAa,EAAK,SAAS,CAUpE,OATI,GACG,EAAS,WAAW,SAAS,EAAK,WAAW,GAAG,EACnD,EAAS,WAAW,KAAK,GAAG,EAAK,WAAW,CAG9C,EAAS,YAAc,IAEvB,EAAI,KAAK,EAAK,CAET,GACN,EAAE,CAAe,MAYpB,MAAO,CACL,CACE,SAJiB,EAJnB,OAAO,GAAY,SACf,EAAmB,EAAS,EAAW,EAAe,EAAQ,CAAC,CAC/D,MAAM,EAAQ,EAAW,EAAe,EAAQ,CAAC,CAEL,EAAU,EAAQ,CAKhE,WAAY,EACZ,YAAa,GACd,CACF,EAKL,GAAI,OAAO,GAAc,UAAY,EAAoB,CACvD,IAAM,EAAsB,EAAE,CAE9B,IAAK,IAAM,KAAU,EAAY,CAC/B,IAAM,EAAW,EAAkC,GACnD,GAAI,GAAW,OAAO,GAAY,UAAW,CAC3C,IAAM,EAAM,MAAM,EAAe,EAA4B,CAAC,EAAO,CAAC,CACtE,EAAQ,KAAK,GAAG,EAAI,EAoBxB,OAfgB,EAAQ,QAAQ,EAAK,IAAS,CAC5C,IAAM,EAAW,EAAI,KAAM,GAAS,EAAK,WAAa,EAAK,SAAS,CACpE,GAAI,EAAU,CACZ,IAAK,IAAM,KAAO,EAAK,WAChB,EAAS,WAAW,SAAS,EAAI,EACpC,EAAS,WAAW,KAAK,EAAI,CAGjC,EAAS,YAAc,QAEvB,EAAI,KAAK,EAAK,CAEhB,OAAO,GACN,EAAE,CAAe,CAUtB,OAJI,OAAO,GAAc,UAAY,OAAO,GAAc,WACjD,EAAe,EAA8B,EAAW,CAG1D,EAAE"}
1
+ {"version":3,"file":"formatFillData.mjs","names":[],"sources":["../../../src/fill/formatFillData.ts"],"sourcesContent":["import { basename, dirname, extname, relative } from 'node:path';\nimport {\n getFormatFromExtension,\n resolveRelativePath,\n} from '@intlayer/chokidar/utils';\nimport { parseStringPattern } from '@intlayer/config/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { DictionaryKey, Fill } from '@intlayer/types/dictionary';\nimport type {\n FilePathPattern,\n FilePathPatternContext,\n} from '@intlayer/types/filePathPattern';\n\nexport type FillData = {\n localeList: Locale[];\n filePath: string;\n isPerLocale: boolean;\n};\n\nexport const formatFillData = async (\n fillField: Fill,\n localeList: Locale[],\n filePath: string,\n dictionaryKey: DictionaryKey,\n configuration: IntlayerConfig\n): Promise<FillData[]> => {\n if (!fillField || typeof fillField === 'boolean') return [];\n\n const { baseDir } = configuration.system;\n const { defaultLocale } = configuration.internationalization;\n\n const extension = extname(filePath);\n const base = basename(filePath);\n\n // Extract the original filename without extensions\n const cleanComponentFileName = base.includes('.content.')\n ? base.split('.content.')[0]\n : base.split('.')[0];\n\n const uncapitalizedName =\n cleanComponentFileName.charAt(0).toLowerCase() +\n cleanComponentFileName.slice(1);\n\n const componentFormat = getFormatFromExtension(extension);\n\n const getContext = (\n locale: Locale,\n patternType?: FilePathPattern\n ): FilePathPatternContext => {\n let format: FilePathPatternContext['format'] = 'json';\n if (typeof patternType === 'string') {\n const extFormat = getFormatFromExtension(extname(patternType) as any);\n if (extFormat) {\n format = extFormat as any;\n }\n }\n\n return {\n key: dictionaryKey,\n componentDirPath: relative(baseDir, dirname(filePath)),\n componentFileName: cleanComponentFileName,\n fileName: uncapitalizedName,\n componentFormat:\n componentFormat as FilePathPatternContext['componentFormat'],\n componentExtension:\n extension as FilePathPatternContext['componentExtension'],\n format,\n locale,\n extension: configuration.content.fileExtensions[0],\n };\n };\n\n const processPattern = async (\n pattern: FilePathPattern,\n locales: Locale[]\n ): Promise<FillData[]> => {\n const dummyLocale = '###########locale###########' as Locale;\n let isPatternPerLocale = false;\n\n if (typeof pattern === 'string') {\n isPatternPerLocale = pattern.includes('{{locale}}');\n } else if (typeof pattern === 'function') {\n const pathWithDummy = await pattern(getContext(dummyLocale, pattern));\n isPatternPerLocale = pathWithDummy.includes(dummyLocale);\n }\n\n if (isPatternPerLocale) {\n const resolvedPaths: FillData[] = [];\n\n // Generate one path per locale\n for (const locale of locales) {\n const rawPath =\n typeof pattern === 'string'\n ? parseStringPattern(pattern, getContext(locale, pattern))\n : await pattern(getContext(locale, pattern));\n\n const absolutePath = resolveRelativePath(rawPath, filePath, baseDir);\n\n resolvedPaths.push({\n filePath: absolutePath,\n localeList: [locale],\n isPerLocale: true,\n });\n }\n\n // Group by filePath in case multiple locales resolve to the same path\n const groupedByFilePath = resolvedPaths.reduce((acc, curr) => {\n const existing = acc.find((item) => item.filePath === curr.filePath);\n if (existing) {\n if (!existing.localeList.includes(curr.localeList[0])) {\n existing.localeList.push(...curr.localeList);\n }\n // If multiple locales share a path, it's no longer strictly per-locale\n existing.isPerLocale = false;\n } else {\n acc.push(curr);\n }\n return acc;\n }, [] as FillData[]);\n\n return groupedByFilePath;\n } else {\n // Single multi-lingual path using default locale for pattern resolution\n const rawPath =\n typeof pattern === 'string'\n ? parseStringPattern(pattern, getContext(defaultLocale, pattern))\n : await pattern(getContext(defaultLocale, pattern));\n\n const absolutePath = resolveRelativePath(rawPath, filePath, baseDir);\n\n return [\n {\n filePath: absolutePath,\n localeList: locales,\n isPerLocale: false,\n },\n ];\n }\n };\n\n // Handle Record of Locales\n if (typeof fillField === 'object' && fillField !== null) {\n const results: FillData[] = [];\n\n for (const locale of localeList) {\n const pattern = (fillField as Record<string, any>)[locale];\n if (pattern && typeof pattern !== 'boolean') {\n const res = await processPattern(pattern as FilePathPattern, [locale]);\n results.push(...res);\n }\n }\n\n // Merge identical file paths if they stem from different locales having the same output path\n const grouped = results.reduce((acc, curr) => {\n const existing = acc.find((item) => item.filePath === curr.filePath);\n if (existing) {\n for (const loc of curr.localeList) {\n if (!existing.localeList.includes(loc)) {\n existing.localeList.push(loc);\n }\n }\n existing.isPerLocale = false;\n } else {\n acc.push(curr);\n }\n return acc;\n }, [] as FillData[]);\n\n return grouped;\n }\n\n // Handle static string or function patterns\n if (typeof fillField === 'string' || typeof fillField === 'function') {\n return processPattern(fillField as FilePathPattern, localeList);\n }\n\n return [];\n};\n"],"mappings":";;;;;AAoBA,MAAa,iBAAiB,OAC5B,WACA,YACA,UACA,eACA,kBACwB;AACxB,KAAI,CAAC,aAAa,OAAO,cAAc,UAAW,QAAO,EAAE;CAE3D,MAAM,EAAE,YAAY,cAAc;CAClC,MAAM,EAAE,kBAAkB,cAAc;CAExC,MAAM,YAAY,QAAQ,SAAS;CACnC,MAAM,OAAO,SAAS,SAAS;CAG/B,MAAM,yBAAyB,KAAK,SAAS,YAAY,GACrD,KAAK,MAAM,YAAY,CAAC,KACxB,KAAK,MAAM,IAAI,CAAC;CAEpB,MAAM,oBACJ,uBAAuB,OAAO,EAAE,CAAC,aAAa,GAC9C,uBAAuB,MAAM,EAAE;CAEjC,MAAM,kBAAkB,uBAAuB,UAAU;CAEzD,MAAM,cACJ,QACA,gBAC2B;EAC3B,IAAI,SAA2C;AAC/C,MAAI,OAAO,gBAAgB,UAAU;GACnC,MAAM,YAAY,uBAAuB,QAAQ,YAAY,CAAQ;AACrE,OAAI,UACF,UAAS;;AAIb,SAAO;GACL,KAAK;GACL,kBAAkB,SAAS,SAAS,QAAQ,SAAS,CAAC;GACtD,mBAAmB;GACnB,UAAU;GAER;GACF,oBACE;GACF;GACA;GACA,WAAW,cAAc,QAAQ,eAAe;GACjD;;CAGH,MAAM,iBAAiB,OACrB,SACA,YACwB;EACxB,MAAM,cAAc;EACpB,IAAI,qBAAqB;AAEzB,MAAI,OAAO,YAAY,SACrB,sBAAqB,QAAQ,SAAS,aAAa;WAC1C,OAAO,YAAY,WAE5B,uBADsB,MAAM,QAAQ,WAAW,aAAa,QAAQ,CAAC,EAClC,SAAS,YAAY;AAG1D,MAAI,oBAAoB;GACtB,MAAM,gBAA4B,EAAE;AAGpC,QAAK,MAAM,UAAU,SAAS;IAM5B,MAAM,eAAe,oBAJnB,OAAO,YAAY,WACf,mBAAmB,SAAS,WAAW,QAAQ,QAAQ,CAAC,GACxD,MAAM,QAAQ,WAAW,QAAQ,QAAQ,CAAC,EAEE,UAAU,QAAQ;AAEpE,kBAAc,KAAK;KACjB,UAAU;KACV,YAAY,CAAC,OAAO;KACpB,aAAa;KACd,CAAC;;AAkBJ,UAd0B,cAAc,QAAQ,KAAK,SAAS;IAC5D,MAAM,WAAW,IAAI,MAAM,SAAS,KAAK,aAAa,KAAK,SAAS;AACpE,QAAI,UAAU;AACZ,SAAI,CAAC,SAAS,WAAW,SAAS,KAAK,WAAW,GAAG,CACnD,UAAS,WAAW,KAAK,GAAG,KAAK,WAAW;AAG9C,cAAS,cAAc;UAEvB,KAAI,KAAK,KAAK;AAEhB,WAAO;MACN,EAAE,CAAe;QAYpB,QAAO,CACL;GACE,UAJiB,oBAJnB,OAAO,YAAY,WACf,mBAAmB,SAAS,WAAW,eAAe,QAAQ,CAAC,GAC/D,MAAM,QAAQ,WAAW,eAAe,QAAQ,CAAC,EAEL,UAAU,QAAQ;GAKhE,YAAY;GACZ,aAAa;GACd,CACF;;AAKL,KAAI,OAAO,cAAc,YAAY,cAAc,MAAM;EACvD,MAAM,UAAsB,EAAE;AAE9B,OAAK,MAAM,UAAU,YAAY;GAC/B,MAAM,UAAW,UAAkC;AACnD,OAAI,WAAW,OAAO,YAAY,WAAW;IAC3C,MAAM,MAAM,MAAM,eAAe,SAA4B,CAAC,OAAO,CAAC;AACtE,YAAQ,KAAK,GAAG,IAAI;;;AAoBxB,SAfgB,QAAQ,QAAQ,KAAK,SAAS;GAC5C,MAAM,WAAW,IAAI,MAAM,SAAS,KAAK,aAAa,KAAK,SAAS;AACpE,OAAI,UAAU;AACZ,SAAK,MAAM,OAAO,KAAK,WACrB,KAAI,CAAC,SAAS,WAAW,SAAS,IAAI,CACpC,UAAS,WAAW,KAAK,IAAI;AAGjC,aAAS,cAAc;SAEvB,KAAI,KAAK,KAAK;AAEhB,UAAO;KACN,EAAE,CAAe;;AAMtB,KAAI,OAAO,cAAc,YAAY,OAAO,cAAc,WACxD,QAAO,eAAe,WAA8B,WAAW;AAGjE,QAAO,EAAE"}
@@ -1,2 +1,25 @@
1
- const e=(t,n=new Set)=>{if(!t||typeof t!=`object`)return n;t.nodeType===`translation`&&t.translation&&Object.keys(t.translation).forEach(e=>{n.add(e)});for(let r of Object.values(t))r&&typeof r==`object`&&e(r,n);return n},t=t=>{let n=e(t.content);return Array.from(n)};export{t as getAvailableLocalesInDictionary};
1
+ //#region src/fill/getAvailableLocalesInDictionary.ts
2
+ /**
3
+ * Recursively traverses dictionary content to find all locales that have actual translations.
4
+ * Returns a Set of locale strings that are present in the translation nodes.
5
+ */
6
+ const extractLocalesFromContent = (content, locales = /* @__PURE__ */ new Set()) => {
7
+ if (!content || typeof content !== "object") return locales;
8
+ if (content.nodeType === "translation" && content.translation) Object.keys(content.translation).forEach((locale) => {
9
+ locales.add(locale);
10
+ });
11
+ for (const value of Object.values(content)) if (value && typeof value === "object") extractLocalesFromContent(value, locales);
12
+ return locales;
13
+ };
14
+ /**
15
+ * Gets all locales that have actual translations in the dictionary content.
16
+ * Only returns locales that are present in at least one translation node.
17
+ */
18
+ const getAvailableLocalesInDictionary = (dictionary) => {
19
+ const localesSet = extractLocalesFromContent(dictionary.content);
20
+ return Array.from(localesSet);
21
+ };
22
+
23
+ //#endregion
24
+ export { getAvailableLocalesInDictionary };
2
25
  //# sourceMappingURL=getAvailableLocalesInDictionary.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"getAvailableLocalesInDictionary.mjs","names":[],"sources":["../../../src/fill/getAvailableLocalesInDictionary.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport type { Locale } from '@intlayer/types/allLocales';\n\n/**\n * Recursively traverses dictionary content to find all locales that have actual translations.\n * Returns a Set of locale strings that are present in the translation nodes.\n */\nconst extractLocalesFromContent = (\n content: any,\n locales: Set<Locale> = new Set()\n): Set<Locale> => {\n if (!content || typeof content !== 'object') {\n return locales;\n }\n\n // Check if this is a translation node\n if (content.nodeType === 'translation' && content.translation) {\n // Add all locale keys from the translation map\n Object.keys(content.translation).forEach((locale) => {\n locales.add(locale as Locale);\n });\n }\n\n // Recursively check nested objects\n for (const value of Object.values(content)) {\n if (value && typeof value === 'object') {\n extractLocalesFromContent(value, locales);\n }\n }\n\n return locales;\n};\n\n/**\n * Gets all locales that have actual translations in the dictionary content.\n * Only returns locales that are present in at least one translation node.\n */\nexport const getAvailableLocalesInDictionary = (\n dictionary: Dictionary\n): Locale[] => {\n const localesSet = extractLocalesFromContent(dictionary.content);\n return Array.from(localesSet);\n};\n"],"mappings":"AAOA,MAAM,GACJ,EACA,EAAuB,IAAI,MACX,CAChB,GAAI,CAAC,GAAW,OAAO,GAAY,SACjC,OAAO,EAIL,EAAQ,WAAa,eAAiB,EAAQ,aAEhD,OAAO,KAAK,EAAQ,YAAY,CAAC,QAAS,GAAW,CACnD,EAAQ,IAAI,EAAiB,EAC7B,CAIJ,IAAK,IAAM,KAAS,OAAO,OAAO,EAAQ,CACpC,GAAS,OAAO,GAAU,UAC5B,EAA0B,EAAO,EAAQ,CAI7C,OAAO,GAOI,EACX,GACa,CACb,IAAM,EAAa,EAA0B,EAAW,QAAQ,CAChE,OAAO,MAAM,KAAK,EAAW"}
1
+ {"version":3,"file":"getAvailableLocalesInDictionary.mjs","names":[],"sources":["../../../src/fill/getAvailableLocalesInDictionary.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport type { Locale } from '@intlayer/types/allLocales';\n\n/**\n * Recursively traverses dictionary content to find all locales that have actual translations.\n * Returns a Set of locale strings that are present in the translation nodes.\n */\nconst extractLocalesFromContent = (\n content: any,\n locales: Set<Locale> = new Set()\n): Set<Locale> => {\n if (!content || typeof content !== 'object') {\n return locales;\n }\n\n // Check if this is a translation node\n if (content.nodeType === 'translation' && content.translation) {\n // Add all locale keys from the translation map\n Object.keys(content.translation).forEach((locale) => {\n locales.add(locale as Locale);\n });\n }\n\n // Recursively check nested objects\n for (const value of Object.values(content)) {\n if (value && typeof value === 'object') {\n extractLocalesFromContent(value, locales);\n }\n }\n\n return locales;\n};\n\n/**\n * Gets all locales that have actual translations in the dictionary content.\n * Only returns locales that are present in at least one translation node.\n */\nexport const getAvailableLocalesInDictionary = (\n dictionary: Dictionary\n): Locale[] => {\n const localesSet = extractLocalesFromContent(dictionary.content);\n return Array.from(localesSet);\n};\n"],"mappings":";;;;;AAOA,MAAM,6BACJ,SACA,0BAAuB,IAAI,KAAK,KAChB;AAChB,KAAI,CAAC,WAAW,OAAO,YAAY,SACjC,QAAO;AAIT,KAAI,QAAQ,aAAa,iBAAiB,QAAQ,YAEhD,QAAO,KAAK,QAAQ,YAAY,CAAC,SAAS,WAAW;AACnD,UAAQ,IAAI,OAAiB;GAC7B;AAIJ,MAAK,MAAM,SAAS,OAAO,OAAO,QAAQ,CACxC,KAAI,SAAS,OAAO,UAAU,SAC5B,2BAA0B,OAAO,QAAQ;AAI7C,QAAO;;;;;;AAOT,MAAa,mCACX,eACa;CACb,MAAM,aAAa,0BAA0B,WAAW,QAAQ;AAChE,QAAO,MAAM,KAAK,WAAW"}
@@ -1,2 +1,50 @@
1
- const e=(t,n)=>{if(t===null)return n===null?void 0:null;if(n==null)return t;if(typeof t!=`object`)return;if(Array.isArray(t)){if(!Array.isArray(n))return t;let r=t.map((t,r)=>e(t,n[r])).filter(e=>e!==void 0);return r.length>0?r:void 0}let r={},i=!1;for(let[a,o]of Object.entries(t)){let t=n?.[a],s=e(o,t);s!==void 0&&(r[a]=s,i=!0)}return i?r:void 0},t=(t,n)=>{if(!n||!n.content)return t;let r=e(t.content,n.content);return{...t,content:r??{}}};export{t as getFilterMissingContentPerLocale};
1
+ //#region src/fill/getFilterMissingContentPerLocale.ts
2
+ /**
3
+ * Recursively compares source content with target content and returns only the missing parts.
4
+ * For per-locale files where content is simple JSON (not translation nodes).
5
+ *
6
+ * @param sourceContent - The source content to check
7
+ * @param targetContent - The existing target content
8
+ * @returns Only the content that's missing in the target
9
+ */
10
+ const filterMissingContent = (sourceContent, targetContent) => {
11
+ if (sourceContent === null) return targetContent === null ? void 0 : null;
12
+ if (targetContent === void 0 || targetContent === null) return sourceContent;
13
+ if (typeof sourceContent !== "object") return;
14
+ if (Array.isArray(sourceContent)) {
15
+ if (!Array.isArray(targetContent)) return sourceContent;
16
+ const missingItems = sourceContent.map((item, index) => filterMissingContent(item, targetContent[index])).filter((item) => item !== void 0);
17
+ return missingItems.length > 0 ? missingItems : void 0;
18
+ }
19
+ const result = {};
20
+ let hasMissingContent = false;
21
+ for (const [key, value] of Object.entries(sourceContent)) {
22
+ const targetValue = targetContent?.[key];
23
+ const missingValue = filterMissingContent(value, targetValue);
24
+ if (missingValue !== void 0) {
25
+ result[key] = missingValue;
26
+ hasMissingContent = true;
27
+ }
28
+ }
29
+ return hasMissingContent ? result : void 0;
30
+ };
31
+ /**
32
+ * Filters a dictionary to only include content that's missing in the target dictionary.
33
+ * Used for per-locale content declarations in 'complete' mode.
34
+ *
35
+ * @param sourceDictionary - The source dictionary with content to translate
36
+ * @param targetDictionary - The existing target dictionary
37
+ * @returns A dictionary with only the missing content
38
+ */
39
+ const getFilterMissingContentPerLocale = (sourceDictionary, targetDictionary) => {
40
+ if (!targetDictionary || !targetDictionary.content) return sourceDictionary;
41
+ const missingContent = filterMissingContent(sourceDictionary.content, targetDictionary.content);
42
+ return {
43
+ ...sourceDictionary,
44
+ content: missingContent ?? {}
45
+ };
46
+ };
47
+
48
+ //#endregion
49
+ export { getFilterMissingContentPerLocale };
2
50
  //# sourceMappingURL=getFilterMissingContentPerLocale.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"getFilterMissingContentPerLocale.mjs","names":[],"sources":["../../../src/fill/getFilterMissingContentPerLocale.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\n\n/**\n * Recursively compares source content with target content and returns only the missing parts.\n * For per-locale files where content is simple JSON (not translation nodes).\n *\n * @param sourceContent - The source content to check\n * @param targetContent - The existing target content\n * @returns Only the content that's missing in the target\n */\nconst filterMissingContent = (sourceContent: any, targetContent: any): any => {\n // Source is null - only missing if target doesn't already have null\n if (sourceContent === null) {\n return targetContent === null ? undefined : null;\n }\n\n // If target doesn't exist or is null, all source content is missing\n if (targetContent === undefined || targetContent === null) {\n return sourceContent;\n }\n\n // Primitive values: if target exists (even if empty string), consider it translated\n if (typeof sourceContent !== 'object') {\n return undefined;\n }\n\n // Handle arrays\n if (Array.isArray(sourceContent)) {\n if (!Array.isArray(targetContent)) {\n return sourceContent;\n }\n\n const missingItems = sourceContent\n .map((item, index) => filterMissingContent(item, targetContent[index]))\n .filter((item) => item !== undefined);\n\n return missingItems.length > 0 ? missingItems : undefined;\n }\n\n // Handle objects\n const result: any = {};\n let hasMissingContent = false;\n\n for (const [key, value] of Object.entries(sourceContent)) {\n const targetValue = targetContent?.[key];\n const missingValue = filterMissingContent(value, targetValue);\n\n if (missingValue !== undefined) {\n result[key] = missingValue;\n hasMissingContent = true;\n }\n }\n\n return hasMissingContent ? result : undefined;\n};\n\n/**\n * Filters a dictionary to only include content that's missing in the target dictionary.\n * Used for per-locale content declarations in 'complete' mode.\n *\n * @param sourceDictionary - The source dictionary with content to translate\n * @param targetDictionary - The existing target dictionary\n * @returns A dictionary with only the missing content\n */\nexport const getFilterMissingContentPerLocale = (\n sourceDictionary: Dictionary,\n targetDictionary: Dictionary | undefined\n): Dictionary => {\n if (!targetDictionary || !targetDictionary.content) {\n // If no target exists, all source content is missing\n return sourceDictionary;\n }\n\n const missingContent = filterMissingContent(\n sourceDictionary.content,\n targetDictionary.content\n );\n\n return {\n ...sourceDictionary,\n content: missingContent ?? {},\n };\n};\n"],"mappings":"AAUA,MAAM,GAAwB,EAAoB,IAA4B,CAE5E,GAAI,IAAkB,KACpB,OAAO,IAAkB,KAAO,IAAA,GAAY,KAI9C,GAAI,GAAiD,KACnD,OAAO,EAIT,GAAI,OAAO,GAAkB,SAC3B,OAIF,GAAI,MAAM,QAAQ,EAAc,CAAE,CAChC,GAAI,CAAC,MAAM,QAAQ,EAAc,CAC/B,OAAO,EAGT,IAAM,EAAe,EAClB,KAAK,EAAM,IAAU,EAAqB,EAAM,EAAc,GAAO,CAAC,CACtE,OAAQ,GAAS,IAAS,IAAA,GAAU,CAEvC,OAAO,EAAa,OAAS,EAAI,EAAe,IAAA,GAIlD,IAAM,EAAc,EAAE,CAClB,EAAoB,GAExB,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAc,CAAE,CACxD,IAAM,EAAc,IAAgB,GAC9B,EAAe,EAAqB,EAAO,EAAY,CAEzD,IAAiB,IAAA,KACnB,EAAO,GAAO,EACd,EAAoB,IAIxB,OAAO,EAAoB,EAAS,IAAA,IAWzB,GACX,EACA,IACe,CACf,GAAI,CAAC,GAAoB,CAAC,EAAiB,QAEzC,OAAO,EAGT,IAAM,EAAiB,EACrB,EAAiB,QACjB,EAAiB,QAClB,CAED,MAAO,CACL,GAAG,EACH,QAAS,GAAkB,EAAE,CAC9B"}
1
+ {"version":3,"file":"getFilterMissingContentPerLocale.mjs","names":[],"sources":["../../../src/fill/getFilterMissingContentPerLocale.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\n\n/**\n * Recursively compares source content with target content and returns only the missing parts.\n * For per-locale files where content is simple JSON (not translation nodes).\n *\n * @param sourceContent - The source content to check\n * @param targetContent - The existing target content\n * @returns Only the content that's missing in the target\n */\nconst filterMissingContent = (sourceContent: any, targetContent: any): any => {\n // Source is null - only missing if target doesn't already have null\n if (sourceContent === null) {\n return targetContent === null ? undefined : null;\n }\n\n // If target doesn't exist or is null, all source content is missing\n if (targetContent === undefined || targetContent === null) {\n return sourceContent;\n }\n\n // Primitive values: if target exists (even if empty string), consider it translated\n if (typeof sourceContent !== 'object') {\n return undefined;\n }\n\n // Handle arrays\n if (Array.isArray(sourceContent)) {\n if (!Array.isArray(targetContent)) {\n return sourceContent;\n }\n\n const missingItems = sourceContent\n .map((item, index) => filterMissingContent(item, targetContent[index]))\n .filter((item) => item !== undefined);\n\n return missingItems.length > 0 ? missingItems : undefined;\n }\n\n // Handle objects\n const result: any = {};\n let hasMissingContent = false;\n\n for (const [key, value] of Object.entries(sourceContent)) {\n const targetValue = targetContent?.[key];\n const missingValue = filterMissingContent(value, targetValue);\n\n if (missingValue !== undefined) {\n result[key] = missingValue;\n hasMissingContent = true;\n }\n }\n\n return hasMissingContent ? result : undefined;\n};\n\n/**\n * Filters a dictionary to only include content that's missing in the target dictionary.\n * Used for per-locale content declarations in 'complete' mode.\n *\n * @param sourceDictionary - The source dictionary with content to translate\n * @param targetDictionary - The existing target dictionary\n * @returns A dictionary with only the missing content\n */\nexport const getFilterMissingContentPerLocale = (\n sourceDictionary: Dictionary,\n targetDictionary: Dictionary | undefined\n): Dictionary => {\n if (!targetDictionary || !targetDictionary.content) {\n // If no target exists, all source content is missing\n return sourceDictionary;\n }\n\n const missingContent = filterMissingContent(\n sourceDictionary.content,\n targetDictionary.content\n );\n\n return {\n ...sourceDictionary,\n content: missingContent ?? {},\n };\n};\n"],"mappings":";;;;;;;;;AAUA,MAAM,wBAAwB,eAAoB,kBAA4B;AAE5E,KAAI,kBAAkB,KACpB,QAAO,kBAAkB,OAAO,SAAY;AAI9C,KAAI,kBAAkB,UAAa,kBAAkB,KACnD,QAAO;AAIT,KAAI,OAAO,kBAAkB,SAC3B;AAIF,KAAI,MAAM,QAAQ,cAAc,EAAE;AAChC,MAAI,CAAC,MAAM,QAAQ,cAAc,CAC/B,QAAO;EAGT,MAAM,eAAe,cAClB,KAAK,MAAM,UAAU,qBAAqB,MAAM,cAAc,OAAO,CAAC,CACtE,QAAQ,SAAS,SAAS,OAAU;AAEvC,SAAO,aAAa,SAAS,IAAI,eAAe;;CAIlD,MAAM,SAAc,EAAE;CACtB,IAAI,oBAAoB;AAExB,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,cAAc,EAAE;EACxD,MAAM,cAAc,gBAAgB;EACpC,MAAM,eAAe,qBAAqB,OAAO,YAAY;AAE7D,MAAI,iBAAiB,QAAW;AAC9B,UAAO,OAAO;AACd,uBAAoB;;;AAIxB,QAAO,oBAAoB,SAAS;;;;;;;;;;AAWtC,MAAa,oCACX,kBACA,qBACe;AACf,KAAI,CAAC,oBAAoB,CAAC,iBAAiB,QAEzC,QAAO;CAGT,MAAM,iBAAiB,qBACrB,iBAAiB,SACjB,iBAAiB,QAClB;AAED,QAAO;EACL,GAAG;EACH,SAAS,kBAAkB,EAAE;EAC9B"}
@@ -1 +1,4 @@
1
- import{writeFill as e}from"./writeFill.mjs";import{fill as t}from"./fill.mjs";export{t as fill,e as writeFill};
1
+ import { writeFill } from "./writeFill.mjs";
2
+ import { fill } from "./fill.mjs";
3
+
4
+ export { fill, writeFill };
@@ -1,2 +1,70 @@
1
- import{listMissingTranslationsWithConfig as e}from"../test/listMissingTranslations.mjs";import{basename as t}from"node:path";import{formatLocale as n}from"@intlayer/chokidar/utils";import*as r from"@intlayer/config/colors";import{colon as i,colorize as a,colorizeKey as o,colorizePath as s,getAppLogger as c}from"@intlayer/config/logger";import{getUnmergedDictionaries as l}from"@intlayer/unmerged-dictionaries-entry";import{getFilterTranslationsOnlyDictionary as u}from"@intlayer/core/plugins";import{getDictionaries as d}from"@intlayer/dictionaries-entry";const f=(f,p,m,h,g)=>{let _=c(g),v=d(g),y=l(g),b=Object.values(y).flat().filter(e=>f.includes(e.localId)),{missingTranslations:x}=e(g),S=Math.max(...b.map(e=>e.key.length)),C=[];for(let e of b){let c=i([` - `,a(`[`,r.GREY_DARK),o(e.key),a(`]`,r.GREY_DARK)].join(``),{colSize:S+6}),l=e.key,d=e.localId,f=v[l];if((e.filled??!1)===!0||(e.fill??g.dictionary?.fill??!1)===!1)continue;let y=e.locale??h;if(!f){_(`${c} Dictionary not found in dictionariesRecord. Skipping.`,{level:`warn`});continue}if(!e.filePath){_(`${c} Dictionary has no file path. Skipping.`,{level:`warn`});continue}let b=u(f,y);if(Object.keys(b).length===0){_(`${c} No content found for dictionary in source locale ${n(y)}. Skipping translation for this dictionary.`,{level:`warn`});continue}let w=p;if(m===`complete`&&(w=x.find(e=>e.key===l)?.locales.filter(e=>p.includes(e))??[]),w.length===0){_(`${c} ${a(`No locales to fill, Skipping`,r.GREY_DARK)} ${s(t(e.filePath))}`,{level:`warn`});continue}C.push({dictionaryKey:l,dictionaryLocalId:d,sourceLocale:y,targetLocales:w,dictionaryPreset:c,dictionaryFilePath:e.filePath})}return C};export{f as listTranslationsTasks};
1
+ import { listMissingTranslationsWithConfig } from "../test/listMissingTranslations.mjs";
2
+ import { basename } from "node:path";
3
+ import { formatLocale } from "@intlayer/chokidar/utils";
4
+ import * as ANSIColors from "@intlayer/config/colors";
5
+ import { colon, colorize, colorizeKey, colorizePath, getAppLogger } from "@intlayer/config/logger";
6
+ import { getUnmergedDictionaries } from "@intlayer/unmerged-dictionaries-entry";
7
+ import { getFilterTranslationsOnlyDictionary } from "@intlayer/core/plugins";
8
+ import { getDictionaries } from "@intlayer/dictionaries-entry";
9
+
10
+ //#region src/fill/listTranslationsTasks.ts
11
+ const listTranslationsTasks = (localIds, outputLocales, mode, baseLocale, configuration) => {
12
+ const appLogger = getAppLogger(configuration);
13
+ const mergedDictionariesRecord = getDictionaries(configuration);
14
+ const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);
15
+ const dictionariesToProcess = Object.values(unmergedDictionariesRecord).flat().filter((dictionary) => localIds.includes(dictionary.localId));
16
+ const { missingTranslations } = listMissingTranslationsWithConfig(configuration);
17
+ const maxKeyLength = Math.max(...dictionariesToProcess.map((dictionary) => dictionary.key.length));
18
+ const translationTasks = [];
19
+ for (const targetUnmergedDictionary of dictionariesToProcess) {
20
+ const dictionaryPreset = colon([
21
+ " - ",
22
+ colorize("[", ANSIColors.GREY_DARK),
23
+ colorizeKey(targetUnmergedDictionary.key),
24
+ colorize("]", ANSIColors.GREY_DARK)
25
+ ].join(""), { colSize: maxKeyLength + 6 });
26
+ const dictionaryKey = targetUnmergedDictionary.key;
27
+ const dictionaryLocalId = targetUnmergedDictionary.localId;
28
+ const mainDictionaryToProcess = mergedDictionariesRecord[dictionaryKey];
29
+ if ((targetUnmergedDictionary.filled ?? false) === true) continue;
30
+ if ((targetUnmergedDictionary.fill ?? configuration.dictionary?.fill ?? false) === false) continue;
31
+ const sourceLocale = targetUnmergedDictionary.locale ?? baseLocale;
32
+ if (!mainDictionaryToProcess) {
33
+ appLogger(`${dictionaryPreset} Dictionary not found in dictionariesRecord. Skipping.`, { level: "warn" });
34
+ continue;
35
+ }
36
+ if (!targetUnmergedDictionary.filePath) {
37
+ appLogger(`${dictionaryPreset} Dictionary has no file path. Skipping.`, { level: "warn" });
38
+ continue;
39
+ }
40
+ const sourceLocaleContent = getFilterTranslationsOnlyDictionary(mainDictionaryToProcess, sourceLocale);
41
+ if (Object.keys(sourceLocaleContent).length === 0) {
42
+ appLogger(`${dictionaryPreset} No content found for dictionary in source locale ${formatLocale(sourceLocale)}. Skipping translation for this dictionary.`, { level: "warn" });
43
+ continue;
44
+ }
45
+ /**
46
+ * In 'complete' mode, filter only the missing locales to translate
47
+ *
48
+ * Skip the dictionary if there are no missing locales to translate
49
+ */
50
+ let outputLocalesList = outputLocales;
51
+ if (mode === "complete") outputLocalesList = missingTranslations.find((missingTranslation) => missingTranslation.key === dictionaryKey)?.locales.filter((locale) => outputLocales.includes(locale)) ?? [];
52
+ if (outputLocalesList.length === 0) {
53
+ appLogger(`${dictionaryPreset} ${colorize("No locales to fill, Skipping", ANSIColors.GREY_DARK)} ${colorizePath(basename(targetUnmergedDictionary.filePath))}`, { level: "warn" });
54
+ continue;
55
+ }
56
+ translationTasks.push({
57
+ dictionaryKey,
58
+ dictionaryLocalId,
59
+ sourceLocale,
60
+ targetLocales: outputLocalesList,
61
+ dictionaryPreset,
62
+ dictionaryFilePath: targetUnmergedDictionary.filePath
63
+ });
64
+ }
65
+ return translationTasks;
66
+ };
67
+
68
+ //#endregion
69
+ export { listTranslationsTasks };
2
70
  //# sourceMappingURL=listTranslationsTasks.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"listTranslationsTasks.mjs","names":[],"sources":["../../../src/fill/listTranslationsTasks.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport { formatLocale } from '@intlayer/chokidar/utils';\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 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":"8iBA2BA,MAAa,GACX,EACA,EACA,EACA,EACA,IACsB,CACtB,IAAM,EAAY,EAAa,EAAc,CAEvC,EAA2B,EAAgB,EAAc,CACzD,EAA6B,EAAwB,EAAc,CAGnE,EADsB,OAAO,OAAO,EAA2B,CAAC,MAAM,CAC1B,OAAQ,GACxD,EAAS,SAAS,EAAW,QAAS,CACvC,CAEK,CAAE,uBACN,EAAkC,EAAc,CAE5C,EAAe,KAAK,IACxB,GAAG,EAAsB,IAAK,GAAe,EAAW,IAAI,OAAO,CACpE,CAEK,EAAsC,EAAE,CAE9C,IAAK,IAAM,KAA4B,EAAuB,CAC5D,IAAM,EAAmB,EACvB,CACE,MACA,EAAS,IAAK,EAAW,UAAU,CACnC,EAAY,EAAyB,IAAI,CACzC,EAAS,IAAK,EAAW,UAAU,CACpC,CAAC,KAAK,GAAG,CACV,CAAE,QAAS,EAAe,EAAG,CAC9B,CAEK,EAAgB,EAAyB,IACzC,EAAoB,EAAyB,QAC7C,EACJ,EAAyB,GAU3B,IATyB,EAAyB,QAAU,MAEnC,KAKvB,EAAyB,MAAQ,EAAc,YAAY,MAAQ,MAE9C,GAAO,SAE9B,IAAM,EAAwB,EAAyB,QACrD,EAEF,GAAI,CAAC,EAAyB,CAC5B,EACE,GAAG,EAAiB,wDACpB,CACE,MAAO,OACR,CACF,CACD,SAGF,GAAI,CAAC,EAAyB,SAAU,CACtC,EAAU,GAAG,EAAiB,yCAA0C,CACtE,MAAO,OACR,CAAC,CACF,SAGF,IAAM,EAAsB,EAC1B,EACA,EACD,CAED,GACE,OAAO,KAAK,EAA+C,CAAC,SAAW,EACvE,CACA,EACE,GAAG,EAAiB,oDAAoD,EAAa,EAAa,CAAC,6CACnG,CACE,MAAO,OACR,CACF,CACD,SAQF,IAAI,EAA8B,EAWlC,GATI,IAAS,aACX,EACE,EACG,KACE,GAAuB,EAAmB,MAAQ,EACpD,EACC,QAAQ,OAAQ,GAAW,EAAc,SAAS,EAAO,CAAC,EAAI,EAAE,EAGpE,EAAkB,SAAW,EAAG,CAClC,EACE,GAAG,EAAiB,GAAG,EAAS,+BAAgC,EAAW,UAAU,CAAC,GAAG,EAAa,EAAS,EAAyB,SAAS,CAAC,GAClJ,CACE,MAAO,OACR,CACF,CACD,SAGF,EAAiB,KAAK,CACpB,gBACA,oBACA,eACA,cAAe,EACf,mBACA,mBAAoB,EAAyB,SAC9C,CAAC,CAIJ,OAAO"}
1
+ {"version":3,"file":"listTranslationsTasks.mjs","names":[],"sources":["../../../src/fill/listTranslationsTasks.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport { formatLocale } from '@intlayer/chokidar/utils';\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 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,YAAY,aAAa,cAAc;CAE7C,MAAM,2BAA2B,gBAAgB,cAAc;CAC/D,MAAM,6BAA6B,wBAAwB,cAAc;CAGzE,MAAM,wBADsB,OAAO,OAAO,2BAA2B,CAAC,MAAM,CAC1B,QAAQ,eACxD,SAAS,SAAS,WAAW,QAAS,CACvC;CAED,MAAM,EAAE,wBACN,kCAAkC,cAAc;CAElD,MAAM,eAAe,KAAK,IACxB,GAAG,sBAAsB,KAAK,eAAe,WAAW,IAAI,OAAO,CACpE;CAED,MAAM,mBAAsC,EAAE;AAE9C,MAAK,MAAM,4BAA4B,uBAAuB;EAC5D,MAAM,mBAAmB,MACvB;GACE;GACA,SAAS,KAAK,WAAW,UAAU;GACnC,YAAY,yBAAyB,IAAI;GACzC,SAAS,KAAK,WAAW,UAAU;GACpC,CAAC,KAAK,GAAG,EACV,EAAE,SAAS,eAAe,GAAG,CAC9B;EAED,MAAM,gBAAgB,yBAAyB;EAC/C,MAAM,oBAAoB,yBAAyB;EACnD,MAAM,0BACJ,yBAAyB;AAG3B,OAFyB,yBAAyB,UAAU,WAEnC,KACvB;AAMF,OAFE,yBAAyB,QAAQ,cAAc,YAAY,QAAQ,WAE9C,MAAO;EAE9B,MAAM,eAAwB,yBAAyB,UACrD;AAEF,MAAI,CAAC,yBAAyB;AAC5B,aACE,GAAG,iBAAiB,yDACpB,EACE,OAAO,QACR,CACF;AACD;;AAGF,MAAI,CAAC,yBAAyB,UAAU;AACtC,aAAU,GAAG,iBAAiB,0CAA0C,EACtE,OAAO,QACR,CAAC;AACF;;EAGF,MAAM,sBAAsB,oCAC1B,yBACA,aACD;AAED,MACE,OAAO,KAAK,oBAA+C,CAAC,WAAW,GACvE;AACA,aACE,GAAG,iBAAiB,oDAAoD,aAAa,aAAa,CAAC,8CACnG,EACE,OAAO,QACR,CACF;AACD;;;;;;;EAQF,IAAI,oBAA8B;AAElC,MAAI,SAAS,WACX,qBACE,oBACG,MACE,uBAAuB,mBAAmB,QAAQ,cACpD,EACC,QAAQ,QAAQ,WAAW,cAAc,SAAS,OAAO,CAAC,IAAI,EAAE;AAGxE,MAAI,kBAAkB,WAAW,GAAG;AAClC,aACE,GAAG,iBAAiB,GAAG,SAAS,gCAAgC,WAAW,UAAU,CAAC,GAAG,aAAa,SAAS,yBAAyB,SAAS,CAAC,IAClJ,EACE,OAAO,QACR,CACF;AACD;;AAGF,mBAAiB,KAAK;GACpB;GACA;GACA;GACA,eAAe;GACf;GACA,oBAAoB,yBAAyB;GAC9C,CAAC;;AAIJ,QAAO"}