@zohodesk/react-cli 1.1.29-exp.1 → 1.1.29-exp.2

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 (221) hide show
  1. package/lib/babel/babel-option-utils/babel-preset-react-option.js +0 -3
  2. package/lib/babel/cmjs-plugins-presets.js +1 -8
  3. package/lib/babel/es-plugins-presets.js +1 -8
  4. package/lib/common/buildEs.js +1 -0
  5. package/lib/common/getEntries.js +2 -13
  6. package/lib/common/getPublicPathConfig.js +0 -6
  7. package/lib/common/index.js +1 -6
  8. package/lib/common/runPreProcess.js +6 -15
  9. package/lib/common/splitChunks.js +2 -21
  10. package/lib/common/sslcertUpdater.js +7 -18
  11. package/lib/common/templateParameters.js +0 -2
  12. package/lib/common/testPattern.js +10 -21
  13. package/lib/common/valueReplacer.js +1 -16
  14. package/lib/configs/jest.config.js +1 -10
  15. package/lib/configs/libAlias.js +8 -14
  16. package/lib/configs/resolvers.js +4 -14
  17. package/lib/configs/webpack.component.umd.config.js +1 -6
  18. package/lib/configs/webpack.css.umd.config.js +6 -14
  19. package/lib/configs/webpack.dev.config.js +1 -14
  20. package/lib/configs/webpack.docs.config.js +1 -9
  21. package/lib/configs/webpack.impact.config.js +1 -8
  22. package/lib/configs/webpack.prod.config.js +4 -17
  23. package/lib/constants.js +9 -18
  24. package/lib/deprecationLogger.js +0 -7
  25. package/lib/hooks/docsProptypeHook.js +4 -8
  26. package/lib/jest/commitedFilesResult.js +4 -46
  27. package/lib/jest/coverageCollector.js +1 -12
  28. package/lib/jest/jsonMaker.js +0 -6
  29. package/lib/jest/preProcessors/cssPreprocessor.js +1 -9
  30. package/lib/jest/preProcessors/jsPreprocessor.js +1 -6
  31. package/lib/jest/preProcessors/otherFilesPreprocessor.js +1 -4
  32. package/lib/jest/result.js +1 -23
  33. package/lib/jest/run.js +7 -18
  34. package/lib/jest/setup.js +8 -60
  35. package/lib/loaderUtils/configsAssetsLoaders.js +2 -12
  36. package/lib/loaderUtils/getCSSLoaders.js +10 -22
  37. package/lib/loaderUtils/getDevJsLoaders.js +4 -13
  38. package/lib/loaderUtils/index.js +1 -4
  39. package/lib/loaderUtils/tests/windowsModification.test.js +0 -1
  40. package/lib/loaderUtils/windowsModification.js +2 -3
  41. package/lib/loaders/__test__/markdownLoader.spec.js +0 -1
  42. package/lib/loaders/composeLoader.js +13 -37
  43. package/lib/loaders/docsLoader.js +1 -12
  44. package/lib/loaders/docsPropsLoader.js +4 -8
  45. package/lib/loaders/enhancedReactLiveConverter.js +2 -23
  46. package/lib/loaders/fileBountryLoader.js +1 -3
  47. package/lib/loaders/fileLoader.js +12 -23
  48. package/lib/loaders/markdownLoader.js +14 -19
  49. package/lib/loaders/reactLiveConvertor.js +5 -15
  50. package/lib/loaders/scriptInstrumentLoader.js +7 -16
  51. package/lib/loaders/selectorMappingLoader.js +7 -26
  52. package/lib/loaders/workerLoader.js +9 -24
  53. package/lib/logger.js +0 -4
  54. package/lib/middlewares/HMRMiddleware.js +13 -27
  55. package/lib/middlewares/SSTMiddleware.js +1 -5
  56. package/lib/pluginUtils/configHtmlWebpackPlugins.js +1 -24
  57. package/lib/pluginUtils/getDevPlugins.js +9 -42
  58. package/lib/pluginUtils/getDocsPlugins.js +3 -13
  59. package/lib/pluginUtils/getLibraryImactPlugins.js +5 -6
  60. package/lib/pluginUtils/getLibraryPlugins.js +2 -8
  61. package/lib/pluginUtils/getProdPlugins.js +8 -47
  62. package/lib/pluginUtils/getServerPlugins.js +2 -8
  63. package/lib/pluginUtils/getUMDCSSPlugins.js +2 -10
  64. package/lib/pluginUtils/getUMDComponentPlugins.js +2 -10
  65. package/lib/pluginUtils/index.js +1 -9
  66. package/lib/plugins/CdnChangePlugin.js +2 -18
  67. package/lib/plugins/CleanupStatsPlugin.js +0 -5
  68. package/lib/plugins/CssOrderControlPlugin.js +3 -6
  69. package/lib/plugins/CustomAttributePlugin.js +14 -19
  70. package/lib/plugins/CustomScriptLoadingStrategyPlugin.js +3 -23
  71. package/lib/plugins/EFCPlugin.js +20 -34
  72. package/lib/plugins/EFCTemplatePlugin.js +19 -30
  73. package/lib/plugins/EfcResourceCleanupPlugin.js +0 -3
  74. package/lib/plugins/EventsHandlingPlugin.js +2 -4
  75. package/lib/plugins/I18NInjectIntoIndexPlugin.js +11 -37
  76. package/lib/plugins/I18nSplitPlugin/I18nDebugPlugin.js +10 -15
  77. package/lib/plugins/I18nSplitPlugin/I18nDependency.js +4 -10
  78. package/lib/plugins/I18nSplitPlugin/I18nDownlodLogic.js +12 -25
  79. package/lib/plugins/I18nSplitPlugin/I18nFilesEmitter.js +55 -133
  80. package/lib/plugins/I18nSplitPlugin/I18nKeysIdentifer.js +12 -23
  81. package/lib/plugins/I18nSplitPlugin/index.js +13 -24
  82. package/lib/plugins/I18nSplitPlugin/utils/applyMetaManifest.js +64 -58
  83. package/lib/plugins/I18nSplitPlugin/utils/collectI18nKeys.js +2 -12
  84. package/lib/plugins/I18nSplitPlugin/utils/createMetaManifest.js +10 -29
  85. package/lib/plugins/I18nSplitPlugin/utils/createRegularManifest.js +8 -19
  86. package/lib/plugins/I18nSplitPlugin/utils/getI18nFileUrlPathTemplate.js +0 -1
  87. package/lib/plugins/I18nSplitPlugin/utils/getI18nKeysFormModules.js +0 -5
  88. package/lib/plugins/I18nSplitPlugin/utils/hashUtils.js +1 -8
  89. package/lib/plugins/I18nSplitPlugin/utils/index.js +0 -4
  90. package/lib/plugins/I18nSplitPlugin/utils/propertiesUtils.js +0 -20
  91. package/lib/plugins/I18nSplitPlugin/utils/unicodeConversion.js +0 -1
  92. package/lib/plugins/ManifestPlugin.js +1 -18
  93. package/lib/plugins/MinifyPlugin.js +1 -10
  94. package/lib/plugins/ModuleStatsPlugin.js +1 -24
  95. package/lib/plugins/OptimizeJSPlugin.js +2 -10
  96. package/lib/plugins/PublicPathCallbackPlugin.js +1 -12
  97. package/lib/plugins/PublicPathChangePlugin.js +6 -39
  98. package/lib/plugins/ReportGeneratePlugin.js +5 -32
  99. package/lib/plugins/RequireVariablePublicPlugin.js +1 -8
  100. package/lib/plugins/ResourceHintsPlugin.js +4 -13
  101. package/lib/plugins/RtlSplitPlugin/OverwriteCssPathForRTL.js +12 -17
  102. package/lib/plugins/RtlSplitPlugin/RtlCssPlugin.js +10 -17
  103. package/lib/plugins/RtlSplitPlugin/replaceCssDirTemplate.js +2 -5
  104. package/lib/plugins/ScriptInstrumentPlugin.js +1 -8
  105. package/lib/plugins/SelectorPlugin.js +6 -32
  106. package/lib/plugins/ServiceWorkerPlugin.js +5 -22
  107. package/lib/plugins/ShadowDOMSupportPlugin.js +4 -41
  108. package/lib/plugins/SourceMapHookPlugin.js +2 -12
  109. package/lib/plugins/StatsPlugin.js +0 -14
  110. package/lib/plugins/TPHashMappingPlugin.js +3 -18
  111. package/lib/plugins/UnusedFilesFindPlugin.js +4 -39
  112. package/lib/plugins/VariableConversionCollector.js +15 -42
  113. package/lib/plugins/index.js +1 -20
  114. package/lib/plugins/libraryImpactPlugin.js +1 -33
  115. package/lib/plugins/newi18nsplitplugin/18nPlugin1.js +306 -0
  116. package/lib/plugins/newi18nsplitplugin/18nPlugin2.js +363 -0
  117. package/lib/plugins/newi18nsplitplugin/18nPlugin3.js +694 -0
  118. package/lib/plugins/newi18nsplitplugin/18nPlugin_hashed.js +1258 -0
  119. package/lib/plugins/newi18nsplitplugin/18nPlugin_working.js +542 -0
  120. package/lib/plugins/newi18nsplitplugin/18nplugin.js +974 -0
  121. package/lib/plugins/newi18nsplitplugin/ChunkManager.js +131 -0
  122. package/lib/plugins/newi18nsplitplugin/GenerateModuleIdToKeysMapPlugin.js +59 -0
  123. package/lib/plugins/newi18nsplitplugin/I18nDiffPlugin.js +262 -0
  124. package/lib/plugins/newi18nsplitplugin/I18nDownloadLogic.js +166 -0
  125. package/lib/plugins/newi18nsplitplugin/I18nPropertiesPlugin.js +111 -0
  126. package/lib/plugins/newi18nsplitplugin/KeyCollector.js +163 -0
  127. package/lib/plugins/newi18nsplitplugin/ManifestGenerator.js +88 -0
  128. package/lib/plugins/newi18nsplitplugin/UnicodeConversionPlugin.js +101 -0
  129. package/lib/plugins/newi18nsplitplugin/constants.js +162 -0
  130. package/lib/plugins/newi18nsplitplugin/utils/I18nKeyHasher.js +78 -0
  131. package/lib/plugins/newi18nsplitplugin/utils/getJsResourceKeys.js +22 -0
  132. package/lib/plugins/newi18nsplitplugin/utils/i18nChunkUtils.js +18 -0
  133. package/lib/plugins/newi18nsplitplugin/utils/manifestGenerator.js +580 -0
  134. package/lib/plugins/newi18nsplitplugin/utils/propertiesUtils.js +54 -0
  135. package/lib/plugins/utils/classHandling.js +0 -6
  136. package/lib/plugins/utils/fileHandling.js +6 -15
  137. package/lib/plugins/utils/tests/fileHandling.test.js +0 -4
  138. package/lib/plugins/variableConvertorUtils.js +14 -29
  139. package/lib/plugins/webpackwatchrunplugin.js +0 -5
  140. package/lib/postcss-plugins/EmptyPlugin.js +3 -4
  141. package/lib/postcss-plugins/ExcludePlugin.js +1 -5
  142. package/lib/postcss-plugins/IncludePlugin.js +1 -5
  143. package/lib/postcss-plugins/RTLSplitPlugin.js +14 -27
  144. package/lib/postcss-plugins/SelectorReplace.js +1 -16
  145. package/lib/postcss-plugins/ValueReplacer.js +7 -6
  146. package/lib/postcss-plugins/__test__/hoverActivePlugin.spec.js +0 -3
  147. package/lib/postcss-plugins/__test__/selectorReplace.test.js +6 -3
  148. package/lib/postcss-plugins/__test__/valueReplacer.spec.js +2 -5
  149. package/lib/postcss-plugins/hoverActivePlugin.js +31 -67
  150. package/lib/postcss-plugins/variableModificationPlugin/ErrorHandler.js +0 -7
  151. package/lib/postcss-plugins/variableModificationPlugin/index.js +28 -49
  152. package/lib/schemas/index.js +3 -9
  153. package/lib/servers/clusterHubServer.js +1 -11
  154. package/lib/servers/devBuild.js +14 -26
  155. package/lib/servers/docsServer.js +1 -3
  156. package/lib/servers/docsServerCore.js +1 -22
  157. package/lib/servers/getCliPath.js +0 -9
  158. package/lib/servers/helpServer.js +1 -6
  159. package/lib/servers/httpsOptions.js +2 -8
  160. package/lib/servers/impactServer.js +3 -35
  161. package/lib/servers/mockserver.js +1 -10
  162. package/lib/servers/nowatchserver.js +12 -37
  163. package/lib/servers/requireLocalOrGlobal.js +6 -17
  164. package/lib/servers/scrServer.js +14 -21
  165. package/lib/servers/server.js +6 -36
  166. package/lib/servers/ssServer.js +1 -17
  167. package/lib/templates/CoverageScriptTemplate.js +0 -14
  168. package/lib/templates/WMSTemplate.js +7 -13
  169. package/lib/templates/linterConstant.js +2 -4
  170. package/lib/utils/babelPresets.js +3 -7
  171. package/lib/utils/clean.js +3 -9
  172. package/lib/utils/copy.js +1 -7
  173. package/lib/utils/copyTimezones.js +1 -9
  174. package/lib/utils/createEventStream.js +1 -6
  175. package/lib/utils/cssClassNameGenerate.js +10 -30
  176. package/lib/utils/cssURLReplacer.js +1 -22
  177. package/lib/utils/dependencyPostPublish.js +1 -10
  178. package/lib/utils/deprecationSupport.js +7 -32
  179. package/lib/utils/fileUtils.js +1 -28
  180. package/lib/utils/folderIterator.js +2 -13
  181. package/lib/utils/getComponents.js +0 -21
  182. package/lib/utils/getCurrentBranch.js +0 -5
  183. package/lib/utils/getDependenciesImpactList.js +1 -22
  184. package/lib/utils/getFileType.js +2 -10
  185. package/lib/utils/getHash.js +1 -8
  186. package/lib/utils/getIp.js +0 -2
  187. package/lib/utils/getOptions.js +16 -53
  188. package/lib/utils/getServerURL.js +1 -10
  189. package/lib/utils/index.js +4 -51
  190. package/lib/utils/init.js +0 -1
  191. package/lib/utils/initPreCommitHook.js +7 -30
  192. package/lib/utils/jsonHelper.js +3 -22
  193. package/lib/utils/libraryImpactConfig.js +2 -5
  194. package/lib/utils/lint/addScripts.js +2 -5
  195. package/lib/utils/lint/checkExistingConfig.js +3 -12
  196. package/lib/utils/lint/copyConfigs.js +0 -3
  197. package/lib/utils/lint/index.js +0 -9
  198. package/lib/utils/lint/lintScripts.js +0 -1
  199. package/lib/utils/lint/lintSetup.js +3 -4
  200. package/lib/utils/lint/lintStagedPreCommitHook.js +0 -1
  201. package/lib/utils/lint/question.js +0 -7
  202. package/lib/utils/lintReporter.js +0 -20
  203. package/lib/utils/log.js +0 -1
  204. package/lib/utils/mailSender.js +1 -8
  205. package/lib/utils/object-manipulation.js +1 -17
  206. package/lib/utils/pullOrigin.js +0 -4
  207. package/lib/utils/reinstallDependencies.js +1 -29
  208. package/lib/utils/removeAttributes.js +1 -8
  209. package/lib/utils/repoClone.js +3 -28
  210. package/lib/utils/request.js +0 -12
  211. package/lib/utils/rtl.js +5 -17
  212. package/lib/utils/selectorReplacer.js +10 -16
  213. package/lib/utils/setEnvVariables.js +0 -2
  214. package/lib/utils/ssTestHack.js +1 -11
  215. package/lib/utils/switchBranch.js +0 -5
  216. package/lib/utils/typeCheck.js +0 -1
  217. package/lib/utils/urlConcat.js +0 -4
  218. package/lib/utils/useExitCleanup.js +9 -10
  219. package/lib/utils/variableConverter.js +22 -31
  220. package/{npm-shrinkwrap.json → package-lock.json} +2098 -1999
  221. package/package.json +1 -1
@@ -0,0 +1,1258 @@
1
+ "use strict";
2
+
3
+ // // const { getAllI18nGroupedBySection, getPropertiesAsJSON } = require('../I18nSplitPlugin/utils/propertiesUtils');
4
+ // // const { collectI18nKeysfromAST, collectI18nKeysfromComments } = require('../I18nSplitPlugin/utils/collectI18nKeys');
5
+ // // const NullFactory = require('webpack/lib/NullFactory');
6
+ // // const { I18nDependency, I18nDependencyTemplate } = require('../I18nSplitPlugin/I18nDependency');
7
+ // // const { RawSource } = require('webpack-sources');
8
+ // // const crypto = require('crypto');
9
+ // // const escodegen = require('escodegen');
10
+ // // const pluginName = 'I18nPlugin';
11
+ // // const esprima = require('esprima');
12
+ // // class I18nPlugin {
13
+ // // constructor(options = {}) {
14
+ // // const { jsResourcePath, mainChunkName, propertiesFolder, disableDefault, jsResource } = options;
15
+ // // if (!jsResourcePath) {
16
+ // // throw new Error('I18nPlugin: "jsResourcePath" option is required.');
17
+ // // }
18
+ // // if (!mainChunkName) {
19
+ // // throw new Error('I18nPlugin: "mainChunkName" option is required.');
20
+ // // }
21
+ // // this.jsResourcePath = jsResourcePath;
22
+ // // this.entryPointName = mainChunkName;
23
+ // // this.jsResourceI18nKeys = jsResource ? getPropertiesAsJSON(jsResource) : {};
24
+ // // // Use getAllI18nGroupedBySection to group keys by sections
25
+ // // this.allI18nKeys = getAllI18nGroupedBySection({
26
+ // // folderPath: propertiesFolder,
27
+ // // disableDefault,
28
+ // // jsResourceI18nKeys: this.jsResourceI18nKeys,
29
+ // // });
30
+ // // console.log('Locales found:', Object.keys(this.allI18nKeys));
31
+ // // // Build keyToSectionMap
32
+ // // this.keyToSectionMap = {};
33
+ // // const locales = Object.keys(this.allI18nKeys);
34
+ // // if (locales.length > 0) {
35
+ // // // Use the first locale to build keyToSectionMap
36
+ // // const firstLocale = locales[0];
37
+ // // const sections = this.allI18nKeys[firstLocale];
38
+ // // console.log(`Sections found in properties files: ${Object.keys(sections).join(', ')}`);
39
+ // // for (const sectionName of Object.keys(sections)) {
40
+ // // const keysInSection = sections[sectionName];
41
+ // // for (const key of Object.keys(keysInSection)) {
42
+ // // this.keyToSectionMap[key] = sectionName;
43
+ // // }
44
+ // // }
45
+ // // }
46
+ // // this.moduleToKeysMap = new Map();
47
+ // // this.keyToModulesMap = new Map();
48
+ // // this.keyToI18nChunkIdMap = {};
49
+ // // // Initialize keyToHashMap and getHash function
50
+ // // this.keyToHashMap = {};
51
+ // // this.getHash = (key) => {
52
+ // // if (!this.keyToHashMap[key]) {
53
+ // // const hash = crypto.createHash('md5').update(key).digest('hex').substring(0, 8);
54
+ // // this.keyToHashMap[key] = hash;
55
+ // // }
56
+ // // return this.keyToHashMap[key];
57
+ // // };
58
+ // // // Process allI18nKeys to replace keys with hashes
59
+ // // for (const locale of locales) {
60
+ // // const sections = this.allI18nKeys[locale];
61
+ // // for (const sectionName in sections) {
62
+ // // const section = sections[sectionName];
63
+ // // const newSection = {};
64
+ // // for (const key in section) {
65
+ // // const hash = this.getHash(key);
66
+ // // newSection[hash] = section[key];
67
+ // // }
68
+ // // sections[sectionName] = newSection;
69
+ // // }
70
+ // // }
71
+ // // }
72
+ // // defineI18nDependency(compilation) {
73
+ // // compilation.dependencyFactories.set(I18nDependency, new NullFactory());
74
+ // // compilation.dependencyTemplates.set(I18nDependency, new I18nDependencyTemplate());
75
+ // // }
76
+ // // apply(compiler) {
77
+ // // compiler.hooks.thisCompilation.tap(pluginName, (compilation, params) => {
78
+ // // this.defineI18nDependency(compilation);
79
+ // // // Handler for parser
80
+ // // const handler = parser => {
81
+ // // parser.hooks.program.tap(pluginName, (ast, comments) => {
82
+ // // const { module } = parser.state;
83
+ // // if (!(module && /\.jsx?$/.test(module.resource))) {
84
+ // // return;
85
+ // // }
86
+ // // // Collect and replace i18n keys
87
+ // // let i18nKeys = collectI18nKeysfromAST(ast, this.jsResourceI18nKeys, this.getHash);
88
+ // // // let commentKeys = collectI18nKeysfromComments(comments, this.jsResourceI18nKeys);
89
+ // // // i18nKeys = i18nKeys.concat(commentKeys);
90
+ // // if (i18nKeys.length) {
91
+ // // try {
92
+ // // const code = escodegen.generate(ast, { comment: true });
93
+ // // // Update the module's source code
94
+ // // module._source._value = code;
95
+ // // } catch (error) {
96
+ // // console.error(`Syntax error in generated code for module ${module.resource}:`, error);
97
+ // // }
98
+ // // // const code = escodegen.generate(ast, { comment: true });
99
+ // // // module._source._value = code;
100
+ // // // Store the hashed keys for this module
101
+ // // const hashedKeys = i18nKeys.map(key => this.getHash(key));
102
+ // // this.moduleToKeysMap.set(module.resource, hashedKeys);
103
+ // // // Map hashed keys to modules
104
+ // // for (const hash of hashedKeys) {
105
+ // // if (!this.keyToModulesMap.has(hash)) {
106
+ // // this.keyToModulesMap.set(hash, new Set());
107
+ // // }
108
+ // // this.keyToModulesMap.get(hash).add(module.resource);
109
+ // // }
110
+ // // }
111
+ // // });
112
+ // // };
113
+ // // const factory = params.normalModuleFactory;
114
+ // // factory.hooks.parser.for('javascript/auto').tap(pluginName, handler);
115
+ // // factory.hooks.parser.for('javascript/dynamic').tap(pluginName, handler);
116
+ // // compilation.hooks.afterOptimizeChunks.tap(pluginName, () => {
117
+ // // this.processCollectedKeys(compilation);
118
+ // // });
119
+ // // });
120
+ // // }
121
+ // // processCollectedKeys(compilation) {
122
+ // // // Map to store chunkId to required sections
123
+ // // this.chunkIdToSectionsMap = {};
124
+ // // this.moduleChunkIdToModulesMap = {};
125
+ // // // Map module resource to chunk IDs
126
+ // // this.moduleResourceToChunkIds = new Map();
127
+ // // // Collect modules for the entry point
128
+ // // const entryPointChunk = compilation.namedChunks.get(this.entryPointName);
129
+ // // const entryPointModules = new Set();
130
+ // // if (entryPointChunk) {
131
+ // // for (const module of entryPointChunk.getModules()) {
132
+ // // if (module.resource) {
133
+ // // entryPointModules.add(module.resource);
134
+ // // }
135
+ // // }
136
+ // // }
137
+ // // // Iterate over all chunks in the compilation
138
+ // // for (const chunk of compilation.chunks) {
139
+ // // const chunkId = chunk.name || chunk.id;
140
+ // // const chunkIdString = String(chunkId);
141
+ // // // Collect all modules in the chunk
142
+ // // const modules = chunk.getModules();
143
+ // // let requiredSections = new Set();
144
+ // // let moduleResources = [];
145
+ // // for (const module of modules) {
146
+ // // const moduleResource = module.resource;
147
+ // // if (moduleResource) {
148
+ // // moduleResources.push(moduleResource);
149
+ // // const keys = this.moduleToKeysMap.get(moduleResource);
150
+ // // if (keys) {
151
+ // // for (const key of keys) {
152
+ // // const section = this.keyToSectionMap[key];
153
+ // // if (section) {
154
+ // // requiredSections.add(section);
155
+ // // }
156
+ // // }
157
+ // // }
158
+ // // // Map module resource to chunk IDs
159
+ // // if (!this.moduleResourceToChunkIds.has(moduleResource)) {
160
+ // // this.moduleResourceToChunkIds.set(moduleResource, new Set());
161
+ // // }
162
+ // // this.moduleResourceToChunkIds.get(moduleResource).add(chunkIdString);
163
+ // // }
164
+ // // }
165
+ // // // Store in the map if there are required sections
166
+ // // if (requiredSections.size > 0) {
167
+ // // this.chunkIdToSectionsMap[chunkIdString] = Array.from(requiredSections);
168
+ // // }
169
+ // // // Map chunkId to module resources
170
+ // // if (moduleResources.length > 0) {
171
+ // // this.moduleChunkIdToModulesMap[chunkIdString] = moduleResources;
172
+ // // }
173
+ // // }
174
+ // // // Collect all used keys
175
+ // // this.allUsedKeys = new Set();
176
+ // // for (const keys of this.moduleToKeysMap.values()) {
177
+ // // for (const key of keys) {
178
+ // // this.allUsedKeys.add(key);
179
+ // // }
180
+ // // }
181
+ // // // Collect entry point keys
182
+ // // this.entryPointKeys = new Set();
183
+ // // for (const moduleResource of entryPointModules) {
184
+ // // const keys = this.moduleToKeysMap.get(moduleResource);
185
+ // // if (keys) {
186
+ // // for (const key of keys) {
187
+ // // this.entryPointKeys.add(key);
188
+ // // }
189
+ // // }
190
+ // // }
191
+ // // // Collect unused keys
192
+ // // this.allKeysInProperties = new Set();
193
+ // // const firstLocale = Object.keys(this.allI18nKeys)[0];
194
+ // // const sections = this.allI18nKeys[firstLocale];
195
+ // // for (const section of Object.values(sections)) {
196
+ // // for (const key of Object.keys(section)) {
197
+ // // this.allKeysInProperties.add(key);
198
+ // // }
199
+ // // }
200
+ // // this.unusedKeys = new Set([...this.allKeysInProperties].filter(key => !this.allUsedKeys.has(key)));
201
+ // // // Remove entry point keys from allUsedKeys
202
+ // // this.remainingKeys = new Set([...this.allUsedKeys].filter(key => !this.entryPointKeys.has(key)));
203
+ // // // Emit the i18n chunks
204
+ // // this.emitI18nChunks(compilation);
205
+ // // }
206
+ // // getValueForKeyInLocale(key, locale) {
207
+ // // const sections = this.allI18nKeys[locale];
208
+ // // for (const sectionName in sections) {
209
+ // // const section = sections[sectionName];
210
+ // // if (key in section) {
211
+ // // return section[key];
212
+ // // }
213
+ // // }
214
+ // // return undefined;
215
+ // // }
216
+ // // emitI18nChunks(compilation) {
217
+ // // const manifest = {
218
+ // // moduleToI18nChunkMap: {},
219
+ // // locales: {},
220
+ // // };
221
+ // // // Get the list of locales
222
+ // // const locales = Object.keys(this.allI18nKeys);
223
+ // // const firstLocale = locales[0];
224
+ // // // Map from i18nChunkId to keys
225
+ // // const i18nChunkIdToKeysMap = {};
226
+ // // let i18nChunkIdCounter = 0;
227
+ // // // **Chunk 0**: Entry Point Keys
228
+ // // const entryPointChunkId = i18nChunkIdCounter++;
229
+ // // i18nChunkIdToKeysMap[entryPointChunkId] = Array.from(this.entryPointKeys);
230
+ // // for (const key of this.entryPointKeys) {
231
+ // // this.keyToI18nChunkIdMap[key] = entryPointChunkId;
232
+ // // }
233
+ // // // **Last Chunk**: Unused Keys
234
+ // // const unusedKeysChunkId = 'unused'; // Using a string to make it distinct
235
+ // // i18nChunkIdToKeysMap[unusedKeysChunkId] = Array.from(this.unusedKeys);
236
+ // // // Remaining Keys: Group into chunks of ~30KB
237
+ // // let currentChunkKeys = [];
238
+ // // let currentChunkSize = 0;
239
+ // // const desiredChunkSize = 100* 1024; // 30KB
240
+ // // for (const key of this.remainingKeys) {
241
+ // // const value = this.getValueForKeyInLocale(key, firstLocale);
242
+ // // const keySize = Buffer.byteLength(key, 'utf8') + Buffer.byteLength(value || '', 'utf8');
243
+ // // if (currentChunkSize + keySize > desiredChunkSize) {
244
+ // // // Assign current chunk
245
+ // // const i18nChunkId = i18nChunkIdCounter++;
246
+ // // i18nChunkIdToKeysMap[i18nChunkId] = currentChunkKeys;
247
+ // // // Map keys to i18nChunkId
248
+ // // for (const chunkKey of currentChunkKeys) {
249
+ // // this.keyToI18nChunkIdMap[chunkKey] = i18nChunkId;
250
+ // // }
251
+ // // // Start a new chunk
252
+ // // currentChunkKeys = [];
253
+ // // currentChunkSize = 0;
254
+ // // }
255
+ // // currentChunkKeys.push(key);
256
+ // // currentChunkSize += keySize;
257
+ // // }
258
+ // // // Assign the remaining keys
259
+ // // if (currentChunkKeys.length > 0) {
260
+ // // const i18nChunkId = i18nChunkIdCounter++;
261
+ // // i18nChunkIdToKeysMap[i18nChunkId] = currentChunkKeys;
262
+ // // // Map keys to i18nChunkId
263
+ // // for (const chunkKey of currentChunkKeys) {
264
+ // // this.keyToI18nChunkIdMap[chunkKey] = i18nChunkId;
265
+ // // }
266
+ // // }
267
+ // // // Now, generate the i18n chunks for each locale
268
+ // // for (const locale of locales) {
269
+ // // manifest.locales[locale] = manifest.locales[locale] || {};
270
+ // // for (const [i18nChunkId, keys] of Object.entries(i18nChunkIdToKeysMap)) {
271
+ // // const i18nData = {};
272
+ // // for (const key of keys) {
273
+ // // const value = this.getValueForKeyInLocale(key, locale);
274
+ // // if (value !== undefined) {
275
+ // // i18nData[key] = value;
276
+ // // }
277
+ // // }
278
+ // // if (Object.keys(i18nData).length > 0) {
279
+ // // const moduleSource = `window.loadI18nChunk(${JSON.stringify(i18nData, null, 2)});`;
280
+ // // const filename = `i18n-chunks/${locale}/chunk-${i18nChunkId}.js`;
281
+ // // compilation.emitAsset(filename, new RawSource(moduleSource));
282
+ // // manifest.locales[locale][i18nChunkId] = filename;
283
+ // // console.log(`Emitted i18n chunk: ${filename}`);
284
+ // // }
285
+ // // }
286
+ // // }
287
+ // // // Now, create moduleToI18nChunkMap
288
+ // // for (const [moduleChunkId, moduleResources] of Object.entries(this.moduleChunkIdToModulesMap)) {
289
+ // // const requiredI18nChunkIds = new Set();
290
+ // // for (const moduleResource of moduleResources) {
291
+ // // const keys = this.moduleToKeysMap.get(moduleResource);
292
+ // // if (keys) {
293
+ // // for (const key of keys) {
294
+ // // const i18nChunkId = this.keyToI18nChunkIdMap[key];
295
+ // // if (i18nChunkId !== undefined) {
296
+ // // requiredI18nChunkIds.add(i18nChunkId);
297
+ // // }
298
+ // // }
299
+ // // }
300
+ // // }
301
+ // // if (requiredI18nChunkIds.size > 0) {
302
+ // // manifest.moduleToI18nChunkMap[moduleChunkId] = Array.from(requiredI18nChunkIds);
303
+ // // } else {
304
+ // // console.log(`No required i18n chunks for module chunk ID ${moduleChunkId}`);
305
+ // // }
306
+ // // }
307
+ // // // Ensure that the main chunk always requires chunk zero
308
+ // // manifest.moduleToI18nChunkMap[this.entryPointName] = manifest.moduleToI18nChunkMap[this.entryPointName] || [];
309
+ // // if (!manifest.moduleToI18nChunkMap[this.entryPointName].includes(entryPointChunkId)) {
310
+ // // manifest.moduleToI18nChunkMap[this.entryPointName].unshift(entryPointChunkId);
311
+ // // }
312
+ // // // Emit the manifest file
313
+ // // const manifestSource = new RawSource(
314
+ // // `window.i18n = window.i18n || {}; window.i18n.manifest = ${JSON.stringify(manifest, null, 2)};`
315
+ // // );
316
+ // // const manifestFilename = 'i18n-chunks/manifest.js';
317
+ // // compilation.emitAsset(manifestFilename, manifestSource);
318
+ // // console.log(`Emitted i18n manifest: ${manifestFilename}`);
319
+ // // }
320
+ // // }
321
+ // // module.exports = I18nPlugin;
322
+ // const { getAllI18nGroupedBySection, getPropertiesAsJSON } = require('../I18nSplitPlugin/utils/propertiesUtils');
323
+ // const { collectI18nKeysfromAST, collectI18nKeysfromComments } = require('../I18nSplitPlugin/utils/collectI18nKeys');
324
+ // const { I18nDependency, I18nDependencyTemplate } = require('../I18nSplitPlugin/I18nDependency');
325
+ // const { RawSource } = require('webpack-sources');
326
+ // const crypto = require('crypto');
327
+ // const escodegen = require('escodegen');
328
+ // const esprima = require('esprima');
329
+ // const NullFactory = require('webpack/lib/NullFactory');
330
+ // const { walk } = require('estree-walker');
331
+ // // const pluginName = 'I18nPlugin';
332
+ // // class I18nPlugin {
333
+ // // constructor(options = {}) {
334
+ // // const { jsResourcePath, mainChunkName, propertiesFolder, disableDefault, jsResource } = options;
335
+ // // if (!jsResourcePath) {
336
+ // // throw new Error('I18nPlugin: "jsResourcePath" option is required.');
337
+ // // }
338
+ // // if (!mainChunkName) {
339
+ // // throw new Error('I18nPlugin: "mainChunkName" option is required.');
340
+ // // }
341
+ // // this.jsResourcePath = jsResourcePath;
342
+ // // this.entryPointName = mainChunkName;
343
+ // // this.jsResourceI18nKeys = jsResource || {};
344
+ // // // Initialize collection maps
345
+ // // this.moduleToKeysMap = new Map();
346
+ // // this.keyToModulesMap = new Map();
347
+ // // this.keyToI18nChunkIdMap = {};
348
+ // // this.keyToHashMap = {};
349
+ // // // Initialize hash function
350
+ // // this.getHash = (key) => {
351
+ // // if (!this.keyToHashMap[key]) {
352
+ // // const hash = crypto.createHash('md5').update(key).digest('hex').substring(0, 8);
353
+ // // this.keyToHashMap[key] = hash;
354
+ // // }
355
+ // // return this.keyToHashMap[key];
356
+ // // };
357
+ // // }
358
+ // // // Process source code and collect i18n keys
359
+ // // processModule(module) {
360
+ // // if (!module.resource || !module.resource.endsWith('.js')) {
361
+ // // return [];
362
+ // // }
363
+ // // try {
364
+ // // const source = module._source._value;
365
+ // // // Parse the source code
366
+ // // const ast = esprima.parse(source, {
367
+ // // comment: true,
368
+ // // tokens: true,
369
+ // // range: true,
370
+ // // loc: true
371
+ // // });
372
+ // // const i18nKeys = new Set();
373
+ // // // Process the AST
374
+ // // walk(ast, {
375
+ // // enter: (node) => {
376
+ // // if (node.type === 'Literal' && typeof node.value === 'string') {
377
+ // // const key = node.value;
378
+ // // if (Object.prototype.hasOwnProperty.call(this.jsResourceI18nKeys, key)) {
379
+ // // i18nKeys.add(key);
380
+ // // const hash = this.getHash(key);
381
+ // // node.value = hash;
382
+ // // node.raw = `'${hash}'`;
383
+ // // }
384
+ // // }
385
+ // // }
386
+ // // });
387
+ // // // Generate modified code if keys were found
388
+ // // if (i18nKeys.size > 0) {
389
+ // // try {
390
+ // // const modifiedCode = escodegen.generate(ast, {
391
+ // // comment: true,
392
+ // // format: {
393
+ // // indent: {
394
+ // // style: ' ',
395
+ // // base: 0
396
+ // // },
397
+ // // preserveBlankLines: true
398
+ // // }
399
+ // // });
400
+ // // module._source._value = modifiedCode;
401
+ // // } catch (error) {
402
+ // // console.error(`Error generating code for ${module.resource}:`, error);
403
+ // // }
404
+ // // }
405
+ // // return Array.from(i18nKeys);
406
+ // // } catch (error) {
407
+ // // console.error(`Error processing module ${module.resource}:`, error);
408
+ // // return [];
409
+ // // }
410
+ // // }
411
+ // // apply(compiler) {
412
+ // // // Process modules during compilation
413
+ // // compiler.hooks.compilation.tap('I18nPlugin', (compilation) => {
414
+ // // // Process modules after they are loaded
415
+ // // compilation.hooks.optimizeModules.tap('I18nPlugin', (modules) => {
416
+ // // modules.forEach(module => {
417
+ // // const keys = this.processModule(module);
418
+ // // if (keys.length > 0) {
419
+ // // // Update module to keys mapping
420
+ // // this.moduleToKeysMap.set(module.resource, keys);
421
+ // // // Update keys to modules mapping
422
+ // // keys.forEach(key => {
423
+ // // if (!this.keyToModulesMap.has(key)) {
424
+ // // this.keyToModulesMap.set(key, new Set());
425
+ // // }
426
+ // // this.keyToModulesMap.get(key).add(module.resource);
427
+ // // });
428
+ // // }
429
+ // // });
430
+ // // });
431
+ // // // Process chunks after optimization
432
+ // // compilation.hooks.afterOptimizeChunks.tap('I18nPlugin', () => {
433
+ // // this.processCollectedKeys(compilation);
434
+ // // });
435
+ // // });
436
+ // // }
437
+ // // processCollectedKeys(compilation) {
438
+ // // // Map chunk IDs to sections and modules
439
+ // // this.chunkIdToSectionsMap = {};
440
+ // // this.moduleChunkIdToModulesMap = {};
441
+ // // this.moduleResourceToChunkIds = new Map();
442
+ // // // Process entry point modules
443
+ // // const entryPointChunk = compilation.namedChunks.get(this.entryPointName);
444
+ // // const entryPointModules = new Set();
445
+ // // if (entryPointChunk) {
446
+ // // for (const module of entryPointChunk.getModules()) {
447
+ // // if (module.resource) {
448
+ // // entryPointModules.add(module.resource);
449
+ // // }
450
+ // // }
451
+ // // }
452
+ // // // Process each chunk
453
+ // // for (const chunk of compilation.chunks) {
454
+ // // const chunkId = chunk.name || chunk.id;
455
+ // // const chunkIdString = String(chunkId);
456
+ // // const moduleResources = [];
457
+ // // // Collect modules for this chunk
458
+ // // for (const module of chunk.getModules()) {
459
+ // // if (module.resource) {
460
+ // // moduleResources.push(module.resource);
461
+ // // // Map module resource to chunk IDs
462
+ // // if (!this.moduleResourceToChunkIds.has(module.resource)) {
463
+ // // this.moduleResourceToChunkIds.set(module.resource, new Set());
464
+ // // }
465
+ // // this.moduleResourceToChunkIds.get(module.resource).add(chunkIdString);
466
+ // // }
467
+ // // }
468
+ // // // Store module resources for this chunk
469
+ // // if (moduleResources.length > 0) {
470
+ // // this.moduleChunkIdToModulesMap[chunkIdString] = moduleResources;
471
+ // // }
472
+ // // }
473
+ // // // Collect used and unused keys
474
+ // // this.collectKeyStats(entryPointModules);
475
+ // // // Emit the i18n chunks
476
+ // // this.emitI18nChunks(compilation);
477
+ // // }
478
+ // // collectKeyStats(entryPointModules) {
479
+ // // // Collect all used keys
480
+ // // this.allUsedKeys = new Set();
481
+ // // for (const keys of this.moduleToKeysMap.values()) {
482
+ // // for (const key of keys) {
483
+ // // this.allUsedKeys.add(key);
484
+ // // }
485
+ // // }
486
+ // // // Collect entry point keys
487
+ // // this.entryPointKeys = new Set();
488
+ // // for (const moduleResource of entryPointModules) {
489
+ // // const keys = this.moduleToKeysMap.get(moduleResource);
490
+ // // if (keys) {
491
+ // // for (const key of keys) {
492
+ // // this.entryPointKeys.add(key);
493
+ // // }
494
+ // // }
495
+ // // }
496
+ // // // Calculate remaining and unused keys
497
+ // // this.allKeysInProperties = new Set(Object.keys(this.jsResourceI18nKeys));
498
+ // // this.unusedKeys = new Set(
499
+ // // [...this.allKeysInProperties].filter(key => !this.allUsedKeys.has(key))
500
+ // // );
501
+ // // this.remainingKeys = new Set(
502
+ // // [...this.allUsedKeys].filter(key => !this.entryPointKeys.has(key))
503
+ // // );
504
+ // // }
505
+ // // emitI18nChunks(compilation) {
506
+ // // const manifest = {
507
+ // // moduleToI18nChunkMap: {},
508
+ // // locales: { default: {} }
509
+ // // };
510
+ // // // Map from i18nChunkId to keys
511
+ // // const i18nChunkIdToKeysMap = {};
512
+ // // let i18nChunkIdCounter = 0;
513
+ // // // Entry Point Keys (Chunk 0)
514
+ // // const entryPointChunkId = i18nChunkIdCounter++;
515
+ // // i18nChunkIdToKeysMap[entryPointChunkId] = Array.from(this.entryPointKeys);
516
+ // // for (const key of this.entryPointKeys) {
517
+ // // this.keyToI18nChunkIdMap[key] = entryPointChunkId;
518
+ // // }
519
+ // // // Unused Keys
520
+ // // const unusedKeysChunkId = 'unused';
521
+ // // i18nChunkIdToKeysMap[unusedKeysChunkId] = Array.from(this.unusedKeys);
522
+ // // // Process remaining keys into chunks
523
+ // // const chunkSize = 100 * 1024; // 100KB chunks
524
+ // // let currentChunk = [];
525
+ // // let currentSize = 0;
526
+ // // for (const key of this.remainingKeys) {
527
+ // // const keySize = Buffer.byteLength(key, 'utf8') +
528
+ // // Buffer.byteLength(this.jsResourceI18nKeys[key] || '', 'utf8');
529
+ // // if (currentSize + keySize > chunkSize && currentChunk.length > 0) {
530
+ // // // Save current chunk
531
+ // // const chunkId = i18nChunkIdCounter++;
532
+ // // i18nChunkIdToKeysMap[chunkId] = currentChunk;
533
+ // // currentChunk.forEach(k => this.keyToI18nChunkIdMap[k] = chunkId);
534
+ // // // Start new chunk
535
+ // // currentChunk = [];
536
+ // // currentSize = 0;
537
+ // // }
538
+ // // currentChunk.push(key);
539
+ // // currentSize += keySize;
540
+ // // }
541
+ // // // Save last chunk if not empty
542
+ // // if (currentChunk.length > 0) {
543
+ // // const chunkId = i18nChunkIdCounter++;
544
+ // // i18nChunkIdToKeysMap[chunkId] = currentChunk;
545
+ // // currentChunk.forEach(k => this.keyToI18nChunkIdMap[k] = chunkId);
546
+ // // }
547
+ // // // Generate chunks
548
+ // // for (const [i18nChunkId, keys] of Object.entries(i18nChunkIdToKeysMap)) {
549
+ // // const i18nData = {};
550
+ // // for (const key of keys) {
551
+ // // const value = this.jsResourceI18nKeys[key];
552
+ // // if (value !== undefined) {
553
+ // // i18nData[this.getHash(key)] = value;
554
+ // // }
555
+ // // }
556
+ // // if (Object.keys(i18nData).length > 0) {
557
+ // // const chunkContent = `window.loadI18nChunk(${JSON.stringify(i18nData, null, 2)});`;
558
+ // // const filename = `i18n-chunks/default/chunk-${i18nChunkId}.js`;
559
+ // // compilation.emitAsset(filename, new RawSource(chunkContent));
560
+ // // manifest.locales.default[i18nChunkId] = filename;
561
+ // // }
562
+ // // }
563
+ // // // Build module to chunk mapping
564
+ // // for (const [moduleChunkId, moduleResources] of Object.entries(this.moduleChunkIdToModulesMap)) {
565
+ // // const requiredI18nChunkIds = new Set();
566
+ // // for (const moduleResource of moduleResources) {
567
+ // // const keys = this.moduleToKeysMap.get(moduleResource);
568
+ // // if (keys) {
569
+ // // for (const key of keys) {
570
+ // // const i18nChunkId = this.keyToI18nChunkIdMap[key];
571
+ // // if (i18nChunkId !== undefined) {
572
+ // // requiredI18nChunkIds.add(i18nChunkId);
573
+ // // }
574
+ // // }
575
+ // // }
576
+ // // }
577
+ // // if (requiredI18nChunkIds.size > 0) {
578
+ // // manifest.moduleToI18nChunkMap[moduleChunkId] = Array.from(requiredI18nChunkIds);
579
+ // // }
580
+ // // }
581
+ // // // Ensure entry point has chunk zero
582
+ // // manifest.moduleToI18nChunkMap[this.entryPointName] =
583
+ // // manifest.moduleToI18nChunkMap[this.entryPointName] || [];
584
+ // // if (!manifest.moduleToI18nChunkMap[this.entryPointName].includes(entryPointChunkId)) {
585
+ // // manifest.moduleToI18nChunkMap[this.entryPointName].unshift(entryPointChunkId);
586
+ // // }
587
+ // // // Emit manifest
588
+ // // const manifestContent =
589
+ // // `window.i18n = window.i18n || {}; window.i18n.manifest = ${JSON.stringify(manifest, null, 2)};`;
590
+ // // compilation.emitAsset('i18n-chunks/manifest.js', new RawSource(manifestContent));
591
+ // // }
592
+ // // }
593
+ // // module.exports = I18nPlugin;
594
+ // const NullFactory = require('webpack/lib/NullFactory');
595
+ // const { RawSource } = require('webpack-sources');
596
+ // const crypto = require('crypto');
597
+ // const { walk } = require('estree-walker');
598
+ // const parser = require('@babel/parser');
599
+ // const generate = require('@babel/generator').default;
600
+ // class I18nPlugin {
601
+ // constructor(options = {}) {
602
+ // const { jsResourcePath, mainChunkName, propertiesFolder, disableDefault, jsResource } = options;
603
+ // if (!jsResourcePath) {
604
+ // throw new Error('I18nPlugin: "jsResourcePath" option is required.');
605
+ // }
606
+ // if (!mainChunkName) {
607
+ // throw new Error('I18nPlugin: "mainChunkName" option is required.');
608
+ // }
609
+ // this.jsResourcePath = jsResourcePath;
610
+ // this.entryPointName = mainChunkName;
611
+ // this.jsResourceI18nKeys = jsResource || {};
612
+ // // Initialize collection maps
613
+ // this.moduleToKeysMap = new Map();
614
+ // this.keyToModulesMap = new Map();
615
+ // this.keyToI18nChunkIdMap = {};
616
+ // this.keyToHashMap = {};
617
+ // // Initialize hash function
618
+ // this.getHash = (key) => {
619
+ // if (!this.keyToHashMap[key]) {
620
+ // const hash = crypto.createHash('md5').update(key).digest('hex').substring(0, 8);
621
+ // this.keyToHashMap[key] = hash;
622
+ // }
623
+ // return this.keyToHashMap[key];
624
+ // };
625
+ // }
626
+ // shouldProcessModule(module) {
627
+ // if (!module.resource) return false;
628
+ // // Skip node_modules except for specific ones we want to process
629
+ // if (module.resource.includes('node_modules')) {
630
+ // const allowedModules = [
631
+ // '@zohodesk'
632
+ // // Add other allowed module prefixes here
633
+ // ];
634
+ // return allowedModules.some(prefix =>
635
+ // module.resource.includes(`node_modules/${prefix}`)
636
+ // );
637
+ // }
638
+ // // Process .js and .jsx files
639
+ // return /\.(js|jsx)$/.test(module.resource);
640
+ // }
641
+ // processModule(module) {
642
+ // if (!this.shouldProcessModule(module)) {
643
+ // return [];
644
+ // }
645
+ // try {
646
+ // const source = module._source._value;
647
+ // // Parse with @babel/parser which handles modern JS better
648
+ // const ast = parser.parse(source, {
649
+ // sourceType: 'module',
650
+ // plugins: [
651
+ // 'jsx',
652
+ // 'typescript',
653
+ // 'classProperties',
654
+ // 'decorators-legacy',
655
+ // 'exportDefaultFrom',
656
+ // 'exportNamespaceFrom',
657
+ // 'objectRestSpread',
658
+ // 'dynamicImport'
659
+ // ]
660
+ // });
661
+ // const i18nKeys = new Set();
662
+ // // Process the AST
663
+ // walk(ast, {
664
+ // enter: (node) => {
665
+ // if (node.type === 'StringLiteral' &&
666
+ // Object.prototype.hasOwnProperty.call(this.jsResourceI18nKeys, node.value)) {
667
+ // const key = node.value;
668
+ // i18nKeys.add(key);
669
+ // const hash = this.getHash(key);
670
+ // node.value = hash;
671
+ // if (node.extra && node.extra.raw) {
672
+ // node.extra.raw = `'${hash}'`;
673
+ // }
674
+ // }
675
+ // }
676
+ // });
677
+ // // Generate modified code if keys were found
678
+ // if (i18nKeys.size > 0) {
679
+ // try {
680
+ // const output = generate(ast, {
681
+ // retainLines: true,
682
+ // compact: false,
683
+ // jsescOption: {
684
+ // quotes: 'single'
685
+ // }
686
+ // });
687
+ // module._source._value = output.code;
688
+ // } catch (error) {
689
+ // console.error(`Error generating code for ${module.resource}:`, error);
690
+ // }
691
+ // }
692
+ // return Array.from(i18nKeys);
693
+ // } catch (error) {
694
+ // console.error(`Error processing module ${module.resource}:`, error);
695
+ // return [];
696
+ // }
697
+ // }
698
+ // apply(compiler) {
699
+ // compiler.hooks.compilation.tap('I18nPlugin', (compilation) => {
700
+ // // Process modules during compilation
701
+ // compilation.hooks.optimizeModules.tap('I18nPlugin', (modules) => {
702
+ // modules.forEach(module => {
703
+ // const keys = this.processModule(module);
704
+ // if (keys.length > 0) {
705
+ // // Update module to keys mapping
706
+ // this.moduleToKeysMap.set(module.resource, keys);
707
+ // // Update keys to modules mapping
708
+ // keys.forEach(key => {
709
+ // if (!this.keyToModulesMap.has(key)) {
710
+ // this.keyToModulesMap.set(key, new Set());
711
+ // }
712
+ // this.keyToModulesMap.get(key).add(module.resource);
713
+ // });
714
+ // }
715
+ // });
716
+ // });
717
+ // // Process chunks after optimization
718
+ // compilation.hooks.afterOptimizeChunks.tap('I18nPlugin', () => {
719
+ // this.processCollectedKeys(compilation);
720
+ // });
721
+ // });
722
+ // }
723
+ // processCollectedKeys(compilation) {
724
+ // // Map chunk IDs to sections and modules
725
+ // this.chunkIdToSectionsMap = {};
726
+ // this.moduleChunkIdToModulesMap = {};
727
+ // this.moduleResourceToChunkIds = new Map();
728
+ // // Process entry point modules
729
+ // const entryPointChunk = compilation.namedChunks.get(this.entryPointName);
730
+ // const entryPointModules = new Set();
731
+ // if (entryPointChunk) {
732
+ // for (const module of entryPointChunk.getModules()) {
733
+ // if (module.resource) {
734
+ // entryPointModules.add(module.resource);
735
+ // }
736
+ // }
737
+ // }
738
+ // // Process each chunk
739
+ // for (const chunk of compilation.chunks) {
740
+ // const chunkId = chunk.name || chunk.id;
741
+ // const chunkIdString = String(chunkId);
742
+ // const moduleResources = [];
743
+ // // Collect modules for this chunk
744
+ // for (const module of chunk.getModules()) {
745
+ // if (module.resource) {
746
+ // moduleResources.push(module.resource);
747
+ // // Map module resource to chunk IDs
748
+ // if (!this.moduleResourceToChunkIds.has(module.resource)) {
749
+ // this.moduleResourceToChunkIds.set(module.resource, new Set());
750
+ // }
751
+ // this.moduleResourceToChunkIds.get(module.resource).add(chunkIdString);
752
+ // }
753
+ // }
754
+ // // Store module resources for this chunk
755
+ // if (moduleResources.length > 0) {
756
+ // this.moduleChunkIdToModulesMap[chunkIdString] = moduleResources;
757
+ // }
758
+ // }
759
+ // // Collect used and unused keys
760
+ // this.collectKeyStats(entryPointModules);
761
+ // // Emit the i18n chunks
762
+ // //this.emitI18nChunks(compilation);
763
+ // }
764
+ // collectKeyStats(entryPointModules) {
765
+ // // Collect all used keys
766
+ // this.allUsedKeys = new Set();
767
+ // for (const keys of this.moduleToKeysMap.values()) {
768
+ // for (const key of keys) {
769
+ // this.allUsedKeys.add(key);
770
+ // }
771
+ // }
772
+ // // Collect entry point keys
773
+ // this.entryPointKeys = new Set();
774
+ // for (const moduleResource of entryPointModules) {
775
+ // const keys = this.moduleToKeysMap.get(moduleResource);
776
+ // if (keys) {
777
+ // for (const key of keys) {
778
+ // this.entryPointKeys.add(key);
779
+ // }
780
+ // }
781
+ // }
782
+ // // Calculate remaining and unused keys
783
+ // this.allKeysInProperties = new Set(Object.keys(this.jsResourceI18nKeys));
784
+ // this.unusedKeys = new Set(
785
+ // [...this.allKeysInProperties].filter(key => !this.allUsedKeys.has(key))
786
+ // );
787
+ // this.remainingKeys = new Set(
788
+ // [...this.allUsedKeys].filter(key => !this.entryPointKeys.has(key))
789
+ // );
790
+ // }
791
+ // emitI18nChunks(compilation) {
792
+ // const manifest = {
793
+ // moduleToI18nChunkMap: {},
794
+ // locales: { default: {} }
795
+ // };
796
+ // // Map from i18nChunkId to keys
797
+ // const i18nChunkIdToKeysMap = {};
798
+ // let i18nChunkIdCounter = 0;
799
+ // // Entry Point Keys (Chunk 0)
800
+ // const entryPointChunkId = i18nChunkIdCounter++;
801
+ // i18nChunkIdToKeysMap[entryPointChunkId] = Array.from(this.entryPointKeys);
802
+ // for (const key of this.entryPointKeys) {
803
+ // this.keyToI18nChunkIdMap[key] = entryPointChunkId;
804
+ // }
805
+ // // Unused Keys
806
+ // const unusedKeysChunkId = 'unused';
807
+ // i18nChunkIdToKeysMap[unusedKeysChunkId] = Array.from(this.unusedKeys);
808
+ // // Process remaining keys into chunks
809
+ // const chunkSize = 100 * 1024; // 100KB chunks
810
+ // let currentChunk = [];
811
+ // let currentSize = 0;
812
+ // for (const key of this.remainingKeys) {
813
+ // const keySize = Buffer.byteLength(key, 'utf8') +
814
+ // Buffer.byteLength(this.jsResourceI18nKeys[key] || '', 'utf8');
815
+ // if (currentSize + keySize > chunkSize && currentChunk.length > 0) {
816
+ // // Save current chunk
817
+ // const chunkId = i18nChunkIdCounter++;
818
+ // i18nChunkIdToKeysMap[chunkId] = currentChunk;
819
+ // currentChunk.forEach(k => this.keyToI18nChunkIdMap[k] = chunkId);
820
+ // // Start new chunk
821
+ // currentChunk = [];
822
+ // currentSize = 0;
823
+ // }
824
+ // currentChunk.push(key);
825
+ // currentSize += keySize;
826
+ // }
827
+ // // Save last chunk if not empty
828
+ // if (currentChunk.length > 0) {
829
+ // const chunkId = i18nChunkIdCounter++;
830
+ // i18nChunkIdToKeysMap[chunkId] = currentChunk;
831
+ // currentChunk.forEach(k => this.keyToI18nChunkIdMap[k] = chunkId);
832
+ // }
833
+ // // Generate chunks
834
+ // for (const [i18nChunkId, keys] of Object.entries(i18nChunkIdToKeysMap)) {
835
+ // const i18nData = {};
836
+ // for (const key of keys) {
837
+ // const value = this.jsResourceI18nKeys[key];
838
+ // if (value !== undefined) {
839
+ // i18nData[this.getHash(key)] = value;
840
+ // }
841
+ // }
842
+ // if (Object.keys(i18nData).length > 0) {
843
+ // const chunkContent = `window.loadI18nChunk(${JSON.stringify(i18nData, null, 2)});`;
844
+ // const filename = `i18n-chunks/default/chunk-${i18nChunkId}.js`;
845
+ // compilation.emitAsset(filename, new RawSource(chunkContent));
846
+ // manifest.locales.default[i18nChunkId] = filename;
847
+ // }
848
+ // }
849
+ // // Build module to chunk mapping
850
+ // for (const [moduleChunkId, moduleResources] of Object.entries(this.moduleChunkIdToModulesMap)) {
851
+ // const requiredI18nChunkIds = new Set();
852
+ // for (const moduleResource of moduleResources) {
853
+ // const keys = this.moduleToKeysMap.get(moduleResource);
854
+ // if (keys) {
855
+ // for (const key of keys) {
856
+ // const i18nChunkId = this.keyToI18nChunkIdMap[key];
857
+ // if (i18nChunkId !== undefined) {
858
+ // requiredI18nChunkIds.add(i18nChunkId);
859
+ // }
860
+ // }
861
+ // }
862
+ // }
863
+ // if (requiredI18nChunkIds.size > 0) {
864
+ // manifest.moduleToI18nChunkMap[moduleChunkId] = Array.from(requiredI18nChunkIds);
865
+ // }
866
+ // }
867
+ // // Ensure entry point has chunk zero
868
+ // manifest.moduleToI18nChunkMap[this.entryPointName] =
869
+ // manifest.moduleToI18nChunkMap[this.entryPointName] || [];
870
+ // if (!manifest.moduleToI18nChunkMap[this.entryPointName].includes(entryPointChunkId)) {
871
+ // manifest.moduleToI18nChunkMap[this.entryPointName].unshift(entryPointChunkId);
872
+ // }
873
+ // // Emit manifest
874
+ // const manifestContent =
875
+ // `window.i18n = window.i18n || {}; window.i18n.manifest = ${JSON.stringify(manifest, null, 2)};`;
876
+ // compilation.emitAsset('i18n-chunks/manifest.js', new RawSource(manifestContent));
877
+ // }
878
+ // }
879
+ // module.exports = I18nPlugin;
880
+ // const { RawSource } = require('webpack-sources');
881
+ // const { getAllI18nGroupedBySection, getPropertiesAsJSON, jsonToString } = require('../I18nSplitPlugin/utils/propertiesUtils');
882
+ // const { collectI18nKeysfromAST, collectI18nKeysfromComments,processModule } = require('../I18nSplitPlugin/utils/collectI18nKeys');
883
+ // const NullFactory = require('webpack/lib/NullFactory');
884
+ // const { I18nDependency, I18nDependencyTemplate } = require('../I18nSplitPlugin/I18nDependency');
885
+ // const I18nKeyHasher = require('./utils/I18nKeyHasher');
886
+ // const crypto = require('crypto');
887
+ // const pluginName = 'I18nSplitPlugin';
888
+ // const MODULE_TYPE = 'json/i18n';
889
+ // class I18nSplitPlugin {
890
+ // constructor(options = {}) {
891
+ // const {
892
+ // jsResource,
893
+ // localeVarName = 'document.documentElement.lang',
894
+ // jsonpFunc = 'window.loadI18nChunk',
895
+ // propertiesFolder,
896
+ // disableDefault = false,
897
+ // filenameTemplate = 'i18n-chunk/[locale]/[name].[chunkhash].i18n.js',
898
+ // i18nManifestFileName = 'i18n-manifest.json',
899
+ // mainChunkName = 'main'
900
+ // } = options;
901
+ // this.options = {
902
+ // localeVarName,
903
+ // jsonpFunc,
904
+ // filenameTemplate,
905
+ // i18nManifestFileName,
906
+ // mainChunkName
907
+ // };
908
+ // // Load and initialize i18n data
909
+ // this.jsResourceI18nKeys = jsResource ? getPropertiesAsJSON(jsResource) : {};
910
+ // this.allI18nData = getAllI18nGroupedBySection({
911
+ // folderPath: propertiesFolder,
912
+ // disableDefault,
913
+ // jsResourceI18nKeys: this.jsResourceI18nKeys
914
+ // });
915
+ // // Initialize key hasher
916
+ // this.keyHasher = new I18nKeyHasher();
917
+ // // Maps and tracking
918
+ // this.moduleToKeysMap = new Map();
919
+ // this.sectionToKeysMap = new Map();
920
+ // this.keyToSectionMap = new Map();
921
+ // this.sectionToChunkIdMap = new Map();
922
+ // this.chunkToSectionsMap = new Map();
923
+ // // Initialize sections and hashes
924
+ // this.initializeMaps();
925
+ // this.initializeHashes();
926
+ // console.log('Locales found:', Object.keys(this.allI18nData));
927
+ // }
928
+ // initializeMaps() {
929
+ // const firstLocale = Object.keys(this.allI18nData)[0];
930
+ // if (!firstLocale) return;
931
+ // const sections = this.allI18nData[firstLocale];
932
+ // console.log(`Sections found: ${Object.keys(sections).join(', ')}`);
933
+ // for (const [sectionName, sectionData] of Object.entries(sections)) {
934
+ // const keys = Object.keys(sectionData);
935
+ // this.sectionToKeysMap.set(sectionName, new Set(keys));
936
+ // keys.forEach(key => this.keyToSectionMap.set(key, sectionName));
937
+ // }
938
+ // }
939
+ // initializeHashes() {
940
+ // const allKeys = new Set();
941
+ // Object.values(this.allI18nData).forEach(localeData => {
942
+ // Object.values(localeData).forEach(sectionData => {
943
+ // Object.keys(sectionData).forEach(key => allKeys.add(key));
944
+ // });
945
+ // });
946
+ // allKeys.forEach(key => {
947
+ // this.keyHasher.hashKey(key);
948
+ // });
949
+ // }
950
+ // apply(compiler) {
951
+ // compiler.hooks.thisCompilation.tap(pluginName, (compilation, params) => {
952
+ // // Set up dependencies
953
+ // this.defineI18nDependency(compilation);
954
+ // // Set up parsing
955
+ // this.setupModuleParsing(compilation, params.normalModuleFactory);
956
+ // // Process chunks after optimization
957
+ // compilation.hooks.afterOptimizeChunks.tap(pluginName, () => {
958
+ // this.processChunks(compilation);
959
+ // });
960
+ // // Emit assets
961
+ // compiler.hooks.emit.tap(pluginName, () => {
962
+ // this.emitAssets(compilation);
963
+ // });
964
+ // });
965
+ // }
966
+ // defineI18nDependency(compilation) {
967
+ // compilation.dependencyFactories.set(I18nDependency, new NullFactory());
968
+ // compilation.dependencyTemplates.set(I18nDependency, new I18nDependencyTemplate());
969
+ // }
970
+ // setupModuleParsing(compilation, factory) {
971
+ // const handler = parser => {
972
+ // parser.hooks.program.tap(pluginName, (ast, comments) => {
973
+ // const { module } = parser.state;
974
+ // if (!(module && /\.jsx?$/.test(module.resource))) return;
975
+ // // Process the module and collect keys
976
+ // const moduleKeys = processModule(module, this.jsResourceI18nKeys, this.keyHasher);
977
+ // if (moduleKeys.length) {
978
+ // // Store keys for chunk generation
979
+ // this.moduleToKeysMap.set(module.resource, moduleKeys);
980
+ // // Add dependency
981
+ // this.addI18nDependency(module, moduleKeys);
982
+ // }
983
+ // });
984
+ // };
985
+ // factory.hooks.parser
986
+ // .for('javascript/auto')
987
+ // .tap(pluginName, handler);
988
+ // factory.hooks.parser
989
+ // .for('javascript/dynamic')
990
+ // .tap(pluginName, handler);
991
+ // }
992
+ // addI18nDependency(module, keys) {
993
+ // const dep = new I18nDependency({
994
+ // identifier: `i18n ${module.resource}`,
995
+ // i18nKeys: keys
996
+ // }, module.context);
997
+ // module.addDependency(dep);
998
+ // }
999
+ // processChunks(compilation) {
1000
+ // let chunkIdCounter = 0;
1001
+ // // Process entry point chunk
1002
+ // const entryChunk = compilation.namedChunks.get(this.options.mainChunkName);
1003
+ // if (entryChunk) {
1004
+ // const entryModules = Array.from(entryChunk.modulesIterable)
1005
+ // .filter(m => m.resource)
1006
+ // .map(m => m.resource);
1007
+ // // Collect entry point sections
1008
+ // const entrySections = new Set();
1009
+ // entryModules.forEach(moduleResource => {
1010
+ // const keys = this.moduleToKeysMap.get(moduleResource) || [];
1011
+ // keys.forEach(key => {
1012
+ // const section = this.keyToSectionMap.get(key);
1013
+ // if (section) entrySections.add(section);
1014
+ // });
1015
+ // });
1016
+ // // Assign chunk IDs to entry sections
1017
+ // entrySections.forEach(section => {
1018
+ // this.sectionToChunkIdMap.set(section, `section_${chunkIdCounter++}`);
1019
+ // });
1020
+ // }
1021
+ // // Process other chunks
1022
+ // for (const chunk of compilation.chunks) {
1023
+ // if (chunk === entryChunk) continue;
1024
+ // const modules = Array.from(chunk.modulesIterable)
1025
+ // .filter(m => m.resource);
1026
+ // const sectionsInChunk = new Set();
1027
+ // modules.forEach(module => {
1028
+ // const keys = this.moduleToKeysMap.get(module.resource) || [];
1029
+ // keys.forEach(key => {
1030
+ // const section = this.keyToSectionMap.get(key);
1031
+ // if (section) sectionsInChunk.add(section);
1032
+ // });
1033
+ // });
1034
+ // if (sectionsInChunk.size > 0) {
1035
+ // // Assign chunk IDs to new sections
1036
+ // sectionsInChunk.forEach(section => {
1037
+ // if (!this.sectionToChunkIdMap.has(section)) {
1038
+ // this.sectionToChunkIdMap.set(section, `section_${chunkIdCounter++}`);
1039
+ // }
1040
+ // });
1041
+ // this.chunkToSectionsMap.set(chunk, Array.from(sectionsInChunk));
1042
+ // }
1043
+ // }
1044
+ // }
1045
+ // emitAssets(compilation) {
1046
+ // const manifest = {
1047
+ // moduleToChunks: {},
1048
+ // hashMap: Object.fromEntries(this.keyHasher.keyHashMap),
1049
+ // locales: {}
1050
+ // };
1051
+ // // Generate chunks for each locale
1052
+ // for (const locale of Object.keys(this.allI18nData)) {
1053
+ // manifest.locales[locale] = {};
1054
+ // // Generate section chunks
1055
+ // for (const [section, chunkId] of this.sectionToChunkIdMap.entries()) {
1056
+ // const keys = this.sectionToKeysMap.get(section) || new Set();
1057
+ // const i18nData = {};
1058
+ // // Use hashed keys in chunks
1059
+ // keys.forEach(key => {
1060
+ // const hash = this.keyHasher.hashKey(key);
1061
+ // const value = this.allI18nData[locale][section]?.[key];
1062
+ // if (value) i18nData[hash] = value;
1063
+ // });
1064
+ // if (Object.keys(i18nData).length > 0) {
1065
+ // const chunkContent = `${this.options.jsonpFunc}(${jsonToString(i18nData)});`;
1066
+ // const fileName = this.getChunkFileName(chunkId, locale);
1067
+ // compilation.emitAsset(fileName, new RawSource(chunkContent));
1068
+ // manifest.locales[locale][chunkId] = fileName;
1069
+ // }
1070
+ // }
1071
+ // }
1072
+ // // Map modules to their required chunks
1073
+ // for (const [moduleResource, keys] of this.moduleToKeysMap.entries()) {
1074
+ // const requiredChunks = new Set();
1075
+ // keys.forEach(key => {
1076
+ // const section = this.keyToSectionMap.get(key);
1077
+ // if (section) {
1078
+ // const chunkId = this.sectionToChunkIdMap.get(section);
1079
+ // if (chunkId) requiredChunks.add(chunkId);
1080
+ // }
1081
+ // });
1082
+ // if (requiredChunks.size > 0) {
1083
+ // manifest.moduleToChunks[moduleResource] = Array.from(requiredChunks);
1084
+ // }
1085
+ // }
1086
+ // // Emit manifest
1087
+ // compilation.emitAsset(
1088
+ // this.options.i18nManifestFileName,
1089
+ // new RawSource(JSON.stringify(manifest, null, 2))
1090
+ // );
1091
+ // console.log(`Emitted manifest: ${this.options.i18nManifestFileName}`);
1092
+ // }
1093
+ // getChunkFileName(chunkId, locale) {
1094
+ // return this.options.filenameTemplate
1095
+ // .replace('[locale]', locale)
1096
+ // .replace('[name]', chunkId)
1097
+ // .replace('[chunkhash]', this.getContentHash(chunkId, locale));
1098
+ // }
1099
+ // getContentHash(chunkId, locale) {
1100
+ // return crypto
1101
+ // .createHash('md5')
1102
+ // .update(`${chunkId}_${locale}`)
1103
+ // .digest('hex')
1104
+ // .slice(0, 8);
1105
+ // }
1106
+ // }
1107
+ // module.exports = I18nSplitPlugin;
1108
+ //const { getAllI18nGroupedBySection, getPropertiesAsJSON } = require('');
1109
+ const {
1110
+ RawSource
1111
+ } = require('webpack-sources');
1112
+ const {
1113
+ getPropertiesAsJSON,
1114
+ jsonToString
1115
+ } = require('../I18nSplitPlugin/utils/propertiesUtils');
1116
+ const path = require('path');
1117
+ const crypto = require('crypto');
1118
+ const NullFactory = require('webpack/lib/NullFactory');
1119
+ const {
1120
+ I18nDependency,
1121
+ I18nDependencyTemplate
1122
+ } = require('../I18nSplitPlugin/I18nDependency');
1123
+ class I18nPlugin {
1124
+ constructor(options = {}) {
1125
+ const {
1126
+ jsResource,
1127
+ localeVarName = 'document.documentElement.lang',
1128
+ jsonpFunc = 'window.loadI18nChunk',
1129
+ propertiesFolder,
1130
+ disableDefault = false,
1131
+ filenameTemplate = 'i18n-chunk/[locale]/[name].i18n.js',
1132
+ i18nManifestFileName = 'i18n-manifest.json',
1133
+ mainChunkName = 'main'
1134
+ } = options;
1135
+ this.options = {
1136
+ localeVarName,
1137
+ jsonpFunc,
1138
+ filenameTemplate,
1139
+ i18nManifestFileName,
1140
+ mainChunkName
1141
+ }; // Load i18n data
1142
+
1143
+ this.jsResourceI18nKeys = jsResource ? getPropertiesAsJSON(jsResource) : {};
1144
+ this.propertiesFolder = propertiesFolder;
1145
+ this.disableDefault = disableDefault; // Track keys and chunks
1146
+
1147
+ this.moduleKeys = new Map();
1148
+ this.chunkKeys = new Map();
1149
+ this.prevHashes = {};
1150
+ }
1151
+ apply(compiler) {
1152
+ // Main compilation hook
1153
+ compiler.hooks.thisCompilation.tap('I18nPlugin', compilation => {
1154
+ // Setup dependency handling
1155
+ compilation.dependencyFactories.set(I18nDependency, new NullFactory());
1156
+ compilation.dependencyTemplates.set(I18nDependency, new I18nDependencyTemplate()); // Parse modules for i18n keys
1157
+
1158
+ const handler = parser => {
1159
+ parser.hooks.program.tap('I18nPlugin', (ast, comments) => {
1160
+ const {
1161
+ module
1162
+ } = parser.state; // Only process JS files
1163
+
1164
+ if (!(module && /\.jsx?$/.test(module.resource))) {
1165
+ return;
1166
+ } // Collect keys from source
1167
+
1168
+ const keys = this.collectKeys(ast, comments);
1169
+ if (keys.length) {
1170
+ this.moduleKeys.set(module, keys);
1171
+ this.addDependency(module, keys);
1172
+ }
1173
+ });
1174
+ }; // Register parser hooks
1175
+
1176
+ compilation.normalModuleFactory.hooks.parser.for('javascript/auto').tap('I18nPlugin', handler);
1177
+ compilation.normalModuleFactory.hooks.parser.for('javascript/dynamic').tap('I18nPlugin', handler);
1178
+ }); // Emit hook for generating files
1179
+
1180
+ compiler.hooks.emit.tap('I18nPlugin', compilation => {
1181
+ this.emitFiles(compilation);
1182
+ });
1183
+ }
1184
+ collectKeys(ast, comments) {
1185
+ const keys = new Set(); // Walk AST
1186
+
1187
+ if (ast && ast.body) {
1188
+ const walk = node => {
1189
+ if (node.type === 'Literal' && typeof node.value === 'string') {
1190
+ if (this.jsResourceI18nKeys[node.value]) {
1191
+ keys.add(node.value);
1192
+ }
1193
+ }
1194
+ for (const key in node) {
1195
+ if (node[key] && typeof node[key] === 'object') {
1196
+ walk(node[key]);
1197
+ }
1198
+ }
1199
+ };
1200
+ ast.body.forEach(walk);
1201
+ } // Check comments
1202
+
1203
+ if (comments) {
1204
+ comments.forEach(comment => {
1205
+ if (comment.value.includes('I18N:')) {
1206
+ const key = comment.value.split('I18N:')[1].trim();
1207
+ if (this.jsResourceI18nKeys[key]) {
1208
+ keys.add(key);
1209
+ }
1210
+ }
1211
+ });
1212
+ }
1213
+ return Array.from(keys);
1214
+ }
1215
+ addDependency(module, keys) {
1216
+ const dep = new I18nDependency({
1217
+ identifier: `i18n-${module.id}`,
1218
+ i18nKeys: keys
1219
+ }, module.context);
1220
+ module.addDependency(dep);
1221
+ }
1222
+ emitFiles(compilation) {
1223
+ // Generate manifest
1224
+ const manifest = {}; // Process chunks
1225
+
1226
+ compilation.chunks.forEach(chunk => {
1227
+ const chunkKeys = new Set(); // Collect keys from chunk modules
1228
+
1229
+ Array.from(chunk.modulesIterable).forEach(module => {
1230
+ const keys = this.moduleKeys.get(module) || [];
1231
+ keys.forEach(key => chunkKeys.add(key));
1232
+ });
1233
+ if (chunkKeys.size) {
1234
+ // Generate i18n files for each locale
1235
+ const locales = fs.readdirSync(this.propertiesFolder).filter(f => f.includes('_') && f.endsWith('.properties')).map(f => f.split('_')[1].split('.')[0]);
1236
+ locales.forEach(locale => {
1237
+ const i18nData = {};
1238
+ chunkKeys.forEach(key => {
1239
+ i18nData[key] = this.jsResourceI18nKeys[key];
1240
+ });
1241
+ const source = `${this.options.jsonpFunc}(${jsonToString(i18nData)});`;
1242
+ const filename = this.getFilename(chunk, locale);
1243
+ compilation.assets[filename] = new RawSource(source);
1244
+ if (!manifest[chunk.id]) {
1245
+ manifest[chunk.id] = {};
1246
+ }
1247
+ manifest[chunk.id][locale] = filename;
1248
+ });
1249
+ }
1250
+ }); // Emit manifest
1251
+
1252
+ compilation.assets[this.options.i18nManifestFileName] = new RawSource(JSON.stringify(manifest, null, 2));
1253
+ }
1254
+ getFilename(chunk, locale) {
1255
+ return this.options.filenameTemplate.replace('[locale]', locale).replace('[name]', chunk.name || chunk.id).replace('[chunkhash]', chunk.contentHash['javascript']);
1256
+ }
1257
+ }
1258
+ module.exports = I18nPlugin;