i18ntk 1.10.2 → 2.0.3

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
package/main/i18ntk-js.js CHANGED
@@ -3,7 +3,7 @@
3
3
  /**
4
4
  * i18ntk JavaScript/TypeScript Command
5
5
  * Specialized command for JavaScript and TypeScript i18n management
6
- *
6
+ *
7
7
  * Usage: i18ntk-js [options]
8
8
  */
9
9
 
@@ -13,7 +13,7 @@ const SecurityUtils = require(path.join(__dirname, '../utils/security.js'));
13
13
  const { getConfig, saveConfig } = require(path.join(__dirname, '../utils/config-helper.js'));
14
14
  const I18nHelper = require(path.join(__dirname, '../utils/i18n-helper.js'));
15
15
  const SetupEnforcer = require(path.join(__dirname, '../utils/setup-enforcer'));
16
- const { program } = require('commander');
16
+ const { program } = require('../utils/mini-commander');
17
17
 
18
18
  (async () => {
19
19
  try {
@@ -37,29 +37,29 @@ class I18ntkJavaScriptCommand {
37
37
  /intl\.formatMessage\s*\(\s*{[^}]*id:\s*["'`]([^"'`]+)["'`]/g,
38
38
  /useTranslations?\s*\(\s*["'`]([^"'`]+)["'`]/g,
39
39
  /getTranslations?\s*\(\s*["'`]([^"'`]+)["'`]/g,
40
-
40
+
41
41
  // React patterns
42
42
  /FormattedMessage\s+id=["'`]([^"'`]+)["'`]/g,
43
43
  /<FormattedMessage[^>]*id={["'`]([^"'`]+)["'`]}/g,
44
44
  /useTranslation\(\)\s*\.t\s*\(\s*["'`]([^"'`]+)["'`]/g,
45
-
45
+
46
46
  // Angular patterns
47
47
  /translate\s*\|\s*translate/g,
48
48
  /\{\{\s*["'`]([^"'`]+)["'`]\s*\|\s*translate\s*}}/g,
49
-
49
+
50
50
  // Vue patterns
51
51
  /\$t\s*\(\s*["'`]([^"'`]+)["'`]/g,
52
52
  /this\.\$t\s*\(\s*["'`]([^"'`]+)["'`]/g,
53
-
53
+
54
54
  // Node.js patterns
55
55
  /__\s*\(\s*["'`]([^"'`]+)["'`]/g,
56
56
  /gettext\s*\(\s*["'`]([^"'`]+)["'`]/g,
57
-
57
+
58
58
  // Template literal patterns
59
59
  /i18n\.t\s*\(\s*`([^`]+)`/g,
60
60
  /t\s*\(\s*`([^`]+)`/g
61
61
  ];
62
-
62
+
63
63
  this.frameworks = {
64
64
  react: {
65
65
  indicators: ['package.json', 'react', 'react-dom'],
@@ -82,7 +82,7 @@ class I18ntkJavaScriptCommand {
82
82
 
83
83
  async init() {
84
84
  console.log('šŸ”§ Initializing i18ntk JavaScript/TypeScript command...');
85
-
85
+
86
86
  program
87
87
  .name('i18ntk-js')
88
88
  .description('i18ntk specialized for JavaScript and TypeScript applications')
@@ -104,13 +104,13 @@ class I18ntkJavaScriptCommand {
104
104
  this.options = program.opts();
105
105
  this.sourceDir = path.resolve(this.options.sourceDir);
106
106
  this.localesDir = path.resolve(this.options.localesDir);
107
-
107
+
108
108
  await this.validateSourceDir();
109
109
  await this.loadConfig();
110
110
  }
111
111
 
112
112
  async validateSourceDir() {
113
- if (!fs.existsSync(this.sourceDir)) {
113
+ if (!SecurityUtils.safeExistsSync(this.sourceDir, path.dirname(this.sourceDir))) {
114
114
  console.error(`āŒ Source directory not found: ${this.sourceDir}`);
115
115
  process.exit(1);
116
116
  }
@@ -137,16 +137,17 @@ class I18ntkJavaScriptCommand {
137
137
  if (this.options.vue) return 'vue';
138
138
  if (this.options.angular) return 'angular';
139
139
  if (this.options.node) return 'node';
140
-
140
+
141
141
  console.log('šŸ” Detecting JavaScript framework...');
142
-
142
+
143
143
  let framework = 'generic';
144
144
 
145
145
  try {
146
146
  const packageJsonPath = path.join(this.sourceDir, 'package.json');
147
- if (fs.existsSync(packageJsonPath)) {
148
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
149
-
147
+ if (SecurityUtils.safeExistsSync(packageJsonPath, this.sourceDir)) {
148
+ const packageJsonContent = SecurityUtils.safeReadFileSync(packageJsonPath, this.sourceDir, 'utf8');
149
+ const packageJson = SecurityUtils.safeParseJSON(packageJsonContent);
150
+
150
151
  const dependencies = {
151
152
  ...packageJson.dependencies || {},
152
153
  ...packageJson.devDependencies || {}
@@ -183,72 +184,72 @@ class I18ntkJavaScriptCommand {
183
184
  findFiles(pattern, extensions = []) {
184
185
  const results = [];
185
186
  const validExtensions = extensions.length > 0 ? extensions : ['.js', '.jsx', '.ts', '.tsx'];
186
-
187
+
187
188
  function scanDir(dir) {
188
- if (!fs.existsSync(dir)) return;
189
-
189
+ if (!SecurityUtils.safeExistsSync(dir, path.dirname(dir))) return;
190
+
190
191
  const items = fs.readdirSync(dir);
191
192
  for (const item of items) {
192
193
  const fullPath = path.join(dir, item);
193
194
  const stat = fs.statSync(fullPath);
194
-
195
+
195
196
  if (stat.isDirectory()) {
196
197
  // Skip node_modules and hidden directories
197
198
  if (item === 'node_modules' || item.startsWith('.')) continue;
198
-
199
+
199
200
  // Skip test directories unless explicitly included
200
- if (!this.options.includeTests &&
201
+ if (!this.options.includeTests &&
201
202
  (item === '__tests__' || item === 'test' || item === 'tests' || item.includes('.test.'))) {
202
203
  continue;
203
204
  }
204
-
205
+
205
206
  scanDir.call(this, fullPath);
206
207
  } else {
207
208
  // Check file extension
208
209
  const ext = path.extname(item);
209
210
  if (validExtensions.includes(ext)) {
210
211
  // Skip test files unless explicitly included
211
- if (!this.options.includeTests &&
212
+ if (!this.options.includeTests &&
212
213
  (item.includes('.test.') || item.includes('.spec.') || item.includes('__test__'))) {
213
214
  continue;
214
215
  }
215
-
216
+
216
217
  results.push(fullPath);
217
218
  }
218
219
  }
219
220
  }
220
221
  }
221
-
222
+
222
223
  scanDir.call(this, this.sourceDir);
223
224
  return results;
224
225
  }
225
226
 
226
227
  async extractTranslations() {
227
228
  console.log('šŸ“¦ Extracting JavaScript/TypeScript translations...');
228
-
229
- const extensions = this.options.typescript
230
- ? ['.js', '.jsx', '.ts', '.tsx']
229
+
230
+ const extensions = this.options.typescript
231
+ ? ['.js', '.jsx', '.ts', '.tsx']
231
232
  : ['.js', '.jsx'];
232
-
233
+
233
234
  const jsFiles = this.findFiles('', extensions);
234
235
  const translations = new Set();
235
-
236
+
236
237
  for (const file of jsFiles) {
237
238
  try {
238
- const content = fs.readFileSync(file, 'utf8');
239
-
239
+ const content = SecurityUtils.safeReadFileSync(file, path.dirname(file), 'utf8');
240
+
240
241
  for (const pattern of this.jsPatterns) {
241
242
  let match;
242
243
  while ((match = pattern.exec(content)) !== null) {
243
244
  translations.add(match[1]);
244
245
  }
245
246
  }
246
-
247
+
247
248
  // Reset regex state for next file
248
249
  for (const pattern of this.jsPatterns) {
249
250
  pattern.lastIndex = 0;
250
251
  }
251
-
252
+
252
253
  } catch (error) {
253
254
  if (this.options.debug) {
254
255
  console.error(`Error reading ${file}:`, error.message);
@@ -261,28 +262,28 @@ class I18ntkJavaScriptCommand {
261
262
  }
262
263
 
263
264
  async createLocaleStructure() {
264
- if (!fs.existsSync(this.localesDir)) {
265
+ if (!SecurityUtils.safeExistsSync(this.localesDir, path.dirname(this.localesDir))) {
265
266
  if (this.options.dryRun) {
266
267
  console.log(`šŸ“ Would create directory: ${this.localesDir}`);
267
268
  return;
268
269
  }
269
-
270
+
270
271
  fs.mkdirSync(this.localesDir, { recursive: true });
271
272
  console.log(`šŸ“ Created locales directory: ${this.localesDir}`);
272
273
  }
273
274
 
274
275
  const languages = ['en', 'es', 'fr', 'de', 'ja', 'ru', 'zh'];
275
-
276
+
276
277
  for (const lang of languages) {
277
278
  const langDir = path.join(this.localesDir, lang);
278
- if (!fs.existsSync(langDir)) {
279
+ if (!SecurityUtils.safeExistsSync(langDir, this.localesDir)) {
279
280
  if (this.options.dryRun) {
280
281
  console.log(`šŸ“ Would create directory: ${langDir}`);
281
282
  continue;
282
283
  }
283
-
284
+
284
285
  fs.mkdirSync(langDir, { recursive: true });
285
-
286
+
286
287
  // Create framework-specific translation files
287
288
  const commonFile = path.join(langDir, 'common.json');
288
289
  const initialContent = {
@@ -306,21 +307,21 @@ class I18ntkJavaScriptCommand {
306
307
  }
307
308
  }
308
309
  };
309
-
310
- fs.writeFileSync(commonFile, JSON.stringify(initialContent, null, 2));
310
+
311
+ SecurityUtils.safeWriteFileSync(commonFile, JSON.stringify(initialContent, null, 2), this.localesDir);
311
312
  }
312
313
  }
313
314
  }
314
315
 
315
316
  async analyzeFramework(framework) {
316
317
  console.log(`šŸ” Analyzing ${framework} project...`);
317
-
318
- const extensions = this.options.typescript
319
- ? ['.js', '.jsx', '.ts', '.tsx']
318
+
319
+ const extensions = this.options.typescript
320
+ ? ['.js', '.jsx', '.ts', '.tsx']
320
321
  : ['.js', '.jsx'];
321
-
322
+
322
323
  const jsFiles = this.findFiles('', extensions);
323
-
324
+
324
325
  const analysis = {
325
326
  framework,
326
327
  typescript: this.options.typescript || false,
@@ -358,14 +359,14 @@ class I18ntkJavaScriptCommand {
358
359
  else if (ext === '.ts') analysis.files.typescript++;
359
360
  else if (ext === '.jsx') analysis.files.jsx++;
360
361
  else if (ext === '.tsx') analysis.files.tsx++;
361
-
362
+
362
363
  if (file.includes('.test.') || file.includes('.spec.')) {
363
364
  analysis.files.test++;
364
365
  }
365
366
 
366
367
  try {
367
- const content = fs.readFileSync(file, 'utf8');
368
-
368
+ const content = SecurityUtils.safeReadFileSync(file, path.dirname(file), 'utf8');
369
+
369
370
  // Check patterns
370
371
  if (content.includes('i18n.t(')) analysis.patterns.i18n_t++;
371
372
  if (content.includes('t(')) analysis.patterns.t_function++;
@@ -374,7 +375,7 @@ class I18ntkJavaScriptCommand {
374
375
  if (content.includes('translate')) analysis.patterns.translate++;
375
376
  if (content.includes('$t(')) analysis.patterns.$t++;
376
377
  if (content.includes('gettext(')) analysis.patterns.gettext++;
377
-
378
+
378
379
  // Detect frameworks
379
380
  if (content.includes('import React') || content.includes('require("react")')) {
380
381
  analysis.frameworks.react = true;
@@ -388,7 +389,7 @@ class I18ntkJavaScriptCommand {
388
389
  if (content.includes('express') || content.includes('node')) {
389
390
  analysis.frameworks.node = true;
390
391
  }
391
-
392
+
392
393
  } catch (error) {
393
394
  // Skip unreadable files
394
395
  }
@@ -398,11 +399,11 @@ class I18ntkJavaScriptCommand {
398
399
  if (analysis.files.total > 0 && analysis.patterns.i18n_t === 0) {
399
400
  analysis.recommendations.push('Consider adding i18n support to your JavaScript/TypeScript files');
400
401
  }
401
-
402
+
402
403
  if (analysis.frameworks.react && analysis.patterns.FormattedMessage === 0) {
403
404
  analysis.recommendations.push('Consider using react-intl or react-i18next for React i18n');
404
405
  }
405
-
406
+
406
407
  if (analysis.frameworks.vue && analysis.patterns.$t === 0) {
407
408
  analysis.recommendations.push('Consider using vue-i18n for Vue.js i18n');
408
409
  }
@@ -410,10 +411,11 @@ class I18ntkJavaScriptCommand {
410
411
  // Check package.json for dependencies
411
412
  try {
412
413
  const packageJsonPath = path.join(this.sourceDir, 'package.json');
413
- if (fs.existsSync(packageJsonPath)) {
414
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
414
+ if (SecurityUtils.safeExistsSync(packageJsonPath, this.sourceDir)) {
415
+ const packageJsonContent = SecurityUtils.safeReadFileSync(packageJsonPath, this.sourceDir, 'utf8');
416
+ const packageJson = SecurityUtils.safeParseJSON(packageJsonContent);
415
417
  const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
416
-
418
+
417
419
  for (const [pkg, version] of Object.entries(deps)) {
418
420
  if (pkg.includes('i18n') || pkg.includes('intl') || pkg.includes('translate')) {
419
421
  analysis.dependencies.push(`${pkg}@${version}`);
@@ -455,12 +457,12 @@ class I18ntkJavaScriptCommand {
455
457
  };
456
458
 
457
459
  const reportPath = path.join(this.sourceDir, 'i18ntk-js-report.json');
458
-
460
+
459
461
  if (this.options.dryRun) {
460
462
  console.log(`šŸ“Š Would create report: ${reportPath}`);
461
463
  console.log('šŸ“‹ Report contents:', JSON.stringify(report, null, 2));
462
464
  } else {
463
- fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
465
+ SecurityUtils.safeWriteFileSync(reportPath, JSON.stringify(report, null, 2), this.sourceDir);
464
466
  console.log(`šŸ“Š Report saved: ${reportPath}`);
465
467
  }
466
468
 
@@ -469,19 +471,19 @@ class I18ntkJavaScriptCommand {
469
471
 
470
472
  async run() {
471
473
  try {
472
- console.log('šŸš€ i18ntk JavaScript/TypeScript Command v1.10.1');
473
- console.log('=' * 60);
474
-
474
+ console.log('šŸš€ i18ntk JavaScript/TypeScript Command v1.10.1');
475
+ console.log('='.repeat(60));
476
+
475
477
  await this.init();
476
-
478
+
477
479
  const framework = await this.detectFramework();
478
480
  const translations = await this.extractTranslations();
479
-
481
+
480
482
  if (!this.options.extractOnly) {
481
483
  await this.createLocaleStructure();
482
484
  const analysis = await this.analyzeFramework(framework);
483
485
  const report = await this.generateReport(analysis, translations);
484
-
486
+
485
487
  console.log('\nāœ… Analysis complete!');
486
488
  console.log(`šŸ“Š Framework: ${framework}`);
487
489
  console.log(`šŸ“„ Total files: ${analysis.files.total}`);
@@ -490,7 +492,7 @@ class I18ntkJavaScriptCommand {
490
492
  } else {
491
493
  console.log(`šŸ“¦ Extracted ${translations.length} translation keys`);
492
494
  }
493
-
495
+
494
496
  } catch (error) {
495
497
  console.error('āŒ Error:', error.message);
496
498
  if (this.options.debug) {
@@ -507,4 +509,4 @@ if (require.main === module) {
507
509
  cmd.run();
508
510
  }
509
511
 
510
- module.exports = I18ntkJavaScriptCommand;
512
+ module.exports = I18ntkJavaScriptCommand;