i18ntk 3.3.0 → 4.1.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/CHANGELOG.md +84 -16
- package/README.md +160 -15
- package/SECURITY.md +16 -8
- package/main/i18ntk-backup.js +370 -73
- package/main/i18ntk-scanner.js +190 -49
- package/main/i18ntk-sizing.js +241 -79
- package/main/i18ntk-usage.js +221 -46
- package/main/i18ntk-validate.js +114 -5
- package/main/manage/commands/FixerCommand.js +23 -21
- package/main/manage/index.js +13 -7
- package/main/manage/services/FileManagementService.js +12 -6
- package/package.json +46 -2
- package/runtime/i18ntk.d.ts +22 -16
- package/runtime/index.d.ts +9 -7
- package/runtime/index.js +246 -50
- package/ui-locales/en.json +1 -1
- package/utils/translate/protection.js +153 -7
- package/utils/watch-locales.js +194 -36
package/main/i18ntk-sizing.js
CHANGED
|
@@ -41,15 +41,17 @@ const { logger } = require('../utils/logger');
|
|
|
41
41
|
const { getGlobalReadline, closeGlobalReadline } = require('../utils/cli');
|
|
42
42
|
const SetupEnforcer = require('../utils/setup-enforcer');
|
|
43
43
|
|
|
44
|
-
// Ensure setup is complete before running
|
|
45
|
-
(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
44
|
+
// Ensure setup is complete before running (only when executed directly)
|
|
45
|
+
if (require.main === module) {
|
|
46
|
+
(async () => {
|
|
47
|
+
try {
|
|
48
|
+
await SetupEnforcer.checkSetupCompleteAsync();
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('Setup check failed:', error.message);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
})();
|
|
54
|
+
}
|
|
53
55
|
|
|
54
56
|
loadTranslations();
|
|
55
57
|
|
|
@@ -82,9 +84,11 @@ class I18nSizingAnalyzer {
|
|
|
82
84
|
this.format = options.format || 'table';
|
|
83
85
|
this.outputReport = options.outputReport || false;
|
|
84
86
|
this.sourceLanguage = options.sourceLanguage || config.sourceLanguage || 'en';
|
|
85
|
-
this.detailed = options.detailed || false;
|
|
86
|
-
this.detailedKeys = options.detailedKeys || false;
|
|
87
|
-
this.
|
|
87
|
+
this.detailed = options.detailed || false;
|
|
88
|
+
this.detailedKeys = options.detailedKeys || false;
|
|
89
|
+
this.predictExpansion = options.predictExpansion || false;
|
|
90
|
+
this.rl = null;
|
|
91
|
+
this.expansionPredictions = null;
|
|
88
92
|
|
|
89
93
|
// Initialize i18n with UI language from config
|
|
90
94
|
const uiLanguage = options.uiLanguage || config.uiLanguage || 'en';
|
|
@@ -490,8 +494,13 @@ class I18nSizingAnalyzer {
|
|
|
490
494
|
});
|
|
491
495
|
this.generateFileComparison();
|
|
492
496
|
|
|
493
|
-
// Generate recommendations
|
|
494
|
-
this.generateRecommendations();
|
|
497
|
+
// Generate recommendations
|
|
498
|
+
this.generateRecommendations();
|
|
499
|
+
|
|
500
|
+
// Generate expansion predictions if requested
|
|
501
|
+
if (this.predictExpansion) {
|
|
502
|
+
this.generateExpansionPredictions();
|
|
503
|
+
}
|
|
495
504
|
}
|
|
496
505
|
|
|
497
506
|
generateFileComparison() {
|
|
@@ -557,6 +566,145 @@ class I18nSizingAnalyzer {
|
|
|
557
566
|
this.stats.summary.recommendations = recommendations;
|
|
558
567
|
}
|
|
559
568
|
|
|
569
|
+
// Language pair expansion reference table (average % expansion from English)
|
|
570
|
+
// Values represent typical character count ratio (target/source) minus 1, as percentage
|
|
571
|
+
getExpansionReference() {
|
|
572
|
+
return {
|
|
573
|
+
de: 35, es: 25, fr: 20, it: 15, pt: 20, nl: 30, sv: 15,
|
|
574
|
+
ru: 50, uk: 45, pl: 30, cs: 25, sk: 25, bg: 40, sr: 40,
|
|
575
|
+
ja: -40, zh: -45, ko: -35, th: -30, vi: -20, km: -5,
|
|
576
|
+
ar: 15, he: 10, fa: 20, tr: 10, fi: 25, hu: 20, el: 15,
|
|
577
|
+
da: 10, nb: 10, ro: 15, id: 5, ms: 5, hi: 15, bn: 20,
|
|
578
|
+
ta: 10, te: 15, mr: 20, gu: 20, ml: 25, kn: 15
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
classifyExpansionRisk(ratio) {
|
|
583
|
+
const absRatio = Math.abs(ratio);
|
|
584
|
+
if (absRatio < 30) return { tier: 'safe', label: 'Safe', color: 'green' };
|
|
585
|
+
if (absRatio < 50) return { tier: 'warning', label: 'Warning', color: 'yellow' };
|
|
586
|
+
return { tier: 'critical', label: 'Critical', color: 'red' };
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
generateExpansionPredictions() {
|
|
590
|
+
const languages = Object.keys(this.stats.languages);
|
|
591
|
+
if (languages.length < 2) return;
|
|
592
|
+
|
|
593
|
+
const baseLanguage = this.stats.summary.baseLanguage || this.config.sourceLanguage || 'en';
|
|
594
|
+
const expansionRef = this.getExpansionReference();
|
|
595
|
+
const predictions = {
|
|
596
|
+
baseLanguage,
|
|
597
|
+
perLanguage: {},
|
|
598
|
+
perKey: {},
|
|
599
|
+
topExpandedKeys: [],
|
|
600
|
+
summary: { safe: 0, warning: 0, critical: 0, total: 0 }
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
for (const lang of languages) {
|
|
604
|
+
if (lang === baseLanguage) continue;
|
|
605
|
+
|
|
606
|
+
const baseStats = this.stats.languages[baseLanguage];
|
|
607
|
+
const langStats = this.stats.languages[lang];
|
|
608
|
+
if (!baseStats || !langStats) continue;
|
|
609
|
+
|
|
610
|
+
const actualRatio = baseStats.totalCharacters > 0
|
|
611
|
+
? ((langStats.totalCharacters - baseStats.totalCharacters) / baseStats.totalCharacters) * 100
|
|
612
|
+
: 0;
|
|
613
|
+
|
|
614
|
+
const referenceRatio = expansionRef[lang] || 10;
|
|
615
|
+
const risk = this.classifyExpansionRisk(actualRatio);
|
|
616
|
+
predictions.perLanguage[lang] = {
|
|
617
|
+
actualExpansionPercent: Math.round(actualRatio * 100) / 100,
|
|
618
|
+
referenceExpansionPercent: referenceRatio,
|
|
619
|
+
riskTier: risk.tier,
|
|
620
|
+
riskLabel: risk.label,
|
|
621
|
+
totalKeys: langStats.totalKeys,
|
|
622
|
+
totalChars: langStats.totalCharacters
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const keyEntries = [];
|
|
627
|
+
for (const [key, langData] of Object.entries(this.stats.keys)) {
|
|
628
|
+
const baseData = langData[baseLanguage];
|
|
629
|
+
if (!baseData || baseData.length === 0) continue;
|
|
630
|
+
|
|
631
|
+
const keyPredictions = {};
|
|
632
|
+
for (const [lang, data] of Object.entries(langData)) {
|
|
633
|
+
if (lang === baseLanguage) continue;
|
|
634
|
+
const ratio = ((data.length - baseData.length) / baseData.length) * 100;
|
|
635
|
+
const risk = this.classifyExpansionRisk(ratio);
|
|
636
|
+
keyPredictions[lang] = {
|
|
637
|
+
sourceLength: baseData.length,
|
|
638
|
+
targetLength: data.length,
|
|
639
|
+
expansionPercent: Math.round(ratio * 100) / 100,
|
|
640
|
+
riskTier: risk.tier
|
|
641
|
+
};
|
|
642
|
+
predictions.summary[risk.tier]++;
|
|
643
|
+
predictions.summary.total++;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
const maxExpansion = Math.max(...Object.values(keyPredictions).map(p => Math.abs(p.expansionPercent)));
|
|
647
|
+
keyEntries.push({ key, maxExpansion, predictions: keyPredictions });
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
keyEntries.sort((a, b) => b.maxExpansion - a.maxExpansion);
|
|
651
|
+
predictions.topExpandedKeys = keyEntries.slice(0, 30);
|
|
652
|
+
predictions.perKey = Object.fromEntries(keyEntries.slice(0, 200).map(e => [e.key, e.predictions]));
|
|
653
|
+
|
|
654
|
+
this.expansionPredictions = predictions;
|
|
655
|
+
this.stats.expansionPredictions = predictions;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
displayExpansionPredictions() {
|
|
659
|
+
if (!this.expansionPredictions) return;
|
|
660
|
+
|
|
661
|
+
const p = this.expansionPredictions;
|
|
662
|
+
console.log('\n' + '='.repeat(60));
|
|
663
|
+
console.log(' EXPANSION PREDICTION ANALYSIS');
|
|
664
|
+
console.log('='.repeat(60));
|
|
665
|
+
console.log(` Base Language: ${p.baseLanguage}`);
|
|
666
|
+
console.log(` Total Key-Language Pairs Analyzed: ${p.summary.total}`);
|
|
667
|
+
console.log(` Safe (<30%): ${p.summary.safe} | Warning (30-50%): ${p.summary.warning} | Critical (>50%): ${p.summary.critical}`);
|
|
668
|
+
|
|
669
|
+
console.log('\n PER-LANGUAGE EXPANSION RATIOS:');
|
|
670
|
+
const langRows = Object.entries(p.perLanguage).map(([lang, data]) => ({
|
|
671
|
+
language: lang,
|
|
672
|
+
actual: `${data.actualExpansionPercent > 0 ? '+' : ''}${data.actualExpansionPercent}%`,
|
|
673
|
+
reference: `${data.referenceExpansionPercent > 0 ? '+' : ''}${data.referenceExpansionPercent}%`,
|
|
674
|
+
risk: data.riskLabel
|
|
675
|
+
}));
|
|
676
|
+
console.log(this.createTable([
|
|
677
|
+
{ key: 'language', label: 'Language' },
|
|
678
|
+
{ key: 'actual', label: 'Actual', align: 'right' },
|
|
679
|
+
{ key: 'reference', label: 'Reference', align: 'right' },
|
|
680
|
+
{ key: 'risk', label: 'Risk Tier' }
|
|
681
|
+
], langRows));
|
|
682
|
+
|
|
683
|
+
if (p.topExpandedKeys.length > 0) {
|
|
684
|
+
console.log('\n TOP EXPANDED KEYS (highest risk of UI overflow):');
|
|
685
|
+
const keyRows = p.topExpandedKeys.slice(0, 15).map(entry => {
|
|
686
|
+
const langs = Object.entries(entry.predictions).map(([l, d]) =>
|
|
687
|
+
`${l}:${d.expansionPercent > 0 ? '+' : ''}${d.expansionPercent}%`
|
|
688
|
+
).join(' ');
|
|
689
|
+
return { key: entry.key, maxExp: `${entry.maxExpansion > 0 ? '+' : ''}${Math.round(entry.maxExpansion)}%`, languages: langs };
|
|
690
|
+
});
|
|
691
|
+
console.log(this.createTable([
|
|
692
|
+
{ key: 'key', label: 'Key' },
|
|
693
|
+
{ key: 'maxExp', label: 'Max Exp', align: 'right' },
|
|
694
|
+
{ key: 'languages', label: 'Per-Language' }
|
|
695
|
+
], keyRows));
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
console.log('\n RECOMMENDATIONS:');
|
|
699
|
+
if (p.summary.critical > 0) {
|
|
700
|
+
console.log(` - ${p.summary.critical} key-language pairs have >50% expansion — review UI layouts for truncation risk`);
|
|
701
|
+
}
|
|
702
|
+
if (p.summary.warning > 0) {
|
|
703
|
+
console.log(` - ${p.summary.warning} key-language pairs have 30-50% expansion — test on target languages`);
|
|
704
|
+
}
|
|
705
|
+
console.log(' - Use the reference expansion ratios to plan UI element sizing for unsupported languages');
|
|
706
|
+
}
|
|
707
|
+
|
|
560
708
|
// Display concise folder-level results
|
|
561
709
|
displayFolderResults() {
|
|
562
710
|
console.log("\n" + t("sizing.sizing_analysis_results"));
|
|
@@ -616,9 +764,13 @@ class I18nSizingAnalyzer {
|
|
|
616
764
|
reportPath: this.outputDir
|
|
617
765
|
}));
|
|
618
766
|
|
|
619
|
-
if (this.detailedKeys) {
|
|
620
|
-
this.displayDetailedKeys();
|
|
621
|
-
}
|
|
767
|
+
if (this.detailedKeys) {
|
|
768
|
+
this.displayDetailedKeys();
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
if (this.predictExpansion && this.expansionPredictions) {
|
|
772
|
+
this.displayExpansionPredictions();
|
|
773
|
+
}
|
|
622
774
|
}
|
|
623
775
|
|
|
624
776
|
displayFileComparison() {
|
|
@@ -874,17 +1026,50 @@ Generated: ${new Date().toISOString()}
|
|
|
874
1026
|
report += `
|
|
875
1027
|
### ${key}
|
|
876
1028
|
`;
|
|
877
|
-
Object.entries(data).forEach(([lang, keyData]) => {
|
|
878
|
-
const length = keyData.length;
|
|
879
|
-
const isEmpty = length === 0;
|
|
880
|
-
const isLong = length > this.threshold;
|
|
881
|
-
const status = isEmpty ? 'EMPTY' : isLong ? 'LONG' : 'OK';
|
|
882
|
-
report += `- ${lang}: ${length} chars [${status}]\n`;
|
|
883
|
-
});
|
|
1029
|
+
Object.entries(data).forEach(([lang, keyData]) => {
|
|
1030
|
+
const length = keyData.length;
|
|
1031
|
+
const isEmpty = length === 0;
|
|
1032
|
+
const isLong = length > this.threshold;
|
|
1033
|
+
const status = isEmpty ? 'EMPTY' : isLong ? 'LONG' : 'OK';
|
|
1034
|
+
report += `- ${lang}: ${length} chars [${status}]\n`;
|
|
1035
|
+
});
|
|
1036
|
+
});
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
// Expansion predictions
|
|
1040
|
+
if (this.expansionPredictions) {
|
|
1041
|
+
const ep = this.expansionPredictions;
|
|
1042
|
+
report += `
|
|
1043
|
+
## Expansion Prediction Analysis
|
|
1044
|
+
|
|
1045
|
+
### Summary
|
|
1046
|
+
- Base Language: ${ep.baseLanguage}
|
|
1047
|
+
- Safe (<30%): ${ep.summary.safe}
|
|
1048
|
+
- Warning (30-50%): ${ep.summary.warning}
|
|
1049
|
+
- Critical (>50%): ${ep.summary.critical}
|
|
1050
|
+
- Total Pairs: ${ep.summary.total}
|
|
1051
|
+
|
|
1052
|
+
### Per-Language Ratios
|
|
1053
|
+
`;
|
|
1054
|
+
Object.entries(ep.perLanguage).forEach(([lang, data]) => {
|
|
1055
|
+
report += `- ${lang}: ${data.actualExpansionPercent > 0 ? '+' : ''}${data.actualExpansionPercent}% (ref: ${data.referenceExpansionPercent > 0 ? '+' : ''}${data.referenceExpansionPercent}%) [${data.riskLabel}]\n`;
|
|
884
1056
|
});
|
|
1057
|
+
|
|
1058
|
+
if (ep.topExpandedKeys.length > 0) {
|
|
1059
|
+
report += `
|
|
1060
|
+
### Top Expanded Keys
|
|
1061
|
+
`;
|
|
1062
|
+
ep.topExpandedKeys.slice(0, 30).forEach((entry, idx) => {
|
|
1063
|
+
report += `${idx + 1}. ${entry.key} (max: ${entry.maxExpansion > 0 ? '+' : ''}${Math.round(entry.maxExpansion)}%)\n`;
|
|
1064
|
+
Object.entries(entry.predictions).forEach(([l, d]) => {
|
|
1065
|
+
report += ` ${l}: ${d.sourceLength} → ${d.targetLength} chars (${d.expansionPercent > 0 ? '+' : ''}${d.expansionPercent}%) [${d.riskTier}]\n`;
|
|
1066
|
+
});
|
|
1067
|
+
report += '\n';
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
885
1070
|
}
|
|
886
1071
|
|
|
887
|
-
return report;
|
|
1072
|
+
return report;
|
|
888
1073
|
}
|
|
889
1074
|
|
|
890
1075
|
// Generate CSV report
|
|
@@ -917,45 +1102,7 @@ Generated: ${new Date().toISOString()}
|
|
|
917
1102
|
}
|
|
918
1103
|
}
|
|
919
1104
|
|
|
920
|
-
//
|
|
921
|
-
async analyze() {
|
|
922
|
-
const startTime = Date.now();
|
|
923
|
-
|
|
924
|
-
try {
|
|
925
|
-
logger.info(t("sizing.starting_i18n_sizing_analysis"));
|
|
926
|
-
logger.info(t("sizing.source_directory", { sourceDir: this.sourceDir }));
|
|
927
|
-
|
|
928
|
-
const files = this.getLanguageFiles();
|
|
929
|
-
|
|
930
|
-
if (files.length === 0) {
|
|
931
|
-
logger.warn(t("sizing.no_translation_files_found"));
|
|
932
|
-
return;
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
logger.info(t("sizing.found_languages", { languages: files.map(f => f.language).join(', ') }));
|
|
936
|
-
|
|
937
|
-
this.analyzeFileSizes(files);
|
|
938
|
-
this.analyzeTranslationContent(files);
|
|
939
|
-
this.generateSizeComparison();
|
|
940
|
-
|
|
941
|
-
if (this.format === 'table') {
|
|
942
|
-
this.displayFolderResults();
|
|
943
|
-
} else if (this.format === 'json') {
|
|
944
|
-
logger.info(t("sizing.analysisStats", { stats: JSON.stringify(this.stats, null, 2) }));
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
await this.generateHumanReadableReport();
|
|
948
|
-
|
|
949
|
-
const endTime = Date.now();
|
|
950
|
-
logger.info(t("sizing.analysis_completed", { duration: ((endTime - startTime) / 1000).toFixed(2) }));
|
|
951
|
-
|
|
952
|
-
} catch (error) {
|
|
953
|
-
logger.error(t("sizing.analysis_failed", { errorMessage: error.message }));
|
|
954
|
-
process.exit(1);
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
// Parse command line arguments without yargs
|
|
1105
|
+
// Parse command line arguments without yargs
|
|
959
1106
|
parseArgs() {
|
|
960
1107
|
const args = process.argv.slice(2);
|
|
961
1108
|
const options = {
|
|
@@ -1018,6 +1165,8 @@ Generated: ${new Date().toISOString()}
|
|
|
1018
1165
|
options.d = options.detailed;
|
|
1019
1166
|
} else if (key === 'detailed-keys') {
|
|
1020
1167
|
options['detailed-keys'] = value.toLowerCase() !== 'false';
|
|
1168
|
+
} else if (key === 'predict-expansion') {
|
|
1169
|
+
options['predict-expansion'] = value.toLowerCase() !== 'false';
|
|
1021
1170
|
} else if (key === 'output-dir') {
|
|
1022
1171
|
options['output-dir'] = value;
|
|
1023
1172
|
}
|
|
@@ -1073,17 +1222,24 @@ Generated: ${new Date().toISOString()}
|
|
|
1073
1222
|
options.detailed = true;
|
|
1074
1223
|
options.d = true;
|
|
1075
1224
|
}
|
|
1076
|
-
} else if (key === 'detailed-keys') {
|
|
1077
|
-
if (nextArg && !nextArg.startsWith('-') && ['true', 'false'].includes(nextArg.toLowerCase())) {
|
|
1078
|
-
options['detailed-keys'] = nextArg.toLowerCase() !== 'false';
|
|
1079
|
-
i++;
|
|
1080
|
-
} else {
|
|
1081
|
-
options['detailed-keys'] = true;
|
|
1082
|
-
}
|
|
1083
|
-
} else if (key === '
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1225
|
+
} else if (key === 'detailed-keys') {
|
|
1226
|
+
if (nextArg && !nextArg.startsWith('-') && ['true', 'false'].includes(nextArg.toLowerCase())) {
|
|
1227
|
+
options['detailed-keys'] = nextArg.toLowerCase() !== 'false';
|
|
1228
|
+
i++;
|
|
1229
|
+
} else {
|
|
1230
|
+
options['detailed-keys'] = true;
|
|
1231
|
+
}
|
|
1232
|
+
} else if (key === 'predict-expansion') {
|
|
1233
|
+
if (nextArg && !nextArg.startsWith('-') && ['true', 'false'].includes(nextArg.toLowerCase())) {
|
|
1234
|
+
options['predict-expansion'] = nextArg.toLowerCase() !== 'false';
|
|
1235
|
+
i++;
|
|
1236
|
+
} else {
|
|
1237
|
+
options['predict-expansion'] = true;
|
|
1238
|
+
}
|
|
1239
|
+
} else if (key === 'output-dir') {
|
|
1240
|
+
options['output-dir'] = nextArg || options['output-dir'];
|
|
1241
|
+
if (nextArg && !nextArg.startsWith('-')) i++;
|
|
1242
|
+
}
|
|
1087
1243
|
}
|
|
1088
1244
|
}
|
|
1089
1245
|
|
|
@@ -1102,6 +1258,7 @@ Options:
|
|
|
1102
1258
|
--source-language <code> Source language baseline for comparisons (default: en)
|
|
1103
1259
|
-d, --detailed Generate detailed report with more information
|
|
1104
1260
|
--detailed-keys Show detailed key-level analysis
|
|
1261
|
+
--predict-expansion Predict UI layout expansion risk per language
|
|
1105
1262
|
--output-dir <dir> Output directory for reports (default: ./i18ntk-reports)
|
|
1106
1263
|
--help Show this help message
|
|
1107
1264
|
`);
|
|
@@ -1124,8 +1281,9 @@ Options:
|
|
|
1124
1281
|
this.languages = args.languages ? args.languages.split(',').map(l => l.trim()) : [];
|
|
1125
1282
|
this.outputReport = args['output-report'] !== undefined ? args['output-report'] : false;
|
|
1126
1283
|
this.format = args.format || 'table';
|
|
1127
|
-
this.detailed = args.detailed;
|
|
1128
|
-
this.detailedKeys = args['detailed-keys'];
|
|
1284
|
+
this.detailed = args.detailed;
|
|
1285
|
+
this.detailedKeys = args['detailed-keys'];
|
|
1286
|
+
this.predictExpansion = args['predict-expansion'] || false;
|
|
1129
1287
|
this.sourceLanguage = args['source-language'] || config.sourceLanguage || this.sourceLanguage || 'en';
|
|
1130
1288
|
|
|
1131
1289
|
if (!fromMenu) {
|
|
@@ -1141,7 +1299,7 @@ Options:
|
|
|
1141
1299
|
|
|
1142
1300
|
const cliHelper = require('../utils/cli-helper');
|
|
1143
1301
|
const pin = await cliHelper.promptPin(t('adminCli.enterPin'));
|
|
1144
|
-
const isValid = await
|
|
1302
|
+
const isValid = await adminAuth.verifyPin(pin);
|
|
1145
1303
|
|
|
1146
1304
|
if (!isValid) {
|
|
1147
1305
|
console.log(t('adminCli.invalidPin'));
|
|
@@ -1183,7 +1341,11 @@ Options:
|
|
|
1183
1341
|
this.generateSizeComparison();
|
|
1184
1342
|
|
|
1185
1343
|
// Display results
|
|
1186
|
-
this.
|
|
1344
|
+
if (this.format === 'table') {
|
|
1345
|
+
this.displayFolderResults();
|
|
1346
|
+
} else if (this.format === 'json') {
|
|
1347
|
+
logger.info(t("sizing.analysisStats", { stats: JSON.stringify(this.stats, null, 2) }));
|
|
1348
|
+
}
|
|
1187
1349
|
|
|
1188
1350
|
// Generate reports if requested
|
|
1189
1351
|
await this.generateHumanReadableReport();
|