@zohodesk/client_build_tool 0.0.18 → 0.0.19-i18n-exp.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(cat:*)",
5
+ "Bash(ls:*)",
6
+ "Bash(npm root:*)",
7
+ "Bash(grep:*)",
8
+ "Bash(source:*)",
9
+ "Bash(echo $CLAUDE_CODE_SUBAGENT_MODEL)",
10
+ "Bash(npm run devMode:*)",
11
+ "Bash(npm run start:*)",
12
+ "Bash(npm run build:*)",
13
+ "Bash(lsof:*)",
14
+ "Bash(xargs kill:*)",
15
+ "Bash(pkill:*)",
16
+ "Bash(node:*)",
17
+ "Bash(git -C /Users/ramaraj-14019/i18nIndexing_plugin/packages/client_build_tool status --short)",
18
+ "Bash(git -C /Users/ramaraj-14019/zoho_iM/zohoim_client/jsapps/imclient status --short)",
19
+ "Bash(git -C /Users/ramaraj-14019/zoho_iM/zohoim_client/jsapps/imclient diff --name-only)",
20
+ "Bash(git -C /Users/ramaraj-14019/zoho_iM/zohoim_client/jsapps/imclient status numericMap.json)",
21
+ "Bash(git -C /Users/ramaraj-14019/i18nIndexing_plugin/packages/client_build_tool status src/shared/bundler/webpack/utils/)",
22
+ "Bash(git -C /Users/ramaraj-14019/i18nIndexing_plugin/packages/client_build_tool show 3.0.0:src/shared/bundler/webpack/utils/)",
23
+ "Bash(git -C /Users/ramaraj-14019/i18nIndexing_plugin/packages/client_build_tool ls-tree:*)",
24
+ "Bash(git -C /Users/ramaraj-14019/i18nIndexing_plugin/packages/client_build_tool show 3.0.0:src/shared/bundler/webpack/custom_plugins/I18nSplitPlugin/utils/propertiesUtils.js)",
25
+ "Bash(curl:*)",
26
+ "Skill(ralph-loop:ralph-loop)",
27
+ "Bash(kill:*)",
28
+ "Bash(npm install:*)",
29
+ "Bash(npm run createEfc:*)",
30
+ "Bash(npm run i18n-sync:*)",
31
+ "Bash(git push:*)"
32
+ ]
33
+ }
34
+ }
@@ -179,6 +179,27 @@ var _default = {
179
179
  jsResource: null,
180
180
  propertiesFolder: null
181
181
  },
182
+ i18nIndexing: {
183
+ enable: {
184
+ value: false,
185
+ cli: 'i18n_indexing'
186
+ },
187
+ jsResourcePath: null,
188
+ propertiesFolderPath: null,
189
+ numericMapPath: null,
190
+ outputFolder: 'i18n-chunk',
191
+ numericFilenameTemplate: 'i18n-chunk/[locale]/numeric.i18n.js',
192
+ dynamicFilenameTemplate: 'i18n-chunk/[locale]/dynamic.i18n.js',
193
+ singleFile: false,
194
+ singleFileTemplate: '[locale].js',
195
+ jsonpFunc: 'window.loadI18nChunk',
196
+ htmlTemplateLabel: '{{--user-locale}}',
197
+ localeVarName: 'window.userLangCode',
198
+ includeContentHash: false,
199
+ emitFiles: true,
200
+ generateManifest: false,
201
+ manifestPath: null
202
+ },
182
203
  publicFolders: {
183
204
  dev: ['...'],
184
205
  prod: ['...']
@@ -96,6 +96,24 @@ var _default = {
96
96
  jsResource: null,
97
97
  propertiesFolder: null
98
98
  },
99
+ i18nIndexing: {
100
+ enable: false,
101
+ jsResourcePath: null,
102
+ propertiesFolderPath: null,
103
+ numericMapPath: null,
104
+ outputFolder: 'i18n-chunk',
105
+ numericFilenameTemplate: 'i18n-chunk/[locale]/numeric.i18n.js',
106
+ dynamicFilenameTemplate: 'i18n-chunk/[locale]/dynamic.i18n.js',
107
+ singleFile: false,
108
+ singleFileTemplate: '[locale].js',
109
+ jsonpFunc: 'window.loadI18nChunk',
110
+ htmlTemplateLabel: '{{--user-locale}}',
111
+ localeVarName: 'window.userLangCode',
112
+ includeContentHash: false,
113
+ emitFiles: true,
114
+ generateManifest: false,
115
+ manifestPath: null
116
+ },
99
117
  publicFolders: {
100
118
  dev: ['...'],
101
119
  prod: ['...']
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+
3
+ const path = require('path');
4
+
5
+ const {
6
+ sources,
7
+ Compilation
8
+ } = require('webpack');
9
+
10
+ const {
11
+ decodeUnicodeEscapes
12
+ } = require('../I18nSplitPlugin/utils/propertiesUtils');
13
+
14
+ const {
15
+ loadNumericMap,
16
+ loadI18nData
17
+ } = require('./utils/i18nDataLoader');
18
+
19
+ const {
20
+ createHash
21
+ } = require('../I18nSplitPlugin/createHash');
22
+
23
+ const {
24
+ pathCreator
25
+ } = require('../I18nSplitPlugin/pathCreator');
26
+
27
+ const {
28
+ RawSource
29
+ } = sources;
30
+ const pluginName = 'I18nNumericIndexPlugin';
31
+
32
+ class I18nNumericIndexPlugin {
33
+ constructor(options) {
34
+ if (!options) {
35
+ throw new Error('[I18nNumericIndexPlugin] options is required');
36
+ }
37
+
38
+ this.options = options;
39
+ }
40
+
41
+ emitChunk(compilation, filename, locale, data, manifest) {
42
+ const content = decodeUnicodeEscapes(JSON.stringify(data));
43
+ const fileContent = `${this.options.jsonpFunc}(${content});`;
44
+ const contentHash = createHash({
45
+ outputOptions: compilation.outputOptions,
46
+ content: fileContent
47
+ });
48
+ let outputPath = pathCreator(filename, compilation, {
49
+ hash: compilation.hash,
50
+ locale,
51
+ chunkName: null,
52
+ chunkId: locale,
53
+ chunkHash: null,
54
+ contentHash
55
+ });
56
+
57
+ if (this.options.includeContentHash && !filename.includes('[contenthash]')) {
58
+ outputPath = outputPath.replace(/\.js$/, `.${contentHash}.js`);
59
+ }
60
+
61
+ if (this.options.generateManifest) {
62
+ manifest[locale] = outputPath.split('/').pop();
63
+ }
64
+
65
+ if (this.options.emitFiles) {
66
+ compilation.emitAsset(outputPath, new RawSource(fileContent));
67
+ }
68
+
69
+ return outputPath;
70
+ }
71
+
72
+ buildNumericData(sortedKeys, totalKeys, jsResourceBase, localeData, englishData) {
73
+ const numericData = {};
74
+
75
+ for (let i = 0; i < totalKeys; i++) {
76
+ const key = sortedKeys[i];
77
+
78
+ if (key && jsResourceBase[key] !== undefined) {
79
+ numericData[i] = localeData[key] ?? englishData[key];
80
+ }
81
+ }
82
+
83
+ return numericData;
84
+ }
85
+
86
+ buildDynamicData(numericKeysSet, jsResourceBase, localeData, englishData) {
87
+ const dynamicData = {};
88
+
89
+ for (const key of Object.keys(jsResourceBase)) {
90
+ if (!numericKeysSet.has(key)) {
91
+ dynamicData[key] = localeData[key] ?? englishData[key];
92
+ }
93
+ }
94
+
95
+ return dynamicData;
96
+ }
97
+
98
+ processLocaleData(compilation, locale, {
99
+ sortedKeys,
100
+ totalKeys,
101
+ numericKeysSet,
102
+ jsResourceBase,
103
+ allI18n,
104
+ englishData,
105
+ manifest
106
+ }) {
107
+ const localeData = allI18n[locale] || {};
108
+ const numericData = this.buildNumericData(sortedKeys, totalKeys, jsResourceBase, localeData, englishData);
109
+ const dynamicData = this.buildDynamicData(numericKeysSet, jsResourceBase, localeData, englishData);
110
+
111
+ if (this.options.singleFile) {
112
+ const combinedData = { ...numericData,
113
+ ...dynamicData
114
+ };
115
+
116
+ if (Object.keys(combinedData).length > 0) {
117
+ const filename = `${this.options.outputFolder}/${this.options.singleFileTemplate}`;
118
+ this.emitChunk(compilation, filename, locale, combinedData, manifest);
119
+ }
120
+ } else {
121
+ if (Object.keys(numericData).length > 0) {
122
+ this.emitChunk(compilation, this.options.numericFilenameTemplate, locale, numericData, manifest);
123
+ }
124
+
125
+ if (Object.keys(dynamicData).length > 0) {
126
+ this.emitChunk(compilation, this.options.dynamicFilenameTemplate, locale, dynamicData, manifest);
127
+ }
128
+ }
129
+ }
130
+
131
+ emitManifest(compilation, manifest) {
132
+ if (!this.options.generateManifest || Object.keys(manifest).length === 0) {
133
+ return;
134
+ }
135
+
136
+ const manifestContent = JSON.stringify(manifest, null, 2);
137
+
138
+ if (this.options.emitFiles) {
139
+ compilation.emitAsset(this.options.manifestPath, new RawSource(manifestContent));
140
+ }
141
+ }
142
+
143
+ processI18nAssets(compilation) {
144
+ const mapPath = path.resolve(compilation.compiler.context, this.options.numericMapPath);
145
+ const {
146
+ sortedKeys,
147
+ totalKeys
148
+ } = loadNumericMap(mapPath, compilation);
149
+ const {
150
+ jsResourceBase,
151
+ allI18n,
152
+ locales
153
+ } = loadI18nData(this.options, compilation);
154
+ if (!locales.length) return;
155
+ const manifest = {};
156
+ const numericKeysSet = new Set(sortedKeys);
157
+ const englishData = allI18n.en_US || jsResourceBase;
158
+ const context = {
159
+ sortedKeys,
160
+ totalKeys,
161
+ numericKeysSet,
162
+ jsResourceBase,
163
+ allI18n,
164
+ englishData,
165
+ manifest
166
+ };
167
+
168
+ for (const locale of locales) {
169
+ this.processLocaleData(compilation, locale, context);
170
+ }
171
+
172
+ this.emitManifest(compilation, manifest);
173
+ }
174
+
175
+ apply(compiler) {
176
+ compiler.hooks.thisCompilation.tap(pluginName, compilation => {
177
+ compilation.hooks.processAssets.tapAsync({
178
+ name: pluginName,
179
+ stage: Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE
180
+ }, (_assets, callback) => {
181
+ if (!this.options.enable) {
182
+ return callback();
183
+ }
184
+
185
+ this.processI18nAssets(compilation);
186
+ callback();
187
+ });
188
+ });
189
+ }
190
+
191
+ }
192
+
193
+ module.exports = {
194
+ I18nNumericIndexPlugin
195
+ };
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+
3
+ const fs = require('fs');
4
+
5
+ const path = require('path');
6
+
7
+ const {
8
+ parseProperties
9
+ } = require('../../../utils/propertiesParser');
10
+
11
+ function loadPropertiesFile(filePath, compilation, description) {
12
+ try {
13
+ const content = fs.readFileSync(filePath, 'utf-8');
14
+ return parseProperties(content);
15
+ } catch (err) {
16
+ if (compilation) {
17
+ compilation.errors.push(new Error(`I18nNumericIndexPlugin: Error loading ${description}: ${err.message}`));
18
+ }
19
+
20
+ return {};
21
+ }
22
+ }
23
+
24
+ function loadNumericMap(numericMapPath, compilation) {
25
+ try {
26
+ const fileContent = fs.readFileSync(numericMapPath, 'utf-8');
27
+ const parsedData = JSON.parse(fileContent);
28
+ const numericIds = Object.values(parsedData.originalKeyToNumericId);
29
+ const maxId = numericIds.length > 0 ? Math.max(...numericIds) : -1;
30
+ const totalKeys = maxId + 1;
31
+ const sortedKeys = new Array(totalKeys);
32
+ Object.entries(parsedData.originalKeyToNumericId).forEach(([key, id]) => {
33
+ sortedKeys[id] = key;
34
+ });
35
+ return {
36
+ sortedKeys,
37
+ totalKeys
38
+ };
39
+ } catch (err) {
40
+ if (compilation) {
41
+ compilation.errors.push(new Error(`I18nNumericIndexPlugin: Error loading numeric map: ${err.message}`));
42
+ }
43
+
44
+ return {
45
+ sortedKeys: [],
46
+ totalKeys: 0
47
+ };
48
+ }
49
+ }
50
+
51
+ function loadAllLocaleFiles(propertiesPath, baseFileName, compilation) {
52
+ const allI18n = {};
53
+ const locales = [];
54
+
55
+ try {
56
+ const files = fs.readdirSync(propertiesPath);
57
+ files.forEach(file => {
58
+ if (file === baseFileName + '.properties') {
59
+ const filePath = path.join(propertiesPath, file);
60
+ const baseData = loadPropertiesFile(filePath, compilation, 'JSResources base');
61
+ allI18n['en_US'] = baseData;
62
+ locales.push('en_US');
63
+ }
64
+ });
65
+ files.forEach(file => {
66
+ if (!file.endsWith('.properties')) return;
67
+ const match = file.match(/^ApplicationResources_([a-z]{2}_[A-Z]{2})\.properties$/);
68
+
69
+ if (match) {
70
+ const locale = match[1];
71
+ const filePath = path.join(propertiesPath, file);
72
+ const localeData = loadPropertiesFile(filePath, compilation, `locale ${locale}`);
73
+ allI18n[locale] = { ...allI18n['en_US'],
74
+ ...localeData
75
+ };
76
+
77
+ if (!locales.includes(locale)) {
78
+ locales.push(locale);
79
+ }
80
+ }
81
+ });
82
+ } catch (err) {
83
+ if (compilation) {
84
+ compilation.errors.push(new Error(`I18nNumericIndexPlugin: Error reading properties folder: ${err.message}`));
85
+ }
86
+ }
87
+
88
+ return {
89
+ allI18n,
90
+ locales
91
+ };
92
+ }
93
+
94
+ function loadI18nData(options, compilation) {
95
+ const jsResourcePath = path.resolve(compilation.compiler.context, options.jsResourcePath);
96
+ const propertiesPath = path.resolve(compilation.compiler.context, options.propertiesFolderPath);
97
+ const baseFileName = path.basename(options.jsResourcePath, '.properties');
98
+ const jsResourceBase = loadPropertiesFile(jsResourcePath, compilation, 'JS resources');
99
+ const {
100
+ allI18n,
101
+ locales
102
+ } = loadAllLocaleFiles(propertiesPath, baseFileName, compilation);
103
+ return {
104
+ jsResourceBase,
105
+ allI18n,
106
+ locales
107
+ };
108
+ }
109
+
110
+ module.exports = {
111
+ loadPropertiesFile,
112
+ loadNumericMap,
113
+ loadAllLocaleFiles,
114
+ loadI18nData
115
+ };
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.decodeUnicodeEscapes = decodeUnicodeEscapes;
6
7
  exports.getAllI18n = getAllI18n;
7
8
  exports.getPropertiesAsJSON = getPropertiesAsJSON;
8
9
  exports.jsonToString = jsonToString;
@@ -13,6 +14,10 @@ var _path = require("path");
13
14
 
14
15
  var _constants = require("../../../../../constants");
15
16
 
17
+ function decodeUnicodeEscapes(str) {
18
+ return str.replace(/\\u([0-9A-Fa-f]{4})/g, (_, code) => String.fromCharCode(parseInt(code, 16)));
19
+ }
20
+
16
21
  function isComment(line) {
17
22
  return line[0] === '#';
18
23
  }
@@ -5,13 +5,21 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.jsLoaders = jsLoaders;
7
7
 
8
- var _babelLoaderConfig = require("./loaderConfigs/babelLoaderConfig");
8
+ var _babelLoaderConfig = require("./loaderConfigs/babelLoaderConfig.js");
9
+
10
+ var _i18nIdReplaceLoaderConfig = require("./loaderConfigs/i18nIdReplaceLoaderConfig.js");
9
11
 
10
12
  function jsLoaders(options) {
13
+ const useLoaders = [(0, _babelLoaderConfig.babelLoaderConfig)(options)];
14
+ const shouldUseNumericIndexing = options.i18nIndexing?.enable || options.i18nChunkSplit?.chunkSplitEnable && options.i18nChunkSplit.useNumericIndexing;
15
+
16
+ if (shouldUseNumericIndexing) {
17
+ useLoaders.push((0, _i18nIdReplaceLoaderConfig.i18nIdReplaceLoaderConfig)(options));
18
+ }
19
+
11
20
  return [{
12
21
  test: /\.js$/,
13
22
  exclude: /node_modules/,
14
- use: [(0, _babelLoaderConfig.babelLoaderConfig)(options)] // include: path.join(appPath, folder)
15
-
23
+ use: useLoaders
16
24
  }];
17
25
  }
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.i18nIdReplaceLoaderConfig = i18nIdReplaceLoaderConfig;
7
+
8
+ var _propertiesUtils = require("../custom_plugins/I18nSplitPlugin/utils/propertiesUtils.js");
9
+
10
+ function getI18nConfig(options) {
11
+ if (options.i18nIndexing?.enable) {
12
+ return {
13
+ jsResourcePath: options.i18nIndexing.jsResourcePath,
14
+ numericMapPath: options.i18nIndexing.numericMapPath
15
+ };
16
+ }
17
+
18
+ if (options.i18nChunkSplit?.chunkSplitEnable && options.i18nChunkSplit.useNumericIndexing) {
19
+ return {
20
+ jsResourcePath: options.i18nChunkSplit.jsResource,
21
+ numericMapPath: options.i18nChunkSplit.numericMapPath
22
+ };
23
+ }
24
+
25
+ return null;
26
+ }
27
+
28
+ function loadJSResources(jsResourcePath) {
29
+ const i18nData = (0, _propertiesUtils.getPropertiesAsJSON)(jsResourcePath);
30
+
31
+ if (Object.keys(i18nData).length === 0) {
32
+ console.warn(`[i18nIdReplaceLoaderConfig] Warning: No i18n data found in JSResource file: ${jsResourcePath}`);
33
+ return {};
34
+ }
35
+
36
+ return i18nData;
37
+ }
38
+
39
+ function i18nIdReplaceLoaderConfig(options) {
40
+ const config = getI18nConfig(options);
41
+
42
+ if (!config) {
43
+ throw new Error('i18nIdReplaceLoader requires either i18nIndexing to be enabled or i18nChunkSplit with useNumericIndexing');
44
+ }
45
+
46
+ if (!config.jsResourcePath) {
47
+ throw new Error('Missing required jsResourcePath in i18n options');
48
+ }
49
+
50
+ if (!config.numericMapPath) {
51
+ throw new Error('numericMapPath is required in i18nIndexing or i18nChunkSplit config');
52
+ }
53
+
54
+ return {
55
+ loader: require.resolve('../loaders/i18nIdReplaceLoader.js'),
56
+ options: {
57
+ allI18nData: loadJSResources(config.jsResourcePath),
58
+ numericMapPath: config.numericMapPath,
59
+ sourceMaps: false
60
+ }
61
+ };
62
+ }
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+
3
+ const fs = require('fs');
4
+
5
+ const parser = require('@babel/parser');
6
+
7
+ const traverse = require('@babel/traverse').default;
8
+
9
+ const generator = require('@babel/generator').default;
10
+
11
+ const t = require('@babel/types');
12
+
13
+ const {
14
+ getOptions
15
+ } = require('loader-utils');
16
+
17
+ function loadNumericMap(numericMapPath) {
18
+ if (!numericMapPath) {
19
+ console.warn('[i18nIdReplaceLoader] numericMapPath option is missing');
20
+ return null;
21
+ }
22
+
23
+ if (!fs.existsSync(numericMapPath)) {
24
+ console.warn(`[i18nIdReplaceLoader] Numeric map file not found: ${numericMapPath}`);
25
+ return null;
26
+ }
27
+
28
+ try {
29
+ const fileContent = fs.readFileSync(numericMapPath, 'utf-8');
30
+ const parsedData = JSON.parse(fileContent);
31
+
32
+ if (!parsedData?.originalKeyToNumericId) {
33
+ console.warn(`[i18nIdReplaceLoader] Invalid numeric map format: missing 'originalKeyToNumericId'`);
34
+ return null;
35
+ }
36
+
37
+ return parsedData.originalKeyToNumericId;
38
+ } catch (err) {
39
+ console.warn(`[i18nIdReplaceLoader] Error reading numeric map: ${err.message}`);
40
+ return null;
41
+ }
42
+ }
43
+
44
+ function transformSource(source, resourcePath, numericIdMap, allI18nData, options) {
45
+ const ast = parser.parse(source, {
46
+ sourceType: 'module',
47
+ plugins: ['jsx', 'typescript', 'classProperties', 'optionalChaining', 'nullishCoalescingOperator'],
48
+ sourceFilename: resourcePath
49
+ });
50
+ let hasTransformations = false;
51
+ traverse(ast, {
52
+ StringLiteral(path) {
53
+ const {
54
+ node
55
+ } = path;
56
+
57
+ if (!(node.value in allI18nData)) {
58
+ return;
59
+ }
60
+
61
+ if (node.value in numericIdMap) {
62
+ path.replaceWith(t.stringLiteral(String(numericIdMap[node.value])));
63
+ hasTransformations = true;
64
+ }
65
+ }
66
+
67
+ });
68
+
69
+ if (!hasTransformations) {
70
+ return null;
71
+ }
72
+
73
+ return generator(ast, {
74
+ sourceMaps: !!options.sourceMaps,
75
+ sourceFileName: resourcePath,
76
+ retainLines: false,
77
+ comments: true
78
+ }, source);
79
+ }
80
+
81
+ module.exports = function i18nIdReplaceLoader(source, map) {
82
+ const resourcePath = this.resourcePath;
83
+ if (this.cacheable) this.cacheable();
84
+ const options = getOptions(this) || {};
85
+ const callback = this.async();
86
+
87
+ if (resourcePath.includes('node_modules') || !resourcePath.includes('src')) {
88
+ return callback(null, source, map);
89
+ }
90
+
91
+ if (!options.allI18nData) {
92
+ return callback(null, source, map);
93
+ }
94
+
95
+ if (options.numericMapPath) {
96
+ this.addDependency(options.numericMapPath);
97
+ }
98
+
99
+ const numericIdMap = loadNumericMap(options.numericMapPath);
100
+
101
+ if (!numericIdMap) {
102
+ return callback(null, source, map);
103
+ }
104
+
105
+ try {
106
+ const output = transformSource(source, resourcePath, numericIdMap, options.allI18nData, options);
107
+
108
+ if (output) {
109
+ callback(null, output.code, output.map);
110
+ } else {
111
+ callback(null, source, map);
112
+ }
113
+ } catch (err) {
114
+ callback(err);
115
+ }
116
+ };
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.configI18nNumericIndexPlugin = configI18nNumericIndexPlugin;
7
+
8
+ var _I18nNumericIndexPlugin = require("../custom_plugins/I18nNumericIndexPlugin/I18nNumericIndexPlugin.js");
9
+
10
+ var _readI18nValues = require("../custom_plugins/I18nSplitPlugin/readI18nValues.js");
11
+
12
+ function configI18nNumericIndexPlugin(options) {
13
+ if (!options.i18nIndexing?.enable) {
14
+ return null;
15
+ }
16
+
17
+ const i18nOpts = options.i18nIndexing;
18
+ const requiredOptions = ['jsResourcePath', 'propertiesFolderPath', 'numericMapPath', 'jsonpFunc', 'localeVarName'];
19
+ const missingOptions = requiredOptions.filter(opt => !i18nOpts[opt]);
20
+
21
+ if (missingOptions.length > 0) {
22
+ console.warn(`[configI18nNumericIndexPlugin] Missing required options: ${missingOptions.join(', ')}`);
23
+ return null;
24
+ }
25
+
26
+ if (i18nOpts.singleFile) {
27
+ if (!i18nOpts.singleFileTemplate) {
28
+ console.warn('[configI18nNumericIndexPlugin] singleFileTemplate is required when singleFile is true');
29
+ return null;
30
+ }
31
+ } else {
32
+ if (!i18nOpts.numericFilenameTemplate || !i18nOpts.numericFilenameTemplate.includes('[locale]')) {
33
+ console.warn('[configI18nNumericIndexPlugin] numericFilenameTemplate must include [locale] placeholder');
34
+ return null;
35
+ }
36
+
37
+ if (!i18nOpts.dynamicFilenameTemplate || !i18nOpts.dynamicFilenameTemplate.includes('[locale]')) {
38
+ console.warn('[configI18nNumericIndexPlugin] dynamicFilenameTemplate must include [locale] placeholder');
39
+ return null;
40
+ }
41
+ }
42
+
43
+ if (i18nOpts.generateManifest && !i18nOpts.manifestPath) {
44
+ console.warn('[configI18nNumericIndexPlugin] manifestPath is required when generateManifest is true');
45
+ return null;
46
+ }
47
+
48
+ const {
49
+ locales,
50
+ allI18nObject
51
+ } = (0, _readI18nValues.readI18nValues)({
52
+ jsResource: i18nOpts.jsResourcePath,
53
+ propertiesFolder: i18nOpts.propertiesFolderPath,
54
+ disableDefault: false
55
+ });
56
+ const numericIndexPluginOptions = {
57
+ enable: i18nOpts.enable,
58
+ jsResourcePath: i18nOpts.jsResourcePath,
59
+ propertiesFolderPath: i18nOpts.propertiesFolderPath,
60
+ numericMapPath: i18nOpts.numericMapPath,
61
+ locales,
62
+ allI18nObject,
63
+ outputFolder: i18nOpts.outputFolder,
64
+ numericFilenameTemplate: i18nOpts.numericFilenameTemplate,
65
+ dynamicFilenameTemplate: i18nOpts.dynamicFilenameTemplate,
66
+ singleFile: i18nOpts.singleFile,
67
+ singleFileTemplate: i18nOpts.singleFileTemplate,
68
+ jsonpFunc: i18nOpts.jsonpFunc,
69
+ includeContentHash: i18nOpts.includeContentHash,
70
+ emitFiles: i18nOpts.emitFiles,
71
+ generateManifest: i18nOpts.generateManifest,
72
+ manifestPath: i18nOpts.manifestPath
73
+ };
74
+ return new _I18nNumericIndexPlugin.I18nNumericIndexPlugin(numericIndexPluginOptions);
75
+ }
@@ -57,10 +57,11 @@ var _configInjectChunkGraphPlugin = require("./pluginConfigs/configInjectChunkGr
57
57
 
58
58
  var _configCssCustomOrderPlugin = require("./pluginConfigs/configCssCustomOrderPlugin");
59
59
 
60
- // import { IgnorePlugin } from 'webpack';
60
+ var _configI18nNumericIndexPlugin = require("./pluginConfigs/configI18nNumericIndexPlugin");
61
+
61
62
  function plugins(options) {
62
63
  const {
63
64
  webpackPlugins
64
65
  } = options;
65
- return [(0, _configEnvVariables.configEnvVariables)(options), (0, _configCustomAttributesPlugin.configCustomAttributesPlugin)(options), (0, _configTPHashMappingPlugin.configTPHashMappingPlugin)(options), (0, _configCopyPublicFolders.configCopyPublicFolders)(options), (0, _configIgnorePlugin.configIgnorePlugin)(options), (0, _configMiniCSSExtractPlugin.configMiniCSSExtractPlugin)(options), (0, _configSelectorWeightPlugin.configSelectorWeightPlugin)(options), (0, _configVariableConversionPlugin.configVariableConversionPlugin)(options), (0, _configI18nSplitPlugin.configI18nSplitPlugin)(options), (0, _configRtlCssPlugin.configRtlCssPlugin)(options), (0, _configHtmlWebpackPlugin.configHtmlWebpackPlugin)(options), (0, _configCustomScriptLoadingStrategyPlugin.configCustomScriptLoadingStrategyPlugin)(options), (0, _configCdnChangePlugin.configCdnChangePlugin)(options), (0, _configServiceWorkerPlugin.configServiceWorkerPlugin)(options), (0, _configEFCTemplatePlugin.configEFCTemplatePlugin)(options), (0, _configResourceHintsPlugin.configResourceHintsPlugin)(options), (0, _configBundleAnalyzer.configBundleAnalyzer)(options), (0, _configManifestJsonPlugin.configManifestJsonPlugin)(options), (0, _configSourceMapPlugin.configSourceMapPlugin)(options), (0, _configProgressPlugin.configProgressPlugin)(options), (0, _configBundleIntegrityReport.configBundleIntegrityReport)(options), (0, _configRuntimeResourceCleanup.configRuntimeResourceCleanup)(options), (0, _configMurphyInjectorPlugin.configMurphyInjectorPlugin)(options), (0, _configCssCustomOrderPlugin.configCssCustomOrderPlugin)(options), (0, _configChunkHierarchyPlugin.configChunkHierarchyPlugin)(options), ...webpackPlugins].filter(Boolean);
66
+ return [(0, _configEnvVariables.configEnvVariables)(options), (0, _configCustomAttributesPlugin.configCustomAttributesPlugin)(options), (0, _configTPHashMappingPlugin.configTPHashMappingPlugin)(options), (0, _configCopyPublicFolders.configCopyPublicFolders)(options), (0, _configIgnorePlugin.configIgnorePlugin)(options), (0, _configMiniCSSExtractPlugin.configMiniCSSExtractPlugin)(options), (0, _configSelectorWeightPlugin.configSelectorWeightPlugin)(options), (0, _configVariableConversionPlugin.configVariableConversionPlugin)(options), (0, _configI18nSplitPlugin.configI18nSplitPlugin)(options), (0, _configRtlCssPlugin.configRtlCssPlugin)(options), (0, _configHtmlWebpackPlugin.configHtmlWebpackPlugin)(options), (0, _configI18nNumericIndexPlugin.configI18nNumericIndexPlugin)(options), (0, _configCustomScriptLoadingStrategyPlugin.configCustomScriptLoadingStrategyPlugin)(options), (0, _configCdnChangePlugin.configCdnChangePlugin)(options), (0, _configServiceWorkerPlugin.configServiceWorkerPlugin)(options), (0, _configEFCTemplatePlugin.configEFCTemplatePlugin)(options), (0, _configResourceHintsPlugin.configResourceHintsPlugin)(options), (0, _configBundleAnalyzer.configBundleAnalyzer)(options), (0, _configManifestJsonPlugin.configManifestJsonPlugin)(options), (0, _configSourceMapPlugin.configSourceMapPlugin)(options), (0, _configProgressPlugin.configProgressPlugin)(options), (0, _configBundleIntegrityReport.configBundleIntegrityReport)(options), (0, _configRuntimeResourceCleanup.configRuntimeResourceCleanup)(options), (0, _configMurphyInjectorPlugin.configMurphyInjectorPlugin)(options), (0, _configCssCustomOrderPlugin.configCssCustomOrderPlugin)(options), (0, _configChunkHierarchyPlugin.configChunkHierarchyPlugin)(options), ...webpackPlugins].filter(Boolean);
66
67
  }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ const fs = require('fs');
4
+
5
+ function decodeUnicodeEscapes(str) {
6
+ return str.replace(/\\u([0-9A-Fa-f]{4})/g, (_, code) => String.fromCharCode(parseInt(code, 16)));
7
+ }
8
+
9
+ function parseProperties(content) {
10
+ const result = {};
11
+ const lines = content.split(/\r?\n/);
12
+
13
+ for (const line of lines) {
14
+ const trimmed = line.trim();
15
+
16
+ if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('!')) {
17
+ continue;
18
+ }
19
+
20
+ const separatorIndex = trimmed.search(/[=:]/);
21
+ if (separatorIndex === -1) continue;
22
+ const key = trimmed.slice(0, separatorIndex).trim().replace(/\\ /g, ' ');
23
+ const value = trimmed.slice(separatorIndex + 1).trim();
24
+
25
+ if (key) {
26
+ result[key] = decodeUnicodeEscapes(value);
27
+ }
28
+ }
29
+
30
+ return result;
31
+ }
32
+
33
+ module.exports = {
34
+ decodeUnicodeEscapes,
35
+ parseProperties
36
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zohodesk/client_build_tool",
3
- "version": "0.0.18",
3
+ "version": "0.0.19-i18n-exp.0",
4
4
  "description": "A CLI tool to build web applications and client libraries",
5
5
  "main": "lib/index.js",
6
6
  "bin": {