i18ntk 2.1.0 → 2.3.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/README.md +87 -50
- package/main/i18ntk-analyze.js +63 -63
- package/main/i18ntk-backup-class.js +37 -41
- package/main/i18ntk-backup.js +28 -30
- package/main/i18ntk-complete.js +75 -74
- package/main/i18ntk-doctor.js +7 -6
- package/main/i18ntk-fixer.js +3 -3
- package/main/i18ntk-init.js +49 -13
- package/main/i18ntk-scanner.js +2 -2
- package/main/i18ntk-sizing.js +36 -37
- package/main/i18ntk-summary.js +4 -4
- package/main/i18ntk-ui.js +95 -96
- package/main/i18ntk-usage.js +31 -19
- package/main/i18ntk-validate.js +78 -27
- package/main/manage/commands/AnalyzeCommand.js +71 -73
- package/main/manage/commands/CommandRouter.js +15 -12
- package/main/manage/commands/FixerCommand.js +94 -38
- package/main/manage/commands/ScannerCommand.js +2 -2
- package/main/manage/commands/ValidateCommand.js +87 -36
- package/main/manage/index.js +165 -152
- package/main/manage/managers/DebugMenu.js +6 -6
- package/main/manage/managers/InteractiveMenu.js +6 -6
- package/main/manage/managers/LanguageMenu.js +12 -6
- package/main/manage/managers/SettingsMenu.js +6 -6
- package/main/manage/services/AuthenticationService.js +5 -6
- package/main/manage/services/ConfigurationService.js +22 -34
- package/main/manage/services/FileManagementService.js +6 -6
- package/main/manage/services/InitService.js +44 -8
- package/main/manage/services/UsageService.js +24 -12
- package/package.json +21 -42
- package/settings/settings-cli.js +5 -5
- package/settings/settings-manager.js +984 -968
- package/ui-locales/de.json +12 -11
- package/ui-locales/en.json +12 -11
- package/ui-locales/es.json +12 -11
- package/ui-locales/fr.json +12 -11
- package/ui-locales/ja.json +12 -11
- package/ui-locales/ru.json +12 -11
- package/ui-locales/zh.json +12 -11
- package/utils/config-helper.js +27 -16
- package/utils/config-manager.js +8 -7
- package/utils/i18n-helper.js +161 -166
- package/utils/init-helper.js +3 -2
- package/utils/json-output.js +11 -10
- package/{scripts → utils}/locale-optimizer.js +61 -60
- package/utils/logger.js +4 -4
- package/utils/safe-json.js +3 -3
- package/utils/secure-backup.js +8 -7
- package/utils/setup-enforcer.js +63 -98
- package/main/i18ntk-go.js +0 -283
- package/main/i18ntk-java.js +0 -380
- package/main/i18ntk-js.js +0 -512
- package/main/i18ntk-manage.js +0 -1694
- package/main/i18ntk-php.js +0 -462
- package/main/i18ntk-py.js +0 -379
- package/main/i18ntk-settings.js +0 -23
- package/main/manage/index-fixed.js +0 -1447
- package/scripts/build-lite.js +0 -279
- package/scripts/deprecate-versions.js +0 -317
- package/scripts/export-translations.js +0 -84
- package/scripts/fix-all-i18n.js +0 -236
- package/scripts/fix-and-purify-i18n.js +0 -233
- package/scripts/fix-locale-control-chars.js +0 -110
- package/scripts/lint-locales.js +0 -80
- package/scripts/prepublish-dev.js +0 -221
- package/scripts/prepublish.js +0 -362
- package/scripts/security-check.js +0 -117
- package/scripts/sync-translations.js +0 -151
- package/scripts/sync-ui-locales.js +0 -20
- package/scripts/validate-all-translations.js +0 -195
- package/scripts/verify-deprecations.js +0 -157
- package/scripts/verify-translations.js +0 -63
- package/utils/security-fixed.js +0 -609
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* @module services/AuthenticationService
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const AdminAuth = require('../../../utils/admin-auth');
|
|
7
|
+
const AdminAuth = require('../../../utils/admin-auth');
|
|
8
|
+
const cliHelper = require('../../../utils/cli-helper');
|
|
8
9
|
|
|
9
10
|
module.exports = class AuthenticationService {
|
|
10
11
|
constructor(config = {}) {
|
|
@@ -74,8 +75,7 @@ module.exports = class AuthenticationService {
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
console.log(ui ? ui.t('adminCli.authRequired') : 'Admin authentication required');
|
|
77
|
-
const
|
|
78
|
-
const pin = await cliHelper.promptPin(ui ? ui.t('adminCli.enterPin') : 'Enter PIN: ');
|
|
78
|
+
const pin = await cliHelper.promptPin(ui ? ui.t('adminCli.enterPin') : 'Enter PIN: ');
|
|
79
79
|
const isValid = await this.verifyPin(pin);
|
|
80
80
|
|
|
81
81
|
if (!isValid) {
|
|
@@ -131,8 +131,7 @@ module.exports = class AuthenticationService {
|
|
|
131
131
|
* @returns {Promise<string>} User input or empty string
|
|
132
132
|
*/
|
|
133
133
|
async prompt(question) {
|
|
134
|
-
|
|
135
|
-
// If interactive not available, return empty string to avoid hangs
|
|
134
|
+
// If interactive not available, return empty string to avoid hangs
|
|
136
135
|
if (!process.stdin.isTTY || process.stdin.destroyed) {
|
|
137
136
|
console.log('\n⚠️ Interactive input not available, using default response.');
|
|
138
137
|
return Promise.resolve('');
|
|
@@ -260,4 +259,4 @@ module.exports = class AuthenticationService {
|
|
|
260
259
|
process.exit(1);
|
|
261
260
|
}
|
|
262
261
|
}
|
|
263
|
-
};
|
|
262
|
+
};
|
|
@@ -8,12 +8,14 @@ const path = require('path');
|
|
|
8
8
|
const configManager = require('../../../settings/settings-manager');
|
|
9
9
|
const { loadTranslations, t, refreshLanguageFromSettings } = require('../../../utils/i18n-helper');
|
|
10
10
|
|
|
11
|
-
const { createPrompt, isInteractive } = require('../../../utils/prompt-helper');
|
|
12
|
-
const { loadConfig, saveConfig, ensureConfigDefaults } = require('../../../utils/config');
|
|
13
|
-
const { getUnifiedConfig, ensureInitialized, validateSourceDir } = require('../../../utils/config-helper');
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
11
|
+
const { createPrompt, isInteractive } = require('../../../utils/prompt-helper');
|
|
12
|
+
const { loadConfig, saveConfig, ensureConfigDefaults } = require('../../../utils/config');
|
|
13
|
+
const { getUnifiedConfig, ensureInitialized, validateSourceDir } = require('../../../utils/config-helper');
|
|
14
|
+
const { checkInitialized } = require('../../../utils/init-helper');
|
|
15
|
+
const cliHelper = require('../../../utils/cli-helper');
|
|
16
|
+
const pkg = require('../../../package.json');
|
|
17
|
+
const SetupEnforcer = require('../../../utils/setup-enforcer');
|
|
18
|
+
const FrameworkDetectionService = require('./FrameworkDetectionService');
|
|
17
19
|
|
|
18
20
|
module.exports = class ConfigurationService {
|
|
19
21
|
constructor(config = {}) {
|
|
@@ -54,9 +56,8 @@ module.exports = class ConfigurationService {
|
|
|
54
56
|
loadTranslations(uiLanguage);
|
|
55
57
|
|
|
56
58
|
// Validate source directory exists
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
validateSourceDir(this.config.sourceDir, 'i18ntk-manage');
|
|
59
|
+
try {
|
|
60
|
+
validateSourceDir(this.config.sourceDir, 'i18ntk-manage');
|
|
60
61
|
} catch (err) {
|
|
61
62
|
console.log(t('init.requiredTitle'));
|
|
62
63
|
console.log(t('init.requiredBody'));
|
|
@@ -102,23 +103,18 @@ module.exports = class ConfigurationService {
|
|
|
102
103
|
// Ensure setup is complete before running any operations
|
|
103
104
|
await SetupEnforcer.checkSetupCompleteAsync();
|
|
104
105
|
|
|
105
|
-
prompt = createPrompt({ noPrompt: args.noPrompt
|
|
106
|
-
const interactive = isInteractive({ noPrompt: args.noPrompt
|
|
106
|
+
prompt = createPrompt({ noPrompt: args.noPrompt });
|
|
107
|
+
const interactive = isInteractive({ noPrompt: args.noPrompt });
|
|
107
108
|
|
|
108
109
|
// Load settings and UI language
|
|
109
110
|
const settings = this.settings || (this.configManager.loadSettings ? this.configManager.loadSettings() : (this.configManager.getConfig ? this.configManager.getConfig() : {}));
|
|
110
111
|
const uiLanguage = args.uiLanguage || settings.uiLanguage || settings.language || this.config.uiLanguage || 'en';
|
|
111
112
|
loadTranslations(uiLanguage);
|
|
112
113
|
|
|
113
|
-
if (args.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (args.help) {
|
|
119
|
-
this.showHelp();
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
114
|
+
if (args.help) {
|
|
115
|
+
this.showHelp();
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
122
118
|
|
|
123
119
|
let cfgAfterInitCheck = {};
|
|
124
120
|
if (interactive) {
|
|
@@ -155,11 +151,7 @@ module.exports = class ConfigurationService {
|
|
|
155
151
|
* @returns {Promise<Object>} Configuration object if initialized
|
|
156
152
|
*/
|
|
157
153
|
async ensureInitializedOrExit(prompt) {
|
|
158
|
-
const {
|
|
159
|
-
const cliHelper = require('../../../utils/cli-helper');
|
|
160
|
-
const pkg = require('../../../package.json');
|
|
161
|
-
|
|
162
|
-
const { initialized, config } = await checkInitialized();
|
|
154
|
+
const { initialized, config } = await checkInitialized();
|
|
163
155
|
|
|
164
156
|
if (!initialized) {
|
|
165
157
|
console.log('\nThis project is not yet initialized with i18ntk.');
|
|
@@ -224,8 +216,7 @@ module.exports = class ConfigurationService {
|
|
|
224
216
|
console.log('Framework detection prompt will be suppressed for this version.');
|
|
225
217
|
} else if (action === 'detect') {
|
|
226
218
|
// Run framework detection
|
|
227
|
-
const
|
|
228
|
-
const frameworkService = new FrameworkDetectionService();
|
|
219
|
+
const frameworkService = new FrameworkDetectionService();
|
|
229
220
|
frameworkService.initialize(this.configManager);
|
|
230
221
|
|
|
231
222
|
const { detectedLanguage, detectedFramework } = await frameworkService.detectEnvironmentAndFramework();
|
|
@@ -260,8 +251,7 @@ module.exports = class ConfigurationService {
|
|
|
260
251
|
* @returns {Promise<boolean>} True if frameworks detected, false otherwise
|
|
261
252
|
*/
|
|
262
253
|
async checkI18nDependencies() {
|
|
263
|
-
const
|
|
264
|
-
const frameworkService = new FrameworkDetectionService();
|
|
254
|
+
const frameworkService = new FrameworkDetectionService();
|
|
265
255
|
frameworkService.initialize(this.configManager);
|
|
266
256
|
return await frameworkService.checkI18nDependencies(null);
|
|
267
257
|
}
|
|
@@ -274,8 +264,7 @@ module.exports = class ConfigurationService {
|
|
|
274
264
|
* @returns {Promise<Object>} Updated configuration
|
|
275
265
|
*/
|
|
276
266
|
async maybePromptFramework(prompt, cfg, currentVersion) {
|
|
277
|
-
const
|
|
278
|
-
const frameworkService = new FrameworkDetectionService();
|
|
267
|
+
const frameworkService = new FrameworkDetectionService();
|
|
279
268
|
frameworkService.initialize(this.configManager);
|
|
280
269
|
return await frameworkService.maybePromptFramework(prompt, cfg, currentVersion);
|
|
281
270
|
}
|
|
@@ -392,8 +381,7 @@ module.exports = class ConfigurationService {
|
|
|
392
381
|
* @returns {Promise<string>} User input or empty string
|
|
393
382
|
*/
|
|
394
383
|
prompt(question) {
|
|
395
|
-
|
|
396
|
-
// If interactive not available, return empty string to avoid hangs
|
|
384
|
+
// If interactive not available, return empty string to avoid hangs
|
|
397
385
|
if (!process.stdin.isTTY || process.stdin.destroyed) {
|
|
398
386
|
console.log('\n⚠️ Interactive input not available, using default response.');
|
|
399
387
|
return Promise.resolve('');
|
|
@@ -446,4 +434,4 @@ module.exports = class ConfigurationService {
|
|
|
446
434
|
getUI() {
|
|
447
435
|
return this.ui;
|
|
448
436
|
}
|
|
449
|
-
};
|
|
437
|
+
};
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* @module services/FileManagementService
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const fs = require('fs');
|
|
9
|
-
const SecurityUtils = require('../../../utils/security');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const SecurityUtils = require('../../../utils/security');
|
|
10
|
+
const cliHelper = require('../../../utils/cli-helper');
|
|
10
11
|
|
|
11
12
|
module.exports = class FileManagementService {
|
|
12
13
|
constructor(config = {}) {
|
|
@@ -108,8 +109,7 @@ module.exports = class FileManagementService {
|
|
|
108
109
|
const authRequired = await this.isAuthRequiredForScript('deleteReports');
|
|
109
110
|
if (authRequired) {
|
|
110
111
|
console.log(`\n${ui ? ui.t('adminPin.protectedAccess') : 'Protected Access'}`);
|
|
111
|
-
const
|
|
112
|
-
const pin = await cliHelper.promptPin((ui ? ui.t('adminPin.enterPin') : 'Enter PIN: ') + ': ');
|
|
112
|
+
const pin = await cliHelper.promptPin((ui ? ui.t('adminPin.enterPin') : 'Enter PIN: ') + ': ');
|
|
113
113
|
const isValid = await this.verifyPin(pin);
|
|
114
114
|
if (!isValid) {
|
|
115
115
|
console.log(ui ? ui.t('adminPin.invalidPin') : 'Invalid PIN');
|
|
@@ -365,4 +365,4 @@ module.exports = class FileManagementService {
|
|
|
365
365
|
// For now, return true as a placeholder
|
|
366
366
|
return true;
|
|
367
367
|
}
|
|
368
|
-
};
|
|
368
|
+
};
|
|
@@ -681,7 +681,7 @@ class InitService {
|
|
|
681
681
|
}
|
|
682
682
|
|
|
683
683
|
// Interactive admin PIN setup
|
|
684
|
-
async promptAdminPinSetup() {
|
|
684
|
+
async promptAdminPinSetup() {
|
|
685
685
|
const { ask, askHidden, flushStdout } = require('../../../utils/cli');
|
|
686
686
|
|
|
687
687
|
console.log('\n' + t('init.adminPinSetupOptional'));
|
|
@@ -733,8 +733,31 @@ class InitService {
|
|
|
733
733
|
}
|
|
734
734
|
} else {
|
|
735
735
|
console.log(t('init.skippingAdminPinSetup'));
|
|
736
|
-
}
|
|
737
|
-
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
async promptBackupConfiguration(skipPrompt = false) {
|
|
740
|
+
const defaultBackupConfig = { enabled: false, maxBackups: 1, location: './i18ntk-backups' };
|
|
741
|
+
if (skipPrompt || !process.stdin.isTTY) {
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
const { ask } = require('../../../utils/cli');
|
|
746
|
+
console.log('\nBackup Settings');
|
|
747
|
+
console.log('Backups are disabled by default to avoid backup recursion and repo pollution.');
|
|
748
|
+
const enableAnswer = await ask('Enable automatic backups? (y/N): ');
|
|
749
|
+
const enabled = ['y', 'yes'].includes(String(enableAnswer || '').trim().toLowerCase());
|
|
750
|
+
|
|
751
|
+
if (!enabled) {
|
|
752
|
+
return defaultBackupConfig;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
const keepAnswer = await ask('How many backups should be kept automatically (1-3, default 1): ');
|
|
756
|
+
const parsedKeep = parseInt(String(keepAnswer || '').trim(), 10);
|
|
757
|
+
const maxBackups = Number.isInteger(parsedKeep) ? Math.min(Math.max(parsedKeep, 1), 3) : 1;
|
|
758
|
+
|
|
759
|
+
return { enabled: true, maxBackups, location: './i18ntk-backups' };
|
|
760
|
+
}
|
|
738
761
|
|
|
739
762
|
// Interactive language selection
|
|
740
763
|
async selectLanguages(skipPrompt = false) {
|
|
@@ -845,11 +868,24 @@ class InitService {
|
|
|
845
868
|
// Prompt for admin PIN setup if not already configured
|
|
846
869
|
const securitySettings = configManager.getConfig().security || {};
|
|
847
870
|
|
|
848
|
-
if (!securitySettings.adminPinEnabled && securitySettings.adminPinPromptOnInit !== false && !args.noPrompt) {
|
|
849
|
-
const { flushStdout } = require('../../../utils/cli');
|
|
850
|
-
await flushStdout();
|
|
851
|
-
await this.promptAdminPinSetup();
|
|
852
|
-
}
|
|
871
|
+
if (!securitySettings.adminPinEnabled && securitySettings.adminPinPromptOnInit !== false && !args.noPrompt) {
|
|
872
|
+
const { flushStdout } = require('../../../utils/cli');
|
|
873
|
+
await flushStdout();
|
|
874
|
+
await this.promptAdminPinSetup();
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
const backupSettings = await this.promptBackupConfiguration(args.noPrompt);
|
|
878
|
+
if (backupSettings) {
|
|
879
|
+
await configManager.updateConfig({
|
|
880
|
+
backup: {
|
|
881
|
+
...(this.config.backup || {}),
|
|
882
|
+
...backupSettings
|
|
883
|
+
}
|
|
884
|
+
});
|
|
885
|
+
this.config.backup = { ...(this.config.backup || {}), ...backupSettings };
|
|
886
|
+
} else if (!this.config.backup) {
|
|
887
|
+
this.config.backup = { enabled: false, maxBackups: 1, location: './i18ntk-backups' };
|
|
888
|
+
}
|
|
853
889
|
|
|
854
890
|
// Get target languages - use args.languages if provided
|
|
855
891
|
let targetLanguages = args.languages || await this.selectLanguages(args.noPrompt);
|
|
@@ -130,9 +130,9 @@ class UsageService {
|
|
|
130
130
|
this.config.includeExtensions = ['.js', '.jsx', '.ts', '.tsx', '.py', '.pyx', '.pyi'];
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
await SecurityUtils.logSecurityEvent(t('usage.analyzerInitialized'), { component: 'i18ntk-usage' });
|
|
133
|
+
await SecurityUtils.logSecurityEvent(t('usage.analyzerInitialized'), 'info', { component: 'i18ntk-usage' });
|
|
134
134
|
} catch (error) {
|
|
135
|
-
await SecurityUtils.logSecurityEvent(t('usage.analyzerInitFailed'), { component: 'i18ntk-usage', error: error.message });
|
|
135
|
+
await SecurityUtils.logSecurityEvent(t('usage.analyzerInitFailed'), 'error', { component: 'i18ntk-usage', error: error.message });
|
|
136
136
|
throw error;
|
|
137
137
|
}
|
|
138
138
|
}
|
|
@@ -237,7 +237,7 @@ class UsageService {
|
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
239
|
} catch (error) {
|
|
240
|
-
await SecurityUtils.logSecurityEvent(t('usage.translationDiscoveryError'), {
|
|
240
|
+
await SecurityUtils.logSecurityEvent(t('usage.translationDiscoveryError'), 'error', {
|
|
241
241
|
component: 'i18ntk-usage',
|
|
242
242
|
directory: currentDir,
|
|
243
243
|
error: error.message
|
|
@@ -311,7 +311,7 @@ class UsageService {
|
|
|
311
311
|
}
|
|
312
312
|
}
|
|
313
313
|
} catch (error) {
|
|
314
|
-
await SecurityUtils.logSecurityEvent(t('usage.fileTraversalError'), {
|
|
314
|
+
await SecurityUtils.logSecurityEvent(t('usage.fileTraversalError'), 'error', {
|
|
315
315
|
component: 'i18ntk-usage',
|
|
316
316
|
directory: currentDir,
|
|
317
317
|
error: error.message
|
|
@@ -466,7 +466,7 @@ class UsageService {
|
|
|
466
466
|
if (isDebug) {
|
|
467
467
|
console.error(error.stack);
|
|
468
468
|
}
|
|
469
|
-
await SecurityUtils.logSecurityEvent(t('usage.translationFileParseError'), {
|
|
469
|
+
await SecurityUtils.logSecurityEvent(t('usage.translationFileParseError'), 'error', {
|
|
470
470
|
component: 'i18ntk-usage',
|
|
471
471
|
file: fileInfo.filePath,
|
|
472
472
|
error: error.message
|
|
@@ -474,7 +474,7 @@ class UsageService {
|
|
|
474
474
|
}
|
|
475
475
|
}
|
|
476
476
|
} catch (error) {
|
|
477
|
-
await SecurityUtils.logSecurityEvent(t('usage.translationKeysLoadError'), {
|
|
477
|
+
await SecurityUtils.logSecurityEvent(t('usage.translationKeysLoadError'), 'error', {
|
|
478
478
|
component: 'i18ntk-usage',
|
|
479
479
|
error: error.message
|
|
480
480
|
});
|
|
@@ -512,10 +512,22 @@ class UsageService {
|
|
|
512
512
|
return keys;
|
|
513
513
|
}
|
|
514
514
|
|
|
515
|
-
collectPlaceholderKeys(obj, prefix = '', language) {
|
|
516
|
-
const patterns = this.placeholderStyles[language] || [];
|
|
517
|
-
const regexes = patterns.
|
|
518
|
-
|
|
515
|
+
collectPlaceholderKeys(obj, prefix = '', language) {
|
|
516
|
+
const patterns = this.placeholderStyles[language] || [];
|
|
517
|
+
const regexes = patterns.reduce((compiled, pattern) => {
|
|
518
|
+
try {
|
|
519
|
+
compiled.push(new RegExp(pattern));
|
|
520
|
+
} catch (error) {
|
|
521
|
+
SecurityUtils.logSecurityEvent('Invalid placeholder regex pattern skipped', 'warn', {
|
|
522
|
+
component: 'i18ntk-usage',
|
|
523
|
+
language,
|
|
524
|
+
pattern,
|
|
525
|
+
error: error.message
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
return compiled;
|
|
529
|
+
}, []);
|
|
530
|
+
if (typeof obj !== 'object' || obj === null) return;
|
|
519
531
|
|
|
520
532
|
for (const [key, value] of Object.entries(obj)) {
|
|
521
533
|
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
@@ -1447,7 +1459,7 @@ class UsageService {
|
|
|
1447
1459
|
} catch (error) {
|
|
1448
1460
|
console.error(t('usage.analysisFailedError'), error.message);
|
|
1449
1461
|
this.closeReadline();
|
|
1450
|
-
SecurityUtils.logSecurityEvent(t('usage.usageAnalysisFailed'), {
|
|
1462
|
+
SecurityUtils.logSecurityEvent(t('usage.usageAnalysisFailed'), 'error', {
|
|
1451
1463
|
component: 'i18ntk-usage',
|
|
1452
1464
|
error: error.message
|
|
1453
1465
|
});
|
|
@@ -1499,4 +1511,4 @@ Analysis Features (v1.8.3):
|
|
|
1499
1511
|
}
|
|
1500
1512
|
}
|
|
1501
1513
|
|
|
1502
|
-
module.exports = UsageService;
|
|
1514
|
+
module.exports = UsageService;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "i18ntk",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "🚀 The fastest
|
|
3
|
+
"version": "2.3.0",
|
|
4
|
+
"description": "🚀 The fastest internationalization toolkit with 97% performance boost! Zero-dependency, enterprise-grade internationalization for React, Vue, Angular, Python, Java, PHP & more. Features PIN protection, auto framework detection, 7+ UI languages, and comprehensive translation management. Perfect for startups to enterprises.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"i18n",
|
|
7
7
|
"internationalization",
|
|
@@ -134,7 +134,6 @@
|
|
|
134
134
|
"./main/*": "./main/*",
|
|
135
135
|
"./utils/*": "./utils/*",
|
|
136
136
|
"./settings/*": "./settings/*",
|
|
137
|
-
"./scripts/*": "./scripts/*",
|
|
138
137
|
"./ui-locales/*": "./ui-locales/*",
|
|
139
138
|
"./package.json": "./package.json"
|
|
140
139
|
},
|
|
@@ -162,9 +161,17 @@
|
|
|
162
161
|
"main/",
|
|
163
162
|
"runtime/",
|
|
164
163
|
"utils/",
|
|
165
|
-
"scripts/",
|
|
166
164
|
"settings/",
|
|
167
165
|
"ui-locales/",
|
|
166
|
+
"!main/manage/index-fixed.js",
|
|
167
|
+
"!main/i18ntk-manage.js",
|
|
168
|
+
"!main/i18ntk-py.js",
|
|
169
|
+
"!main/i18ntk-js.js",
|
|
170
|
+
"!main/i18ntk-java.js",
|
|
171
|
+
"!main/i18ntk-php.js",
|
|
172
|
+
"!main/i18ntk-go.js",
|
|
173
|
+
"!main/i18ntk-settings.js",
|
|
174
|
+
"!utils/security-fixed.js",
|
|
168
175
|
"LICENSE",
|
|
169
176
|
"package.json",
|
|
170
177
|
"README.md"
|
|
@@ -220,50 +227,21 @@
|
|
|
220
227
|
},
|
|
221
228
|
"preferGlobal": true,
|
|
222
229
|
"versionInfo": {
|
|
223
|
-
"version": "2.
|
|
224
|
-
"releaseDate": "
|
|
225
|
-
"lastUpdated": "
|
|
230
|
+
"version": "2.3.0",
|
|
231
|
+
"releaseDate": "12/04/2026",
|
|
232
|
+
"lastUpdated": "12/04/2026",
|
|
226
233
|
"maintainer": "Vladimir Noskov",
|
|
227
234
|
"changelog": "./CHANGELOG.md",
|
|
228
235
|
"documentation": "./README.md",
|
|
229
236
|
"apiReference": "./docs/api/API_REFERENCE.md",
|
|
230
237
|
"majorChanges": [
|
|
231
|
-
"
|
|
232
|
-
"
|
|
233
|
-
"
|
|
234
|
-
"
|
|
235
|
-
"FRAMEWORK: Setup-complete projects are recognized as internal i18ntk framework to avoid repeated detection prompts",
|
|
236
|
-
"SECURITY: Reduced false-positive config sanitization warnings for valid date/time report settings"
|
|
238
|
+
"CRITICAL FIX: Resolved sizing and usage-analysis regressions in v2 command flow.",
|
|
239
|
+
"PACKAGING: Reduced publish footprint by removing internal development scripts and legacy fixed-file artifacts.",
|
|
240
|
+
"SECURITY: Hardened release checks and added explicit support guidance to update from pre-2.3.0 versions.",
|
|
241
|
+
"I18N: Completed internal UI locale parity and actionable untranslated-key cleanup across supported languages."
|
|
237
242
|
],
|
|
238
243
|
"breakingChanges": [],
|
|
239
|
-
"
|
|
240
|
-
"1.0.x",
|
|
241
|
-
"1.1.x",
|
|
242
|
-
"1.2.x",
|
|
243
|
-
"1.3.x",
|
|
244
|
-
"1.4.x",
|
|
245
|
-
"1.5.x",
|
|
246
|
-
"1.6.0",
|
|
247
|
-
"1.6.1",
|
|
248
|
-
"1.6.2",
|
|
249
|
-
"1.6.3",
|
|
250
|
-
"1.7.0",
|
|
251
|
-
"1.7.1",
|
|
252
|
-
"1.7.2",
|
|
253
|
-
"1.7.3",
|
|
254
|
-
"1.7.4",
|
|
255
|
-
"1.7.5",
|
|
256
|
-
"1.7.6",
|
|
257
|
-
"1.8.0",
|
|
258
|
-
"1.8.1",
|
|
259
|
-
"1.8.2",
|
|
260
|
-
"1.8.3",
|
|
261
|
-
"1.9.0",
|
|
262
|
-
"1.10.1",
|
|
263
|
-
"1.10.2",
|
|
264
|
-
"1.10.3"
|
|
265
|
-
],
|
|
266
|
-
"nextVersion": "2.2.0",
|
|
244
|
+
"nextVersion": "2.4.0",
|
|
267
245
|
"supportedNodeVersions": ">=16.0.0",
|
|
268
246
|
"supportedFrameworks": {
|
|
269
247
|
"react-i18next": ">=11.0.0",
|
|
@@ -284,7 +262,8 @@
|
|
|
284
262
|
"fastapi": ">=0.70.0",
|
|
285
263
|
"spring-boot": ">=2.5.0",
|
|
286
264
|
"laravel": ">=8.0.0"
|
|
287
|
-
}
|
|
265
|
+
},
|
|
266
|
+
"supportPolicy": "Versions earlier than 2.3.0 may be unstable or insecure. Upgrade to 2.3.0 or newer."
|
|
288
267
|
},
|
|
289
268
|
"_comment": "This package is zero-dependency and uses only native Node.js modules"
|
|
290
269
|
}
|
package/settings/settings-cli.js
CHANGED
|
@@ -12,7 +12,7 @@ const settingsManager = new SettingsManager();
|
|
|
12
12
|
const UIi18n = require('../main/i18ntk-ui');
|
|
13
13
|
const configManager = require('../utils/config-manager');
|
|
14
14
|
const { loadTranslations, t } = require('../utils/i18n-helper');
|
|
15
|
-
loadTranslations(null, path.resolve(__dirname, '..', '
|
|
15
|
+
loadTranslations(null, path.resolve(__dirname, '..', 'ui-locales'));
|
|
16
16
|
|
|
17
17
|
const AdminAuth = require('../utils/admin-auth');
|
|
18
18
|
const uiI18n = new UIi18n();
|
|
@@ -567,8 +567,8 @@ class SettingsCLI {
|
|
|
567
567
|
'backupRetention': { min: 1, max: 30, type: 'int', unit: 'days' },
|
|
568
568
|
'logRetention': { min: 1, max: 90, type: 'int', unit: 'days' },
|
|
569
569
|
'retentionDays': { min: 1, max: 365, type: 'int', unit: 'days' },
|
|
570
|
-
'maxBackups': { min: 1, max:
|
|
571
|
-
};
|
|
570
|
+
'maxBackups': { min: 1, max: 3, type: 'int' }
|
|
571
|
+
};
|
|
572
572
|
|
|
573
573
|
for (const [field, rules] of Object.entries(validations)) {
|
|
574
574
|
if (key.includes(field)) {
|
|
@@ -610,7 +610,7 @@ class SettingsCLI {
|
|
|
610
610
|
}
|
|
611
611
|
if (key === 'removeUiLanguages') {
|
|
612
612
|
if (this.rl && this.rl.pause) this.rl.pause();
|
|
613
|
-
const LocaleOptimizer = require('../
|
|
613
|
+
const LocaleOptimizer = require('../utils/locale-optimizer.js');
|
|
614
614
|
const optimizer = new LocaleOptimizer();
|
|
615
615
|
await optimizer.interactiveSelect();
|
|
616
616
|
// Re-initialize readline if it was closed by locale optimizer
|
|
@@ -2135,4 +2135,4 @@ Note: Use arrow keys and Enter to navigate the interactive menu.
|
|
|
2135
2135
|
console.error('Stack trace:', error.stack);
|
|
2136
2136
|
process.exit(1);
|
|
2137
2137
|
});
|
|
2138
|
-
}
|
|
2138
|
+
}
|