@zohodesk/client_build_tool 0.0.11-exp.17.0 → 0.0.11-exp.18.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.
- package/lib/schemas/defaultConfigValues.js +5 -0
- package/lib/schemas/defaultConfigValuesOnly.js +1 -0
- package/lib/shared/bundler/webpack/custom_plugins/I18nNumericIndexPlugin/I18nGroupRuntimeModule.js +0 -5
- package/lib/shared/bundler/webpack/custom_plugins/I18nNumericIndexPlugin/I18nNumericIndexHtmlInjectorPlugin.js +0 -1
- package/lib/shared/bundler/webpack/custom_plugins/I18nNumericIndexPlugin/I18nNumericIndexPlugin.js +36 -13
- package/lib/shared/bundler/webpack/loaderConfigs/i18nIdReplaceLoaderConfig.js +16 -6
- package/lib/shared/bundler/webpack/loaders/i18nIdReplaceLoader.js +43 -17
- package/lib/shared/bundler/webpack/pluginConfigs/configI18nNumericIndexPlugin.js +13 -7
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/example-single-file-config.js +0 -59
- package/packages/client_build_tool/test-i18n-config.js +0 -22
|
@@ -193,6 +193,11 @@ var _default = {
|
|
|
193
193
|
htmlTemplateLabel: '{{--user-locale}}',
|
|
194
194
|
localeVarName: 'window.userLangCode',
|
|
195
195
|
singleFile: false,
|
|
196
|
+
// When true, locales are restricted to keys present in base JSResources.properties
|
|
197
|
+
restrictToBaseKeys: {
|
|
198
|
+
value: false,
|
|
199
|
+
cli: 'i18n_restrict_to_base'
|
|
200
|
+
},
|
|
196
201
|
includeContentHash: false,
|
|
197
202
|
generateManifest: false,
|
|
198
203
|
manifestPath: null,
|
package/lib/shared/bundler/webpack/custom_plugins/I18nNumericIndexPlugin/I18nGroupRuntimeModule.js
CHANGED
|
@@ -29,7 +29,6 @@ class I18nGroupRuntimeModule extends _webpack.RuntimeModule {
|
|
|
29
29
|
return `
|
|
30
30
|
// I18n Group Loading Runtime
|
|
31
31
|
(function() {
|
|
32
|
-
console.log('[I18n Runtime] Initializing i18n group loader with groups:', ${JSON.stringify(chunkToGroup)});
|
|
33
32
|
var loadedGroups = {};
|
|
34
33
|
var chunkToGroup = ${JSON.stringify(chunkToGroup)};
|
|
35
34
|
|
|
@@ -52,7 +51,6 @@ class I18nGroupRuntimeModule extends _webpack.RuntimeModule {
|
|
|
52
51
|
.replace('[locale]', locale)
|
|
53
52
|
.replace('i18n-chunk/', __webpack_require__.p + 'i18n-chunk/');
|
|
54
53
|
|
|
55
|
-
console.log('[I18n Runtime] Loading i18n group:', groupName, 'from:', i18nUrl);
|
|
56
54
|
|
|
57
55
|
var script = document.createElement('script');
|
|
58
56
|
script.src = i18nUrl;
|
|
@@ -60,12 +58,10 @@ class I18nGroupRuntimeModule extends _webpack.RuntimeModule {
|
|
|
60
58
|
|
|
61
59
|
script.onload = function() {
|
|
62
60
|
loadedGroups[groupName] = true;
|
|
63
|
-
console.log('[I18n Runtime] Successfully loaded i18n group:', groupName);
|
|
64
61
|
resolve();
|
|
65
62
|
};
|
|
66
63
|
|
|
67
64
|
script.onerror = function() {
|
|
68
|
-
console.error('[I18n Runtime] Failed to load i18n group:', groupName);
|
|
69
65
|
reject(new Error('Failed to load i18n group: ' + groupName));
|
|
70
66
|
};
|
|
71
67
|
|
|
@@ -84,7 +80,6 @@ class I18nGroupRuntimeModule extends _webpack.RuntimeModule {
|
|
|
84
80
|
// Check if this chunk needs an i18n group
|
|
85
81
|
var groupName = chunkToGroup[chunkId];
|
|
86
82
|
if (groupName && !loadedGroups[groupName]) {
|
|
87
|
-
console.log('[I18n Runtime] Chunk', chunkId, 'requires i18n group:', groupName);
|
|
88
83
|
// Load the i18n group before the chunk
|
|
89
84
|
var i18nPromise = loadI18nGroup(groupName);
|
|
90
85
|
// Chain the promises so i18n loads first
|
|
@@ -19,7 +19,6 @@ class I18nNumericIndexHtmlInjectorPlugin {
|
|
|
19
19
|
HtmlWebpackPlugin.getHooks(compilation).beforeAssetTagGeneration.tapAsync(pluginName, (hookData, cb) => {
|
|
20
20
|
// Skip HTML injection if injectI18nUrlInIndex is false
|
|
21
21
|
if (!this.options.injectI18nUrlInIndex) {
|
|
22
|
-
console.log('[I18nNumericIndexHtmlInjectorPlugin] Skipping HTML injection (injectI18nUrlInIndex is false)');
|
|
23
22
|
return cb(null, hookData);
|
|
24
23
|
}
|
|
25
24
|
|
package/lib/shared/bundler/webpack/custom_plugins/I18nNumericIndexPlugin/I18nNumericIndexPlugin.js
CHANGED
|
@@ -26,7 +26,6 @@ const pluginName = 'I18nNumericIndexPlugin';
|
|
|
26
26
|
|
|
27
27
|
class I18nNumericIndexPlugin {
|
|
28
28
|
constructor(options) {
|
|
29
|
-
console.log('[I18nNumericIndexPlugin] Plugin initialized with options:', JSON.stringify(options, null, 2));
|
|
30
29
|
this.options = { ...options,
|
|
31
30
|
singleFile: options.singleFile || false,
|
|
32
31
|
singleFileTemplate: options.singleFileTemplate || '[locale].js',
|
|
@@ -34,8 +33,7 @@ class I18nNumericIndexPlugin {
|
|
|
34
33
|
generateManifest: options.generateManifest || false,
|
|
35
34
|
outputFolder: options.outputFolder || 'i18n-chunk',
|
|
36
35
|
manifestPath: options.manifestPath || null,
|
|
37
|
-
emitFiles: options.emitFiles !== undefined ? options.emitFiles : true
|
|
38
|
-
|
|
36
|
+
emitFiles: options.emitFiles !== undefined ? options.emitFiles : true
|
|
39
37
|
};
|
|
40
38
|
this.numericMap = {};
|
|
41
39
|
this.customGroups = {};
|
|
@@ -48,11 +46,9 @@ class I18nNumericIndexPlugin {
|
|
|
48
46
|
compiler.hooks.thisCompilation.tap(pluginName, compilation => {
|
|
49
47
|
// Add runtime module for group-based loading
|
|
50
48
|
if (this.options.customGroups) {
|
|
51
|
-
// Add runtime module unconditionally to ensure it's always available
|
|
52
49
|
compilation.hooks.additionalTreeRuntimeRequirements.tap(pluginName, (chunk, set) => {
|
|
53
50
|
// Only add to the main/entry chunk to avoid duplication
|
|
54
51
|
if (chunk.name === 'main' || chunk.hasRuntime()) {
|
|
55
|
-
console.log('[I18nNumericIndexPlugin] Adding I18nGroupRuntimeModule to chunk:', chunk.name || chunk.id);
|
|
56
52
|
compilation.addRuntimeModule(chunk, new _I18nGroupRuntimeModule.I18nGroupRuntimeModule({
|
|
57
53
|
customGroups: this.options.customGroups,
|
|
58
54
|
localeVarName: this.options.localeVarName,
|
|
@@ -104,7 +100,6 @@ class I18nNumericIndexPlugin {
|
|
|
104
100
|
}
|
|
105
101
|
|
|
106
102
|
processI18nFiles(compilation) {
|
|
107
|
-
console.log('[I18nNumericIndexPlugin] Starting to process i18n files - plugin is active');
|
|
108
103
|
const {
|
|
109
104
|
jsResourcePath,
|
|
110
105
|
propertiesFolderPath,
|
|
@@ -116,7 +111,6 @@ class I18nNumericIndexPlugin {
|
|
|
116
111
|
} = this.options;
|
|
117
112
|
|
|
118
113
|
if (!jsResourcePath || !propertiesFolderPath) {
|
|
119
|
-
console.log('[I18nNumericIndexPlugin] Missing required paths - jsResourcePath:', jsResourcePath, 'propertiesFolderPath:', propertiesFolderPath);
|
|
120
114
|
return;
|
|
121
115
|
} // Load existing numeric map if available
|
|
122
116
|
|
|
@@ -135,7 +129,8 @@ class I18nNumericIndexPlugin {
|
|
|
135
129
|
} // Read JSResources.properties
|
|
136
130
|
|
|
137
131
|
|
|
138
|
-
|
|
132
|
+
let jsResourceKeys = (0, _propertiesUtils.getPropertiesAsJSON)(jsResourcePath);
|
|
133
|
+
jsResourceKeys = this.normalizeObjectValues(jsResourceKeys); // Parse custom groups from banner markers
|
|
139
134
|
|
|
140
135
|
if (customGroups) {
|
|
141
136
|
this.parseCustomGroups(jsResourcePath, customGroups);
|
|
@@ -146,6 +141,10 @@ class I18nNumericIndexPlugin {
|
|
|
146
141
|
folderPath: propertiesFolderPath,
|
|
147
142
|
disableDefault: false,
|
|
148
143
|
jsResourceI18nKeys: jsResourceKeys
|
|
144
|
+
}); // Normalize locale values
|
|
145
|
+
|
|
146
|
+
Object.keys(allI18nObject).forEach(loc => {
|
|
147
|
+
allI18nObject[loc] = this.normalizeObjectValues(allI18nObject[loc]);
|
|
149
148
|
}); // For en_US, use only JSResources (don't merge with ApplicationResources_en_US)
|
|
150
149
|
|
|
151
150
|
if (allI18nObject['en_US']) {
|
|
@@ -153,6 +152,21 @@ class I18nNumericIndexPlugin {
|
|
|
153
152
|
} else {
|
|
154
153
|
// If en_US doesn't exist in the folder, create it from JSResources
|
|
155
154
|
allI18nObject['en_US'] = jsResourceKeys;
|
|
155
|
+
} // If requested, restrict all locales to base (English) keys only
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
if (this.options.restrictToBaseKeys) {
|
|
159
|
+
const baseKeys = Object.keys(jsResourceKeys);
|
|
160
|
+
Object.keys(allI18nObject).forEach(locale => {
|
|
161
|
+
const merged = { ...jsResourceKeys,
|
|
162
|
+
...allI18nObject[locale]
|
|
163
|
+
};
|
|
164
|
+
const filtered = {};
|
|
165
|
+
baseKeys.forEach(k => {
|
|
166
|
+
filtered[k] = merged[k];
|
|
167
|
+
});
|
|
168
|
+
allI18nObject[locale] = filtered;
|
|
169
|
+
});
|
|
156
170
|
}
|
|
157
171
|
|
|
158
172
|
const locales = Object.keys(allI18nObject); // Process each locale
|
|
@@ -315,9 +329,8 @@ class I18nNumericIndexPlugin {
|
|
|
315
329
|
emitChunk(compilation, filenameTemplate, locale, data, jsonpFunc, groupName = null, fileType = null) {
|
|
316
330
|
if (!filenameTemplate || Object.keys(data).length === 0) {
|
|
317
331
|
return null;
|
|
318
|
-
}
|
|
332
|
+
} // Generate content regardless of emitFiles flag (needed for runtime)
|
|
319
333
|
|
|
320
|
-
console.log('[I18nNumericIndexPlugin] Processing chunk for locale:', locale, 'fileType:', fileType, 'dataKeys:', Object.keys(data).length, 'groupName:', groupName, 'emitFiles:', this.options.emitFiles); // Generate content regardless of emitFiles flag (needed for runtime)
|
|
321
334
|
|
|
322
335
|
const content = this.generateChunkContent(data, jsonpFunc, groupName);
|
|
323
336
|
let outputPath = this.constructFilePath(filenameTemplate, locale); // Handle [contenthash] placeholder in template
|
|
@@ -350,10 +363,7 @@ class I18nNumericIndexPlugin {
|
|
|
350
363
|
|
|
351
364
|
|
|
352
365
|
if (this.options.emitFiles) {
|
|
353
|
-
console.log('[I18nNumericIndexPlugin] Emitting file:', outputPath);
|
|
354
366
|
compilation.emitAsset(outputPath, new RawSource(content));
|
|
355
|
-
} else {
|
|
356
|
-
console.log('[I18nNumericIndexPlugin] Skipping file emission for:', outputPath, '(emitFiles is false)');
|
|
357
367
|
}
|
|
358
368
|
|
|
359
369
|
return outputPath;
|
|
@@ -371,6 +381,19 @@ class I18nNumericIndexPlugin {
|
|
|
371
381
|
return `${jsonpFunc}(${jsonString});`;
|
|
372
382
|
}
|
|
373
383
|
|
|
384
|
+
normalizeValue(value) {
|
|
385
|
+
if (typeof value !== 'string') return value;
|
|
386
|
+
return value.replace(/\\t/g, '\t').replace(/\\n/g, '\n').replace(/\\r/g, '\r').replace(/\\f/g, '\f').replace(/\\:/g, ':').replace(/\\=/g, '=').replace(/\\ /g, ' ');
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
normalizeObjectValues(obj) {
|
|
390
|
+
const out = {};
|
|
391
|
+
Object.keys(obj || {}).forEach(k => {
|
|
392
|
+
out[k] = this.normalizeValue(obj[k]);
|
|
393
|
+
});
|
|
394
|
+
return out;
|
|
395
|
+
}
|
|
396
|
+
|
|
374
397
|
}
|
|
375
398
|
|
|
376
399
|
exports.default = I18nNumericIndexPlugin;
|
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
const {
|
|
4
4
|
getPropertiesAsJSON
|
|
5
5
|
} = require('../custom_plugins/I18nSplitPlugin/utils/propertiesUtils');
|
|
6
|
-
/**
|
|
7
|
-
* Load i18n data from JSResources file once for all chunks
|
|
8
|
-
*/
|
|
9
6
|
|
|
7
|
+
const fs = require('fs');
|
|
10
8
|
|
|
11
9
|
function loadJSResourcesOnce(options) {
|
|
12
10
|
let jsResourcePath; // Determine the JSResource path based on configuration
|
|
@@ -36,10 +34,20 @@ function loadJSResourcesOnce(options) {
|
|
|
36
34
|
throw new Error(`Error reading JSResource file ${jsResourcePath}: ${err.message}`);
|
|
37
35
|
}
|
|
38
36
|
}
|
|
39
|
-
/**
|
|
40
|
-
* Configure the i18n ID replace loader
|
|
41
|
-
*/
|
|
42
37
|
|
|
38
|
+
function readNumericMapOnce(numericMapPath) {
|
|
39
|
+
if (!numericMapPath) return null;
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
if (!fs.existsSync(numericMapPath)) return null;
|
|
43
|
+
const fileContent = fs.readFileSync(numericMapPath, 'utf-8');
|
|
44
|
+
const parsed = JSON.parse(fileContent);
|
|
45
|
+
if (!parsed) return null;
|
|
46
|
+
return parsed.originalKeyToNumericId ? parsed.originalKeyToNumericId : parsed;
|
|
47
|
+
} catch (err) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
43
51
|
|
|
44
52
|
function i18nIdReplaceLoaderConfig(options, webpackContext) {
|
|
45
53
|
let numericMapPath; // Determine the numeric map path based on configuration
|
|
@@ -61,10 +69,12 @@ function i18nIdReplaceLoaderConfig(options, webpackContext) {
|
|
|
61
69
|
|
|
62
70
|
const i18nKeyReplaceLoaderPath = require.resolve('../loaders/i18nIdReplaceLoader.js');
|
|
63
71
|
|
|
72
|
+
const numericIdMap = readNumericMapOnce(numericMapPath);
|
|
64
73
|
const loaderOptions = {
|
|
65
74
|
allI18nData: allI18nData,
|
|
66
75
|
sourceMaps: false,
|
|
67
76
|
numericMapPath: numericMapPath,
|
|
77
|
+
numericIdMap: numericIdMap || undefined,
|
|
68
78
|
devMode: options.i18nIndexing?.devMode || false,
|
|
69
79
|
includePaths: options.i18nIndexing?.loaderOptions?.includePaths || [],
|
|
70
80
|
excludePaths: options.i18nIndexing?.loaderOptions?.excludePaths || ['node_modules', 'tests']
|
|
@@ -20,7 +20,16 @@ module.exports = function i18nIdReplaceLoader(source, map) {
|
|
|
20
20
|
const resourcePath = this.resourcePath;
|
|
21
21
|
this.cacheable && this.cacheable();
|
|
22
22
|
const options = getOptions(this) || {};
|
|
23
|
-
const callback = this.async();
|
|
23
|
+
const callback = this.async();
|
|
24
|
+
let numericMapAbsPath = null;
|
|
25
|
+
|
|
26
|
+
if (options.numericMapPath) {
|
|
27
|
+
try {
|
|
28
|
+
numericMapAbsPath = path.isAbsolute(options.numericMapPath) ? options.numericMapPath : path.resolve(this.rootContext || this.context || process.cwd(), options.numericMapPath);
|
|
29
|
+
this.addDependency(numericMapAbsPath);
|
|
30
|
+
} catch (e) {}
|
|
31
|
+
} // Skip files in excluded paths
|
|
32
|
+
|
|
24
33
|
|
|
25
34
|
if (options.excludePaths) {
|
|
26
35
|
const shouldExclude = options.excludePaths.some(excludePath => resourcePath.includes(excludePath));
|
|
@@ -42,29 +51,46 @@ module.exports = function i18nIdReplaceLoader(source, map) {
|
|
|
42
51
|
|
|
43
52
|
if (!options.allI18nData || Object.keys(options.allI18nData).length === 0) {
|
|
44
53
|
return callback(new Error(`i18nIdReplaceLoader: 'allI18nData' option is missing or empty`));
|
|
45
|
-
} // Load numeric ID mapping
|
|
54
|
+
} // Load numeric ID mapping (use injected map if provided; fallback to memoized file read)
|
|
46
55
|
|
|
47
56
|
|
|
48
|
-
let numericIdMap = null;
|
|
57
|
+
let numericIdMap = options.numericIdMap || null;
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
try {
|
|
60
|
+
if (!numericIdMap && (numericMapAbsPath || options.numericMapPath)) {
|
|
61
|
+
// Module-level static cache
|
|
62
|
+
if (!global.__CBT_I18N_NUMERIC_MAP_CACHE__) {
|
|
63
|
+
global.__CBT_I18N_NUMERIC_MAP_CACHE__ = {};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const cache = global.__CBT_I18N_NUMERIC_MAP_CACHE__;
|
|
67
|
+
const p = numericMapAbsPath || options.numericMapPath;
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const stat = fs.statSync(p);
|
|
71
|
+
const key = `${p}`;
|
|
72
|
+
const mtime = stat && stat.mtimeMs ? stat.mtimeMs : 0;
|
|
73
|
+
const hit = cache[key];
|
|
74
|
+
|
|
75
|
+
if (hit && hit.mtime === mtime && hit.map) {
|
|
76
|
+
numericIdMap = hit.map;
|
|
77
|
+
} else if (fs.existsSync(p)) {
|
|
78
|
+
const txt = fs.readFileSync(p, 'utf-8');
|
|
79
|
+
const parsed = JSON.parse(txt);
|
|
80
|
+
const mapObj = parsed && parsed.originalKeyToNumericId ? parsed.originalKeyToNumericId : parsed;
|
|
81
|
+
|
|
82
|
+
if (mapObj && typeof mapObj === 'object') {
|
|
83
|
+
cache[key] = {
|
|
84
|
+
mtime,
|
|
85
|
+
map: mapObj
|
|
86
|
+
};
|
|
87
|
+
numericIdMap = mapObj;
|
|
63
88
|
}
|
|
64
89
|
}
|
|
90
|
+
} catch (e) {// ignore and proceed without map
|
|
65
91
|
}
|
|
66
|
-
} catch (err) {// Silently continue without numeric mapping
|
|
67
92
|
}
|
|
93
|
+
} catch (e) {// ignore
|
|
68
94
|
} // If no numeric map available, return source as-is
|
|
69
95
|
|
|
70
96
|
|
|
@@ -11,8 +11,6 @@ var _I18nNumericIndexHtmlInjectorPlugin = require("../custom_plugins/I18nNumeric
|
|
|
11
11
|
|
|
12
12
|
var _readI18nValues = require("../custom_plugins/I18nSplitPlugin/readI18nValues");
|
|
13
13
|
|
|
14
|
-
var _path = _interopRequireDefault(require("path"));
|
|
15
|
-
|
|
16
14
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
15
|
|
|
18
16
|
function configI18nNumericIndexPlugin(options) {
|
|
@@ -22,7 +20,17 @@ function configI18nNumericIndexPlugin(options) {
|
|
|
22
20
|
|
|
23
21
|
const i18nOpts = options.i18nIndexing;
|
|
24
22
|
const isDevelopment = options.isDevelopment || false; // Get isDevelopment from options
|
|
25
|
-
//
|
|
23
|
+
// If we are only doing numeric ID replacement (no files to emit and no HTML injection, and no custom groups),
|
|
24
|
+
// we can skip creating plugin instances to save build time.
|
|
25
|
+
|
|
26
|
+
const emitFiles = i18nOpts.emitFiles !== undefined ? i18nOpts.emitFiles : true;
|
|
27
|
+
const injectHtml = i18nOpts.injectI18nUrlInIndex !== undefined ? i18nOpts.injectI18nUrlInIndex : true;
|
|
28
|
+
const hasCustomGroups = !!(i18nOpts.customGroups && Object.keys(i18nOpts.customGroups || {}).length);
|
|
29
|
+
|
|
30
|
+
if (!emitFiles && !injectHtml && !hasCustomGroups) {
|
|
31
|
+
return [];
|
|
32
|
+
} // Validate required options
|
|
33
|
+
|
|
26
34
|
|
|
27
35
|
const requiredOptions = ['jsResourcePath', 'propertiesFolderPath', 'numericMapPath', 'jsonpFunc', 'htmlTemplateLabel', 'localeVarName'];
|
|
28
36
|
const missingOptions = requiredOptions.filter(opt => !i18nOpts[opt]);
|
|
@@ -77,14 +85,13 @@ function configI18nNumericIndexPlugin(options) {
|
|
|
77
85
|
jsonpFunc: i18nOpts.jsonpFunc,
|
|
78
86
|
localeVarName: i18nOpts.localeVarName,
|
|
79
87
|
singleFile: i18nOpts.singleFile || false,
|
|
88
|
+
restrictToBaseKeys: i18nOpts.restrictToBaseKeys || false,
|
|
80
89
|
includeContentHash: i18nOpts.includeContentHash || false,
|
|
81
90
|
generateManifest: i18nOpts.generateManifest || false,
|
|
82
91
|
manifestPath: i18nOpts.manifestPath || null,
|
|
83
92
|
customGroups: i18nOpts.customGroups || null,
|
|
84
93
|
emitFiles: i18nOpts.emitFiles !== undefined ? i18nOpts.emitFiles : true,
|
|
85
|
-
|
|
86
|
-
isDevelopment: isDevelopment // Pass through for reference
|
|
87
|
-
|
|
94
|
+
isDevelopment: isDevelopment
|
|
88
95
|
}; // HTML injector options
|
|
89
96
|
|
|
90
97
|
const htmlInjectorOptions = {
|
|
@@ -95,7 +102,6 @@ function configI18nNumericIndexPlugin(options) {
|
|
|
95
102
|
htmlTemplateLabel: i18nOpts.htmlTemplateLabel,
|
|
96
103
|
singleFile: i18nOpts.singleFile || false,
|
|
97
104
|
i18nAssetsPublicPathPrefix: '',
|
|
98
|
-
// HtmlWebpackPlugin handles publicPath
|
|
99
105
|
injectI18nUrlInIndex: i18nOpts.injectI18nUrlInIndex !== undefined ? i18nOpts.injectI18nUrlInIndex : true,
|
|
100
106
|
// Control HTML injection
|
|
101
107
|
isDevelopment: isDevelopment
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zohodesk/client_build_tool",
|
|
3
|
-
"version": "0.0.11-exp.
|
|
3
|
+
"version": "0.0.11-exp.17.0",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@zohodesk/client_build_tool",
|
|
9
|
-
"version": "0.0.11-exp.
|
|
9
|
+
"version": "0.0.11-exp.17.0",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@babel/cli": "7.17.10",
|
package/package.json
CHANGED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
// Example configuration for single-file i18n mode
|
|
2
|
-
// When singleFile is true, output will be: i18n/en_US.js, i18n/fr_FR.js, etc.
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
i18nIndexing: {
|
|
6
|
-
enable: true,
|
|
7
|
-
|
|
8
|
-
// Output folder for all i18n files
|
|
9
|
-
outputFolder: 'i18n',
|
|
10
|
-
|
|
11
|
-
// Input paths
|
|
12
|
-
jsResourcePath: './resources/ApplicationResources.properties',
|
|
13
|
-
propertiesFolderPath: './resources',
|
|
14
|
-
numericMapPath: './numericMap.json',
|
|
15
|
-
|
|
16
|
-
// Single-file mode configuration
|
|
17
|
-
singleFile: true,
|
|
18
|
-
singleFileTemplate: '[locale].js', // Will create: i18n/en_US.js, i18n/fr_FR.js, etc.
|
|
19
|
-
|
|
20
|
-
// These are ignored in single-file mode but kept for backward compatibility
|
|
21
|
-
numericFilenameTemplate: '[locale]/numeric.i18n.js',
|
|
22
|
-
dynamicFilenameTemplate: '[locale]/dynamic.i18n.js',
|
|
23
|
-
|
|
24
|
-
// Runtime configuration
|
|
25
|
-
jsonpFunc: 'window.loadI18n',
|
|
26
|
-
htmlTemplateLabel: '{{--user-locale}}',
|
|
27
|
-
localeVarName: 'window.userLangCode',
|
|
28
|
-
|
|
29
|
-
// Optimization options
|
|
30
|
-
includeContentHash: true, // Will add hash: i18n/en_US.abc123.js
|
|
31
|
-
generateManifest: true,
|
|
32
|
-
manifestPath: 'i18n/manifest.json', // Custom manifest location
|
|
33
|
-
|
|
34
|
-
// Loader options
|
|
35
|
-
loaderOptions: {
|
|
36
|
-
includePaths: ['src'],
|
|
37
|
-
excludePaths: ['node_modules', 'tests']
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/*
|
|
43
|
-
Output structure with these settings:
|
|
44
|
-
|
|
45
|
-
build/
|
|
46
|
-
├── i18n/
|
|
47
|
-
│ ├── en_US.abc123.js # Combined numeric + dynamic keys with content hash
|
|
48
|
-
│ ├── fr_FR.def456.js
|
|
49
|
-
│ ├── de_DE.ghi789.js
|
|
50
|
-
│ └── manifest.json # Maps original names to hashed versions
|
|
51
|
-
└── index.html # HTML with injected script tag for locale
|
|
52
|
-
|
|
53
|
-
Manifest content example:
|
|
54
|
-
{
|
|
55
|
-
"i18n/en_US.js": "en_US.abc123.js",
|
|
56
|
-
"i18n/fr_FR.js": "fr_FR.def456.js",
|
|
57
|
-
"i18n/de_DE.js": "de_DE.ghi789.js"
|
|
58
|
-
}
|
|
59
|
-
*/
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
// Test configuration for i18n indexing features
|
|
2
|
-
module.exports = {
|
|
3
|
-
i18nIndexing: {
|
|
4
|
-
enable: true,
|
|
5
|
-
outputFolder: 'i18n', // Changed from default 'i18n-chunk'
|
|
6
|
-
jsResourcePath: './test-data/JSResources.properties',
|
|
7
|
-
propertiesFolderPath: './test-data/properties',
|
|
8
|
-
numericMapPath: './test-data/i18n-numeric-map.json',
|
|
9
|
-
numericFilenameTemplate: '[locale]/numeric.js',
|
|
10
|
-
dynamicFilenameTemplate: '[locale]/dynamic.js',
|
|
11
|
-
jsonpFunc: 'window.loadI18n',
|
|
12
|
-
htmlTemplateLabel: '{{locale}}',
|
|
13
|
-
localeVarName: 'window.userLocale',
|
|
14
|
-
singleFile: false,
|
|
15
|
-
includeContentHash: true, // Enable content hashing
|
|
16
|
-
generateManifest: true, // Enable manifest generation
|
|
17
|
-
loaderOptions: {
|
|
18
|
-
includePaths: ['src'],
|
|
19
|
-
excludePaths: ['node_modules', 'tests', 'lib']
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
};
|