i18ntk 1.10.2 → 2.0.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 (108) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +141 -1191
  3. package/main/i18ntk-analyze.js +65 -84
  4. package/main/i18ntk-backup-class.js +420 -0
  5. package/main/i18ntk-backup.js +3 -3
  6. package/main/i18ntk-complete.js +90 -65
  7. package/main/i18ntk-doctor.js +123 -103
  8. package/main/i18ntk-fixer.js +61 -725
  9. package/main/i18ntk-go.js +14 -15
  10. package/main/i18ntk-init.js +77 -26
  11. package/main/i18ntk-java.js +27 -32
  12. package/main/i18ntk-js.js +70 -68
  13. package/main/i18ntk-manage.js +129 -30
  14. package/main/i18ntk-php.js +75 -75
  15. package/main/i18ntk-py.js +55 -56
  16. package/main/i18ntk-scanner.js +59 -57
  17. package/main/i18ntk-setup.js +9 -404
  18. package/main/i18ntk-sizing.js +6 -6
  19. package/main/i18ntk-summary.js +21 -18
  20. package/main/i18ntk-ui.js +11 -10
  21. package/main/i18ntk-usage.js +54 -18
  22. package/main/i18ntk-validate.js +13 -13
  23. package/main/manage/commands/AnalyzeCommand.js +1124 -0
  24. package/main/manage/commands/BackupCommand.js +62 -0
  25. package/main/manage/commands/CommandRouter.js +295 -0
  26. package/main/manage/commands/CompleteCommand.js +61 -0
  27. package/main/manage/commands/DoctorCommand.js +60 -0
  28. package/main/manage/commands/FixerCommand.js +624 -0
  29. package/main/manage/commands/InitCommand.js +62 -0
  30. package/main/manage/commands/ScannerCommand.js +654 -0
  31. package/main/manage/commands/SizingCommand.js +60 -0
  32. package/main/manage/commands/SummaryCommand.js +61 -0
  33. package/main/manage/commands/UsageCommand.js +60 -0
  34. package/main/manage/commands/ValidateCommand.js +978 -0
  35. package/main/manage/index-fixed.js +1447 -0
  36. package/main/manage/index.js +1462 -0
  37. package/main/manage/managers/DebugMenu.js +140 -0
  38. package/main/manage/managers/InteractiveMenu.js +177 -0
  39. package/main/manage/managers/LanguageMenu.js +62 -0
  40. package/main/manage/managers/SettingsMenu.js +53 -0
  41. package/main/manage/services/AuthenticationService.js +263 -0
  42. package/main/manage/services/ConfigurationService-fixed.js +449 -0
  43. package/main/manage/services/ConfigurationService.js +449 -0
  44. package/main/manage/services/FileManagementService.js +368 -0
  45. package/main/manage/services/FrameworkDetectionService.js +458 -0
  46. package/main/manage/services/InitService.js +1051 -0
  47. package/main/manage/services/SetupService.js +462 -0
  48. package/main/manage/services/SummaryService.js +450 -0
  49. package/main/manage/services/UsageService.js +1502 -0
  50. package/package.json +32 -29
  51. package/runtime/enhanced.d.ts +221 -221
  52. package/runtime/index.d.ts +29 -29
  53. package/runtime/index.full.d.ts +331 -331
  54. package/runtime/index.js +7 -6
  55. package/scripts/build-lite.js +17 -17
  56. package/scripts/deprecate-versions.js +23 -6
  57. package/scripts/export-translations.js +5 -5
  58. package/scripts/fix-all-i18n.js +3 -3
  59. package/scripts/fix-and-purify-i18n.js +3 -2
  60. package/scripts/fix-locale-control-chars.js +110 -0
  61. package/scripts/lint-locales.js +80 -0
  62. package/scripts/locale-optimizer.js +8 -8
  63. package/scripts/prepublish.js +21 -21
  64. package/scripts/security-check.js +117 -117
  65. package/scripts/sync-translations.js +4 -4
  66. package/scripts/sync-ui-locales.js +9 -8
  67. package/scripts/validate-all-translations.js +8 -7
  68. package/scripts/verify-deprecations.js +157 -161
  69. package/scripts/verify-translations.js +6 -5
  70. package/settings/i18ntk-config.json +282 -282
  71. package/settings/language-config.json +5 -5
  72. package/settings/settings-cli.js +9 -9
  73. package/settings/settings-manager.js +18 -18
  74. package/ui-locales/de.json +2417 -2348
  75. package/ui-locales/en.json +2415 -2352
  76. package/ui-locales/es.json +2425 -2353
  77. package/ui-locales/fr.json +2418 -2348
  78. package/ui-locales/ja.json +2463 -2361
  79. package/ui-locales/ru.json +2463 -2359
  80. package/ui-locales/zh.json +2418 -2351
  81. package/utils/admin-auth.js +2 -2
  82. package/utils/admin-cli.js +297 -297
  83. package/utils/admin-pin.js +9 -9
  84. package/utils/cli-helper.js +9 -9
  85. package/utils/config-helper.js +73 -104
  86. package/utils/config-manager.js +204 -171
  87. package/utils/config.js +5 -4
  88. package/utils/env-manager.js +249 -263
  89. package/utils/framework-detector.js +27 -24
  90. package/utils/i18n-helper.js +85 -41
  91. package/utils/init-helper.js +152 -94
  92. package/utils/json-output.js +98 -98
  93. package/utils/mini-commander.js +179 -0
  94. package/utils/missing-key-validator.js +5 -5
  95. package/utils/plugin-loader.js +40 -29
  96. package/utils/prompt.js +14 -44
  97. package/utils/safe-json.js +40 -0
  98. package/utils/secure-errors.js +3 -3
  99. package/utils/security-check-improved.js +390 -0
  100. package/utils/security-config.js +5 -5
  101. package/utils/security-fixed.js +607 -0
  102. package/utils/security.js +652 -602
  103. package/utils/setup-enforcer.js +136 -44
  104. package/utils/setup-validator.js +33 -32
  105. package/utils/ultra-performance-optimizer.js +11 -9
  106. package/utils/watch-locales.js +2 -1
  107. package/utils/prompt-fixed.js +0 -55
  108. package/utils/security-check.js +0 -454
@@ -145,9 +145,9 @@ function showFrameworkWarningOnce(ui) {
145
145
  try {
146
146
  const path = require('path');
147
147
  const fs = require('fs');
148
- const localePath = path.join(__dirname, '..', 'ui-locales', 'en.json');
149
- if (fs.existsSync(localePath)) {
150
- const translations = JSON.parse(fs.readFileSync(localePath, 'utf8'));
148
+ const localePath = path.join(__dirname, '..', 'resources', 'i18n', 'ui-locales', 'en.json');
149
+ if (SecurityUtils.safeExistsSync(localePath)) {
150
+ const translations = JSON.parse(SecurityUtils.safeReadFileSync(localePath, path.dirname(localePath), 'utf8'));
151
151
  t = (key) => {
152
152
  const keys = key.split('.');
153
153
  let result = translations;
@@ -170,9 +170,9 @@ function showFrameworkWarningOnce(ui) {
170
170
  const settings = settingsManager.loadSettings();
171
171
  const currentLang = settings.uiLanguage || 'en';
172
172
 
173
- const localePath = path.join(__dirname, '..', 'ui-locales', `${currentLang}.json`);
174
- if (fs.existsSync(localePath)) {
175
- const translations = JSON.parse(fs.readFileSync(localePath, 'utf8'));
173
+ const localePath = path.join(__dirname, '..', 'resources', 'i18n', 'ui-locales', `${currentLang}.json`);
174
+ if (SecurityUtils.safeExistsSync(localePath)) {
175
+ const translations = JSON.parse(SecurityUtils.safeReadFileSync(localePath, path.dirname(localePath), 'utf8'));
176
176
  t = (key) => {
177
177
  const keys = key.split('.');
178
178
  let result = translations;
@@ -183,9 +183,9 @@ function showFrameworkWarningOnce(ui) {
183
183
  };
184
184
  } else {
185
185
  // Fallback to English
186
- const enLocalePath = path.join(__dirname, '..', 'ui-locales', 'en.json');
187
- if (fs.existsSync(enLocalePath)) {
188
- const translations = JSON.parse(fs.readFileSync(enLocalePath, 'utf8'));
186
+ const enLocalePath = path.join(__dirname, '..', 'resources', 'i18n', 'ui-locales', 'en.json');
187
+ if (SecurityUtils.safeExistsSync(enLocalePath)) {
188
+ const translations = JSON.parse(SecurityUtils.safeReadFileSync(enLocalePath, path.dirname(enLocalePath), 'utf8'));
189
189
  t = (key) => {
190
190
  const keys = key.split('.');
191
191
  let result = translations;
@@ -4,11 +4,11 @@
4
4
  * Configuration is managed through settings files only
5
5
  */
6
6
 
7
- const fs = require('fs');
8
- const path = require('path');
9
- const configManager = require('./config-manager');
10
- const SecurityUtils = require('./security');
11
- const {loadTranslations} = require('./i18n-helper');
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const configManager = require('./config-manager');
10
+ const SecurityUtils = require('./security');
11
+ const {loadTranslations} = require('./i18n-helper');
12
12
  const SettingsManager = require('../settings/settings-manager');
13
13
  const { envManager } = require('./env-manager');
14
14
  const settingsManager = new SettingsManager();
@@ -49,7 +49,7 @@ async function getUnifiedConfig(scriptName, cliArgs = {}) {
49
49
  }
50
50
  settingsDir = safeConfigDir;
51
51
  const configFile = path.join(settingsDir, 'i18ntk-config.json');
52
- cfg = fs.existsSync(configFile) ? JSON.parse(fs.readFileSync(configFile, 'utf8')) : {};
52
+ cfg = SecurityUtils.safeExistsSync(configFile) ? JSON.parse(SecurityUtils.safeReadFileSync(configFile, settingsDir, 'utf8')) : {};
53
53
  projectRoot = settingsDir;
54
54
  cfg.projectRoot = projectRoot;
55
55
  cfg.sourceDir = path.resolve(projectRoot, toStr(cfg.sourceDir) || './locales');
@@ -108,7 +108,7 @@ async function getUnifiedConfig(scriptName, cliArgs = {}) {
108
108
  }
109
109
 
110
110
  // Auto-fix i18nDir if missing but sourceDir exists
111
- if (!fs.existsSync(cfg.i18nDir) && fs.existsSync(cfg.sourceDir)) {
111
+ if (!SecurityUtils.safeExistsSync(cfg.i18nDir) && SecurityUtils.safeExistsSync(cfg.sourceDir)) {
112
112
  await configManager.updateConfig({ i18nDir: configManager.toRelative(cfg.sourceDir) });
113
113
  cfg.i18nDir = cfg.sourceDir;
114
114
  }
@@ -289,7 +289,7 @@ function parseCommonArgs(args) {
289
289
  }
290
290
 
291
291
  if (!parsed.uiLanguage) {
292
- const envLang = envManager.get('I18NTK_LANG');
292
+ const envLang = envManager.get('I18NTK_UI_LANGUAGE');
293
293
  if (envLang && envLang !== 'en') {
294
294
  parsed.uiLanguage = envLang;
295
295
  }
@@ -371,7 +371,7 @@ function displayHelp(scriptName, additionalOptions = {}) {
371
371
  console.log(`\nEnvironment Variables:`);
372
372
  console.log(` I18NTK_LOG_LEVEL Logging level (error, warn, info, debug, silent)`);
373
373
  console.log(` I18NTK_OUTDIR Output directory for reports`);
374
- console.log(` I18NTK_LANG UI language (en, de, es, fr, ru, ja, zh)`);
374
+ console.log(` I18NTK_UI_LANGUAGE UI language (en, de, es, fr, ru, ja, zh)`);
375
375
  console.log(` I18NTK_SILENT Run in silent mode (true/false)`);
376
376
  console.log(` I18NTK_DEBUG_LOCALES Enable debug logging for locale loading`);
377
377
  console.log(` I18NTK_SOURCE_DIR Source directory for scanning`);
@@ -397,7 +397,11 @@ function displayHelp(scriptName, additionalOptions = {}) {
397
397
  * @param {string} dirPath - Directory path
398
398
  */
399
399
  function ensureDirectory(dirPath) {
400
- if (!fs.existsSync(dirPath)) {
400
+ if (!dirPath || typeof dirPath !== 'string') {
401
+ // Silently handle undefined or invalid paths to prevent security errors
402
+ return;
403
+ }
404
+ if (!SecurityUtils.safeExistsSync(dirPath)) {
401
405
  fs.mkdirSync(dirPath, { recursive: true });
402
406
  }
403
407
  }
@@ -419,83 +423,35 @@ function displayPaths(cfg = {}) {
419
423
  }
420
424
 
421
425
  // Ensure project has been initialized with source language files
422
- async function ensureInitialized(cfg) {
423
- try {
424
- // Check if initialization has been marked as complete
425
- const configPath = path.join(path.dirname(require.main.filename), '..', 'settings', 'initialization.json');
426
- let initStatus = { initialized: false, version: null, timestamp: null };
427
-
428
- if (fs.existsSync(configPath)) {
429
- try {
430
- initStatus = JSON.parse(fs.readFileSync(configPath, 'utf8'));
431
- // If initialized and version matches current, skip further checks
432
- if (initStatus.initialized && initStatus.version === '1.8.3') {
433
- return true;
434
- }
435
- } catch (e) {
436
- // Invalid initialization file, proceed with normal check
437
- }
438
- }
439
-
440
- const sourceDir = cfg.sourceDir;
441
- const sourceLanguage = cfg.sourceLanguage || 'en';
442
- const langDir = path.join(sourceDir, sourceLanguage);
443
-
444
- const hasLanguageFiles = fs.existsSync(langDir) &&
445
- fs.readdirSync(langDir).some(f => f.endsWith('.json'));
446
-
447
- // If language files exist and we're upgrading, mark as initialized
448
- if (hasLanguageFiles) {
449
- const initDir = path.dirname(configPath);
450
- ensureDirectory(initDir);
451
- fs.writeFileSync(configPath, JSON.stringify({
452
- initialized: true,
453
- version: '1.8.3',
454
- timestamp: new Date().toISOString(),
455
- sourceDir: sourceDir,
456
- sourceLanguage: sourceLanguage
457
- }, null, 2));
458
- return true;
459
- }
460
-
461
- const nonInteractive = !process.stdin.isTTY;
462
-
463
- if (nonInteractive) {
464
- console.warn(`Missing source language files in ${langDir}. Running initialization...`);
465
- await initializeSourceFiles(sourceDir, sourceLanguage);
466
-
467
- // Mark initialization as complete
468
- const initDir = path.dirname(configPath);
469
- ensureDirectory(initDir);
470
- fs.writeFileSync(configPath, JSON.stringify({
471
- initialized: true,
472
- version: '1.8.3',
473
- timestamp: new Date().toISOString(),
474
- sourceDir: sourceDir,
475
- sourceLanguage: sourceLanguage
476
- }, null, 2));
477
- return true;
478
- }
479
-
480
- const answer = await ask(`Source language files not found in ${langDir}. Run initialization now? (y/N) `);
481
- const { closeGlobalReadline } = require('./cli');
482
- closeGlobalReadline();
483
-
484
- if (answer.trim().toLowerCase().startsWith('y')) {
485
- await initializeSourceFiles(sourceDir, sourceLanguage);
486
-
487
- // Mark initialization as complete
488
- const initDir = path.dirname(configPath);
489
- ensureDirectory(initDir);
490
- fs.writeFileSync(configPath, JSON.stringify({
491
- initialized: true,
492
- version: '1.8.3',
493
- timestamp: new Date().toISOString(),
494
- sourceDir: sourceDir,
495
- sourceLanguage: sourceLanguage
496
- }, null, 2));
497
- return true;
498
- }
426
+ async function ensureInitialized(cfg) {
427
+ try {
428
+ const { checkInitialized } = require('./init-helper');
429
+ const sourceDir = cfg?.sourceDir || './locales';
430
+ const sourceLanguage = cfg?.sourceLanguage || 'en';
431
+
432
+ const { initialized } = await checkInitialized({ sourceDir, sourceLanguage });
433
+ if (initialized) {
434
+ return true;
435
+ }
436
+
437
+ const nonInteractive = !process.stdin.isTTY;
438
+
439
+ if (nonInteractive) {
440
+ const langDir = path.join(sourceDir, sourceLanguage);
441
+ console.warn(`Missing source language files in ${langDir}. Running initialization...`);
442
+ await initializeSourceFiles(sourceDir, sourceLanguage);
443
+ return true;
444
+ }
445
+
446
+ const langDir = path.join(sourceDir, sourceLanguage);
447
+ const answer = await ask(`Source language files not found in ${langDir}. Run initialization now? (y/N) `);
448
+ const { closeGlobalReadline } = require('./cli');
449
+ closeGlobalReadline();
450
+
451
+ if (answer.trim().toLowerCase().startsWith('y')) {
452
+ await initializeSourceFiles(sourceDir, sourceLanguage);
453
+ return true;
454
+ }
499
455
  return false;
500
456
  } catch (err) {
501
457
  console.error(`Initialization check failed: ${err.message}`);
@@ -532,36 +488,49 @@ async function initializeSourceFiles(sourceDir, sourceLang) {
532
488
  ensureDirectory(sourceDir);
533
489
 
534
490
  // Write the default source language file
535
- fs.writeFileSync(sourceFile, JSON.stringify(defaultContent, null, 2));
491
+ SecurityUtils.safeWriteFileSync(sourceFile, JSON.stringify(defaultContent, null, 2));
536
492
 
537
493
  // Create directories for supported languages
538
494
  const supportedLanguages = ['es', 'fr', 'de', 'ja', 'ru', 'zh', 'pt'];
539
495
 
540
496
  supportedLanguages.forEach(lang => {
541
497
  const langFile = path.join(sourceDir, `${lang}.json`);
542
- if (!fs.existsSync(langFile)) {
498
+ if (!SecurityUtils.safeExistsSync(langFile)) {
543
499
  // Create empty object structure for each language
544
500
  const emptyStructure = {
545
501
  app: {},
546
502
  common: {},
547
503
  navigation: {}
548
504
  };
549
- fs.writeFileSync(langFile, JSON.stringify(emptyStructure, null, 2));
505
+ SecurityUtils.safeWriteFileSync(langFile, JSON.stringify(emptyStructure, null, 2));
550
506
  }
551
507
  });
552
508
 
553
- // Create i18ntk-config.json if it doesn't exist
554
- const configFile = 'i18ntk-config.json';
555
- if (!fs.existsSync(configFile)) {
556
- const defaultConfig = {
557
- version: "1.8.3",
558
- sourceDir: sourceDir,
559
- outputDir: "./i18ntk-reports",
560
- defaultLanguage: sourceLang,
561
- supportedLanguages: [sourceLang, 'es', 'fr', 'de', 'ja', 'ru', 'zh', 'pt'],
562
- security: {
563
- adminPinEnabled: true,
564
- sessionTimeout: 1800000,
509
+ // Create v2 project config if it doesn't exist
510
+ const configFile = '.i18ntk-config';
511
+ if (!SecurityUtils.safeExistsSync(configFile)) {
512
+ const version = (() => {
513
+ try {
514
+ return require('../package.json').version;
515
+ } catch {
516
+ return '2.0.0';
517
+ }
518
+ })();
519
+ const defaultConfig = {
520
+ version,
521
+ sourceDir: sourceDir,
522
+ outputDir: "./i18ntk-reports",
523
+ defaultLanguage: sourceLang,
524
+ supportedLanguages: [sourceLang, 'es', 'fr', 'de', 'ja', 'ru', 'zh', 'pt'],
525
+ setup: {
526
+ completed: true,
527
+ completedAt: new Date().toISOString(),
528
+ version,
529
+ setupId: `setup_${Date.now()}`
530
+ },
531
+ security: {
532
+ adminPinEnabled: true,
533
+ sessionTimeout: 1800000,
565
534
  maxFailedAttempts: 3
566
535
  },
567
536
  performance: {
@@ -570,7 +539,7 @@ async function initializeSourceFiles(sourceDir, sourceLang) {
570
539
  batchSize: 1000
571
540
  }
572
541
  };
573
- fs.writeFileSync(configFile, JSON.stringify(defaultConfig, null, 2));
542
+ SecurityUtils.safeWriteFileSync(configFile, JSON.stringify(defaultConfig, null, 2));
574
543
  }
575
544
  }
576
545
 
@@ -586,4 +555,4 @@ module.exports = {
586
555
  displayPaths,
587
556
  ensureInitialized,
588
557
 
589
- };
558
+ };