i18ntk 1.7.0 → 1.7.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.
package/main/i18ntk-ui.js CHANGED
@@ -6,6 +6,7 @@
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
  const SettingsManager = require('../settings/settings-manager');
9
+ const legacyConfigManager = require('../utils/config-manager');
9
10
  const configManager = SettingsManager;
10
11
 
11
12
  class UIi18n {
@@ -223,6 +224,11 @@ this.translations = {};
223
224
  await configManager.updateConfig(settings);
224
225
  }
225
226
  }
227
+
228
+ // Keep legacy config-manager in sync for modules using it directly
229
+ if (legacyConfigManager && legacyConfigManager.updateConfig) {
230
+ await legacyConfigManager.updateConfig({ language, uiLanguage: language });
231
+ }
226
232
  } catch (error) {
227
233
  console.error(`Error saving language preference: ${error.message}`);
228
234
  }
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  /**
3
3
  * I18N USAGE ANALYSIS TOOLKIT - Version 1.6.3
4
4
  *
@@ -25,7 +25,7 @@ const fs = require('fs');
25
25
  const path = require('path');
26
26
  const { loadTranslations, t } = require('../utils/i18n-helper');
27
27
  const { getGlobalReadline, closeGlobalReadline, askHidden } = require('../utils/cli');
28
- loadTranslations(process.env.I18NTK_LANG || 'en');
28
+ loadTranslations(process.env.I18NTK_LANG);
29
29
  const configManager = require('../utils/config-manager');
30
30
  const SecurityUtils = require('../utils/security');
31
31
  const AdminCLI = require('../utils/admin-cli');
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  // Check for uppercase command usage and provide helpful error
4
4
  const commandLine = process.argv.join(' ');
@@ -38,7 +38,7 @@ if (isUppercase) {
38
38
  const fs = require('fs');
39
39
  const path = require('path');
40
40
  const { loadTranslations, t } = require('../utils/i18n-helper');
41
- loadTranslations(process.env.I18NTK_LANG || 'en');
41
+ loadTranslations(process.env.I18NTK_LANG);
42
42
  const configManager = require('../utils/config-manager');
43
43
  const SecurityUtils = require('../utils/security');
44
44
  const AdminCLI = require('../utils/admin-cli');
@@ -75,7 +75,11 @@ class I18nValidator {
75
75
  const uiLanguage = (this.config && this.config.uiLanguage) || 'en';
76
76
  loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'ui-locales'));
77
77
 
78
- SecurityUtils.logSecurityEvent('I18n validator initializing', 'info', 'Initializing I18n validator');
78
+ SecurityUtils.logSecurityEvent(
79
+ 'I18n validator initializing',
80
+ 'info',
81
+ { message: 'Initializing I18n validator' }
82
+ );
79
83
 
80
84
  // Use the i18n directory for language files
81
85
  this.sourceDir = this.config.i18nDir || this.config.sourceDir;
@@ -102,9 +106,17 @@ class I18nValidator {
102
106
 
103
107
  displayPaths({ sourceDir: this.sourceDir, i18nDir: this.i18nDir, outputDir: this.config.outputDir });
104
108
 
105
- SecurityUtils.logSecurityEvent('I18n validator initialized successfully', 'info', 'I18n validator initialized successfully');
109
+ SecurityUtils.logSecurityEvent(
110
+ 'I18n validator initialized successfully',
111
+ 'info',
112
+ { message: 'I18n validator initialized successfully' }
113
+ );
106
114
  } catch (error) {
107
- SecurityUtils.logSecurityEvent('I18n validator initialization error', 'error', `Validator initialization error: ${error.message}`);
115
+ SecurityUtils.logSecurityEvent(
116
+ 'I18n validator initialization error',
117
+ 'error',
118
+ { message: `Validator initialization error: ${error.message}` }
119
+ );
108
120
  throw error;
109
121
  }
110
122
  }
@@ -240,10 +252,18 @@ class I18nValidator {
240
252
  const content = fs.readFileSync(filePath, 'utf8');
241
253
  const parsed = SecurityUtils.safeParseJSON(content);
242
254
 
243
- SecurityUtils.logSecurityEvent(t('validate.jsonValidated'), 'info', `JSON syntax validated: ${filePath}`);
255
+ SecurityUtils.logSecurityEvent(
256
+ t('validate.jsonValidated'),
257
+ 'info',
258
+ { message: `JSON syntax validated: ${filePath}` }
259
+ );
244
260
  return { valid: true, data: parsed };
245
261
  } catch (error) {
246
- SecurityUtils.logSecurityEvent(t('validate.jsonValidationError'), 'error', `JSON validation error: ${error.message}`);
262
+ SecurityUtils.logSecurityEvent(
263
+ t('validate.jsonValidationError'),
264
+ 'error',
265
+ { message: `JSON validation error: ${error.message}` }
266
+ );
247
267
  return {
248
268
  valid: false,
249
269
  error: error.message,
@@ -338,7 +358,11 @@ class I18nValidator {
338
358
  // Validate a single language
339
359
  async validateLanguage(language) {
340
360
  try {
341
- SecurityUtils.logSecurityEvent(t('validate.languageValidation'), 'info', `Validating language: ${language}`);
361
+ SecurityUtils.logSecurityEvent(
362
+ t('validate.languageValidation'),
363
+ 'info',
364
+ { message: `Validating language: ${language}` }
365
+ );
342
366
 
343
367
  const sanitizedLanguage = SecurityUtils.sanitizeInput(language);
344
368
  const languageDir = path.join(this.sourceDir, sanitizedLanguage);
@@ -737,12 +761,20 @@ class I18nValidator {
737
761
  const execute = async () => {
738
762
 
739
763
  console.log(t('validate.startingValidationProcess'));
740
- SecurityUtils.logSecurityEvent(t('validate.runStarted'), 'info', 'Starting validation run');
764
+ SecurityUtils.logSecurityEvent(
765
+ t('validate.runStarted'),
766
+ 'info',
767
+ { message: 'Starting validation run' }
768
+ );
741
769
 
742
770
  const result = await this.validate();
743
771
 
744
772
  console.log(t('validate.validationProcessCompletedSuccessfully'));
745
- SecurityUtils.logSecurityEvent(t('validate.runCompleted'), 'info', 'Validation run completed successfully');
773
+ SecurityUtils.logSecurityEvent(
774
+ t('validate.runCompleted'),
775
+ 'info',
776
+ { message: 'Validation run completed successfully' }
777
+ );
746
778
  return result;
747
779
  };
748
780
 
@@ -766,7 +798,11 @@ class I18nValidator {
766
798
  } catch (error) {
767
799
  console.error(t('validate.validationError', { error: error.message }));
768
800
  console.error(t('validate.stackTrace', { stack: error.stack }));
769
- SecurityUtils.logSecurityEvent(t('validate.runError'), 'error', `Validation run failed: ${error.message}`);
801
+ SecurityUtils.logSecurityEvent(
802
+ t('validate.runError'),
803
+ 'error',
804
+ { message: `Validation run failed: ${error.message}` }
805
+ );
770
806
  throw error;
771
807
  }
772
808
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18ntk",
3
- "version": "1.7.0",
3
+ "version": "1.7.2",
4
4
  "description": "i18ntk (i18n Toolkit) - Ultra-extreme performance enterprise-grade internationalization management toolkit with 97% performance improvement (15.38ms for 200k keys), advanced security with PIN protection, comprehensive backup & recovery, and edge case handling for JavaScript/TypeScript projects",
5
5
  "keywords": [
6
6
  "i18n",
@@ -65,7 +65,8 @@
65
65
  "i18ntk-doctor": "main/i18ntk-doctor.js"
66
66
  },
67
67
  "directories": {
68
- "doc": "docs"
68
+ "doc": "docs",
69
+ "test": "tests"
69
70
  },
70
71
  "files": [
71
72
  "main/",
@@ -102,7 +103,7 @@
102
103
  "sizing": "node main/i18ntk-sizing.js",
103
104
  "summary": "node main/i18ntk-summary.js",
104
105
  "full-coverage": "npm run complete && npm run analyze",
105
- "verify-package": "node dev/verify-package.js",
106
+ "verify-package": "node verify-package.js",
106
107
  "smoke:pack": "node scripts/smoke-pack.js",
107
108
  "prepublishOnly": "npm run verify-package && npm run smoke:pack",
108
109
  "test": "node scripts/test-runner.js",
@@ -135,8 +136,6 @@
135
136
  "deprecate:old-versions": "node scripts/deprecate-versions.js",
136
137
  "build:lite": "node scripts/build-lite.js"
137
138
  },
138
- "dependencies": {
139
- },
140
139
  "engines": {
141
140
  "node": ">=16.0.0"
142
141
  },
@@ -145,7 +144,7 @@
145
144
  },
146
145
  "preferGlobal": true,
147
146
  "versionInfo": {
148
- "version": "1.7.0",
147
+ "version": "1.7.2",
149
148
  "releaseDate": "27/07/2025",
150
149
  "lastUpdated": "10/08/2025",
151
150
  "maintainer": "Vladimir Noskov",
@@ -176,7 +175,7 @@
176
175
  "1.6.2",
177
176
  "1.6.3"
178
177
  ],
179
- "nextVersion": "1.7.0",
178
+ "nextVersion": "1.8.0",
180
179
  "supportedNodeVersions": ">=16.0.0",
181
180
  "supportedFrameworks": {
182
181
  "react-i18next": ">=11.0.0",
@@ -194,5 +193,5 @@
194
193
  "i18next": ">=21.0.0"
195
194
  }
196
195
  },
197
- "devDependencies": {}
196
+ "dependencies": {}
198
197
  }
@@ -0,0 +1,21 @@
1
+ const assert = require('assert');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const AdminAuth = require('../utils/admin-auth');
5
+
6
+ (async () => {
7
+ const configPath = path.join(require('../settings/settings-manager').configDir, '.i18n-admin-config.json');
8
+ const auth = new AdminAuth();
9
+
10
+ try {
11
+ for (const pin of ['1234', '12345', '123456']) {
12
+ await auth.setupPin(pin);
13
+ const result = await auth.verifyPin(pin);
14
+ assert.strictEqual(result, true, `${pin.length}-digit PIN should be verified`);
15
+ }
16
+ console.log('admin-auth pin format tests passed');
17
+ } finally {
18
+ await auth.cleanup();
19
+ if (fs.existsSync(configPath)) fs.unlinkSync(configPath);
20
+ }
21
+ })();
@@ -316,7 +316,7 @@ class PrepublishCleaner {
316
316
  }
317
317
 
318
318
  async resetSecuritySettings() {
319
- const configPath = path.join(this.projectRoot, 'settings', '.i18n-admin-config.json');
319
+ const configPath = path.join(require('../settings/settings-manager').configDir, '.i18n-admin-config.json');
320
320
 
321
321
  if (fs.existsSync(configPath)) {
322
322
  const defaultConfig = {
@@ -2,6 +2,6 @@
2
2
  "enabled": false,
3
3
  "pinHash": null,
4
4
  "salt": null,
5
- "createdAt": "2025-08-10T04:31:56.830Z",
6
- "lastModified": "2025-08-10T04:34:52.796Z"
5
+ "createdAt": "2025-08-10T19:59:40.084Z",
6
+ "lastModified": "2025-08-10T20:19:12.192Z"
7
7
  }
@@ -182,7 +182,6 @@
182
182
  "saveDebugLogs": false,
183
183
  "debugLogPath": "./debug.log"
184
184
  },
185
- "sizeLimit": null,
186
185
  "sourceLanguage": "en",
187
186
  "defaultLanguages": [
188
187
  "de",
@@ -0,0 +1,7 @@
1
+ {
2
+ "initialized": true,
3
+ "version": "1.7.1",
4
+ "timestamp": "2024-12-19T10:30:00.000Z",
5
+ "sourceDir": "./locales",
6
+ "sourceLanguage": "en"
7
+ }
@@ -11,7 +11,7 @@ const settingsManager = require('./settings-manager');
11
11
  const UIi18n = require('../main/i18ntk-ui');
12
12
  const configManager = require('../utils/config-manager');
13
13
  const { loadTranslations, t } = require('../utils/i18n-helper');
14
- loadTranslations(process.env.I18NTK_LANG || 'en');
14
+ loadTranslations(process.env.I18NTK_LANG);
15
15
 
16
16
  const AdminAuth = require('../utils/admin-auth');
17
17
  const uiI18n = new UIi18n();
@@ -9,8 +9,8 @@ const path = require('path');
9
9
 
10
10
  class SettingsManager {
11
11
  constructor() {
12
- const projectRoot = process.cwd();
13
- this.configDir = path.join(projectRoot, 'settings');
12
+ const packageDir = __dirname;
13
+ this.configDir = packageDir;
14
14
  this.configFile = path.join(this.configDir, 'i18ntk-config.json');
15
15
  this.lastBackupTime = 0;
16
16
  this.backupDebounceMs = 5000; // 5 seconds debounce
@@ -453,6 +453,8 @@
453
453
  "addingMissingKeys": "➕ Fehlende Schlüssel werden zu Übersetzungsdateien hinzugefügt...",
454
454
  "processing": "🔄 Verarbeite {language}...",
455
455
  "addedKeys": "✅ {count} fehlende Schlüssel hinzugefügt",
456
+ "changeDetails": "📝 {file}: {key}",
457
+ "andMore": "...und {count} weitere",
456
458
  "noChangesNeeded": "✅ Keine Änderungen für {language} erforderlich",
457
459
  "summaryTitle": "📊 ABSCHLUSSZUSAMMENFASSUNG",
458
460
  "totalChanges": "📝 Gesamtänderungen: {totalChanges}",
@@ -453,6 +453,8 @@
453
453
  "addingMissingKeys": "➕ Adding missing keys to translation files...",
454
454
  "processing": "🔄 Processing {language}...",
455
455
  "addedKeys": "✅ Added {count} missing keys",
456
+ "changeDetails": "📝 {file}: {key}",
457
+ "andMore": "...and {count} more",
456
458
  "noChangesNeeded": "✅ No changes needed for {language}",
457
459
  "summaryTitle": "📊 COMPLETION SUMMARY",
458
460
  "totalChanges": "📝 Total changes: {totalChanges}",
@@ -453,6 +453,8 @@
453
453
  "addingMissingKeys": "➕ Agregando claves faltantes a los archivos de traducción...",
454
454
  "processing": "🔄 Procesando {language}...",
455
455
  "addedKeys": "✅ Agregadas {count} claves faltantes",
456
+ "changeDetails": "📝 {file}: {key}",
457
+ "andMore": "...y {count} más",
456
458
  "noChangesNeeded": "✅ No se necesitan cambios para {language}",
457
459
  "summaryTitle": "📊 RESUMEN DE COMPLETADO",
458
460
  "totalChanges": "📝 Cambios totales: {totalChanges}",
@@ -453,6 +453,8 @@
453
453
  "addingMissingKeys": "➕ Ajout des clés manquantes aux fichiers de traduction...",
454
454
  "processing": "🔄 Traitement de {language}...",
455
455
  "addedKeys": "✅ Ajouté {count} clés manquantes",
456
+ "changeDetails": "📝 {file} : {key}",
457
+ "andMore": "...et {count} de plus",
456
458
  "noChangesNeeded": "✅ Aucun changement nécessaire pour {language}",
457
459
  "summaryTitle": "📊 RÉSUMÉ DE COMPLÉTION",
458
460
  "totalChanges": "📝 Total des changements : {totalChanges}",
@@ -453,6 +453,8 @@
453
453
  "addingMissingKeys": "➕ 翻訳ファイルに不足しているキーを追加中...",
454
454
  "processing": "🔄 {language} を処理中...",
455
455
  "addedKeys": "✅ {count} 件の不足しているキーを追加しました",
456
+ "changeDetails": "📝 {file}: {key}",
457
+ "andMore": "...さらに {count} 件",
456
458
  "noChangesNeeded": "✅ {language} には変更の必要がありません",
457
459
  "summaryTitle": "📊 補完サマリー",
458
460
  "totalChanges": "📝 合計変更: {totalChanges}",
@@ -442,41 +442,43 @@
442
442
  "n": ""
443
443
  },
444
444
  "complete": {
445
- "configLoadedSuccessfully": "Configuration loaded successfully",
446
- "configLoadingFailed": "Configuration loading failed",
447
- "title": "🌍 I18N TRANSLATION COMPLETION",
445
+ "configLoadedSuccessfully": "⚙️ Конфигурация успешно загружена",
446
+ "configLoadingFailed": "⚙️ Загрузка конфигурации не удалась",
447
+ "title": "🌍 I18N ПОЛНОТА ПЕРЕВОДА",
448
448
  "separator": "============================================================",
449
- "sourceDir": "📁 Source directory: {sourceDir}",
450
- "sourceLanguage": "🌐 Source language: {sourceLanguage}",
451
- "dryRunMode": "🧪 Dry run mode - no changes will be made",
452
- "languages": "🌍 Available languages: {languages}",
453
- "addingMissingKeys": "➕ Adding missing keys to translation files...",
454
- "processing": "🔄 Processing {language}...",
455
- "addedKeys": "✅ Added {count} missing keys",
456
- "noChangesNeeded": " No changes needed for {language}",
457
- "summaryTitle": "📊 COMPLETION SUMMARY",
458
- "totalChanges": "📝 Total changes: {totalChanges}",
459
- "languagesProcessed": "🌍 Languages processed: {languagesProcessed}",
460
- "missingKeysAdded": " Missing keys added: {missingKeysAdded}",
461
- "nextStepsTitle": "📋 NEXT STEPS",
462
- "nextStep1": "1. Run usage analysis:",
449
+ "sourceDir": "📁 Исходный каталог: {sourceDir}",
450
+ "sourceLanguage": "🌐 Исходный язык: {sourceLanguage}",
451
+ "dryRunMode": "🧪 Режим тестового запуска - изменения не будут применены",
452
+ "languages": "🌍 Доступные языки: {languages}",
453
+ "addingMissingKeys": "➕ Добавление отсутствующих ключей в файлы перевода...",
454
+ "processing": "🔄 Обработка {language}...",
455
+ "addedKeys": "✅ Добавлено {count} отсутствующих ключей",
456
+ "changeDetails": "📝 {file}: {key}",
457
+ "andMore": "...и ещё {count}",
458
+ "noChangesNeeded": " Для {language} не требуется изменений",
459
+ "summaryTitle": "📊 Сводка по завершению перевода",
460
+ "totalChanges": "📝 Всего изменений: {totalChanges}",
461
+ "languagesProcessed": "🌍 Обработано языков: {languagesProcessed}",
462
+ "missingKeysAdded": " Добавлено отсутствующих ключей: {missingKeysAdded}",
463
+ "nextStepsTitle": "📋 ДАЛЬНЕЙШИЕ ШАГИ",
464
+ "nextStep1": "1. Запустите анализ использования:",
463
465
  "nextStep2": " node i18ntk-usage.js --output-report",
464
- "nextStep3": "2. Validate translations:",
466
+ "nextStep3": "2. Проверьте переводы:",
465
467
  "nextStep4": " node i18ntk-validate.js",
466
- "nextStep5": "3. Analyze patterns:",
468
+ "nextStep5": "3. Проверьте шаблоны:",
467
469
  "nextStep6": " node i18ntk-analyze.js",
468
- "allKeysAvailable": "🎉 All translation keys are now available!",
469
- "runWithoutDryRun": "💡 Run without --dry-run to apply changes",
470
- "deletingOldReport": "🗑️ Deleting old report...",
471
- "generatingFreshAnalysis": "📊 Generating fresh usage analysis...",
472
- "couldNotGenerate": "❌ Could not generate usage analysis",
473
- "reportNotFound": "📋 Usage report not found. Using common keys...",
474
- "foundMissingKeys": "📋 Found {count} missing keys from usage analysis",
475
- "couldNotParse": "❌ Could not parse usage report. Using common keys..."
470
+ "allKeysAvailable": "🎉 Все ключи перевода теперь доступны!",
471
+ "runWithoutDryRun": "💡 Запустите без --dry-run, чтобы применить изменения",
472
+ "deletingOldReport": "🗑️ Удаление старого отчёта...",
473
+ "generatingFreshAnalysis": "📊 Генерация свежего анализа использования...",
474
+ "couldNotGenerate": "❌ Не удалось сгенерировать анализ использования",
475
+ "reportNotFound": "📋 Отчёт использования не найден. Используется общие ключи...",
476
+ "foundMissingKeys": "📋 Найдено {count} отсутствующих ключей из анализа использования",
477
+ "couldNotParse": "❌ Не удалось разобрать отчёт использования. Используется общие ключи..."
476
478
  },
477
- "noTranslationLanguagesFound": "No Translation Languages Found",
478
- "failedToAnalyzeLanguage": "Failed To Analyze Language",
479
- "translationCompletenessAnalysisFailed": "Translation Completeness Analysis Failed"
479
+ "noTranslationLanguagesFound": "🌍 Целевых языков не найдено",
480
+ "failedToAnalyzeLanguage": " Не удалось проанализировать язык",
481
+ "translationCompletenessAnalysisFailed": " Анализ полноты перевода не удался"
480
482
  },
481
483
  "validate": {
482
484
  "help_message": "\nI18n Валидатор переводов\n\nИспользование: node i18ntk-validate.js [опции]\n\nОпции:\n --source-dir <dir> Директория исходников для сканирования (по умолчанию: ./locales)\n --i18n-dir <dir> Директория I18n (по умолчанию: ./locales)\n --output-report Сгенерировать подробный отчёт\n --output-dir <dir> Директория для отчётов (по умолчанию: ./i18ntk-reports)\n --help Показать справку\n\nПримеры:\n node i18ntk-validate.js --output-report\n node i18ntk-validate.js --source-dir=./app --i18n-dir=./locales\n node i18ntk-validate.js --output-dir=./analysis --output-report\n",
@@ -1035,7 +1037,7 @@
1035
1037
  },
1036
1038
  "usage": {
1037
1039
  "title": "📊 Проверка Использования Ключей Перевода",
1038
- "noUsedKeysHint": "Found translations but no usage in source. Check --source-dir and translationPatterns."
1040
+ "noUsedKeysHint": "🔍 Найдено переводы, но они не используются в исходном коде. Проверьте --source-dir и translationPatterns."
1039
1041
  },
1040
1042
  "analyze": {
1041
1043
  "title": "🔍 Анализ Переводов"
@@ -1094,8 +1096,8 @@
1094
1096
  "pathTraversalAttempt": "path_traversal_attempt",
1095
1097
  "pathValidated": "✅ Путь успешно проверен",
1096
1098
  "pathValidationError": "path_validation_error",
1097
- "fileTooLarge": "Безопасность: Файл слишком большой: {filePath}",
1098
- "fileReadError": "Безопасность: Ошибка чтения файла: {errorMessage}",
1099
+ "fileTooLarge": "🔒 Безопасность: Файл слишком большой: {filePath}",
1100
+ "fileReadError": "🔒 Безопасность: Ошибка чтения файла: {errorMessage}",
1099
1101
  "contentTooLargeForFile": "Безопасность: Содержимое слишком велико для файла: {filePath}",
1100
1102
  "fileWriteError": "Безопасность: Ошибка записи файла: {errorMessage}",
1101
1103
  "jsonStringTooLarge": "Безопасность: JSON-строка слишком длинная",
@@ -453,6 +453,8 @@
453
453
  "addingMissingKeys": "➕ 正在向翻译文件添加缺失键...",
454
454
  "processing": "🔄 正在处理 {language}...",
455
455
  "addedKeys": "✅ 已添加 {count} 个缺失键",
456
+ "changeDetails": "📝 {file}:{key}",
457
+ "andMore": "...以及 {count} 个更多",
456
458
  "noChangesNeeded": "✅ {language} 无需更改",
457
459
  "summaryTitle": "📊 完成摘要",
458
460
  "totalChanges": "📝 总更改: {totalChanges}",