i18ntk 1.10.1 → 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 (110) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +141 -1185
  3. package/main/i18ntk-analyze.js +149 -133
  4. package/main/i18ntk-backup-class.js +420 -0
  5. package/main/i18ntk-backup.js +4 -4
  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 +76 -25
  11. package/main/i18ntk-java.js +27 -32
  12. package/main/i18ntk-js.js +70 -68
  13. package/main/i18ntk-manage.js +128 -29
  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 +10 -396
  18. package/main/i18ntk-sizing.js +46 -40
  19. package/main/i18ntk-summary.js +21 -18
  20. package/main/i18ntk-ui.js +11 -10
  21. package/main/i18ntk-usage.js +55 -19
  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 -30
  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 +13 -5
  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 +23 -15
  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 +23 -20
  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 +152 -103
  86. package/utils/config-manager.js +204 -164
  87. package/utils/config.js +5 -4
  88. package/utils/env-manager.js +256 -0
  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/logger.js +6 -2
  94. package/utils/mini-commander.js +179 -0
  95. package/utils/missing-key-validator.js +5 -5
  96. package/utils/plugin-loader.js +29 -11
  97. package/utils/prompt.js +14 -44
  98. package/utils/safe-json.js +40 -0
  99. package/utils/secure-errors.js +3 -3
  100. package/utils/security-check-improved.js +390 -0
  101. package/utils/security-config.js +5 -5
  102. package/utils/security-fixed.js +607 -0
  103. package/utils/security.js +462 -248
  104. package/utils/setup-enforcer.js +136 -44
  105. package/utils/setup-validator.js +33 -32
  106. package/utils/terminal-icons.js +1 -1
  107. package/utils/ultra-performance-optimizer.js +11 -9
  108. package/utils/watch-locales.js +2 -1
  109. package/utils/prompt-fixed.js +0 -55
  110. package/utils/security-check.js +0 -450
@@ -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,12 +4,13 @@
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
+ const { envManager } = require('./env-manager');
13
14
  const settingsManager = new SettingsManager();
14
15
 
15
16
  const { ask } = require('./cli');
@@ -48,7 +49,7 @@ async function getUnifiedConfig(scriptName, cliArgs = {}) {
48
49
  }
49
50
  settingsDir = safeConfigDir;
50
51
  const configFile = path.join(settingsDir, 'i18ntk-config.json');
51
- cfg = fs.existsSync(configFile) ? JSON.parse(fs.readFileSync(configFile, 'utf8')) : {};
52
+ cfg = SecurityUtils.safeExistsSync(configFile) ? JSON.parse(SecurityUtils.safeReadFileSync(configFile, settingsDir, 'utf8')) : {};
52
53
  projectRoot = settingsDir;
53
54
  cfg.projectRoot = projectRoot;
54
55
  cfg.sourceDir = path.resolve(projectRoot, toStr(cfg.sourceDir) || './locales');
@@ -56,7 +57,14 @@ async function getUnifiedConfig(scriptName, cliArgs = {}) {
56
57
  cfg.outputDir = path.resolve(projectRoot, toStr(cfg.outputDir) || './i18ntk-reports');
57
58
  } else {
58
59
  cfg = configManager.getConfig();
59
- projectRoot = path.resolve(cfg.projectRoot || '.');
60
+ // Use current working directory instead of hardcoded path
61
+ const isHardcodedPath = cfg.projectRoot && cfg.projectRoot.includes('i18n-management-toolkit-main');
62
+ projectRoot = isHardcodedPath ? process.cwd() : path.resolve(cfg.projectRoot || '.');
63
+
64
+ // Update config with dynamic project root
65
+ if (isHardcodedPath) {
66
+ cfg.projectRoot = '.';
67
+ }
60
68
 
61
69
  const updates = {};
62
70
  const sourceDirArg = toStr(cliArgs.sourceDir);
@@ -100,7 +108,7 @@ async function getUnifiedConfig(scriptName, cliArgs = {}) {
100
108
  }
101
109
 
102
110
  // Auto-fix i18nDir if missing but sourceDir exists
103
- if (!fs.existsSync(cfg.i18nDir) && fs.existsSync(cfg.sourceDir)) {
111
+ if (!SecurityUtils.safeExistsSync(cfg.i18nDir) && SecurityUtils.safeExistsSync(cfg.sourceDir)) {
104
112
  await configManager.updateConfig({ i18nDir: configManager.toRelative(cfg.sourceDir) });
105
113
  cfg.i18nDir = cfg.sourceDir;
106
114
  }
@@ -231,6 +239,18 @@ function parseCommonArgs(args) {
231
239
  case 'ui-language':
232
240
  parsed.uiLanguage = sanitizedValue;
233
241
  break;
242
+ case 'log-level':
243
+ parsed.logLevel = sanitizedValue;
244
+ break;
245
+ case 'framework':
246
+ parsed.frameworkPreference = sanitizedValue;
247
+ break;
248
+ case 'silent':
249
+ parsed.silent = sanitizedValue === 'true' || sanitizedValue === true;
250
+ break;
251
+ case 'debug-locales':
252
+ parsed.debugLocales = sanitizedValue === 'true' || sanitizedValue === true;
253
+ break;
234
254
  case 'strict':
235
255
  parsed.strictMode = true;
236
256
  break;
@@ -260,6 +280,49 @@ function parseCommonArgs(args) {
260
280
  }
261
281
  }
262
282
 
283
+ // Apply environment variable defaults if CLI args not provided
284
+ if (!parsed.logLevel) {
285
+ const envLogLevel = envManager.get('I18NTK_LOG_LEVEL');
286
+ if (envLogLevel && envLogLevel !== 'error') {
287
+ parsed.logLevel = envLogLevel;
288
+ }
289
+ }
290
+
291
+ if (!parsed.uiLanguage) {
292
+ const envLang = envManager.get('I18NTK_UI_LANGUAGE');
293
+ if (envLang && envLang !== 'en') {
294
+ parsed.uiLanguage = envLang;
295
+ }
296
+ }
297
+
298
+ if (!parsed.outputDir) {
299
+ const envOutDir = envManager.get('I18NTK_OUTDIR');
300
+ if (envOutDir && envOutDir !== './i18ntk-reports') {
301
+ parsed.outputDir = envOutDir;
302
+ }
303
+ }
304
+
305
+ if (!parsed.sourceDir) {
306
+ const envSourceDir = envManager.get('I18NTK_SOURCE_DIR');
307
+ if (envSourceDir && envSourceDir !== './locales') {
308
+ parsed.sourceDir = envSourceDir;
309
+ }
310
+ }
311
+
312
+ if (!parsed.i18nDir) {
313
+ const envI18nDir = envManager.get('I18NTK_I18N_DIR');
314
+ if (envI18nDir && envI18nDir !== './locales') {
315
+ parsed.i18nDir = envI18nDir;
316
+ }
317
+ }
318
+
319
+ if (!parsed.frameworkPreference) {
320
+ const envFramework = envManager.get('I18NTK_FRAMEWORK_PREFERENCE');
321
+ if (envFramework && envFramework !== 'auto') {
322
+ parsed.frameworkPreference = envFramework;
323
+ }
324
+ }
325
+
263
326
  return parsed;
264
327
  }
265
328
 
@@ -275,6 +338,10 @@ function displayHelp(scriptName, additionalOptions = {}) {
275
338
  'output-dir': 'Output directory for reports',
276
339
  'source-language': 'Source language code (e.g., en, de)',
277
340
  'ui-language': 'UI language for messages',
341
+ 'log-level': 'Logging level (error, warn, info, debug, silent)',
342
+ 'framework': 'Preferred framework (auto, react, vue, etc.)',
343
+ 'silent': 'Run in silent mode (true/false)',
344
+ 'debug-locales': 'Enable debug logging for locale loading (true/false)',
278
345
  'strict': 'Enable strict validation mode',
279
346
  'no-prompt': 'Skip interactive prompts',
280
347
  'help': 'Show this help message',
@@ -301,15 +368,28 @@ function displayHelp(scriptName, additionalOptions = {}) {
301
368
  console.log(` --${flag.padEnd(15)} ${description}`);
302
369
  });
303
370
 
371
+ console.log(`\nEnvironment Variables:`);
372
+ console.log(` I18NTK_LOG_LEVEL Logging level (error, warn, info, debug, silent)`);
373
+ console.log(` I18NTK_OUTDIR Output directory for reports`);
374
+ console.log(` I18NTK_UI_LANGUAGE UI language (en, de, es, fr, ru, ja, zh)`);
375
+ console.log(` I18NTK_SILENT Run in silent mode (true/false)`);
376
+ console.log(` I18NTK_DEBUG_LOCALES Enable debug logging for locale loading`);
377
+ console.log(` I18NTK_SOURCE_DIR Source directory for scanning`);
378
+ console.log(` I18NTK_I18N_DIR Directory containing i18n files`);
379
+ console.log(` I18NTK_PROJECT_ROOT Project root directory`);
380
+ console.log(` I18NTK_FRAMEWORK_PREFERENCE Preferred framework (auto, react, vue, etc.)`);
381
+
304
382
  console.log(`\nExamples:`);
305
383
  console.log(` node ${scriptName}.js --source-dir=./locales`);
306
384
  console.log(` node ${scriptName}.js --source-dir=./app --i18n-dir=./locales`);
307
385
  console.log(` node ${scriptName}.js --output-dir=./i18ntk-reports`);
386
+ console.log(` I18NTK_LOG_LEVEL=debug node ${scriptName}.js --source-dir=./locales`);
308
387
  console.log(` npx i18ntk ${scriptName.replace('i18ntk-', '')} --help`);
309
388
 
310
389
  console.log('\nConfiguration:');
311
390
  console.log(` Settings are loaded from ${configManager.CONFIG_PATH}`);
312
391
  console.log(' Use --source-dir, --i18n-dir, and --output-dir to override');
392
+ console.log(' Environment variables can also be used for configuration');
313
393
  }
314
394
 
315
395
  /**
@@ -317,7 +397,11 @@ function displayHelp(scriptName, additionalOptions = {}) {
317
397
  * @param {string} dirPath - Directory path
318
398
  */
319
399
  function ensureDirectory(dirPath) {
320
- 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)) {
321
405
  fs.mkdirSync(dirPath, { recursive: true });
322
406
  }
323
407
  }
@@ -339,83 +423,35 @@ function displayPaths(cfg = {}) {
339
423
  }
340
424
 
341
425
  // Ensure project has been initialized with source language files
342
- async function ensureInitialized(cfg) {
343
- try {
344
- // Check if initialization has been marked as complete
345
- const configPath = path.join(path.dirname(require.main.filename), '..', 'settings', 'initialization.json');
346
- let initStatus = { initialized: false, version: null, timestamp: null };
347
-
348
- if (fs.existsSync(configPath)) {
349
- try {
350
- initStatus = JSON.parse(fs.readFileSync(configPath, 'utf8'));
351
- // If initialized and version matches current, skip further checks
352
- if (initStatus.initialized && initStatus.version === '1.8.3') {
353
- return true;
354
- }
355
- } catch (e) {
356
- // Invalid initialization file, proceed with normal check
357
- }
358
- }
359
-
360
- const sourceDir = cfg.sourceDir;
361
- const sourceLanguage = cfg.sourceLanguage || 'en';
362
- const langDir = path.join(sourceDir, sourceLanguage);
363
-
364
- const hasLanguageFiles = fs.existsSync(langDir) &&
365
- fs.readdirSync(langDir).some(f => f.endsWith('.json'));
366
-
367
- // If language files exist and we're upgrading, mark as initialized
368
- if (hasLanguageFiles) {
369
- const initDir = path.dirname(configPath);
370
- ensureDirectory(initDir);
371
- fs.writeFileSync(configPath, JSON.stringify({
372
- initialized: true,
373
- version: '1.8.3',
374
- timestamp: new Date().toISOString(),
375
- sourceDir: sourceDir,
376
- sourceLanguage: sourceLanguage
377
- }, null, 2));
378
- return true;
379
- }
380
-
381
- const nonInteractive = !process.stdin.isTTY;
382
-
383
- if (nonInteractive) {
384
- console.warn(`Missing source language files in ${langDir}. Running initialization...`);
385
- await initializeSourceFiles(sourceDir, sourceLanguage);
386
-
387
- // Mark initialization as complete
388
- const initDir = path.dirname(configPath);
389
- ensureDirectory(initDir);
390
- fs.writeFileSync(configPath, JSON.stringify({
391
- initialized: true,
392
- version: '1.8.3',
393
- timestamp: new Date().toISOString(),
394
- sourceDir: sourceDir,
395
- sourceLanguage: sourceLanguage
396
- }, null, 2));
397
- return true;
398
- }
399
-
400
- const answer = await ask(`Source language files not found in ${langDir}. Run initialization now? (y/N) `);
401
- const { closeGlobalReadline } = require('./cli');
402
- closeGlobalReadline();
403
-
404
- if (answer.trim().toLowerCase().startsWith('y')) {
405
- await initializeSourceFiles(sourceDir, sourceLanguage);
406
-
407
- // Mark initialization as complete
408
- const initDir = path.dirname(configPath);
409
- ensureDirectory(initDir);
410
- fs.writeFileSync(configPath, JSON.stringify({
411
- initialized: true,
412
- version: '1.8.3',
413
- timestamp: new Date().toISOString(),
414
- sourceDir: sourceDir,
415
- sourceLanguage: sourceLanguage
416
- }, null, 2));
417
- return true;
418
- }
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
+ }
419
455
  return false;
420
456
  } catch (err) {
421
457
  console.error(`Initialization check failed: ${err.message}`);
@@ -452,36 +488,49 @@ async function initializeSourceFiles(sourceDir, sourceLang) {
452
488
  ensureDirectory(sourceDir);
453
489
 
454
490
  // Write the default source language file
455
- fs.writeFileSync(sourceFile, JSON.stringify(defaultContent, null, 2));
491
+ SecurityUtils.safeWriteFileSync(sourceFile, JSON.stringify(defaultContent, null, 2));
456
492
 
457
493
  // Create directories for supported languages
458
494
  const supportedLanguages = ['es', 'fr', 'de', 'ja', 'ru', 'zh', 'pt'];
459
495
 
460
496
  supportedLanguages.forEach(lang => {
461
497
  const langFile = path.join(sourceDir, `${lang}.json`);
462
- if (!fs.existsSync(langFile)) {
498
+ if (!SecurityUtils.safeExistsSync(langFile)) {
463
499
  // Create empty object structure for each language
464
500
  const emptyStructure = {
465
501
  app: {},
466
502
  common: {},
467
503
  navigation: {}
468
504
  };
469
- fs.writeFileSync(langFile, JSON.stringify(emptyStructure, null, 2));
505
+ SecurityUtils.safeWriteFileSync(langFile, JSON.stringify(emptyStructure, null, 2));
470
506
  }
471
507
  });
472
508
 
473
- // Create i18ntk-config.json if it doesn't exist
474
- const configFile = 'i18ntk-config.json';
475
- if (!fs.existsSync(configFile)) {
476
- const defaultConfig = {
477
- version: "1.8.3",
478
- sourceDir: sourceDir,
479
- outputDir: "./i18ntk-reports",
480
- defaultLanguage: sourceLang,
481
- supportedLanguages: [sourceLang, 'es', 'fr', 'de', 'ja', 'ru', 'zh', 'pt'],
482
- security: {
483
- adminPinEnabled: true,
484
- 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,
485
534
  maxFailedAttempts: 3
486
535
  },
487
536
  performance: {
@@ -490,7 +539,7 @@ async function initializeSourceFiles(sourceDir, sourceLang) {
490
539
  batchSize: 1000
491
540
  }
492
541
  };
493
- fs.writeFileSync(configFile, JSON.stringify(defaultConfig, null, 2));
542
+ SecurityUtils.safeWriteFileSync(configFile, JSON.stringify(defaultConfig, null, 2));
494
543
  }
495
544
  }
496
545
 
@@ -506,4 +555,4 @@ module.exports = {
506
555
  displayPaths,
507
556
  ensureInitialized,
508
557
 
509
- };
558
+ };