@intlayer/engine 9.2.0 → 9.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. package/README.md +24 -24
  2. package/dist/assets/initConfig/templates/cjs.txt +1 -1
  3. package/dist/assets/initConfig/templates/mjs.txt +1 -1
  4. package/dist/assets/initConfig/templates/ts.txt +1 -1
  5. package/dist/cjs/_virtual/_rolldown/runtime.cjs +1 -2
  6. package/dist/cjs/_virtual/_utils_asset.cjs +2 -1
  7. package/dist/cjs/buildIntlayerDictionary/buildIntlayerDictionary.cjs +14 -2
  8. package/dist/cjs/buildIntlayerDictionary/buildIntlayerDictionary.cjs.map +1 -1
  9. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs +26 -5
  10. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs.map +1 -1
  11. package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs +43 -6
  12. package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs.map +1 -1
  13. package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs +2 -1
  14. package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs.map +1 -1
  15. package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs +96 -0
  16. package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs.map +1 -0
  17. package/dist/cjs/buildIntlayerDictionary/writeRemoteDictionary.cjs +4 -2
  18. package/dist/cjs/buildIntlayerDictionary/writeRemoteDictionary.cjs.map +1 -1
  19. package/dist/cjs/buildIntlayerDictionary/writeUnmergedDictionary.cjs.map +1 -1
  20. package/dist/cjs/cleanOutputDir.cjs.map +1 -1
  21. package/dist/cjs/cleanRemovedContentDeclaration.cjs +7 -4
  22. package/dist/cjs/cleanRemovedContentDeclaration.cjs.map +1 -1
  23. package/dist/cjs/createDictionaryEntryPoint/createDictionaryEntryPoint.cjs +5 -3
  24. package/dist/cjs/createDictionaryEntryPoint/createDictionaryEntryPoint.cjs.map +1 -1
  25. package/dist/cjs/createDictionaryEntryPoint/generateDictionaryListContent.cjs.map +1 -1
  26. package/dist/cjs/createDictionaryEntryPoint/getBuiltDictionariesPath.cjs.map +1 -1
  27. package/dist/cjs/createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.cjs.map +1 -1
  28. package/dist/cjs/createDictionaryEntryPoint/getBuiltFetchDictionariesPath.cjs.map +1 -1
  29. package/dist/cjs/createDictionaryEntryPoint/getBuiltRemoteDictionariesPath.cjs.map +1 -1
  30. package/dist/cjs/createDictionaryEntryPoint/getBuiltUnmergedDictionariesPath.cjs.map +1 -1
  31. package/dist/cjs/createType/createModuleAugmentation.cjs +2 -1
  32. package/dist/cjs/createType/createModuleAugmentation.cjs.map +1 -1
  33. package/dist/cjs/createType/createType.cjs.map +1 -1
  34. package/dist/cjs/detectFormatCommand.cjs.map +1 -1
  35. package/dist/cjs/docReview/alignBlocks.cjs +1 -1
  36. package/dist/cjs/docReview/alignBlocks.cjs.map +1 -1
  37. package/dist/cjs/docReview/computeSimilarity.cjs +0 -1
  38. package/dist/cjs/docReview/computeSimilarity.cjs.map +1 -1
  39. package/dist/cjs/docReview/mapChangedLinesToBlocks.cjs +0 -1
  40. package/dist/cjs/docReview/mapChangedLinesToBlocks.cjs.map +1 -1
  41. package/dist/cjs/docReview/normalizeBlock.cjs +0 -1
  42. package/dist/cjs/docReview/normalizeBlock.cjs.map +1 -1
  43. package/dist/cjs/docReview/planActions.cjs +0 -1
  44. package/dist/cjs/docReview/planActions.cjs.map +1 -1
  45. package/dist/cjs/docReview/rebuildDocument.cjs +0 -1
  46. package/dist/cjs/docReview/rebuildDocument.cjs.map +1 -1
  47. package/dist/cjs/docReview/reviewReport.cjs +2 -1
  48. package/dist/cjs/docReview/reviewReport.cjs.map +1 -1
  49. package/dist/cjs/docReview/segmentDocument.cjs +0 -1
  50. package/dist/cjs/docReview/segmentDocument.cjs.map +1 -1
  51. package/dist/cjs/fetchDistantDictionaries.cjs +107 -13
  52. package/dist/cjs/fetchDistantDictionaries.cjs.map +1 -1
  53. package/dist/cjs/filterInvalidDictionaries.cjs.map +1 -1
  54. package/dist/cjs/formatDictionary.cjs.map +1 -1
  55. package/dist/cjs/getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.cjs.map +1 -1
  56. package/dist/cjs/handleAdditionalContentDeclarationFile.cjs +4 -2
  57. package/dist/cjs/handleAdditionalContentDeclarationFile.cjs.map +1 -1
  58. package/dist/cjs/handleContentDeclarationFileChange.cjs +6 -2
  59. package/dist/cjs/handleContentDeclarationFileChange.cjs.map +1 -1
  60. package/dist/cjs/handleContentDeclarationFileMoved.cjs.map +1 -1
  61. package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs +4 -2
  62. package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs.map +1 -1
  63. package/dist/cjs/init/cms.cjs.map +1 -1
  64. package/dist/cjs/init/frameworkSetup/nextAppRouter/detect.cjs.map +1 -1
  65. package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs +1 -3
  66. package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs.map +1 -1
  67. package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs +2 -1
  68. package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs.map +1 -1
  69. package/dist/cjs/init/frameworkSetup/nextAppRouter/templates.cjs +0 -1
  70. package/dist/cjs/init/frameworkSetup/nextAppRouter/templates.cjs.map +1 -1
  71. package/dist/cjs/init/frameworkSetup/tanstackStart/detect.cjs.map +1 -1
  72. package/dist/cjs/init/frameworkSetup/tanstackStart/index.cjs +3 -5
  73. package/dist/cjs/init/frameworkSetup/tanstackStart/index.cjs.map +1 -1
  74. package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs +2 -1
  75. package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs.map +1 -1
  76. package/dist/cjs/init/frameworkSetup/tanstackStart/templates.cjs +18 -12
  77. package/dist/cjs/init/frameworkSetup/tanstackStart/templates.cjs.map +1 -1
  78. package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs +58 -15
  79. package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs.map +1 -1
  80. package/dist/cjs/init/index.cjs +66 -38
  81. package/dist/cjs/init/index.cjs.map +1 -1
  82. package/dist/cjs/init/utils/configManipulation.cjs.map +1 -1
  83. package/dist/cjs/init/utils/fileSystem.cjs +3 -1
  84. package/dist/cjs/init/utils/fileSystem.cjs.map +1 -1
  85. package/dist/cjs/init/utils/githubActions.cjs.map +1 -1
  86. package/dist/cjs/init/utils/jsonParser.cjs +0 -1
  87. package/dist/cjs/init/utils/jsonParser.cjs.map +1 -1
  88. package/dist/cjs/init/utils/nextCompilerBabel.cjs.map +1 -1
  89. package/dist/cjs/init/utils/packageManager.cjs +4 -2
  90. package/dist/cjs/init/utils/packageManager.cjs.map +1 -1
  91. package/dist/cjs/init/utils/tsConfig.cjs.map +1 -1
  92. package/dist/cjs/init/utils/version.cjs +0 -1
  93. package/dist/cjs/init/utils/version.cjs.map +1 -1
  94. package/dist/cjs/initConfig/index.cjs +12 -8
  95. package/dist/cjs/initConfig/index.cjs.map +1 -1
  96. package/dist/cjs/installSkills/index.cjs.map +1 -1
  97. package/dist/cjs/listDictionariesPath.cjs +6 -5
  98. package/dist/cjs/listDictionariesPath.cjs.map +1 -1
  99. package/dist/cjs/listGitFiles.cjs.map +1 -1
  100. package/dist/cjs/listProjects.cjs +2 -1
  101. package/dist/cjs/listProjects.cjs.map +1 -1
  102. package/dist/cjs/loadDictionaries/getIntlayerBundle.cjs +2 -1
  103. package/dist/cjs/loadDictionaries/getIntlayerBundle.cjs.map +1 -1
  104. package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs +8 -5
  105. package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs.map +1 -1
  106. package/dist/cjs/loadDictionaries/loadDictionaries.cjs +4 -2
  107. package/dist/cjs/loadDictionaries/loadDictionaries.cjs.map +1 -1
  108. package/dist/cjs/loadDictionaries/loadLocalDictionaries.cjs.map +1 -1
  109. package/dist/cjs/loadDictionaries/loadMarkdownContentDeclaration.cjs.map +1 -1
  110. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs +3 -2
  111. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs.map +1 -1
  112. package/dist/cjs/loadDictionaries/loadYamlContentDeclaration.cjs +2 -1
  113. package/dist/cjs/loadDictionaries/loadYamlContentDeclaration.cjs.map +1 -1
  114. package/dist/cjs/loadDictionaries/log.cjs +38 -11
  115. package/dist/cjs/loadDictionaries/log.cjs.map +1 -1
  116. package/dist/cjs/loadDictionaries/logTypeScriptErrors.cjs.map +1 -1
  117. package/dist/cjs/logConfigDetails.cjs +4 -3
  118. package/dist/cjs/logConfigDetails.cjs.map +1 -1
  119. package/dist/cjs/prepareIntlayer.cjs +5 -3
  120. package/dist/cjs/prepareIntlayer.cjs.map +1 -1
  121. package/dist/cjs/reduceDictionaryContent/applyMask.cjs +0 -1
  122. package/dist/cjs/reduceDictionaryContent/applyMask.cjs.map +1 -1
  123. package/dist/cjs/reduceDictionaryContent/reduceDictionaryContent.cjs +2 -1
  124. package/dist/cjs/reduceDictionaryContent/reduceDictionaryContent.cjs.map +1 -1
  125. package/dist/cjs/scan/calculateScore.cjs +0 -1
  126. package/dist/cjs/scan/calculateScore.cjs.map +1 -1
  127. package/dist/cjs/scan/checks.cjs +1 -1
  128. package/dist/cjs/scan/checks.cjs.map +1 -1
  129. package/dist/cjs/scan/parseHtml.cjs +0 -1
  130. package/dist/cjs/scan/parseHtml.cjs.map +1 -1
  131. package/dist/cjs/scan/scanWebsite.cjs.map +1 -1
  132. package/dist/cjs/syncPluginKit/createFileAdapter.cjs +2 -1
  133. package/dist/cjs/syncPluginKit/createFileAdapter.cjs.map +1 -1
  134. package/dist/cjs/syncPluginKit/createSyncPlugin.cjs +4 -1
  135. package/dist/cjs/syncPluginKit/createSyncPlugin.cjs.map +1 -1
  136. package/dist/cjs/syncPluginKit/extractKeyAndLocaleFromPath.cjs +0 -1
  137. package/dist/cjs/syncPluginKit/extractKeyAndLocaleFromPath.cjs.map +1 -1
  138. package/dist/cjs/syncPluginKit/filePathPatternHelpers.cjs +0 -1
  139. package/dist/cjs/syncPluginKit/filePathPatternHelpers.cjs.map +1 -1
  140. package/dist/cjs/utils/autoDecorateContent.cjs.map +1 -1
  141. package/dist/cjs/utils/babelParser.cjs.map +1 -1
  142. package/dist/cjs/utils/buildComponentFilesList.cjs.map +1 -1
  143. package/dist/cjs/utils/buildFilesList.cjs.map +1 -1
  144. package/dist/cjs/utils/chunkArray.cjs +23 -0
  145. package/dist/cjs/utils/chunkArray.cjs.map +1 -0
  146. package/dist/cjs/utils/formatter.cjs.map +1 -1
  147. package/dist/cjs/utils/getContentExtension.cjs +1 -4
  148. package/dist/cjs/utils/getContentExtension.cjs.map +1 -1
  149. package/dist/cjs/utils/getFormatFromExtension.cjs +0 -1
  150. package/dist/cjs/utils/getFormatFromExtension.cjs.map +1 -1
  151. package/dist/cjs/utils/getPathHash.cjs +0 -1
  152. package/dist/cjs/utils/getPathHash.cjs.map +1 -1
  153. package/dist/cjs/utils/index.cjs +2 -0
  154. package/dist/cjs/utils/mergeChunks.cjs +0 -1
  155. package/dist/cjs/utils/mergeChunks.cjs.map +1 -1
  156. package/dist/cjs/utils/pLimit.cjs +0 -1
  157. package/dist/cjs/utils/pLimit.cjs.map +1 -1
  158. package/dist/cjs/utils/readDictionariesFromDisk.cjs.map +1 -1
  159. package/dist/cjs/utils/reduceObjectFormat.cjs +0 -1
  160. package/dist/cjs/utils/reduceObjectFormat.cjs.map +1 -1
  161. package/dist/cjs/utils/resolveObjectPromises.cjs +0 -1
  162. package/dist/cjs/utils/resolveObjectPromises.cjs.map +1 -1
  163. package/dist/cjs/utils/resolveRelativePath.cjs +4 -1
  164. package/dist/cjs/utils/resolveRelativePath.cjs.map +1 -1
  165. package/dist/cjs/utils/runOnce.cjs +2 -2
  166. package/dist/cjs/utils/runOnce.cjs.map +1 -1
  167. package/dist/cjs/utils/runParallel/bin.cjs.map +1 -1
  168. package/dist/cjs/utils/runParallel/bootstrap.cjs +0 -1
  169. package/dist/cjs/utils/runParallel/bootstrap.cjs.map +1 -1
  170. package/dist/cjs/utils/runParallel/index.cjs.map +1 -1
  171. package/dist/cjs/utils/runParallel/spawnPosix.cjs.map +1 -1
  172. package/dist/cjs/utils/runParallel/spawnWin32.cjs.map +1 -1
  173. package/dist/cjs/utils/sortAlphabetically.cjs +0 -1
  174. package/dist/cjs/utils/sortAlphabetically.cjs.map +1 -1
  175. package/dist/cjs/utils/splitTextByLine.cjs +0 -1
  176. package/dist/cjs/utils/splitTextByLine.cjs.map +1 -1
  177. package/dist/cjs/utils/verifyIdenticObjectFormat.cjs +0 -1
  178. package/dist/cjs/utils/verifyIdenticObjectFormat.cjs.map +1 -1
  179. package/dist/cjs/watcher.cjs +4 -2
  180. package/dist/cjs/watcher.cjs.map +1 -1
  181. package/dist/cjs/writeConfiguration/index.cjs +2 -1
  182. package/dist/cjs/writeConfiguration/index.cjs.map +1 -1
  183. package/dist/cjs/writeContentDeclaration/detectExportedComponentName.cjs +0 -1
  184. package/dist/cjs/writeContentDeclaration/detectExportedComponentName.cjs.map +1 -1
  185. package/dist/cjs/writeContentDeclaration/processContentDeclarationContent.cjs.map +1 -1
  186. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs +173 -109
  187. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs.map +1 -1
  188. package/dist/cjs/writeContentDeclaration/transformJSONFile.cjs +6 -5
  189. package/dist/cjs/writeContentDeclaration/transformJSONFile.cjs.map +1 -1
  190. package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs +9 -3
  191. package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs.map +1 -1
  192. package/dist/cjs/writeContentDeclaration/writeJSFile.cjs +2 -1
  193. package/dist/cjs/writeContentDeclaration/writeJSFile.cjs.map +1 -1
  194. package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs +2 -1
  195. package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs.map +1 -1
  196. package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs +4 -2
  197. package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs.map +1 -1
  198. package/dist/cjs/writeFileIfChanged.cjs.map +1 -1
  199. package/dist/esm/_virtual/_utils_asset.mjs +2 -1
  200. package/dist/esm/buildIntlayerDictionary/buildIntlayerDictionary.mjs +15 -3
  201. package/dist/esm/buildIntlayerDictionary/buildIntlayerDictionary.mjs.map +1 -1
  202. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs +26 -5
  203. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs.map +1 -1
  204. package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs +43 -6
  205. package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs.map +1 -1
  206. package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs +2 -1
  207. package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs.map +1 -1
  208. package/dist/esm/buildIntlayerDictionary/writeNestedDictionary.mjs +92 -0
  209. package/dist/esm/buildIntlayerDictionary/writeNestedDictionary.mjs.map +1 -0
  210. package/dist/esm/buildIntlayerDictionary/writeRemoteDictionary.mjs +4 -2
  211. package/dist/esm/buildIntlayerDictionary/writeRemoteDictionary.mjs.map +1 -1
  212. package/dist/esm/cleanRemovedContentDeclaration.mjs +7 -4
  213. package/dist/esm/cleanRemovedContentDeclaration.mjs.map +1 -1
  214. package/dist/esm/createDictionaryEntryPoint/createDictionaryEntryPoint.mjs +5 -3
  215. package/dist/esm/createDictionaryEntryPoint/createDictionaryEntryPoint.mjs.map +1 -1
  216. package/dist/esm/createType/createModuleAugmentation.mjs +2 -1
  217. package/dist/esm/createType/createModuleAugmentation.mjs.map +1 -1
  218. package/dist/esm/docReview/alignBlocks.mjs +1 -1
  219. package/dist/esm/docReview/alignBlocks.mjs.map +1 -1
  220. package/dist/esm/docReview/reviewReport.mjs +2 -1
  221. package/dist/esm/docReview/reviewReport.mjs.map +1 -1
  222. package/dist/esm/fetchDistantDictionaries.mjs +107 -13
  223. package/dist/esm/fetchDistantDictionaries.mjs.map +1 -1
  224. package/dist/esm/handleAdditionalContentDeclarationFile.mjs +4 -2
  225. package/dist/esm/handleAdditionalContentDeclarationFile.mjs.map +1 -1
  226. package/dist/esm/handleContentDeclarationFileChange.mjs +6 -2
  227. package/dist/esm/handleContentDeclarationFileChange.mjs.map +1 -1
  228. package/dist/esm/handleUnlinkedContentDeclarationFile.mjs +4 -2
  229. package/dist/esm/handleUnlinkedContentDeclarationFile.mjs.map +1 -1
  230. package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs +1 -3
  231. package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs.map +1 -1
  232. package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs +2 -1
  233. package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs.map +1 -1
  234. package/dist/esm/init/frameworkSetup/tanstackStart/index.mjs +4 -6
  235. package/dist/esm/init/frameworkSetup/tanstackStart/index.mjs.map +1 -1
  236. package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs +2 -1
  237. package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs.map +1 -1
  238. package/dist/esm/init/frameworkSetup/tanstackStart/templates.mjs +17 -10
  239. package/dist/esm/init/frameworkSetup/tanstackStart/templates.mjs.map +1 -1
  240. package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs +59 -16
  241. package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs.map +1 -1
  242. package/dist/esm/init/index.mjs +66 -38
  243. package/dist/esm/init/index.mjs.map +1 -1
  244. package/dist/esm/init/utils/configManipulation.mjs.map +1 -1
  245. package/dist/esm/init/utils/fileSystem.mjs +3 -1
  246. package/dist/esm/init/utils/fileSystem.mjs.map +1 -1
  247. package/dist/esm/init/utils/packageManager.mjs +4 -2
  248. package/dist/esm/init/utils/packageManager.mjs.map +1 -1
  249. package/dist/esm/initConfig/index.mjs +12 -8
  250. package/dist/esm/initConfig/index.mjs.map +1 -1
  251. package/dist/esm/listDictionariesPath.mjs +6 -5
  252. package/dist/esm/listDictionariesPath.mjs.map +1 -1
  253. package/dist/esm/listProjects.mjs +2 -1
  254. package/dist/esm/listProjects.mjs.map +1 -1
  255. package/dist/esm/loadDictionaries/getIntlayerBundle.mjs +2 -1
  256. package/dist/esm/loadDictionaries/getIntlayerBundle.mjs.map +1 -1
  257. package/dist/esm/loadDictionaries/loadContentDeclaration.mjs +8 -5
  258. package/dist/esm/loadDictionaries/loadContentDeclaration.mjs.map +1 -1
  259. package/dist/esm/loadDictionaries/loadDictionaries.mjs +4 -2
  260. package/dist/esm/loadDictionaries/loadDictionaries.mjs.map +1 -1
  261. package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs +3 -2
  262. package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs.map +1 -1
  263. package/dist/esm/loadDictionaries/loadYamlContentDeclaration.mjs +2 -1
  264. package/dist/esm/loadDictionaries/loadYamlContentDeclaration.mjs.map +1 -1
  265. package/dist/esm/loadDictionaries/log.mjs +38 -11
  266. package/dist/esm/loadDictionaries/log.mjs.map +1 -1
  267. package/dist/esm/logConfigDetails.mjs +4 -3
  268. package/dist/esm/logConfigDetails.mjs.map +1 -1
  269. package/dist/esm/prepareIntlayer.mjs +5 -3
  270. package/dist/esm/prepareIntlayer.mjs.map +1 -1
  271. package/dist/esm/reduceDictionaryContent/reduceDictionaryContent.mjs +2 -1
  272. package/dist/esm/reduceDictionaryContent/reduceDictionaryContent.mjs.map +1 -1
  273. package/dist/esm/scan/checks.mjs +1 -1
  274. package/dist/esm/scan/checks.mjs.map +1 -1
  275. package/dist/esm/syncPluginKit/createFileAdapter.mjs +2 -1
  276. package/dist/esm/syncPluginKit/createFileAdapter.mjs.map +1 -1
  277. package/dist/esm/syncPluginKit/createSyncPlugin.mjs +4 -1
  278. package/dist/esm/syncPluginKit/createSyncPlugin.mjs.map +1 -1
  279. package/dist/esm/utils/babelParser.mjs.map +1 -1
  280. package/dist/esm/utils/chunkArray.mjs +22 -0
  281. package/dist/esm/utils/chunkArray.mjs.map +1 -0
  282. package/dist/esm/utils/getContentExtension.mjs +1 -3
  283. package/dist/esm/utils/getContentExtension.mjs.map +1 -1
  284. package/dist/esm/utils/index.mjs +2 -1
  285. package/dist/esm/utils/resolveRelativePath.mjs +4 -1
  286. package/dist/esm/utils/resolveRelativePath.mjs.map +1 -1
  287. package/dist/esm/utils/runOnce.mjs +2 -2
  288. package/dist/esm/utils/runOnce.mjs.map +1 -1
  289. package/dist/esm/watcher.mjs +4 -2
  290. package/dist/esm/watcher.mjs.map +1 -1
  291. package/dist/esm/writeConfiguration/index.mjs +2 -1
  292. package/dist/esm/writeConfiguration/index.mjs.map +1 -1
  293. package/dist/esm/writeContentDeclaration/transformJSFile.mjs +173 -109
  294. package/dist/esm/writeContentDeclaration/transformJSFile.mjs.map +1 -1
  295. package/dist/esm/writeContentDeclaration/transformJSONFile.mjs +6 -5
  296. package/dist/esm/writeContentDeclaration/transformJSONFile.mjs.map +1 -1
  297. package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs +9 -3
  298. package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs.map +1 -1
  299. package/dist/esm/writeContentDeclaration/writeJSFile.mjs +2 -1
  300. package/dist/esm/writeContentDeclaration/writeJSFile.mjs.map +1 -1
  301. package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs +2 -1
  302. package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs.map +1 -1
  303. package/dist/esm/writeContentDeclaration/writeYamlFile.mjs +4 -2
  304. package/dist/esm/writeContentDeclaration/writeYamlFile.mjs.map +1 -1
  305. package/dist/types/buildIntlayerDictionary/buildIntlayerDictionary.d.ts.map +1 -1
  306. package/dist/types/buildIntlayerDictionary/writeDynamicDictionary.d.ts +14 -2
  307. package/dist/types/buildIntlayerDictionary/writeDynamicDictionary.d.ts.map +1 -1
  308. package/dist/types/buildIntlayerDictionary/writeFetchDictionary.d.ts +16 -2
  309. package/dist/types/buildIntlayerDictionary/writeFetchDictionary.d.ts.map +1 -1
  310. package/dist/types/buildIntlayerDictionary/writeNestedDictionary.d.ts +54 -0
  311. package/dist/types/buildIntlayerDictionary/writeNestedDictionary.d.ts.map +1 -0
  312. package/dist/types/fetchDistantDictionaries.d.ts +26 -0
  313. package/dist/types/fetchDistantDictionaries.d.ts.map +1 -1
  314. package/dist/types/formatDictionary.d.ts +2 -0
  315. package/dist/types/formatDictionary.d.ts.map +1 -1
  316. package/dist/types/init/frameworkSetup/tanstackStart/templates.d.ts +9 -4
  317. package/dist/types/init/frameworkSetup/tanstackStart/templates.d.ts.map +1 -1
  318. package/dist/types/init/frameworkSetup/tanstackStart/transforms.d.ts +6 -2
  319. package/dist/types/init/frameworkSetup/tanstackStart/transforms.d.ts.map +1 -1
  320. package/dist/types/loadDictionaries/log.d.ts +16 -1
  321. package/dist/types/loadDictionaries/log.d.ts.map +1 -1
  322. package/dist/types/utils/chunkArray.d.ts +16 -0
  323. package/dist/types/utils/chunkArray.d.ts.map +1 -0
  324. package/dist/types/utils/index.d.ts +2 -1
  325. package/dist/types/writeContentDeclaration/transformJSFile.d.ts.map +1 -1
  326. package/package.json +11 -11
package/README.md CHANGED
@@ -47,27 +47,27 @@ With **per-locale content files**, **TypeScript autocompletion**, **tree-shakabl
47
47
 
48
48
  ## Keys benefits of Intlayer:
49
49
 
50
- | Feature | Description |
51
- | --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/frameworks.png?raw=true" alt="Feature" width="700"> | **Cross-Frameworks Support**<br><br>Intlayer is compatible with all major frameworks and libraries, including Next.js, React, Vite, Vue.js, Nuxt, Preact, Express, and more. |
53
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/javascript_content_management.jpg?raw=true" alt="Feature" width="700"> | **JavaScript-Powered Content Management**<br><br>Harness the flexibility of JavaScript to define and manage your content efficiently. <br><br> - [Content declaration](https://intlayer.org/doc/concept/content) |
54
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/per_locale_content_declaration_file.png?raw=true" alt="Feature" width="700"> | **Per-Locale Content Declaration File**<br><br>Speed up your development by declaring your content once, before auto generation.<br><br> - [Per-Locale Content Declaration File](https://intlayer.org/doc/concept/per-locale-file) |
55
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/compiler.jpg?raw=true" alt="Feature" width="700"> | **Compiler**<br><br>The Intlayer Compiler extract automatically the content from the components and generate the dictionary files.<br><br> - [Compiler](https://intlayer.org/doc/compiler) |
56
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true" alt="Feature" width="700"> | **Type-Safe Environment**<br><br>Leverage TypeScript to ensure your content definitions and code are error-free, while also benefiting from IDE autocompletion.<br><br> - [TypeScript configuration](https://intlayer.org/doc/environment/vite-and-react#configure-typescript) |
57
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/config_file.png?raw=true" alt="Feature" width="700"> | **Simplified Setup**<br><br>Get up and running quickly with minimal configuration. Adjust settings for internationalization, routing, AI, build, and content handling with ease. <br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
58
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/content_retrieval.png?raw=true" alt="Feature" width="700"> | **Simplified Content Retrieval**<br><br>No need to call your `t` function for each piece of content. Retrieve all your content directly using a single hook.<br><br> - [React integration](https://intlayer.org/doc/environment/create-react-app) |
59
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/server_component.png?raw=true" alt="Feature" width="700"> | **Consistent Server Component Implementation**<br><br>Perfectly suited for Next.js server components, use the same implementation for both client and server components, no need to pass your `t` function across each server component. <br><br> - [Server Components](https://intlayer.org/doc/environment/nextjs#step-7-utilize-content-in-your-code) |
60
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/file_tree.png?raw=true" alt="Feature" width="700"> | **Organized Codebase**<br><br>Keep your codebase more organized: 1 component = 1 dictionary in the same folder. Translations close to their respective components, enhance maintainability and clarity. <br><br> - [How Intlayer works](https://intlayer.org/doc/concept/how-works-intlayer) |
61
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/url_routing.png?raw=true" alt="Feature" width="700"> | **Enhanced Routing**<br><br>Full support of app routing, adapting seamlessly to complex application structures, for Next.js, React, Vite, Vue.js, etc.<br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
62
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/markdown.png?raw=true" alt="Feature" width="700"> | **Markdown Support**<br><br>Import and interpret, locale files and remote Markdown for multilingual content like privacy policies, documentation, etc. Interpret and make Markdown metadata accessible in your code.<br><br> - [Content files](https://intlayer.org/doc/concept/content/file) |
63
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/visual_editor.png?raw=true" alt="Feature" width="700"> | **Free Visual Editor & CMS**<br><br>A free visual editor and CMS are available for content writers, removing the need for a localization platform. Keep your content synchronized using Git, or externalize it totally or partially with the CMS.<br><br> - [Intlayer Editor](https://intlayer.org/doc/concept/editor) <br> - [Intlayer CMS](https://intlayer.org/doc/concept/cms) |
64
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png?raw=true" alt="Feature" width="700"> | **Tree-shakable Content**<br><br>Tree-shakable content, reducing the size of the final bundle. Loads content per component, excluding any unused content from your bundle. Supports lazy loading to enhance app loading efficiency. <br><br> - [App build optimization](https://intlayer.org/doc/concept/how-works-intlayer#app-build-optimization) |
65
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/static_rendering.png?raw=true" alt="Feature" width="700"> | **Static Rendering**<br><br>Doesn't block Static Rendering. <br><br> - [Next.js integration](https://intlayer.org/doc/environment/nextjs) |
66
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/AI_translation.png?raw=true" alt="Feature" width="700"> | **AI-Powered Translation**<br><br>Transform your website into 231 languages with just one click using Intlayer's advanced AI-powered translation tools using your own AI provider / API key. <br><br> - [CI/CD integration](https://intlayer.org/doc/concept/ci-cd) <br> - [Intlayer CLI](https://intlayer.org/doc/concept/cli) <br> - [Auto fill](https://intlayer.org/doc/concept/auto-fill) |
67
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/mcp.png?raw=true" alt="Feature" width="700"> | **MCP Server Integration**<br><br>Provides an MCP (Model Context Protocol) server for IDE automation, enabling seamless content management and i18n workflows directly within your development environment. <br><br> - [MCP Server](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/mcp_server.md) |
68
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/vscode_extension.png?raw=true" alt="Feature" width="700"> | **VSCode Extension**<br><br>Intlayer provides a VSCode extension to help you manage your content and translations, building your dictionaries, translating your content, and more. <br><br> - [VSCode Extension](https://intlayer.org/doc/vs-code-extension) |
69
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/interoperability.png?raw=true" alt="Feature" width="700"> | **Interoperability**<br><br>Allow interoperability with react-i18next, next-i18next, next-intl, react-intl, vue-i18n. <br><br> - [Intlayer and react-intl](https://intlayer.org/blog/intlayer-with-react-intl) <br> - [Intlayer and next-intl](https://intlayer.org/blog/intlayer-with-next-intl) <br> - [Intlayer and next-i18next](https://intlayer.org/blog/intlayer-with-next-i18next) <br> - [Intlayer and vue-i18n](https://intlayer.org/blog/intlayer-with-vue-i18n) |
70
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/benchmark.png?raw=true" alt="Feature" width="700"> | **Performances & Benchmark**<br><br>Uses advanced tree-shaking and dynamic loading to boost performances and keep the solution as light as possible. <br><br> - [Performances & Benchmark](https://intlayer.org/doc/benchmark) |
50
+ | Feature | Description |
51
+ | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/frameworks.png?raw=true" alt="Feature" width="700"> | **Cross-Frameworks Support**<br><br>Intlayer is compatible with all major frameworks and libraries, including Next.js, React, Vite, Vue.js, Nuxt, Preact, Express, and more. |
53
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/javascript_content_management.jpg?raw=true" alt="Feature" width="700"> | **JavaScript-Powered Content Management**<br><br>Harness the flexibility of JavaScript to define and manage your content efficiently. <br><br> - [Content declaration](https://intlayer.org/doc/concept/content) |
54
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/per_locale_content_declaration_file.png?raw=true" alt="Feature" width="700"> | **Per-Locale Content Declaration File**<br><br>Speed up your development by declaring your content once, before auto generation.<br><br> - [Per-Locale Content Declaration File](https://intlayer.org/doc/concept/per-locale-file) |
55
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/compiler.jpg?raw=true" alt="Feature" width="700"> | **Compiler**<br><br>The Intlayer Compiler extract automatically the content from the components and generate the dictionary files.<br><br> - [Compiler](https://intlayer.org/doc/compiler) |
56
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true" alt="Feature" width="700"> | **Type-Safe Environment**<br><br>Leverage TypeScript to ensure your content definitions and code are error-free, while also benefiting from IDE autocompletion.<br><br> - [TypeScript configuration](https://intlayer.org/doc/environment/vite-and-react#configure-typescript) |
57
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/config_file.png?raw=true" alt="Feature" width="700"> | **Simplified Setup**<br><br>Get up and running quickly with minimal configuration. Adjust settings for internationalization, routing, AI, build, and content handling with ease. <br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
58
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/content_retrieval.png?raw=true" alt="Feature" width="700"> | **Simplified Content Retrieval**<br><br>No need to call your `t` function for each piece of content. Retrieve all your content directly using a single hook.<br><br> - [React integration](https://intlayer.org/doc/environment/create-react-app) |
59
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/server_component.png?raw=true" alt="Feature" width="700"> | **Consistent Server Component Implementation**<br><br>Perfectly suited for Next.js server components, use the same implementation for both client and server components, no need to pass your `t` function across each server component. <br><br> - [Server Components](https://intlayer.org/doc/environment/nextjs#step-7-utilize-content-in-your-code) |
60
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/file_tree.png?raw=true" alt="Feature" width="700"> | **Organized Codebase**<br><br>Keep your codebase more organized: 1 component = 1 dictionary in the same folder. Translations close to their respective components, enhance maintainability and clarity. <br><br> - [How Intlayer works](https://intlayer.org/doc/concept/how-works-intlayer) |
61
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/url_routing.png?raw=true" alt="Feature" width="700"> | **Enhanced Routing**<br><br>Full support of app routing, adapting seamlessly to complex application structures, for Next.js, React, Vite, Vue.js, etc.<br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
62
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/markdown.png?raw=true" alt="Feature" width="700"> | **Markdown Support**<br><br>Import and interpret, locale files and remote Markdown for multilingual content like privacy policies, documentation, etc. Interpret and make Markdown metadata accessible in your code.<br><br> - [Content files](https://intlayer.org/doc/concept/content/file) |
63
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/visual_editor.png?raw=true" alt="Feature" width="700"> | **Free Visual Editor & CMS**<br><br>A free visual editor and CMS are available for content writers, removing the need for a localization platform. Keep your content synchronized using Git, or externalize it totally or partially with the CMS.<br><br> - [Intlayer Editor](https://intlayer.org/doc/concept/editor) <br> - [Intlayer CMS](https://intlayer.org/doc/concept/cms) |
64
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png?raw=true" alt="Feature" width="700"> | **Tree-shakable Content**<br><br>Tree-shakable content, reducing the size of the final bundle. Loads content per component, excluding any unused content from your bundle. Supports lazy loading to enhance app loading efficiency. <br><br> - [App build optimization](https://intlayer.org/doc/concept/how-works-intlayer#app-build-optimization) |
65
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/static_rendering.png?raw=true" alt="Feature" width="700"> | **Static Rendering**<br><br>Doesn't block Static Rendering. <br><br> - [Next.js integration](https://intlayer.org/doc/environment/nextjs) |
66
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/AI_translation.png?raw=true" alt="Feature" width="700"> | **AI-Powered Translation**<br><br>Transform your website into 231 languages with just one click using Intlayer's advanced AI-powered translation tools using your own AI provider / API key. <br><br> - [CI/CD integration](https://intlayer.org/doc/concept/ci-cd) <br> - [Intlayer CLI](https://intlayer.org/doc/concept/cli) <br> - [Auto fill](https://intlayer.org/doc/concept/auto-fill) |
67
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/mcp.png?raw=true" alt="Feature" width="700"> | **MCP Server Integration**<br><br>Provides an MCP (Model Context Protocol) server for IDE automation, enabling seamless content management and i18n workflows directly within your development environment. <br><br> - [MCP Server](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/mcp_server.md) |
68
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/vscode_extension.png?raw=true" alt="Feature" width="700"> | **VSCode Extension**<br><br>Intlayer provides a VSCode extension to help you manage your content and translations, building your dictionaries, translating your content, and more. <br><br> - [VSCode Extension](https://intlayer.org/doc/vs-code-extension) |
69
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/interoperability.png?raw=true" alt="Feature" width="700"> | **Interoperability**<br><br>Allow interoperability with react-i18next, next-i18next, next-intl, react-intl, vue-i18n. <br><br> - [Intlayer and react-intl](https://intlayer.org/blog/intlayer-with-react-intl) <br> - [Intlayer and next-intl](https://intlayer.org/blog/intlayer-with-next-intl) <br> - [Intlayer and next-i18next](https://intlayer.org/blog/intlayer-with-next-i18next) <br> - [Intlayer and vue-i18n](https://intlayer.org/blog/intlayer-with-vue-i18n) <br> - [Intlayer compat adapters](https://intlayer.org/doc/compatibility) |
70
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/benchmark.png?raw=true" alt="Feature" width="700"> | **Performances & Benchmark**<br><br>Uses advanced tree-shaking and dynamic loading to boost performances and keep the solution as light as possible. <br><br> - [Performances & Benchmark](https://intlayer.org/doc/benchmark) |
71
71
 
72
72
  ---
73
73
 
@@ -162,7 +162,7 @@ Explore our comprehensive documentation to get started with Intlayer and learn h
162
162
  <li><a href="https://intlayer.org/doc/concept/cms" rel=''>Intlayer CMS</a></li>
163
163
  <li><a href="https://intlayer.org/doc/concept/content" rel=''>Dictionary</a>
164
164
  <ul>
165
- <li><a href="https://intlayer.org/doc/concept/content/per-locale-file" rel=''>Per-Locale Content Declaration File</a></li>
165
+ <li><a href="https://intlayer.org/doc/concept/per-locale-file" rel=''>Per-Locale Content Declaration File</a></li>
166
166
  <li><a href="https://intlayer.org/doc/concept/content/translation" rel=''>Translation</a></li>
167
167
  <li><a href="https://intlayer.org/doc/concept/content/enumeration" rel=''>Enumeration</a></li>
168
168
  <li><a href="https://intlayer.org/doc/concept/content/condition" rel=''>Condition</a></li>
@@ -183,7 +183,7 @@ Explore our comprehensive documentation to get started with Intlayer and learn h
183
183
  <ul>
184
184
  <li><a href="https://intlayer.org/doc/environment/nextjs/15" rel=''>Next.js 15</a></li>
185
185
  <li><a href="https://intlayer.org/doc/environment/nextjs/14" rel=''>Next.js 14 (App Router)</a></li>
186
- <li><a href="https://intlayer.org/doc/environment/nextjs/next-with-Page-Router" rel=''>Next.js Page Router</a></li>
186
+ <li><a href="https://intlayer.org/doc/environment/nextjs/next-with-page-router" rel=''>Next.js Page Router</a></li>
187
187
  <li><a href="https://intlayer.org/doc/environment/nextjs/compiler" rel=''>Next.js using Compiler</a></li>
188
188
  </ul>
189
189
  </li>
@@ -212,7 +212,7 @@ Explore our comprehensive documentation to get started with Intlayer and learn h
212
212
  <li><a href="https://intlayer.org/doc/environment/sveltekit" rel=''>SvelteKit</a></li>
213
213
  <li><a href="https://intlayer.org/doc/environment/vite-and-preact" rel=''>Vite + Preact</a></li>
214
214
  <li><a href="https://intlayer.org/doc/environment/vite-and-vue" rel=''>Vite + Vue</a></li>
215
- <li><a href="https://intlayer.org/doc/environment/vite-and-nuxt" rel=''>Vite + Nuxt</a></li>
215
+ <li><a href="https://intlayer.org/doc/environment/nuxt-and-vue" rel=''>Vite + Nuxt</a></li>
216
216
  <li><a href="https://intlayer.org/doc/environment/vite-and-solid" rel=''>Vite + Solid</a></li>
217
217
  <li><a href="https://intlayer.org/doc/environment/angular" rel=''>Angular</a></li>
218
218
  <li>
@@ -49,7 +49,7 @@ const config = {
49
49
  ai: {
50
50
  /**
51
51
  * AI provider to use.
52
- * Options: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai'
52
+ * Options: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai', 'lmstudio', 'moonshotai'
53
53
  */
54
54
  provider: 'openai',
55
55
  model: 'gpt-5-mini',
@@ -49,7 +49,7 @@ const config = {
49
49
  ai: {
50
50
  /**
51
51
  * AI provider to use.
52
- * Options: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai'
52
+ * Options: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai', 'lmstudio', 'moonshotai'
53
53
  */
54
54
  provider: 'openai',
55
55
  model: 'gpt-5-mini',
@@ -48,7 +48,7 @@ const config: IntlayerConfig = {
48
48
  ai: {
49
49
  /**
50
50
  * AI provider to use.
51
- * Options: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai'
51
+ * Options: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai', 'lmstudio', 'moonshotai'
52
52
  */
53
53
  provider: 'openai',
54
54
  model: 'gpt-5-mini',
@@ -19,11 +19,10 @@ var __copyProps = (to, from, except, desc) => {
19
19
  }
20
20
  return to;
21
21
  };
22
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
23
23
  value: mod,
24
24
  enumerable: true
25
25
  }) : target, mod));
26
26
 
27
27
  //#endregion
28
-
29
28
  exports.__toESM = __toESM;
@@ -70,10 +70,11 @@ const readAsset = (relPath, encoding = "utf8") => {
70
70
  const distRoot = findDistRoot(here) ?? (0, node_path.resolve)(here, "..", "..", "dist");
71
71
  const assetsRoot = (0, node_path.join)(distRoot, "assets");
72
72
  const tried = [];
73
+ const callerDirAbs = getCallerDir();
73
74
  /**
74
75
  * Transform dist/(esm|cjs)/... and _virtual/ prefix to clean subpath (Windows-safe)
75
76
  */
76
- const callerSubpath = (0, node_path.relative)(distRoot, getCallerDir()).split("\\").join("/").replace(/^(?:dist\/)?(?:esm|cjs)\//, "").replace(/^_virtual\//, "");
77
+ const callerSubpath = (0, node_path.relative)(distRoot, callerDirAbs).split("\\").join("/").replace(/^(?:dist\/)?(?:esm|cjs)\//, "").replace(/^_virtual\//, "");
77
78
  if (relPath.startsWith("./") || relPath.startsWith("../")) {
78
79
  const fromCallerAbs = (0, node_path.resolve)(assetsRoot, callerSubpath, relPath);
79
80
  tried.push(fromCallerAbs);
@@ -3,6 +3,7 @@ const require_utils_readDictionariesFromDisk = require('../utils/readDictionarie
3
3
  const require_buildIntlayerDictionary_writeDynamicDictionary = require('./writeDynamicDictionary.cjs');
4
4
  const require_buildIntlayerDictionary_writeFetchDictionary = require('./writeFetchDictionary.cjs');
5
5
  const require_buildIntlayerDictionary_writeMergedDictionary = require('./writeMergedDictionary.cjs');
6
+ const require_buildIntlayerDictionary_writeNestedDictionary = require('./writeNestedDictionary.cjs');
6
7
  const require_buildIntlayerDictionary_writeUnmergedDictionary = require('./writeUnmergedDictionary.cjs');
7
8
  let _intlayer_config_logger = require("@intlayer/config/logger");
8
9
  let _intlayer_config_defaultValues = require("@intlayer/config/defaultValues");
@@ -36,6 +37,8 @@ const buildDictionary = async (localDictionariesEntries, configuration, options)
36
37
  }
37
38
  const unmergedDictionaries = await require_buildIntlayerDictionary_writeUnmergedDictionary.writeUnmergedDictionaries(unmergedDictionariesToUpdate, configuration, env);
38
39
  const mergedDictionaries = await require_buildIntlayerDictionary_writeMergedDictionary.writeMergedDictionaries(unmergedDictionaries, configuration);
40
+ const nestedDictionaryGraph = (0, _intlayer_core_dictionaryManipulator.getNestedDictionaryGraph)(Object.values(require_utils_readDictionariesFromDisk.readDictionariesFromDisk(configuration.system.dictionariesDir)));
41
+ await require_buildIntlayerDictionary_writeNestedDictionary.writeNestedDictionaries(nestedDictionaryGraph, configuration, formats);
39
42
  const dictionariesToBuildDynamic = {};
40
43
  const qualifiedDictionariesToBuildDynamic = {};
41
44
  const keysToBuildFetch = /* @__PURE__ */ new Set();
@@ -57,14 +60,23 @@ const buildDictionary = async (localDictionariesEntries, configuration, options)
57
60
  };
58
61
  if (mode === "fetch") keysToBuildFetch.add(key);
59
62
  }
63
+ for (const consumerKey of Object.keys(dictionariesToBuildDynamic)) for (const nestedKey of nestedDictionaryGraph.get(consumerKey) ?? []) {
64
+ if (dictionariesToBuildDynamic[nestedKey]) continue;
65
+ const nestedResult = mergedDictionaries[nestedKey];
66
+ if (!nestedResult || (0, _intlayer_core_dictionaryManipulator.isQualifiedDictionaryGroup)(nestedResult.dictionary)) continue;
67
+ dictionariesToBuildDynamic[nestedKey] = {
68
+ dictionaryPath: nestedResult.dictionaryPath,
69
+ dictionary: nestedResult.dictionary
70
+ };
71
+ }
60
72
  let dynamicDictionaries = null;
61
- if (Object.keys(dictionariesToBuildDynamic).length > 0) dynamicDictionaries = await require_buildIntlayerDictionary_writeDynamicDictionary.writeDynamicDictionary(dictionariesToBuildDynamic, configuration, formats);
73
+ if (Object.keys(dictionariesToBuildDynamic).length > 0) dynamicDictionaries = await require_buildIntlayerDictionary_writeDynamicDictionary.writeDynamicDictionary(dictionariesToBuildDynamic, configuration, formats, nestedDictionaryGraph);
62
74
  if (Object.keys(qualifiedDictionariesToBuildDynamic).length > 0) await require_buildIntlayerDictionary_writeDynamicDictionary.writeDynamicQualifiedDictionaries(qualifiedDictionariesToBuildDynamic, configuration, formats);
63
75
  let fetchDictionaries = null;
64
76
  if (dynamicDictionaries && keysToBuildFetch.size > 0) {
65
77
  const dictionariesToBuildFetch = {};
66
78
  for (const key of keysToBuildFetch) if (dynamicDictionaries[key]) dictionariesToBuildFetch[key] = dynamicDictionaries[key];
67
- if (Object.keys(dictionariesToBuildFetch).length > 0) fetchDictionaries = await require_buildIntlayerDictionary_writeFetchDictionary.writeFetchDictionary(dictionariesToBuildFetch, configuration, formats);
79
+ if (Object.keys(dictionariesToBuildFetch).length > 0) fetchDictionaries = await require_buildIntlayerDictionary_writeFetchDictionary.writeFetchDictionary(dictionariesToBuildFetch, configuration, formats, nestedDictionaryGraph);
68
80
  }
69
81
  return {
70
82
  unmergedDictionaries,
@@ -1 +1 @@
1
- {"version":3,"file":"buildIntlayerDictionary.cjs","names":["OUTPUT_FORMAT","IMPORT_MODE","readDictionariesFromDisk","writeUnmergedDictionaries","writeMergedDictionaries","writeDynamicDictionary","writeDynamicQualifiedDictionaries","writeFetchDictionary"],"sources":["../../../src/buildIntlayerDictionary/buildIntlayerDictionary.ts"],"sourcesContent":["import { IMPORT_MODE, OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport { isQualifiedDictionaryGroup } from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { readDictionariesFromDisk } from '../utils/readDictionariesFromDisk';\nimport {\n type LocalizedDictionaryOutput,\n type QualifiedMergedDictionaryOutput,\n writeDynamicDictionary,\n writeDynamicQualifiedDictionaries,\n} from './writeDynamicDictionary';\nimport { writeFetchDictionary } from './writeFetchDictionary';\nimport {\n type PlainMergedDictionaryOutput,\n writeMergedDictionaries,\n} from './writeMergedDictionary';\nimport { writeUnmergedDictionaries } from './writeUnmergedDictionary';\n\nexport type BuildDictionariesOptions = Partial<{\n formats: typeof OUTPUT_FORMAT;\n importOtherDictionaries: boolean;\n env: 'prod' | 'dev';\n}>;\n\nconst defaultOptions = {\n formats: OUTPUT_FORMAT,\n importOtherDictionaries: true,\n env: 'dev',\n} as const satisfies BuildDictionariesOptions;\n\n/**\n * This function transpile the bundled code to to make dictionaries as JSON files\n */\nexport const buildDictionary = async (\n localDictionariesEntries: Dictionary[],\n configuration: IntlayerConfig,\n options?: BuildDictionariesOptions\n) => {\n const importMode =\n configuration?.build?.importMode ??\n configuration?.dictionary?.importMode ??\n IMPORT_MODE;\n\n const { importOtherDictionaries, env, formats } = {\n ...defaultOptions,\n ...options,\n };\n\n const unmergedDictionariesToUpdate: Dictionary[] = [\n ...localDictionariesEntries,\n ];\n\n if (importOtherDictionaries) {\n const prevUnmergedDictionaries: Record<string, Dictionary[]> =\n readDictionariesFromDisk(configuration.system.unmergedDictionariesDir);\n\n // Reinsert other dictionaries with the same key to avoid merging errors\n for (const dictionaryToWrite of localDictionariesEntries) {\n const allPrebuiltUnmergedDictionaries =\n prevUnmergedDictionaries[dictionaryToWrite.key]!;\n\n if (allPrebuiltUnmergedDictionaries?.length > 0) {\n // Do not add the same dictionary again by filtering out the one with the same localId\n const otherUnmergedDictionaries =\n allPrebuiltUnmergedDictionaries?.filter(\n (unmergedDictionary) =>\n unmergedDictionary.localId !== dictionaryToWrite.localId\n );\n\n unmergedDictionariesToUpdate.push(...(otherUnmergedDictionaries ?? []));\n }\n }\n }\n\n const unmergedDictionaries = await writeUnmergedDictionaries(\n unmergedDictionariesToUpdate,\n configuration,\n env\n );\n\n const mergedDictionaries = await writeMergedDictionaries(\n unmergedDictionaries,\n configuration\n );\n\n const dictionariesToBuildDynamic: PlainMergedDictionaryOutput = {};\n const qualifiedDictionariesToBuildDynamic: QualifiedMergedDictionaryOutput =\n {};\n const keysToBuildFetch = new Set<string>();\n\n for (const [key, mergedResult] of Object.entries(mergedDictionaries)) {\n const dictionary = mergedResult.dictionary;\n\n if (isQualifiedDictionaryGroup(dictionary)) {\n // Collections / variants resolve their qualifier at\n // runtime from a selector. Static mode keeps every entry in one JSON;\n // dynamic mode splits them into one chunk per (locale, qualifierId).\n const entryMode = dictionary.importMode ?? importMode;\n\n if (entryMode === 'dynamic') {\n qualifiedDictionariesToBuildDynamic[key] = {\n dictionaryPath: mergedResult.dictionaryPath,\n dictionary,\n };\n } else if (entryMode === 'fetch') {\n const appLogger = getAppLogger(configuration);\n appLogger(\n `Dictionary ${colorizeKey(key)} uses 'fetch' import mode with (${dictionary.qualifierTypes.join(', ')}) entries — fetch mode is not qualifier-aware yet, falling back to static import.`,\n { level: 'warn' }\n );\n }\n\n continue;\n }\n\n const mode = dictionary.importMode ?? importMode;\n\n if (mode === 'dynamic' || mode === 'fetch') {\n dictionariesToBuildDynamic[key] = {\n dictionaryPath: mergedResult.dictionaryPath,\n dictionary,\n };\n }\n\n if (mode === 'fetch') {\n keysToBuildFetch.add(key);\n }\n }\n\n let dynamicDictionaries: LocalizedDictionaryOutput | null = null;\n\n if (Object.keys(dictionariesToBuildDynamic).length > 0) {\n dynamicDictionaries = await writeDynamicDictionary(\n dictionariesToBuildDynamic,\n configuration,\n formats\n );\n }\n\n if (Object.keys(qualifiedDictionariesToBuildDynamic).length > 0) {\n await writeDynamicQualifiedDictionaries(\n qualifiedDictionariesToBuildDynamic,\n configuration,\n formats\n );\n }\n\n let fetchDictionaries: LocalizedDictionaryOutput | null = null;\n\n if (dynamicDictionaries && keysToBuildFetch.size > 0) {\n const dictionariesToBuildFetch: LocalizedDictionaryOutput = {};\n\n for (const key of keysToBuildFetch) {\n if (dynamicDictionaries[key]) {\n dictionariesToBuildFetch[key] = dynamicDictionaries[key];\n }\n }\n\n if (Object.keys(dictionariesToBuildFetch).length > 0) {\n fetchDictionaries = await writeFetchDictionary(\n dictionariesToBuildFetch,\n configuration,\n formats\n );\n }\n }\n\n return {\n unmergedDictionaries,\n mergedDictionaries,\n dynamicDictionaries,\n fetchDictionaries,\n };\n};\n"],"mappings":";;;;;;;;;;;AAyBA,MAAM,iBAAiB;CACrB,SAASA;CACT,yBAAyB;CACzB,KAAK;AACP;;;;AAKA,MAAa,kBAAkB,OAC7B,0BACA,eACA,YACG;CACH,MAAM,aACJ,eAAe,OAAO,cACtB,eAAe,YAAY,cAC3BC;CAEF,MAAM,EAAE,yBAAyB,KAAK,YAAY;EAChD,GAAG;EACH,GAAG;CACL;CAEA,MAAM,+BAA6C,CACjD,GAAG,wBACL;CAEA,IAAI,yBAAyB;EAC3B,MAAM,2BACJC,gEAAyB,cAAc,OAAO,uBAAuB;EAGvE,KAAK,MAAM,qBAAqB,0BAA0B;GACxD,MAAM,kCACJ,yBAAyB,kBAAkB;GAE7C,IAAI,iCAAiC,SAAS,GAAG;IAE/C,MAAM,4BACJ,iCAAiC,QAC9B,uBACC,mBAAmB,YAAY,kBAAkB,OACrD;IAEF,6BAA6B,KAAK,GAAI,6BAA6B,CAAC,CAAE;GACxE;EACF;CACF;CAEA,MAAM,uBAAuB,MAAMC,kFACjC,8BACA,eACA,GACF;CAEA,MAAM,qBAAqB,MAAMC,8EAC/B,sBACA,aACF;CAEA,MAAM,6BAA0D,CAAC;CACjE,MAAM,sCACJ,CAAC;CACH,MAAM,mCAAmB,IAAI,IAAY;CAEzC,KAAK,MAAM,CAAC,KAAK,iBAAiB,OAAO,QAAQ,kBAAkB,GAAG;EACpE,MAAM,aAAa,aAAa;EAEhC,yEAA+B,UAAU,GAAG;GAI1C,MAAM,YAAY,WAAW,cAAc;GAE3C,IAAI,cAAc,WAChB,oCAAoC,OAAO;IACzC,gBAAgB,aAAa;IAC7B;GACF;QACK,IAAI,cAAc,SAEvB,0CAD+B,aACvB,CAAC,CACP,uDAA0B,GAAG,EAAE,kCAAkC,WAAW,eAAe,KAAK,IAAI,EAAE,oFACtG,EAAE,OAAO,OAAO,CAClB;GAGF;EACF;EAEA,MAAM,OAAO,WAAW,cAAc;EAEtC,IAAI,SAAS,aAAa,SAAS,SACjC,2BAA2B,OAAO;GAChC,gBAAgB,aAAa;GAC7B;EACF;EAGF,IAAI,SAAS,SACX,iBAAiB,IAAI,GAAG;CAE5B;CAEA,IAAI,sBAAwD;CAE5D,IAAI,OAAO,KAAK,0BAA0B,CAAC,CAAC,SAAS,GACnD,sBAAsB,MAAMC,8EAC1B,4BACA,eACA,OACF;CAGF,IAAI,OAAO,KAAK,mCAAmC,CAAC,CAAC,SAAS,GAC5D,MAAMC,yFACJ,qCACA,eACA,OACF;CAGF,IAAI,oBAAsD;CAE1D,IAAI,uBAAuB,iBAAiB,OAAO,GAAG;EACpD,MAAM,2BAAsD,CAAC;EAE7D,KAAK,MAAM,OAAO,kBAChB,IAAI,oBAAoB,MACtB,yBAAyB,OAAO,oBAAoB;EAIxD,IAAI,OAAO,KAAK,wBAAwB,CAAC,CAAC,SAAS,GACjD,oBAAoB,MAAMC,0EACxB,0BACA,eACA,OACF;CAEJ;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF"}
1
+ {"version":3,"file":"buildIntlayerDictionary.cjs","names":["OUTPUT_FORMAT","IMPORT_MODE","readDictionariesFromDisk","writeUnmergedDictionaries","writeMergedDictionaries","getNestedDictionaryGraph","writeNestedDictionaries","isQualifiedDictionaryGroup","getAppLogger","colorizeKey","writeDynamicDictionary","writeDynamicQualifiedDictionaries","writeFetchDictionary"],"sources":["../../../src/buildIntlayerDictionary/buildIntlayerDictionary.ts"],"sourcesContent":["import { IMPORT_MODE, OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport {\n getNestedDictionaryGraph,\n isQualifiedDictionaryGroup,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { readDictionariesFromDisk } from '../utils/readDictionariesFromDisk';\nimport {\n type LocalizedDictionaryOutput,\n type QualifiedMergedDictionaryOutput,\n writeDynamicDictionary,\n writeDynamicQualifiedDictionaries,\n} from './writeDynamicDictionary';\nimport { writeFetchDictionary } from './writeFetchDictionary';\nimport {\n type PlainMergedDictionaryOutput,\n writeMergedDictionaries,\n} from './writeMergedDictionary';\nimport { writeNestedDictionaries } from './writeNestedDictionary';\nimport { writeUnmergedDictionaries } from './writeUnmergedDictionary';\n\nexport type BuildDictionariesOptions = Partial<{\n formats: typeof OUTPUT_FORMAT;\n importOtherDictionaries: boolean;\n env: 'prod' | 'dev';\n}>;\n\nconst defaultOptions = {\n formats: OUTPUT_FORMAT,\n importOtherDictionaries: true,\n env: 'dev',\n} as const satisfies BuildDictionariesOptions;\n\n/**\n * This function transpile the bundled code to to make dictionaries as JSON files\n */\nexport const buildDictionary = async (\n localDictionariesEntries: Dictionary[],\n configuration: IntlayerConfig,\n options?: BuildDictionariesOptions\n) => {\n const importMode =\n configuration?.build?.importMode ??\n configuration?.dictionary?.importMode ??\n IMPORT_MODE;\n\n const { importOtherDictionaries, env, formats } = {\n ...defaultOptions,\n ...options,\n };\n\n const unmergedDictionariesToUpdate: Dictionary[] = [\n ...localDictionariesEntries,\n ];\n\n if (importOtherDictionaries) {\n const prevUnmergedDictionaries: Record<string, Dictionary[]> =\n readDictionariesFromDisk(configuration.system.unmergedDictionariesDir);\n\n // Reinsert other dictionaries with the same key to avoid merging errors\n for (const dictionaryToWrite of localDictionariesEntries) {\n const allPrebuiltUnmergedDictionaries =\n prevUnmergedDictionaries[dictionaryToWrite.key]!;\n\n if (allPrebuiltUnmergedDictionaries?.length > 0) {\n // Do not add the same dictionary again by filtering out the one with the same localId\n const otherUnmergedDictionaries =\n allPrebuiltUnmergedDictionaries?.filter(\n (unmergedDictionary) =>\n unmergedDictionary.localId !== dictionaryToWrite.localId\n );\n\n unmergedDictionariesToUpdate.push(...(otherUnmergedDictionaries ?? []));\n }\n }\n }\n\n const unmergedDictionaries = await writeUnmergedDictionaries(\n unmergedDictionariesToUpdate,\n configuration,\n env\n );\n\n const mergedDictionaries = await writeMergedDictionaries(\n unmergedDictionaries,\n configuration\n );\n\n // `nest()` dependency graph, read back from disk so it stays complete on\n // incremental rebuilds where only a subset of dictionaries was regenerated.\n // Every artifact kind attaches its dependencies, letting `getNesting` resolve\n // them locally instead of through the registry the optimizer strips.\n const nestedDictionaryGraph = getNestedDictionaryGraph(\n Object.values(\n readDictionariesFromDisk<Record<string, Dictionary>>(\n configuration.system.dictionariesDir\n )\n )\n );\n\n await writeNestedDictionaries(nestedDictionaryGraph, configuration, formats);\n\n const dictionariesToBuildDynamic: PlainMergedDictionaryOutput = {};\n const qualifiedDictionariesToBuildDynamic: QualifiedMergedDictionaryOutput =\n {};\n const keysToBuildFetch = new Set<string>();\n\n for (const [key, mergedResult] of Object.entries(mergedDictionaries)) {\n const dictionary = mergedResult.dictionary;\n\n if (isQualifiedDictionaryGroup(dictionary)) {\n // Collections / variants resolve their qualifier at\n // runtime from a selector. Static mode keeps every entry in one JSON;\n // dynamic mode splits them into one chunk per (locale, qualifierId).\n const entryMode = dictionary.importMode ?? importMode;\n\n if (entryMode === 'dynamic') {\n qualifiedDictionariesToBuildDynamic[key] = {\n dictionaryPath: mergedResult.dictionaryPath,\n dictionary,\n };\n } else if (entryMode === 'fetch') {\n const appLogger = getAppLogger(configuration);\n appLogger(\n `Dictionary ${colorizeKey(key)} uses 'fetch' import mode with (${dictionary.qualifierTypes.join(', ')}) entries — fetch mode is not qualifier-aware yet, falling back to static import.`,\n { level: 'warn' }\n );\n }\n\n continue;\n }\n\n const mode = dictionary.importMode ?? importMode;\n\n if (mode === 'dynamic' || mode === 'fetch') {\n dictionariesToBuildDynamic[key] = {\n dictionaryPath: mergedResult.dictionaryPath,\n dictionary,\n };\n }\n\n if (mode === 'fetch') {\n keysToBuildFetch.add(key);\n }\n }\n\n // A lazily loaded dictionary resolves its `nest()` references from chunks\n // loaded by the same loader, so its nest targets need dynamic artifacts of\n // their own — whatever import mode they declare for their own call sites.\n for (const consumerKey of Object.keys(dictionariesToBuildDynamic)) {\n for (const nestedKey of nestedDictionaryGraph.get(consumerKey) ?? []) {\n if (dictionariesToBuildDynamic[nestedKey]) continue;\n\n const nestedResult = mergedDictionaries[nestedKey];\n if (\n !nestedResult ||\n isQualifiedDictionaryGroup(nestedResult.dictionary)\n ) {\n continue;\n }\n\n dictionariesToBuildDynamic[nestedKey] = {\n dictionaryPath: nestedResult.dictionaryPath,\n dictionary: nestedResult.dictionary,\n };\n }\n }\n\n let dynamicDictionaries: LocalizedDictionaryOutput | null = null;\n\n if (Object.keys(dictionariesToBuildDynamic).length > 0) {\n dynamicDictionaries = await writeDynamicDictionary(\n dictionariesToBuildDynamic,\n configuration,\n formats,\n nestedDictionaryGraph\n );\n }\n\n if (Object.keys(qualifiedDictionariesToBuildDynamic).length > 0) {\n await writeDynamicQualifiedDictionaries(\n qualifiedDictionariesToBuildDynamic,\n configuration,\n formats\n );\n }\n\n let fetchDictionaries: LocalizedDictionaryOutput | null = null;\n\n if (dynamicDictionaries && keysToBuildFetch.size > 0) {\n const dictionariesToBuildFetch: LocalizedDictionaryOutput = {};\n\n for (const key of keysToBuildFetch) {\n if (dynamicDictionaries[key]) {\n dictionariesToBuildFetch[key] = dynamicDictionaries[key];\n }\n }\n\n if (Object.keys(dictionariesToBuildFetch).length > 0) {\n fetchDictionaries = await writeFetchDictionary(\n dictionariesToBuildFetch,\n configuration,\n formats,\n nestedDictionaryGraph\n );\n }\n }\n\n return {\n unmergedDictionaries,\n mergedDictionaries,\n dynamicDictionaries,\n fetchDictionaries,\n };\n};\n"],"mappings":";;;;;;;;;;;;AA6BA,MAAM,iBAAiB;CACrB,SAASA;CACT,yBAAyB;CACzB,KAAK;AACP;;;;AAKA,MAAa,kBAAkB,OAC7B,0BACA,eACA,YACG;CACH,MAAM,aACJ,eAAe,OAAO,cACtB,eAAe,YAAY,cAC3BC;CAEF,MAAM,EAAE,yBAAyB,KAAK,YAAY;EAChD,GAAG;EACH,GAAG;CACL;CAEA,MAAM,+BAA6C,CACjD,GAAG,wBACL;CAEA,IAAI,yBAAyB;EAC3B,MAAM,2BACJC,gEAAyB,cAAc,OAAO,uBAAuB;EAGvE,KAAK,MAAM,qBAAqB,0BAA0B;GACxD,MAAM,kCACJ,yBAAyB,kBAAkB;GAE7C,IAAI,iCAAiC,SAAS,GAAG;IAE/C,MAAM,4BACJ,iCAAiC,QAC9B,uBACC,mBAAmB,YAAY,kBAAkB,OACrD;IAEF,6BAA6B,KAAK,GAAI,6BAA6B,CAAC,CAAE;GACxE;EACF;CACF;CAEA,MAAM,uBAAuB,MAAMC,kFACjC,8BACA,eACA,GACF;CAEA,MAAM,qBAAqB,MAAMC,8EAC/B,sBACA,aACF;CAMA,MAAM,4BAAwBC,+DAC5B,OAAO,OACLH,gEACE,cAAc,OAAO,eACvB,CACF,CACF;CAEA,MAAMI,8EAAwB,uBAAuB,eAAe,OAAO;CAE3E,MAAM,6BAA0D,CAAC;CACjE,MAAM,sCACJ,CAAC;CACH,MAAM,mCAAmB,IAAI,IAAY;CAEzC,KAAK,MAAM,CAAC,KAAK,iBAAiB,OAAO,QAAQ,kBAAkB,GAAG;EACpE,MAAM,aAAa,aAAa;EAEhC,QAAIC,iEAA2B,UAAU,GAAG;GAI1C,MAAM,YAAY,WAAW,cAAc;GAE3C,IAAI,cAAc,WAChB,oCAAoC,OAAO;IACzC,gBAAgB,aAAa;IAC7B;GACF;QACK,IAAI,cAAc,SAEvB,IADkBC,sCAAa,aACvB,CAAC,CACP,kBAAcC,qCAAY,GAAG,EAAE,kCAAkC,WAAW,eAAe,KAAK,IAAI,EAAE,oFACtG,EAAE,OAAO,OAAO,CAClB;GAGF;EACF;EAEA,MAAM,OAAO,WAAW,cAAc;EAEtC,IAAI,SAAS,aAAa,SAAS,SACjC,2BAA2B,OAAO;GAChC,gBAAgB,aAAa;GAC7B;EACF;EAGF,IAAI,SAAS,SACX,iBAAiB,IAAI,GAAG;CAE5B;CAKA,KAAK,MAAM,eAAe,OAAO,KAAK,0BAA0B,GAC9D,KAAK,MAAM,aAAa,sBAAsB,IAAI,WAAW,KAAK,CAAC,GAAG;EACpE,IAAI,2BAA2B,YAAY;EAE3C,MAAM,eAAe,mBAAmB;EACxC,IACE,CAAC,oBACDF,iEAA2B,aAAa,UAAU,GAElD;EAGF,2BAA2B,aAAa;GACtC,gBAAgB,aAAa;GAC7B,YAAY,aAAa;EAC3B;CACF;CAGF,IAAI,sBAAwD;CAE5D,IAAI,OAAO,KAAK,0BAA0B,CAAC,CAAC,SAAS,GACnD,sBAAsB,MAAMG,8EAC1B,4BACA,eACA,SACA,qBACF;CAGF,IAAI,OAAO,KAAK,mCAAmC,CAAC,CAAC,SAAS,GAC5D,MAAMC,yFACJ,qCACA,eACA,OACF;CAGF,IAAI,oBAAsD;CAE1D,IAAI,uBAAuB,iBAAiB,OAAO,GAAG;EACpD,MAAM,2BAAsD,CAAC;EAE7D,KAAK,MAAM,OAAO,kBAChB,IAAI,oBAAoB,MACtB,yBAAyB,OAAO,oBAAoB;EAIxD,IAAI,OAAO,KAAK,wBAAwB,CAAC,CAAC,SAAS,GACjD,oBAAoB,MAAMC,0EACxB,0BACA,eACA,SACA,qBACF;CAEJ;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF"}
@@ -18,15 +18,35 @@ const DICTIONARIES_SUBDIR = "json";
18
18
  * emitted JavaScript.
19
19
  */
20
20
  const escapeJsLiteral = (value) => value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
21
+ /** Loader expression for one `(key, locale)` per-locale chunk. */
22
+ const buildPerLocaleLoader = (key, locale, format) => {
23
+ const path = `./${DICTIONARIES_SUBDIR}/${key}/${locale}.json`;
24
+ return format === "esm" ? `import('${path}').then(m => m.default)` : `Promise.resolve(require('${path}'))`;
25
+ };
21
26
  /**
22
27
  * Generates the content of a dictionary entry point file.
28
+ *
29
+ * When the dictionary references other dictionaries through `nest()`, the
30
+ * loader for a locale resolves the referenced dictionaries alongside it and
31
+ * attaches them as `nestedDictionaries`. The nest targets then travel in the
32
+ * same lazy chunk as their consumer, and `getNesting` resolves them from that
33
+ * local reference instead of the global registry — which the build
34
+ * optimization strips.
35
+ *
36
+ * @param key - The dictionary key.
37
+ * @param locales - Locales to emit a loader for.
38
+ * @param format - Output module format.
39
+ * @param nestedKeys - Keys referenced through `nest()`, transitively.
23
40
  */
24
- const generateDictionaryEntryPoint = (key, locales, format = "esm") => {
41
+ const generateDictionaryEntryPoint = (key, locales, format = "esm", nestedKeys = []) => {
25
42
  const sortedLocales = [...locales].sort((a, b) => String(a).localeCompare(String(b)));
43
+ const sortedNestedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));
26
44
  const safeKey = escapeJsLiteral(key);
27
45
  const localeEntries = sortedLocales.map((locale) => {
28
46
  const safeLocale = escapeJsLiteral(locale);
29
- return format === "esm" ? ` '${safeLocale}': () => import('./${DICTIONARIES_SUBDIR}/${safeKey}/${safeLocale}.json').then(m => m.default)` : ` '${safeLocale}': () => Promise.resolve(require('./${DICTIONARIES_SUBDIR}/${safeKey}/${safeLocale}.json'))`;
47
+ const ownLoader = buildPerLocaleLoader(safeKey, safeLocale, format);
48
+ if (sortedNestedKeys.length === 0) return ` '${safeLocale}': () => ${ownLoader}`;
49
+ return ` '${safeLocale}': () => Promise.all([\n ${ownLoader},\n ${sortedNestedKeys.map((nestedKey) => buildPerLocaleLoader(escapeJsLiteral(nestedKey), safeLocale, format)).join(",\n ")}\n ]).then(([_dictionary, ..._nested]) => ({\n ..._dictionary,\n nestedDictionaries: { ${sortedNestedKeys.map((nestedKey, index) => `'${escapeJsLiteral(nestedKey)}': _nested[${index}]`).join(", ")} }\n }))`;
30
50
  }).join(",\n");
31
51
  if (format === "esm") return `const content = {\n${localeEntries}\n};\n\nexport default content;\n`;
32
52
  return `module.exports = {\n${localeEntries}\n};\n`;
@@ -95,7 +115,7 @@ const generateQualifiedDictionaryEntryPoint = (key, qualifierTypes, entries, loc
95
115
  * // .intlayer/dynamic_dictionary/dictionaries/fr_home.json
96
116
  * ```
97
117
  */
98
- const writeDynamicDictionary = async (mergedDictionaries, configuration, formats = _intlayer_config_defaultValues.OUTPUT_FORMAT) => {
118
+ const writeDynamicDictionary = async (mergedDictionaries, configuration, formats = _intlayer_config_defaultValues.OUTPUT_FORMAT, nestedDictionaryGraph = /* @__PURE__ */ new Map()) => {
99
119
  const { locales, defaultLocale } = configuration.internationalization;
100
120
  const { dynamicDictionariesDir } = configuration.system;
101
121
  const dictDir = (0, node_path.resolve)(dynamicDictionariesDir, DICTIONARIES_SUBDIR);
@@ -121,7 +141,7 @@ const writeDynamicDictionary = async (mergedDictionaries, configuration, formats
121
141
  resultDictionariesPaths[key] = localizedDictionariesPathsRecord;
122
142
  await require_utils_parallelize.parallelize(formats, async (format) => {
123
143
  const extension = format === "cjs" ? "cjs" : "mjs";
124
- const content = generateDictionaryEntryPoint(key, locales, format);
144
+ const content = generateDictionaryEntryPoint(key, locales, format, [...nestedDictionaryGraph.get(key) ?? []]);
125
145
  const dynEntryPath = (0, node_path.resolve)(dynamicDictionariesDir, `${key}.${extension}`);
126
146
  (0, _intlayer_config_utils.assertPathWithin)(dynEntryPath, dynamicDictionariesDir);
127
147
  await require_writeFileIfChanged.writeFileIfChanged(dynEntryPath, content).catch((err) => {
@@ -180,7 +200,8 @@ const writeDynamicQualifiedDictionaries = async (qualifiedDictionaries, configur
180
200
  await (0, node_fs_promises.mkdir)(entryDir, { recursive: true });
181
201
  await require_utils_parallelize.parallelize(locales, async (locale) => {
182
202
  const localizedDictionary = (0, _intlayer_core_plugins.getPerLocaleDictionary)(entry, locale, defaultLocale);
183
- await require_writeJsonIfChanged.writeJsonIfChanged((0, node_path.resolve)(entryDir, `${locale}.json`), localizedDictionary).catch((err) => {
203
+ const resultFilePath = (0, node_path.resolve)(entryDir, `${locale}.json`);
204
+ await require_writeJsonIfChanged.writeJsonIfChanged(resultFilePath, localizedDictionary).catch((err) => {
184
205
  console.error(`Error creating localized ${key}/${segments.join("/")}/${locale}.json:`, err);
185
206
  });
186
207
  });
@@ -1 +1 @@
1
- {"version":3,"file":"writeDynamicDictionary.cjs","names":["QUALIFIER_DYNAMIC_TYPES_KEY","OUTPUT_FORMAT","parallelize","writeJsonIfChanged","writeFileIfChanged","COMPOSITE_ID_SEPARATOR"],"sources":["../../../src/buildIntlayerDictionary/writeDynamicDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport {\n COMPOSITE_ID_SEPARATOR,\n QUALIFIER_DYNAMIC_TYPES_KEY,\n reconstructQualifiedEntry,\n} from '@intlayer/core/dictionaryManipulator';\nimport { getPerLocaleDictionary } from '@intlayer/core/plugins';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type {\n Dictionary,\n DictionaryQualifierType,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport type { PlainMergedDictionaryOutput } from './writeMergedDictionary';\n\nexport type DictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary;\n};\n\nexport type LocalizedDictionaryResult = Partial<\n Record<Locale, DictionaryResult>\n>;\n\nexport type LocalizedDictionaryOutput = Record<\n string,\n LocalizedDictionaryResult\n>;\n\nconst DICTIONARIES_SUBDIR = 'json'; // Necessary to add a static first dir for Turbopack\n\n/**\n * Escapes a value interpolated into a single-quoted literal of a generated\n * loader module, so keys or segments containing `'` or `\\` cannot break the\n * emitted JavaScript.\n */\nconst escapeJsLiteral = (value: string): string =>\n value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n\n/**\n * Generates the content of a dictionary entry point file.\n */\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n\n const safeKey = escapeJsLiteral(key);\n\n const localeEntries = sortedLocales\n .map((locale) => {\n const safeLocale = escapeJsLiteral(locale);\n return format === 'esm'\n ? ` '${safeLocale}': () => import('./${DICTIONARIES_SUBDIR}/${safeKey}/${safeLocale}.json').then(m => m.default)`\n : ` '${safeLocale}': () => Promise.resolve(require('./${DICTIONARIES_SUBDIR}/${safeKey}/${safeLocale}.json'))`;\n })\n .join(',\\n');\n\n if (format === 'esm') {\n return (\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * A nested loader tree: one level per declared dimension, leaves are loader\n * expression strings.\n */\ntype LoaderTree = { [segment: string]: LoaderTree | string };\n\n/**\n * One entry of a qualified loader map.\n *\n * `treeSegments` is where the entry lives in the loader tree (its composite id\n * segments); `chunkSegments` is the chunk path it loads. They differ when the\n * entry aliases another entry with identical content (e.g. array-variant\n * fan-out): the alias keeps its own tree position but points at the canonical\n * entry's chunk, so equal content is emitted — and downloaded — only once.\n */\nexport type QualifiedEntrySegments = {\n treeSegments: string[];\n chunkSegments: string[];\n};\n\nconst buildLoaderExpression = (\n key: string,\n chunkSegments: string[],\n locale: string,\n format: 'cjs' | 'esm'\n): string => {\n const path = escapeJsLiteral(\n `./${DICTIONARIES_SUBDIR}/${key}/${chunkSegments.join('/')}/${locale}.json`\n );\n\n return format === 'esm'\n ? `() => import('${path}').then(m => m.default)`\n : `() => Promise.resolve(require('${path}'))`;\n};\n\nconst buildLoaderTree = (\n key: string,\n entries: QualifiedEntrySegments[],\n locale: string,\n format: 'cjs' | 'esm'\n): LoaderTree => {\n const root: LoaderTree = {};\n\n for (const { treeSegments, chunkSegments } of entries) {\n let node = root;\n\n treeSegments.forEach((segment, index) => {\n if (index === treeSegments.length - 1) {\n node[segment] = buildLoaderExpression(\n key,\n chunkSegments,\n locale,\n format\n );\n return;\n }\n\n node[segment] = (node[segment] as LoaderTree | undefined) ?? {};\n node = node[segment] as LoaderTree;\n });\n }\n\n return root;\n};\n\nconst serializeLoaderTree = (tree: LoaderTree, indentLevel: number): string => {\n const pad = ' '.repeat(indentLevel);\n const innerPad = ' '.repeat(indentLevel + 1);\n\n const lines = Object.keys(tree)\n .sort((a, b) => a.localeCompare(b))\n .map((segment) => {\n const value = tree[segment]!;\n const serialized =\n typeof value === 'string'\n ? value\n : serializeLoaderTree(value, indentLevel + 1);\n\n return `${innerPad}'${escapeJsLiteral(segment)}': ${serialized}`;\n });\n\n return `{\\n${lines.join(',\\n')}\\n${pad}}`;\n};\n\n/**\n * Generates the entry point of a qualified dictionary (collection / variant,\n * possibly combined). Under each locale the loader map nests one\n * level per declared dimension (canonical order) and carries a marker listing\n * those dimensions so the runtime can walk the tree.\n *\n * One static `import()` is emitted per leaf `(locale, …segments)` chunk, which\n * keeps the output compatible with bundlers that reject template-literal\n * dynamic imports (Turbopack). Entries whose content is identical share one\n * chunk: their leaves point at the canonical entry's import path.\n */\nexport const generateQualifiedDictionaryEntryPoint = (\n key: string,\n qualifierTypes: DictionaryQualifierType[],\n entries: QualifiedEntrySegments[],\n locales: string[],\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n\n const localeEntries = sortedLocales\n .map((locale) => {\n const tree = buildLoaderTree(key, entries, locale, format);\n return ` '${escapeJsLiteral(locale)}': ${serializeLoaderTree(tree, 1)}`;\n })\n .join(',\\n');\n\n const marker = ` '${QUALIFIER_DYNAMIC_TYPES_KEY}': ${JSON.stringify(qualifierTypes)}`;\n\n if (format === 'esm') {\n return (\n `const content = {\\n${marker},\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${marker},\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/dynamic_dictionary/dictionaries/en_home.json\n * // .intlayer/dynamic_dictionary/dictionaries/fr_home.json\n * ```\n */\nexport const writeDynamicDictionary = async (\n mergedDictionaries: PlainMergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<LocalizedDictionaryOutput> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Merge dictionaries with the same key and write to dictionariesDir\n await parallelize(\n Object.entries(mergedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, dictionaryEntry]) => {\n if (key === 'undefined') return;\n\n const localizedDictionariesPathsRecord: LocalizedDictionaryResult = {};\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n await mkdir(keyDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n dictionaryEntry.dictionary,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/locale.json\n const resultFilePath = resolve(keyDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${locale}.json:`,\n err\n );\n }\n );\n\n localizedDictionariesPathsRecord[locale] = {\n dictionaryPath: resultFilePath,\n dictionary: localizedDictionary,\n };\n });\n\n resultDictionariesPaths[key] = localizedDictionariesPathsRecord;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(key, locales, format);\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n\n return resultDictionariesPaths;\n};\n\nexport type QualifiedMergedDictionaryResult = {\n dictionaryPath: string;\n dictionary: QualifiedDictionaryGroup;\n};\n\nexport type QualifiedMergedDictionaryOutput = Record<\n string,\n QualifiedMergedDictionaryResult\n>;\n\n/**\n * Writes the dynamic chunks and entry points of qualified dictionaries\n * (collections, variants — possibly combined) in\n * `importMode: 'dynamic'`.\n *\n * Each entry is reduced to one per-locale chunk written to a path nested by\n * dimension — `json/{key}/{seg1}/{seg2}/{locale}.json` — and a single\n * `{key}.{ext}` entry point exposes the matching nested loader tree, so the\n * entry point is discovered and aggregated exactly like a plain dynamic one.\n */\nexport const writeDynamicQualifiedDictionaries = async (\n qualifiedDictionaries: QualifiedMergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<void> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n await parallelize(\n Object.entries(qualifiedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, { dictionary: group }]) => {\n if (key === 'undefined') return;\n\n const entryIds = Object.keys(group.content);\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n\n // Entries with identical content (e.g. array-variant fan-out) share one\n // chunk: only the first entry per content identity writes files; the\n // others become aliases whose loaders point at the canonical chunk path.\n const canonicalSegmentsByContent = new Map<string, string[]>();\n const entries: QualifiedEntrySegments[] = [];\n const canonicalEntryIds: string[] = [];\n\n for (const entryId of entryIds) {\n const treeSegments = entryId.split(COMPOSITE_ID_SEPARATOR);\n const contentIdentity = JSON.stringify(group.content[entryId]);\n const canonicalSegments =\n canonicalSegmentsByContent.get(contentIdentity);\n\n if (canonicalSegments) {\n entries.push({ treeSegments, chunkSegments: canonicalSegments });\n continue;\n }\n\n canonicalSegmentsByContent.set(contentIdentity, treeSegments);\n entries.push({ treeSegments, chunkSegments: treeSegments });\n canonicalEntryIds.push(entryId);\n }\n\n await parallelize(canonicalEntryIds, async (entryId) => {\n // Rebuild a resolvable dictionary from the content node + composite id\n // so per-locale extraction sees the same `{ key, content }` shape.\n const entry = reconstructQualifiedEntry(group, entryId);\n\n const segments = entryId.split(COMPOSITE_ID_SEPARATOR);\n\n const entryDir = resolve(keyDir, ...segments);\n assertPathWithin(entryDir, keyDir);\n await mkdir(entryDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n entry,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/<…segments>/locale.json\n const resultFilePath = resolve(entryDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${segments.join('/')}/${locale}.json:`,\n err\n );\n }\n );\n });\n });\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateQualifiedDictionaryEntryPoint(\n key,\n group.qualifierTypes,\n entries,\n locales,\n format\n );\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"writeDynamicDictionary.cjs","names":["QUALIFIER_DYNAMIC_TYPES_KEY","OUTPUT_FORMAT","resolve","mkdir","parallelize","getPerLocaleDictionary","writeJsonIfChanged","writeFileIfChanged","colorizePath","COMPOSITE_ID_SEPARATOR","reconstructQualifiedEntry"],"sources":["../../../src/buildIntlayerDictionary/writeDynamicDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport {\n COMPOSITE_ID_SEPARATOR,\n QUALIFIER_DYNAMIC_TYPES_KEY,\n reconstructQualifiedEntry,\n} from '@intlayer/core/dictionaryManipulator';\nimport { getPerLocaleDictionary } from '@intlayer/core/plugins';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type {\n Dictionary,\n DictionaryQualifierType,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport type { PlainMergedDictionaryOutput } from './writeMergedDictionary';\n\nexport type DictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary;\n};\n\nexport type LocalizedDictionaryResult = Partial<\n Record<Locale, DictionaryResult>\n>;\n\nexport type LocalizedDictionaryOutput = Record<\n string,\n LocalizedDictionaryResult\n>;\n\nconst DICTIONARIES_SUBDIR = 'json'; // Necessary to add a static first dir for Turbopack\n\n/**\n * Escapes a value interpolated into a single-quoted literal of a generated\n * loader module, so keys or segments containing `'` or `\\` cannot break the\n * emitted JavaScript.\n */\nconst escapeJsLiteral = (value: string): string =>\n value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n\n/** Loader expression for one `(key, locale)` per-locale chunk. */\nconst buildPerLocaleLoader = (\n key: string,\n locale: string,\n format: 'cjs' | 'esm'\n): string => {\n const path = `./${DICTIONARIES_SUBDIR}/${key}/${locale}.json`;\n\n return format === 'esm'\n ? `import('${path}').then(m => m.default)`\n : `Promise.resolve(require('${path}'))`;\n};\n\n/**\n * Generates the content of a dictionary entry point file.\n *\n * When the dictionary references other dictionaries through `nest()`, the\n * loader for a locale resolves the referenced dictionaries alongside it and\n * attaches them as `nestedDictionaries`. The nest targets then travel in the\n * same lazy chunk as their consumer, and `getNesting` resolves them from that\n * local reference instead of the global registry — which the build\n * optimization strips.\n *\n * @param key - The dictionary key.\n * @param locales - Locales to emit a loader for.\n * @param format - Output module format.\n * @param nestedKeys - Keys referenced through `nest()`, transitively.\n */\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n format: 'cjs' | 'esm' = 'esm',\n nestedKeys: string[] = []\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n const sortedNestedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));\n\n const safeKey = escapeJsLiteral(key);\n\n const localeEntries = sortedLocales\n .map((locale) => {\n const safeLocale = escapeJsLiteral(locale);\n const ownLoader = buildPerLocaleLoader(safeKey, safeLocale, format);\n\n if (sortedNestedKeys.length === 0) {\n return ` '${safeLocale}': () => ${ownLoader}`;\n }\n\n const nestedLoaders = sortedNestedKeys\n .map((nestedKey) =>\n buildPerLocaleLoader(escapeJsLiteral(nestedKey), safeLocale, format)\n )\n .join(',\\n ');\n\n const attachedEntries = sortedNestedKeys\n .map(\n (nestedKey, index) =>\n `'${escapeJsLiteral(nestedKey)}': _nested[${index}]`\n )\n .join(', ');\n\n return (\n ` '${safeLocale}': () => Promise.all([\\n` +\n ` ${ownLoader},\\n` +\n ` ${nestedLoaders}\\n` +\n ` ]).then(([_dictionary, ..._nested]) => ({\\n` +\n ` ..._dictionary,\\n` +\n ` nestedDictionaries: { ${attachedEntries} }\\n` +\n ` }))`\n );\n })\n .join(',\\n');\n\n if (format === 'esm') {\n return (\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * A nested loader tree: one level per declared dimension, leaves are loader\n * expression strings.\n */\ntype LoaderTree = { [segment: string]: LoaderTree | string };\n\n/**\n * One entry of a qualified loader map.\n *\n * `treeSegments` is where the entry lives in the loader tree (its composite id\n * segments); `chunkSegments` is the chunk path it loads. They differ when the\n * entry aliases another entry with identical content (e.g. array-variant\n * fan-out): the alias keeps its own tree position but points at the canonical\n * entry's chunk, so equal content is emitted — and downloaded — only once.\n */\nexport type QualifiedEntrySegments = {\n treeSegments: string[];\n chunkSegments: string[];\n};\n\nconst buildLoaderExpression = (\n key: string,\n chunkSegments: string[],\n locale: string,\n format: 'cjs' | 'esm'\n): string => {\n const path = escapeJsLiteral(\n `./${DICTIONARIES_SUBDIR}/${key}/${chunkSegments.join('/')}/${locale}.json`\n );\n\n return format === 'esm'\n ? `() => import('${path}').then(m => m.default)`\n : `() => Promise.resolve(require('${path}'))`;\n};\n\nconst buildLoaderTree = (\n key: string,\n entries: QualifiedEntrySegments[],\n locale: string,\n format: 'cjs' | 'esm'\n): LoaderTree => {\n const root: LoaderTree = {};\n\n for (const { treeSegments, chunkSegments } of entries) {\n let node = root;\n\n treeSegments.forEach((segment, index) => {\n if (index === treeSegments.length - 1) {\n node[segment] = buildLoaderExpression(\n key,\n chunkSegments,\n locale,\n format\n );\n return;\n }\n\n node[segment] = (node[segment] as LoaderTree | undefined) ?? {};\n node = node[segment] as LoaderTree;\n });\n }\n\n return root;\n};\n\nconst serializeLoaderTree = (tree: LoaderTree, indentLevel: number): string => {\n const pad = ' '.repeat(indentLevel);\n const innerPad = ' '.repeat(indentLevel + 1);\n\n const lines = Object.keys(tree)\n .sort((a, b) => a.localeCompare(b))\n .map((segment) => {\n const value = tree[segment]!;\n const serialized =\n typeof value === 'string'\n ? value\n : serializeLoaderTree(value, indentLevel + 1);\n\n return `${innerPad}'${escapeJsLiteral(segment)}': ${serialized}`;\n });\n\n return `{\\n${lines.join(',\\n')}\\n${pad}}`;\n};\n\n/**\n * Generates the entry point of a qualified dictionary (collection / variant,\n * possibly combined). Under each locale the loader map nests one\n * level per declared dimension (canonical order) and carries a marker listing\n * those dimensions so the runtime can walk the tree.\n *\n * One static `import()` is emitted per leaf `(locale, …segments)` chunk, which\n * keeps the output compatible with bundlers that reject template-literal\n * dynamic imports (Turbopack). Entries whose content is identical share one\n * chunk: their leaves point at the canonical entry's import path.\n */\nexport const generateQualifiedDictionaryEntryPoint = (\n key: string,\n qualifierTypes: DictionaryQualifierType[],\n entries: QualifiedEntrySegments[],\n locales: string[],\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n\n const localeEntries = sortedLocales\n .map((locale) => {\n const tree = buildLoaderTree(key, entries, locale, format);\n return ` '${escapeJsLiteral(locale)}': ${serializeLoaderTree(tree, 1)}`;\n })\n .join(',\\n');\n\n const marker = ` '${QUALIFIER_DYNAMIC_TYPES_KEY}': ${JSON.stringify(qualifierTypes)}`;\n\n if (format === 'esm') {\n return (\n `const content = {\\n${marker},\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${marker},\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/dynamic_dictionary/dictionaries/en_home.json\n * // .intlayer/dynamic_dictionary/dictionaries/fr_home.json\n * ```\n */\nexport const writeDynamicDictionary = async (\n mergedDictionaries: PlainMergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT,\n nestedDictionaryGraph: Map<string, Set<string>> = new Map()\n): Promise<LocalizedDictionaryOutput> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Merge dictionaries with the same key and write to dictionariesDir\n await parallelize(\n Object.entries(mergedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, dictionaryEntry]) => {\n if (key === 'undefined') return;\n\n const localizedDictionariesPathsRecord: LocalizedDictionaryResult = {};\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n await mkdir(keyDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n dictionaryEntry.dictionary,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/locale.json\n const resultFilePath = resolve(keyDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${locale}.json:`,\n err\n );\n }\n );\n\n localizedDictionariesPathsRecord[locale] = {\n dictionaryPath: resultFilePath,\n dictionary: localizedDictionary,\n };\n });\n\n resultDictionariesPaths[key] = localizedDictionariesPathsRecord;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(key, locales, format, [\n ...(nestedDictionaryGraph.get(key) ?? []),\n ]);\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n\n return resultDictionariesPaths;\n};\n\nexport type QualifiedMergedDictionaryResult = {\n dictionaryPath: string;\n dictionary: QualifiedDictionaryGroup;\n};\n\nexport type QualifiedMergedDictionaryOutput = Record<\n string,\n QualifiedMergedDictionaryResult\n>;\n\n/**\n * Writes the dynamic chunks and entry points of qualified dictionaries\n * (collections, variants — possibly combined) in\n * `importMode: 'dynamic'`.\n *\n * Each entry is reduced to one per-locale chunk written to a path nested by\n * dimension — `json/{key}/{seg1}/{seg2}/{locale}.json` — and a single\n * `{key}.{ext}` entry point exposes the matching nested loader tree, so the\n * entry point is discovered and aggregated exactly like a plain dynamic one.\n */\nexport const writeDynamicQualifiedDictionaries = async (\n qualifiedDictionaries: QualifiedMergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<void> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n await parallelize(\n Object.entries(qualifiedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, { dictionary: group }]) => {\n if (key === 'undefined') return;\n\n const entryIds = Object.keys(group.content);\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n\n // Entries with identical content (e.g. array-variant fan-out) share one\n // chunk: only the first entry per content identity writes files; the\n // others become aliases whose loaders point at the canonical chunk path.\n const canonicalSegmentsByContent = new Map<string, string[]>();\n const entries: QualifiedEntrySegments[] = [];\n const canonicalEntryIds: string[] = [];\n\n for (const entryId of entryIds) {\n const treeSegments = entryId.split(COMPOSITE_ID_SEPARATOR);\n const contentIdentity = JSON.stringify(group.content[entryId]);\n const canonicalSegments =\n canonicalSegmentsByContent.get(contentIdentity);\n\n if (canonicalSegments) {\n entries.push({ treeSegments, chunkSegments: canonicalSegments });\n continue;\n }\n\n canonicalSegmentsByContent.set(contentIdentity, treeSegments);\n entries.push({ treeSegments, chunkSegments: treeSegments });\n canonicalEntryIds.push(entryId);\n }\n\n await parallelize(canonicalEntryIds, async (entryId) => {\n // Rebuild a resolvable dictionary from the content node + composite id\n // so per-locale extraction sees the same `{ key, content }` shape.\n const entry = reconstructQualifiedEntry(group, entryId);\n\n const segments = entryId.split(COMPOSITE_ID_SEPARATOR);\n\n const entryDir = resolve(keyDir, ...segments);\n assertPathWithin(entryDir, keyDir);\n await mkdir(entryDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n entry,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/<…segments>/locale.json\n const resultFilePath = resolve(entryDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${segments.join('/')}/${locale}.json:`,\n err\n );\n }\n );\n });\n });\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateQualifiedDictionaryEntryPoint(\n key,\n group.qualifierTypes,\n entries,\n locales,\n format\n );\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n};\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_utils_parallelize = require('../utils/parallelize.cjs');
3
3
  const require_writeFileIfChanged = require('../writeFileIfChanged.cjs');
4
+ const require_utils_getPathHash = require('../utils/getPathHash.cjs');
4
5
  let node_fs_promises = require("node:fs/promises");
5
6
  let node_path = require("node:path");
6
7
  let _intlayer_config_logger = require("@intlayer/config/logger");
@@ -8,11 +9,47 @@ let _intlayer_config_utils = require("@intlayer/config/utils");
8
9
  let _intlayer_config_defaultValues = require("@intlayer/config/defaultValues");
9
10
 
10
11
  //#region src/buildIntlayerDictionary/writeFetchDictionary.ts
11
- const generateDictionaryEntryPoint = (key, locales, relativePrefix, format = "esm") => {
12
+ /**
13
+ * Local identifier of the dynamic loader backing a nest target's fallback.
14
+ * Hashed so any dictionary key yields a valid identifier.
15
+ */
16
+ const dynamicLoaderIdentifier = (key) => `_dyn${require_utils_getPathHash.getPathHash(key)}`;
17
+ /**
18
+ * Fetches one dictionary for a locale from the live-sync server, falling back
19
+ * to its own build-time dynamic chunk when the request fails.
20
+ *
21
+ * `fallbackLoader` must be the loader of `key` itself — a nest target falling
22
+ * back to its consumer's chunk would attach the wrong content.
23
+ */
24
+ const buildLiveFetchExpression = (key, locale, fallbackLoader) => `(async () => {
25
+ try {
26
+ const res = await fetch(\`\${editor.liveSyncURL}/dictionaries/${key}/${locale}\`);\n return await res.json();\n } catch {\n return ${fallbackLoader}['${locale}']();\n }\n })()`;
27
+ /**
28
+ * Generates the live (fetch-mode) entry point of a dictionary.
29
+ *
30
+ * When the dictionary references others through `nest()`, those are fetched
31
+ * live alongside it and attached as `nestedDictionaries`, so a remote edit to a
32
+ * nested dictionary propagates through the reference instead of resolving
33
+ * against the build-time snapshot.
34
+ *
35
+ * @param key - The dictionary key.
36
+ * @param locales - Locales to emit a loader for.
37
+ * @param relativePrefix - Relative path to the dynamic dictionaries directory.
38
+ * @param format - Output module format.
39
+ * @param nestedKeys - Keys referenced through `nest()`, transitively.
40
+ */
41
+ const generateDictionaryEntryPoint = (key, locales, relativePrefix, format = "esm", nestedKeys = []) => {
12
42
  const extension = format === "cjs" ? "cjs" : "mjs";
13
- const localeEntries = locales.sort((a, b) => String(a).localeCompare(String(b))).map((locale) => ` '${locale}': async () => {\n try {\n const res = await fetch(\`\${editor.liveSyncURL}/dictionaries/${key}/${locale}\`);\n return await res.json();\n } catch {\n return dynContent['${locale}']();\n }\n }`).join(",\n");
14
- if (format === "esm") return `import { editor } from 'intlayer';\nimport dynContent from '${relativePrefix}/${key}.${extension}';\n\nconst content = {\n${localeEntries}\n};\n\nexport default content;\n`;
15
- return `const { editor } = require('intlayer');\nconst dynContent = require('${relativePrefix}/${key}.${extension}');\n\nmodule.exports = {\n${localeEntries}\n};\n`;
43
+ const sortedNestedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));
44
+ const localeEntries = locales.sort((a, b) => String(a).localeCompare(String(b))).map((locale) => {
45
+ if (sortedNestedKeys.length === 0) return ` '${locale}': async () => {\n try {\n const res = await fetch(\`\${editor.liveSyncURL}/dictionaries/${key}/${locale}\`);\n return await res.json();\n } catch {\n return dynContent['${locale}']();\n }\n }`;
46
+ const nestedFetches = sortedNestedKeys.map((nestedKey) => buildLiveFetchExpression(nestedKey, locale, dynamicLoaderIdentifier(nestedKey))).join(",\n ");
47
+ const attachedEntries = sortedNestedKeys.map((nestedKey, index) => `'${nestedKey}': _nested[${index}]`).join(", ");
48
+ return ` '${locale}': async () => {\n const [_dictionary, ..._nested] = await Promise.all([\n ${buildLiveFetchExpression(key, locale, "dynContent")},\n ${nestedFetches}\n ]);\n return { ..._dictionary, nestedDictionaries: { ${attachedEntries} } };\n }`;
49
+ }).join(",\n");
50
+ const nestedImports = sortedNestedKeys.map((nestedKey) => format === "esm" ? `import ${dynamicLoaderIdentifier(nestedKey)} from '${relativePrefix}/${nestedKey}.${extension}';` : `const ${dynamicLoaderIdentifier(nestedKey)} = require('${relativePrefix}/${nestedKey}.${extension}');`).join("\n");
51
+ if (format === "esm") return `import { editor } from 'intlayer';\nimport dynContent from '${relativePrefix}/${key}.${extension}';\n${nestedImports}\n\nconst content = {\n${localeEntries}\n};\n\nexport default content;\n`;
52
+ return `const { editor } = require('intlayer');\nconst dynContent = require('${relativePrefix}/${key}.${extension}');\n${nestedImports}\n\nmodule.exports = {\n${localeEntries}\n};\n`;
16
53
  };
17
54
  /**
18
55
  * Write the localized dictionaries to the dictionariesDir
@@ -30,7 +67,7 @@ const generateDictionaryEntryPoint = (key, locales, relativePrefix, format = "es
30
67
  * // .intlayer/fetch_dictionary/home.cjs
31
68
  * ```
32
69
  */
33
- const writeFetchDictionary = async (dynamicDictionaries, configuration, formats = _intlayer_config_defaultValues.OUTPUT_FORMAT) => {
70
+ const writeFetchDictionary = async (dynamicDictionaries, configuration, formats = _intlayer_config_defaultValues.OUTPUT_FORMAT, nestedDictionaryGraph = /* @__PURE__ */ new Map()) => {
34
71
  const { fetchDictionariesDir, dynamicDictionariesDir } = configuration.system;
35
72
  const { locales } = configuration.internationalization;
36
73
  let relativePrefix = (0, _intlayer_config_utils.normalizePath)((0, node_path.relative)(fetchDictionariesDir, dynamicDictionariesDir));
@@ -41,7 +78,7 @@ const writeFetchDictionary = async (dynamicDictionaries, configuration, formats
41
78
  if (key === "undefined") return;
42
79
  await require_utils_parallelize.parallelize(formats, async (format) => {
43
80
  const extension = format === "cjs" ? "cjs" : "mjs";
44
- const content = generateDictionaryEntryPoint(key, locales, relativePrefix, format);
81
+ const content = generateDictionaryEntryPoint(key, locales, relativePrefix, format, [...nestedDictionaryGraph.get(key) ?? []]);
45
82
  const fetchEntryPath = (0, node_path.resolve)(fetchDictionariesDir, `${key}.${extension}`);
46
83
  (0, _intlayer_config_utils.assertPathWithin)(fetchEntryPath, fetchDictionariesDir);
47
84
  await require_writeFileIfChanged.writeFileIfChanged(fetchEntryPath, content).catch((err) => {
@@ -1 +1 @@
1
- {"version":3,"file":"writeFetchDictionary.cjs","names":["OUTPUT_FORMAT","parallelize","writeFileIfChanged"],"sources":["../../../src/buildIntlayerDictionary/writeFetchDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin, normalizePath } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport type { LocalizedDictionaryOutput } from './writeDynamicDictionary';\n\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n relativePrefix: string,\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n\n const localeEntries = locales\n .sort((a, b) => String(a).localeCompare(String(b)))\n .map(\n (locale) =>\n ` '${locale}': async () => {\\n` +\n ` try {\\n` +\n ` const res = await fetch(\\`\\${editor.liveSyncURL}/dictionaries/${key}/${locale}\\`);\\n` +\n ` return await res.json();\\n` +\n ` } catch {\\n` +\n ` return dynContent['${locale}']();\\n` +\n ` }\\n` +\n ` }`\n )\n .join(',\\n');\n\n if (format === 'esm') {\n return (\n `import { editor } from 'intlayer';\\n` +\n `import dynContent from '${relativePrefix}/${key}.${extension}';\\n\\n` +\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return (\n `const { editor } = require('intlayer');\\n` +\n `const dynContent = require('${relativePrefix}/${key}.${extension}');\\n\\n` +\n `module.exports = {\\n${localeEntries}\\n};\\n`\n );\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/fetch_dictionary/home.mjs\n * // .intlayer/fetch_dictionary/home.cjs\n * ```\n */\nexport const writeFetchDictionary = async (\n dynamicDictionaries: LocalizedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<LocalizedDictionaryOutput> => {\n const { fetchDictionariesDir, dynamicDictionariesDir } = configuration.system;\n const { locales } = configuration.internationalization;\n\n // Compute relative path from fetch dir to dynamic dir\n let relativePrefix = normalizePath(\n relative(fetchDictionariesDir, dynamicDictionariesDir)\n );\n if (!relativePrefix.startsWith('.')) {\n relativePrefix = `./${relativePrefix}`;\n }\n\n await mkdir(resolve(fetchDictionariesDir), { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Write entry points for each dictionary in parallel\n await parallelize(Object.entries(dynamicDictionaries), async ([key]) => {\n if (key === 'undefined') return;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(\n key,\n locales,\n relativePrefix,\n format\n );\n\n const fetchEntryPath = resolve(\n fetchDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(fetchEntryPath, fetchDictionariesDir);\n\n await writeFileIfChanged(fetchEntryPath, content).catch((err) => {\n console.error(\n `Error creating fetch ${colorizePath(fetchEntryPath)}:`,\n err\n );\n });\n });\n });\n\n return resultDictionariesPaths;\n};\n"],"mappings":";;;;;;;;;;AAUA,MAAa,gCACX,KACA,SACA,gBACA,SAAwB,UACb;CACX,MAAM,YAAY,WAAW,QAAQ,QAAQ;CAE7C,MAAM,gBAAgB,QACnB,MAAM,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,cAAc,OAAO,CAAC,CAAC,CAAC,CAAC,CAClD,KACE,WACC,MAAM,OAAO,mGAE0D,IAAI,GAAG,OAAO,gFAGzD,OAAO,kBAGvC,CAAC,CACA,KAAK,KAAK;CAEb,IAAI,WAAW,OACb,OACE,+DAC2B,eAAe,GAAG,IAAI,GAAG,UAAU,2BACxC,cAAc;CAIxC,OACE,wEAC+B,eAAe,GAAG,IAAI,GAAG,UAAU,6BAC3C,cAAc;AAEzC;;;;;;;;;;;;;;;;;AAkBA,MAAa,uBAAuB,OAClC,qBACA,eACA,UAA6BA,iDACU;CACvC,MAAM,EAAE,sBAAsB,2BAA2B,cAAc;CACvE,MAAM,EAAE,YAAY,cAAc;CAGlC,IAAI,mFACO,sBAAsB,sBAAsB,CACvD;CACA,IAAI,CAAC,eAAe,WAAW,GAAG,GAChC,iBAAiB,KAAK;CAGxB,yDAAoB,oBAAoB,GAAG,EAAE,WAAW,KAAK,CAAC;CAE9D,MAAM,0BAAqD,CAAC;CAG5D,MAAMC,sCAAY,OAAO,QAAQ,mBAAmB,GAAG,OAAO,CAAC,SAAS;EACtE,IAAI,QAAQ,aAAa;EAEzB,MAAMA,sCAAY,SAAS,OAAO,WAAW;GAC3C,MAAM,YAAY,WAAW,QAAQ,QAAQ;GAC7C,MAAM,UAAU,6BACd,KACA,SACA,gBACA,MACF;GAEA,MAAM,wCACJ,sBACA,GAAG,IAAI,GAAG,WACZ;GACA,6CAAiB,gBAAgB,oBAAoB;GAErD,MAAMC,8CAAmB,gBAAgB,OAAO,CAAC,CAAC,OAAO,QAAQ;IAC/D,QAAQ,MACN,kEAAqC,cAAc,EAAE,IACrD,GACF;GACF,CAAC;EACH,CAAC;CACH,CAAC;CAED,OAAO;AACT"}
1
+ {"version":3,"file":"writeFetchDictionary.cjs","names":["getPathHash","OUTPUT_FORMAT","normalizePath","relative","mkdir","resolve","parallelize","writeFileIfChanged","colorizePath"],"sources":["../../../src/buildIntlayerDictionary/writeFetchDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin, normalizePath } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { getPathHash } from '../utils/getPathHash';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport type { LocalizedDictionaryOutput } from './writeDynamicDictionary';\n\n/**\n * Local identifier of the dynamic loader backing a nest target's fallback.\n * Hashed so any dictionary key yields a valid identifier.\n */\nconst dynamicLoaderIdentifier = (key: string): string =>\n `_dyn${getPathHash(key)}`;\n\n/**\n * Fetches one dictionary for a locale from the live-sync server, falling back\n * to its own build-time dynamic chunk when the request fails.\n *\n * `fallbackLoader` must be the loader of `key` itself — a nest target falling\n * back to its consumer's chunk would attach the wrong content.\n */\nconst buildLiveFetchExpression = (\n key: string,\n locale: string,\n fallbackLoader: string\n): string =>\n `(async () => {\\n` +\n ` try {\\n` +\n ` const res = await fetch(\\`\\${editor.liveSyncURL}/dictionaries/${key}/${locale}\\`);\\n` +\n ` return await res.json();\\n` +\n ` } catch {\\n` +\n ` return ${fallbackLoader}['${locale}']();\\n` +\n ` }\\n` +\n ` })()`;\n\n/**\n * Generates the live (fetch-mode) entry point of a dictionary.\n *\n * When the dictionary references others through `nest()`, those are fetched\n * live alongside it and attached as `nestedDictionaries`, so a remote edit to a\n * nested dictionary propagates through the reference instead of resolving\n * against the build-time snapshot.\n *\n * @param key - The dictionary key.\n * @param locales - Locales to emit a loader for.\n * @param relativePrefix - Relative path to the dynamic dictionaries directory.\n * @param format - Output module format.\n * @param nestedKeys - Keys referenced through `nest()`, transitively.\n */\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n relativePrefix: string,\n format: 'cjs' | 'esm' = 'esm',\n nestedKeys: string[] = []\n): string => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const sortedNestedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));\n\n const localeEntries = locales\n .sort((a, b) => String(a).localeCompare(String(b)))\n .map((locale) => {\n if (sortedNestedKeys.length === 0) {\n return (\n ` '${locale}': async () => {\\n` +\n ` try {\\n` +\n ` const res = await fetch(\\`\\${editor.liveSyncURL}/dictionaries/${key}/${locale}\\`);\\n` +\n ` return await res.json();\\n` +\n ` } catch {\\n` +\n ` return dynContent['${locale}']();\\n` +\n ` }\\n` +\n ` }`\n );\n }\n\n const nestedFetches = sortedNestedKeys\n .map((nestedKey) =>\n buildLiveFetchExpression(\n nestedKey,\n locale,\n dynamicLoaderIdentifier(nestedKey)\n )\n )\n .join(',\\n ');\n\n const attachedEntries = sortedNestedKeys\n .map((nestedKey, index) => `'${nestedKey}': _nested[${index}]`)\n .join(', ');\n\n return (\n ` '${locale}': async () => {\\n` +\n ` const [_dictionary, ..._nested] = await Promise.all([\\n` +\n ` ${buildLiveFetchExpression(key, locale, 'dynContent')},\\n` +\n ` ${nestedFetches}\\n` +\n ` ]);\\n` +\n ` return { ..._dictionary, nestedDictionaries: { ${attachedEntries} } };\\n` +\n ` }`\n );\n })\n .join(',\\n');\n\n // Each nest target falls back to its own dynamic chunk when the live request\n // fails, so a failure never attaches the consumer's content under its key.\n const nestedImports = sortedNestedKeys\n .map((nestedKey) =>\n format === 'esm'\n ? `import ${dynamicLoaderIdentifier(nestedKey)} from '${relativePrefix}/${nestedKey}.${extension}';`\n : `const ${dynamicLoaderIdentifier(nestedKey)} = require('${relativePrefix}/${nestedKey}.${extension}');`\n )\n .join('\\n');\n\n if (format === 'esm') {\n return (\n `import { editor } from 'intlayer';\\n` +\n `import dynContent from '${relativePrefix}/${key}.${extension}';\\n` +\n `${nestedImports}\\n\\n` +\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return (\n `const { editor } = require('intlayer');\\n` +\n `const dynContent = require('${relativePrefix}/${key}.${extension}');\\n` +\n `${nestedImports}\\n\\n` +\n `module.exports = {\\n${localeEntries}\\n};\\n`\n );\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/fetch_dictionary/home.mjs\n * // .intlayer/fetch_dictionary/home.cjs\n * ```\n */\nexport const writeFetchDictionary = async (\n dynamicDictionaries: LocalizedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT,\n nestedDictionaryGraph: Map<string, Set<string>> = new Map()\n): Promise<LocalizedDictionaryOutput> => {\n const { fetchDictionariesDir, dynamicDictionariesDir } = configuration.system;\n const { locales } = configuration.internationalization;\n\n // Compute relative path from fetch dir to dynamic dir\n let relativePrefix = normalizePath(\n relative(fetchDictionariesDir, dynamicDictionariesDir)\n );\n if (!relativePrefix.startsWith('.')) {\n relativePrefix = `./${relativePrefix}`;\n }\n\n await mkdir(resolve(fetchDictionariesDir), { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Write entry points for each dictionary in parallel\n await parallelize(Object.entries(dynamicDictionaries), async ([key]) => {\n if (key === 'undefined') return;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(\n key,\n locales,\n relativePrefix,\n format,\n [...(nestedDictionaryGraph.get(key) ?? [])]\n );\n\n const fetchEntryPath = resolve(\n fetchDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(fetchEntryPath, fetchDictionariesDir);\n\n await writeFileIfChanged(fetchEntryPath, content).catch((err) => {\n console.error(\n `Error creating fetch ${colorizePath(fetchEntryPath)}:`,\n err\n );\n });\n });\n });\n\n return resultDictionariesPaths;\n};\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAM,2BAA2B,QAC/B,OAAOA,sCAAY,GAAG;;;;;;;;AASxB,MAAM,4BACJ,KACA,QACA,mBAEA;;wEAEyE,IAAI,GAAG,OAAO,0EAGrE,eAAe,IAAI,OAAO;;;;;;;;;;;;;;;AAkB9C,MAAa,gCACX,KACA,SACA,gBACA,SAAwB,OACxB,aAAuB,CAAC,MACb;CACX,MAAM,YAAY,WAAW,QAAQ,QAAQ;CAC7C,MAAM,mBAAmB,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;CAE1E,MAAM,gBAAgB,QACnB,MAAM,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,cAAc,OAAO,CAAC,CAAC,CAAC,CAAC,CAClD,KAAK,WAAW;EACf,IAAI,iBAAiB,WAAW,GAC9B,OACE,MAAM,OAAO,mGAE0D,IAAI,GAAG,OAAO,gFAGzD,OAAO;EAMvC,MAAM,gBAAgB,iBACnB,KAAK,cACJ,yBACE,WACA,QACA,wBAAwB,SAAS,CACnC,CACF,CAAC,CACA,KAAK,SAAS;EAEjB,MAAM,kBAAkB,iBACrB,KAAK,WAAW,UAAU,IAAI,UAAU,aAAa,MAAM,EAAE,CAAC,CAC9D,KAAK,IAAI;EAEZ,OACE,MAAM,OAAO,mFAEN,yBAAyB,KAAK,QAAQ,YAAY,EAAE,SACpD,cAAc,gEAEiC,gBAAgB;CAG1E,CAAC,CAAC,CACD,KAAK,KAAK;CAIb,MAAM,gBAAgB,iBACnB,KAAK,cACJ,WAAW,QACP,UAAU,wBAAwB,SAAS,EAAE,SAAS,eAAe,GAAG,UAAU,GAAG,UAAU,MAC/F,SAAS,wBAAwB,SAAS,EAAE,cAAc,eAAe,GAAG,UAAU,GAAG,UAAU,IACzG,CAAC,CACA,KAAK,IAAI;CAEZ,IAAI,WAAW,OACb,OACE,+DAC2B,eAAe,GAAG,IAAI,GAAG,UAAU,MAC3D,cAAc,yBACK,cAAc;CAIxC,OACE,wEAC+B,eAAe,GAAG,IAAI,GAAG,UAAU,OAC/D,cAAc,0BACM,cAAc;AAEzC;;;;;;;;;;;;;;;;;AAkBA,MAAa,uBAAuB,OAClC,qBACA,eACA,UAA6BC,8CAC7B,wCAAkD,IAAI,IAAI,MACnB;CACvC,MAAM,EAAE,sBAAsB,2BAA2B,cAAc;CACvE,MAAM,EAAE,YAAY,cAAc;CAGlC,IAAI,qBAAiBC,0CACnBC,oBAAS,sBAAsB,sBAAsB,CACvD;CACA,IAAI,CAAC,eAAe,WAAW,GAAG,GAChC,iBAAiB,KAAK;CAGxB,UAAMC,4BAAMC,mBAAQ,oBAAoB,GAAG,EAAE,WAAW,KAAK,CAAC;CAE9D,MAAM,0BAAqD,CAAC;CAG5D,MAAMC,sCAAY,OAAO,QAAQ,mBAAmB,GAAG,OAAO,CAAC,SAAS;EACtE,IAAI,QAAQ,aAAa;EAEzB,MAAMA,sCAAY,SAAS,OAAO,WAAW;GAC3C,MAAM,YAAY,WAAW,QAAQ,QAAQ;GAC7C,MAAM,UAAU,6BACd,KACA,SACA,gBACA,QACA,CAAC,GAAI,sBAAsB,IAAI,GAAG,KAAK,CAAC,CAAE,CAC5C;GAEA,MAAM,qBAAiBD,mBACrB,sBACA,GAAG,IAAI,GAAG,WACZ;GACA,6CAAiB,gBAAgB,oBAAoB;GAErD,MAAME,8CAAmB,gBAAgB,OAAO,CAAC,CAAC,OAAO,QAAQ;IAC/D,QAAQ,MACN,4BAAwBC,sCAAa,cAAc,EAAE,IACrD,GACF;GACF,CAAC;EACH,CAAC;CACH,CAAC;CAED,OAAO;AACT"}
@@ -29,7 +29,8 @@ const writeMergedDictionaries = async (groupedDictionaries, configuration) => {
29
29
  await (0, node_fs_promises.mkdir)((0, node_path.resolve)(dictionariesDir), { recursive: true });
30
30
  const results = await require_utils_parallelize.parallelize(Object.entries(groupedDictionaries), async ([key, dictionariesEntry]) => {
31
31
  if (key === "undefined") return;
32
- const mergedDictionary = (0, _intlayer_core_dictionaryManipulator.mergeQualifiedDictionaries)((0, _intlayer_core_dictionaryManipulator.normalizeDictionaries)(dictionariesEntry.dictionaries, configuration));
32
+ const normalizedDictionaries = (0, _intlayer_core_dictionaryManipulator.normalizeDictionaries)(dictionariesEntry.dictionaries, configuration);
33
+ const mergedDictionary = (0, _intlayer_core_dictionaryManipulator.mergeQualifiedDictionaries)(normalizedDictionaries);
33
34
  const outputFileName = `${key}.json`;
34
35
  const resultFilePath = (0, node_path.resolve)(dictionariesDir, outputFileName);
35
36
  (0, _intlayer_config_utils.assertPathWithin)(resultFilePath, dictionariesDir);