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.
- package/LICENSE +1 -1
- package/README.md +141 -1191
- package/main/i18ntk-analyze.js +65 -84
- package/main/i18ntk-backup-class.js +420 -0
- package/main/i18ntk-backup.js +3 -3
- package/main/i18ntk-complete.js +90 -65
- package/main/i18ntk-doctor.js +123 -103
- package/main/i18ntk-fixer.js +61 -725
- package/main/i18ntk-go.js +14 -15
- package/main/i18ntk-init.js +77 -26
- package/main/i18ntk-java.js +27 -32
- package/main/i18ntk-js.js +70 -68
- package/main/i18ntk-manage.js +129 -30
- package/main/i18ntk-php.js +75 -75
- package/main/i18ntk-py.js +55 -56
- package/main/i18ntk-scanner.js +59 -57
- package/main/i18ntk-setup.js +9 -404
- package/main/i18ntk-sizing.js +6 -6
- package/main/i18ntk-summary.js +21 -18
- package/main/i18ntk-ui.js +11 -10
- package/main/i18ntk-usage.js +54 -18
- package/main/i18ntk-validate.js +13 -13
- package/main/manage/commands/AnalyzeCommand.js +1124 -0
- package/main/manage/commands/BackupCommand.js +62 -0
- package/main/manage/commands/CommandRouter.js +295 -0
- package/main/manage/commands/CompleteCommand.js +61 -0
- package/main/manage/commands/DoctorCommand.js +60 -0
- package/main/manage/commands/FixerCommand.js +624 -0
- package/main/manage/commands/InitCommand.js +62 -0
- package/main/manage/commands/ScannerCommand.js +654 -0
- package/main/manage/commands/SizingCommand.js +60 -0
- package/main/manage/commands/SummaryCommand.js +61 -0
- package/main/manage/commands/UsageCommand.js +60 -0
- package/main/manage/commands/ValidateCommand.js +978 -0
- package/main/manage/index-fixed.js +1447 -0
- package/main/manage/index.js +1462 -0
- package/main/manage/managers/DebugMenu.js +140 -0
- package/main/manage/managers/InteractiveMenu.js +177 -0
- package/main/manage/managers/LanguageMenu.js +62 -0
- package/main/manage/managers/SettingsMenu.js +53 -0
- package/main/manage/services/AuthenticationService.js +263 -0
- package/main/manage/services/ConfigurationService-fixed.js +449 -0
- package/main/manage/services/ConfigurationService.js +449 -0
- package/main/manage/services/FileManagementService.js +368 -0
- package/main/manage/services/FrameworkDetectionService.js +458 -0
- package/main/manage/services/InitService.js +1051 -0
- package/main/manage/services/SetupService.js +462 -0
- package/main/manage/services/SummaryService.js +450 -0
- package/main/manage/services/UsageService.js +1502 -0
- package/package.json +32 -29
- package/runtime/enhanced.d.ts +221 -221
- package/runtime/index.d.ts +29 -29
- package/runtime/index.full.d.ts +331 -331
- package/runtime/index.js +7 -6
- package/scripts/build-lite.js +17 -17
- package/scripts/deprecate-versions.js +23 -6
- package/scripts/export-translations.js +5 -5
- package/scripts/fix-all-i18n.js +3 -3
- package/scripts/fix-and-purify-i18n.js +3 -2
- package/scripts/fix-locale-control-chars.js +110 -0
- package/scripts/lint-locales.js +80 -0
- package/scripts/locale-optimizer.js +8 -8
- package/scripts/prepublish.js +21 -21
- package/scripts/security-check.js +117 -117
- package/scripts/sync-translations.js +4 -4
- package/scripts/sync-ui-locales.js +9 -8
- package/scripts/validate-all-translations.js +8 -7
- package/scripts/verify-deprecations.js +157 -161
- package/scripts/verify-translations.js +6 -5
- package/settings/i18ntk-config.json +282 -282
- package/settings/language-config.json +5 -5
- package/settings/settings-cli.js +9 -9
- package/settings/settings-manager.js +18 -18
- package/ui-locales/de.json +2417 -2348
- package/ui-locales/en.json +2415 -2352
- package/ui-locales/es.json +2425 -2353
- package/ui-locales/fr.json +2418 -2348
- package/ui-locales/ja.json +2463 -2361
- package/ui-locales/ru.json +2463 -2359
- package/ui-locales/zh.json +2418 -2351
- package/utils/admin-auth.js +2 -2
- package/utils/admin-cli.js +297 -297
- package/utils/admin-pin.js +9 -9
- package/utils/cli-helper.js +9 -9
- package/utils/config-helper.js +73 -104
- package/utils/config-manager.js +204 -171
- package/utils/config.js +5 -4
- package/utils/env-manager.js +249 -263
- package/utils/framework-detector.js +27 -24
- package/utils/i18n-helper.js +85 -41
- package/utils/init-helper.js +152 -94
- package/utils/json-output.js +98 -98
- package/utils/mini-commander.js +179 -0
- package/utils/missing-key-validator.js +5 -5
- package/utils/plugin-loader.js +40 -29
- package/utils/prompt.js +14 -44
- package/utils/safe-json.js +40 -0
- package/utils/secure-errors.js +3 -3
- package/utils/security-check-improved.js +390 -0
- package/utils/security-config.js +5 -5
- package/utils/security-fixed.js +607 -0
- package/utils/security.js +652 -602
- package/utils/setup-enforcer.js +136 -44
- package/utils/setup-validator.js +33 -32
- package/utils/ultra-performance-optimizer.js +11 -9
- package/utils/watch-locales.js +2 -1
- package/utils/prompt-fixed.js +0 -55
- package/utils/security-check.js +0 -454
package/main/i18ntk-setup.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* i18ntk-setup.js - Foundational Setup Script
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* This script runs before all other initialization or operational scripts.
|
|
7
7
|
* It configures the core framework, detects programming language/framework,
|
|
8
8
|
* specifies translation file locations, and establishes essential prerequisites.
|
|
@@ -11,417 +11,22 @@
|
|
|
11
11
|
const fs = require('fs');
|
|
12
12
|
const path = require('path');
|
|
13
13
|
|
|
14
|
-
const
|
|
14
|
+
const SecurityUtils = require('../utils/security');
|
|
15
|
+
const configManager = require('../utils/config-manager');
|
|
16
|
+
const SetupService = require('./manage/services/SetupService');
|
|
15
17
|
|
|
16
18
|
class I18nSetupManager {
|
|
17
19
|
constructor() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
detectedFramework: null,
|
|
21
|
-
sourceDir: './locales',
|
|
22
|
-
outputDir: './i18ntk-reports',
|
|
23
|
-
frameworkConfig: {},
|
|
24
|
-
prerequisites: {},
|
|
25
|
-
optimization: {
|
|
26
|
-
mode: 'auto',
|
|
27
|
-
cacheEnabled: true,
|
|
28
|
-
batchSize: 1000
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
this.supportedLanguages = ['javascript', 'typescript', 'python', 'java', 'go', 'php'];
|
|
32
|
-
this.supportedFrameworks = {
|
|
33
|
-
javascript: ['react', 'vue', 'angular', 'nextjs', 'nuxt', 'svelte'],
|
|
34
|
-
typescript: ['react', 'vue', 'angular', 'nextjs', 'nuxt'],
|
|
35
|
-
python: ['django', 'flask', 'fastapi'],
|
|
36
|
-
java: ['spring', 'spring-boot', 'quarkus'],
|
|
37
|
-
go: ['gin', 'echo', 'fiber'],
|
|
38
|
-
php: ['laravel', 'symfony', 'wordpress']
|
|
39
|
-
};
|
|
20
|
+
// Use the new SetupService for core business logic
|
|
21
|
+
this.setupService = new SetupService();
|
|
40
22
|
}
|
|
41
23
|
|
|
42
24
|
async setup() {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
await this.detectEnvironment();
|
|
48
|
-
await this.configureFramework();
|
|
49
|
-
await this.validatePrerequisites();
|
|
50
|
-
await this.optimizeForLanguage();
|
|
51
|
-
await this.generateSetupReport();
|
|
52
|
-
|
|
53
|
-
console.log('✅ Setup completed successfully!');
|
|
54
|
-
return this.config;
|
|
55
|
-
} catch (error) {
|
|
56
|
-
console.error('❌ Setup failed:', error.message);
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
25
|
+
// Delegate to SetupService for all business logic
|
|
26
|
+
return await this.setupService.setup();
|
|
59
27
|
}
|
|
60
28
|
|
|
61
|
-
|
|
62
|
-
console.log('📍 Detecting environment...');
|
|
63
|
-
|
|
64
|
-
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
65
|
-
const pyprojectPath = path.join(process.cwd(), 'pyproject.toml');
|
|
66
|
-
const requirementsPath = path.join(process.cwd(), 'requirements.txt');
|
|
67
|
-
const goModPath = path.join(process.cwd(), 'go.mod');
|
|
68
|
-
const pomPath = path.join(process.cwd(), 'pom.xml');
|
|
69
|
-
const composerPath = path.join(process.cwd(), 'composer.json');
|
|
70
|
-
|
|
71
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
72
|
-
this.config.detectedLanguage = 'javascript';
|
|
73
|
-
await this.detectNodeFramework(packageJsonPath);
|
|
74
|
-
} else if (fs.existsSync(pyprojectPath) || fs.existsSync(requirementsPath)) {
|
|
75
|
-
this.config.detectedLanguage = 'python';
|
|
76
|
-
await this.detectPythonFramework();
|
|
77
|
-
} else if (fs.existsSync(goModPath)) {
|
|
78
|
-
this.config.detectedLanguage = 'go';
|
|
79
|
-
this.config.detectedFramework = 'generic';
|
|
80
|
-
} else if (fs.existsSync(pomPath)) {
|
|
81
|
-
this.config.detectedLanguage = 'java';
|
|
82
|
-
await this.detectJavaFramework(pomPath);
|
|
83
|
-
} else if (fs.existsSync(composerPath)) {
|
|
84
|
-
this.config.detectedLanguage = 'php';
|
|
85
|
-
await this.detectPhpFramework(composerPath);
|
|
86
|
-
} else {
|
|
87
|
-
this.config.detectedLanguage = 'generic';
|
|
88
|
-
this.config.detectedFramework = 'generic';
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
console.log(` Language: ${this.config.detectedLanguage}`);
|
|
92
|
-
console.log(` Framework: ${this.config.detectedFramework}`);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async detectNodeFramework(packageJsonPath) {
|
|
96
|
-
try {
|
|
97
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
98
|
-
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
99
|
-
|
|
100
|
-
if (deps.react || deps['react-dom']) this.config.detectedFramework = 'react';
|
|
101
|
-
else if (deps.vue || deps['vue-router']) this.config.detectedFramework = 'vue';
|
|
102
|
-
else if (deps['@angular/core']) this.config.detectedFramework = 'angular';
|
|
103
|
-
else if (deps.next) this.config.detectedFramework = 'nextjs';
|
|
104
|
-
else if (deps.nuxt) this.config.detectedFramework = 'nuxt';
|
|
105
|
-
else if (deps.svelte) this.config.detectedFramework = 'svelte';
|
|
106
|
-
else this.config.detectedFramework = 'generic';
|
|
107
|
-
} catch (error) {
|
|
108
|
-
this.config.detectedFramework = 'generic';
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async detectPythonFramework() {
|
|
113
|
-
try {
|
|
114
|
-
const requirementsPath = path.join(process.cwd(), 'requirements.txt');
|
|
115
|
-
if (fs.existsSync(requirementsPath)) {
|
|
116
|
-
const requirements = fs.readFileSync(requirementsPath, 'utf8');
|
|
117
|
-
if (requirements.includes('django')) this.config.detectedFramework = 'django';
|
|
118
|
-
else if (requirements.includes('flask')) this.config.detectedFramework = 'flask';
|
|
119
|
-
else if (requirements.includes('fastapi')) this.config.detectedFramework = 'fastapi';
|
|
120
|
-
else this.config.detectedFramework = 'generic';
|
|
121
|
-
} else {
|
|
122
|
-
this.config.detectedFramework = 'generic';
|
|
123
|
-
}
|
|
124
|
-
} catch (error) {
|
|
125
|
-
this.config.detectedFramework = 'generic';
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
async detectJavaFramework(pomPath) {
|
|
130
|
-
try {
|
|
131
|
-
const pomContent = fs.readFileSync(pomPath, 'utf8');
|
|
132
|
-
if (pomContent.includes('spring-boot')) this.config.detectedFramework = 'spring-boot';
|
|
133
|
-
else if (pomContent.includes('spring')) this.config.detectedFramework = 'spring';
|
|
134
|
-
else if (pomContent.includes('quarkus')) this.config.detectedFramework = 'quarkus';
|
|
135
|
-
else this.config.detectedFramework = 'generic';
|
|
136
|
-
} catch (error) {
|
|
137
|
-
this.config.detectedFramework = 'generic';
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async detectPhpFramework(composerPath) {
|
|
142
|
-
try {
|
|
143
|
-
const composer = JSON.parse(fs.readFileSync(composerPath, 'utf8'));
|
|
144
|
-
const deps = composer.require || {};
|
|
145
|
-
|
|
146
|
-
if (deps['laravel/framework']) this.config.detectedFramework = 'laravel';
|
|
147
|
-
else if (deps['symfony/framework-bundle']) this.config.detectedFramework = 'symfony';
|
|
148
|
-
else if (deps['wordpress']) this.config.detectedFramework = 'wordpress';
|
|
149
|
-
else this.config.detectedFramework = 'generic';
|
|
150
|
-
} catch (error) {
|
|
151
|
-
this.config.detectedFramework = 'generic';
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
async configureFramework() {
|
|
156
|
-
console.log('⚙️ Configuring framework...');
|
|
157
|
-
|
|
158
|
-
const frameworkConfigs = {
|
|
159
|
-
javascript: {
|
|
160
|
-
sourcePatterns: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'],
|
|
161
|
-
i18nLibraries: ['i18next', 'react-i18next', 'vue-i18n', '@angular/localize'],
|
|
162
|
-
defaultLocalePath: './src/locales',
|
|
163
|
-
extractPatterns: [
|
|
164
|
-
/t\(['"`]([^'"`]+)['"`]/g,
|
|
165
|
-
/i18n\.t\(['"`]([^'"`]+)['"`]/g,
|
|
166
|
-
/\$t\(['"`]([^'"`]+)['"`]/g
|
|
167
|
-
]
|
|
168
|
-
},
|
|
169
|
-
python: {
|
|
170
|
-
sourcePatterns: ['**/*.py'],
|
|
171
|
-
i18nLibraries: ['django', 'flask-babel', 'babel'],
|
|
172
|
-
defaultLocalePath: './locale',
|
|
173
|
-
extractPatterns: [
|
|
174
|
-
/_\(['"`]([^'"`]+)['"`]/g,
|
|
175
|
-
/gettext\(['"`]([^'"`]+)['"`]/g
|
|
176
|
-
]
|
|
177
|
-
},
|
|
178
|
-
go: {
|
|
179
|
-
sourcePatterns: ['**/*.go'],
|
|
180
|
-
i18nLibraries: ['go-i18n', 'nicksnyder/go-i18n'],
|
|
181
|
-
defaultLocalePath: './locales',
|
|
182
|
-
extractPatterns: [
|
|
183
|
-
/Localize\([^)]*MessageID:\s*['"`]([^'"`]+)['"`]/g
|
|
184
|
-
]
|
|
185
|
-
},
|
|
186
|
-
java: {
|
|
187
|
-
sourcePatterns: ['**/*.java'],
|
|
188
|
-
i18nLibraries: ['spring-boot-starter-web', 'spring-context'],
|
|
189
|
-
defaultLocalePath: './src/main/resources/messages',
|
|
190
|
-
extractPatterns: [
|
|
191
|
-
/getMessage\(['"`]([^'"`]+)['"`]/g,
|
|
192
|
-
/@Value\(['"`]([^'"`]+)['"`]/g
|
|
193
|
-
]
|
|
194
|
-
},
|
|
195
|
-
php: {
|
|
196
|
-
sourcePatterns: ['**/*.php'],
|
|
197
|
-
i18nLibraries: ['gettext', 'symfony/translation'],
|
|
198
|
-
defaultLocalePath: './resources/lang',
|
|
199
|
-
extractPatterns: [
|
|
200
|
-
/_\(['"`]([^'"`]+)['"`]/g,
|
|
201
|
-
/trans\(['"`]([^'"`]+)['"`]/g
|
|
202
|
-
]
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
this.config.frameworkConfig = frameworkConfigs[this.config.detectedLanguage] || frameworkConfigs.javascript;
|
|
207
|
-
|
|
208
|
-
// Auto-detect source directory
|
|
209
|
-
const possiblePaths = [
|
|
210
|
-
this.config.frameworkConfig.defaultLocalePath,
|
|
211
|
-
'./locales',
|
|
212
|
-
'./i18n',
|
|
213
|
-
'./translations',
|
|
214
|
-
'./src/i18n',
|
|
215
|
-
'./app/i18n'
|
|
216
|
-
];
|
|
217
|
-
|
|
218
|
-
for (const dirPath of possiblePaths) {
|
|
219
|
-
if (fs.existsSync(dirPath)) {
|
|
220
|
-
this.config.sourceDir = dirPath;
|
|
221
|
-
break;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
console.log(` Source directory: ${this.config.sourceDir}`);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
async validatePrerequisites() {
|
|
229
|
-
console.log('🔍 Validating prerequisites...');
|
|
230
|
-
|
|
231
|
-
this.config.prerequisites = {
|
|
232
|
-
nodeVersion: process.version,
|
|
233
|
-
nodeVersionValid: parseInt(process.version.slice(1).split('.')[0]) >= 16,
|
|
234
|
-
hasPackageJson: fs.existsSync('package.json'),
|
|
235
|
-
hasLocales: fs.existsSync(this.config.sourceDir),
|
|
236
|
-
hasGit: this.checkCommand('git'),
|
|
237
|
-
hasNpm: this.checkCommand('npm'),
|
|
238
|
-
hasPython: this.checkCommand('python3') || this.checkCommand('python'),
|
|
239
|
-
hasJava: this.checkCommand('java'),
|
|
240
|
-
hasGo: this.checkCommand('go'),
|
|
241
|
-
hasPhp: this.checkCommand('php')
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
// Check for i18n libraries
|
|
245
|
-
if (this.config.detectedLanguage === 'javascript') {
|
|
246
|
-
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
247
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
248
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
249
|
-
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
250
|
-
|
|
251
|
-
this.config.prerequisites.hasI18nLibrary = Object.keys(deps).some(dep =>
|
|
252
|
-
this.config.frameworkConfig.i18nLibraries.some(lib => dep.includes(lib))
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
Object.entries(this.config.prerequisites).forEach(([key, value]) => {
|
|
258
|
-
if (typeof value === 'boolean') {
|
|
259
|
-
console.log(` ${key}: ${value ? '✅' : '❌'}`);
|
|
260
|
-
} else {
|
|
261
|
-
console.log(` ${key}: ${value}`);
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
checkCommand(command) {
|
|
267
|
-
// Secure command checking without child_process
|
|
268
|
-
const extensions = process.platform === 'win32' ? ['.exe', '.cmd', '.bat'] : [''];
|
|
269
|
-
const pathEnv = process.env.PATH || process.env.Path || '';
|
|
270
|
-
const pathDirs = pathEnv.split(process.platform === 'win32' ? ';' : ':');
|
|
271
|
-
|
|
272
|
-
for (const dir of pathDirs) {
|
|
273
|
-
for (const ext of extensions) {
|
|
274
|
-
const fullPath = path.join(dir, command + ext);
|
|
275
|
-
try {
|
|
276
|
-
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
277
|
-
return true;
|
|
278
|
-
}
|
|
279
|
-
} catch {
|
|
280
|
-
// Ignore errors accessing files
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
return false;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
async optimizeForLanguage() {
|
|
288
|
-
console.log('🚀 Optimizing for language...');
|
|
289
|
-
|
|
290
|
-
const optimizationStrategies = {
|
|
291
|
-
javascript: {
|
|
292
|
-
mode: 'extreme',
|
|
293
|
-
cacheEnabled: true,
|
|
294
|
-
batchSize: 1000,
|
|
295
|
-
parallelProcessing: true,
|
|
296
|
-
treeShaking: true
|
|
297
|
-
},
|
|
298
|
-
python: {
|
|
299
|
-
mode: 'ultra',
|
|
300
|
-
cacheEnabled: true,
|
|
301
|
-
batchSize: 500,
|
|
302
|
-
asyncProcessing: true,
|
|
303
|
-
lazyLoading: true
|
|
304
|
-
},
|
|
305
|
-
go: {
|
|
306
|
-
mode: 'extreme',
|
|
307
|
-
cacheEnabled: true,
|
|
308
|
-
batchSize: 2000,
|
|
309
|
-
concurrentProcessing: true,
|
|
310
|
-
memoryOptimization: true
|
|
311
|
-
},
|
|
312
|
-
java: {
|
|
313
|
-
mode: 'ultra',
|
|
314
|
-
cacheEnabled: true,
|
|
315
|
-
batchSize: 800,
|
|
316
|
-
jvmOptimization: true,
|
|
317
|
-
connectionPooling: true
|
|
318
|
-
},
|
|
319
|
-
php: {
|
|
320
|
-
mode: 'optimized',
|
|
321
|
-
cacheEnabled: true,
|
|
322
|
-
batchSize: 300,
|
|
323
|
-
opcacheEnabled: true,
|
|
324
|
-
memoryLimit: '256M'
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
this.config.optimization = {
|
|
329
|
-
...this.config.optimization,
|
|
330
|
-
...optimizationStrategies[this.config.detectedLanguage]
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
// Update configuration using SettingsManager
|
|
334
|
-
const SettingsManager = require('../settings/settings-manager');
|
|
335
|
-
const settingsManager = new SettingsManager();
|
|
336
|
-
|
|
337
|
-
console.log('🔧 About to update settings with:', {
|
|
338
|
-
setup: {
|
|
339
|
-
completed: true,
|
|
340
|
-
completedAt: new Date().toISOString(),
|
|
341
|
-
version: require('../package.json').version,
|
|
342
|
-
setupId: `setup_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
settingsManager.updateSettings({
|
|
347
|
-
'sourceDir': this.config.sourceDir,
|
|
348
|
-
'outputDir': this.config.outputDir,
|
|
349
|
-
'detectedLanguage': this.config.detectedLanguage,
|
|
350
|
-
'detectedFramework': this.config.detectedFramework,
|
|
351
|
-
'optimization': this.config.optimization,
|
|
352
|
-
'prerequisites': this.config.prerequisites,
|
|
353
|
-
'security.adminPinEnabled': false,
|
|
354
|
-
'security.sessionTimeout': 1800000,
|
|
355
|
-
'security.maxFailedAttempts': 3,
|
|
356
|
-
'setup.completed': true,
|
|
357
|
-
'setup.completedAt': new Date().toISOString(),
|
|
358
|
-
'setup.version': require('../package.json').version,
|
|
359
|
-
'setup.setupId': `setup_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
console.log(` Configuration updated in settings/i18ntk-config.json`);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
async generateSetupReport() {
|
|
366
|
-
console.log('📊 Generating setup report...');
|
|
367
|
-
|
|
368
|
-
const report = {
|
|
369
|
-
timestamp: new Date().toISOString(),
|
|
370
|
-
setup: {
|
|
371
|
-
language: this.config.detectedLanguage,
|
|
372
|
-
framework: this.config.detectedFramework,
|
|
373
|
-
sourceDirectory: this.config.sourceDir,
|
|
374
|
-
optimizationMode: this.config.optimization.mode,
|
|
375
|
-
prerequisitesMet: Object.values(this.config.prerequisites).filter(v => v === true).length,
|
|
376
|
-
totalPrerequisites: Object.values(this.config.prerequisites).filter(v => typeof v === 'boolean').length
|
|
377
|
-
},
|
|
378
|
-
recommendations: this.generateRecommendations(),
|
|
379
|
-
nextSteps: [
|
|
380
|
-
'Run i18ntk-init to initialize your project',
|
|
381
|
-
'Run i18ntk-analyze to scan for translations',
|
|
382
|
-
'Run i18ntk-validate to validate your setup'
|
|
383
|
-
]
|
|
384
|
-
};
|
|
385
|
-
|
|
386
|
-
// Save report using SettingsManager
|
|
387
|
-
const settingsManager = new SettingsManager();
|
|
388
|
-
settingsManager.updateSetting('setupReport', report);
|
|
389
|
-
|
|
390
|
-
// Also save a local copy for user reference
|
|
391
|
-
const reportPath = path.join(process.cwd(), 'i18ntk-setup-report.json');
|
|
392
|
-
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
393
|
-
console.log(` Setup report saved: ${reportPath}`);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
generateRecommendations() {
|
|
397
|
-
const recommendations = [];
|
|
398
|
-
|
|
399
|
-
if (!this.config.prerequisites.hasLocales) {
|
|
400
|
-
recommendations.push({
|
|
401
|
-
type: 'warning',
|
|
402
|
-
message: 'No locale directory found. Run i18ntk-init to create one.',
|
|
403
|
-
action: 'i18ntk-init'
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
if (this.config.detectedLanguage === 'javascript' && !this.config.prerequisites.hasI18nLibrary) {
|
|
408
|
-
recommendations.push({
|
|
409
|
-
type: 'info',
|
|
410
|
-
message: 'Consider installing an i18n library for better integration',
|
|
411
|
-
action: 'npm install i18next'
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
if (!this.config.prerequisites.nodeVersionValid) {
|
|
416
|
-
recommendations.push({
|
|
417
|
-
type: 'error',
|
|
418
|
-
message: 'Node.js version 16+ required',
|
|
419
|
-
action: 'Upgrade Node.js'
|
|
420
|
-
});
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
return recommendations;
|
|
424
|
-
}
|
|
29
|
+
|
|
425
30
|
}
|
|
426
31
|
|
|
427
32
|
// CLI interface
|
package/main/i18ntk-sizing.js
CHANGED
|
@@ -50,7 +50,7 @@ const SetupEnforcer = require('../utils/setup-enforcer');
|
|
|
50
50
|
}
|
|
51
51
|
})();
|
|
52
52
|
|
|
53
|
-
loadTranslations(
|
|
53
|
+
loadTranslations();
|
|
54
54
|
|
|
55
55
|
// Get configuration from settings manager
|
|
56
56
|
function getConfig() {
|
|
@@ -83,7 +83,7 @@ class I18nSizingAnalyzer {
|
|
|
83
83
|
|
|
84
84
|
// Initialize i18n with UI language from config
|
|
85
85
|
const uiLanguage = options.uiLanguage || config.uiLanguage || 'en';
|
|
86
|
-
loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'ui-locales'));
|
|
86
|
+
loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));
|
|
87
87
|
this.stats = {
|
|
88
88
|
files: {},
|
|
89
89
|
languages: {},
|
|
@@ -179,7 +179,7 @@ class I18nSizingAnalyzer {
|
|
|
179
179
|
const stats = SecurityUtils.safeStatSync(langFile, process.cwd());
|
|
180
180
|
if (!stats) return;
|
|
181
181
|
|
|
182
|
-
let content = SecurityUtils.safeReadFileSync(langFile, process.cwd());
|
|
182
|
+
let content = SecurityUtils.safeReadFileSync(langFile, process.cwd(), 'utf8');
|
|
183
183
|
if (typeof content !== "string") content = "";
|
|
184
184
|
totalSize += stats.size;
|
|
185
185
|
totalLines += content.split('\n').length;
|
|
@@ -203,7 +203,7 @@ class I18nSizingAnalyzer {
|
|
|
203
203
|
const stats = SecurityUtils.safeStatSync(filePath, process.cwd());
|
|
204
204
|
if (!stats) return;
|
|
205
205
|
|
|
206
|
-
let content = SecurityUtils.safeReadFileSync(filePath, process.cwd());
|
|
206
|
+
let content = SecurityUtils.safeReadFileSync(filePath, process.cwd(), 'utf8');
|
|
207
207
|
if (typeof content !== "string") content = "";
|
|
208
208
|
this.stats.files[language] = {
|
|
209
209
|
file,
|
|
@@ -229,7 +229,7 @@ class I18nSizingAnalyzer {
|
|
|
229
229
|
if (langFiles) {
|
|
230
230
|
// Handle nested directory structure - combine all JSON files
|
|
231
231
|
langFiles.forEach(langFile => {
|
|
232
|
-
const rawContent = SecurityUtils.safeReadFileSync(langFile, process.cwd());
|
|
232
|
+
const rawContent = SecurityUtils.safeReadFileSync(langFile, process.cwd(), 'utf8');
|
|
233
233
|
const fileContent = SecurityUtils.safeParseJSON(rawContent);
|
|
234
234
|
if (fileContent) {
|
|
235
235
|
const fileName = path.basename(langFile, '.json');
|
|
@@ -238,7 +238,7 @@ class I18nSizingAnalyzer {
|
|
|
238
238
|
});
|
|
239
239
|
} else {
|
|
240
240
|
// Handle single file structure
|
|
241
|
-
const rawContent = SecurityUtils.safeReadFileSync(filePath, process.cwd());
|
|
241
|
+
const rawContent = SecurityUtils.safeReadFileSync(filePath, process.cwd(), 'utf8');
|
|
242
242
|
combinedContent = SecurityUtils.safeParseJSON(rawContent) || {};
|
|
243
243
|
}
|
|
244
244
|
|
package/main/i18ntk-summary.js
CHANGED
|
@@ -19,7 +19,7 @@ const SetupEnforcer = require('../utils/setup-enforcer');
|
|
|
19
19
|
}
|
|
20
20
|
})();
|
|
21
21
|
|
|
22
|
-
loadTranslations( 'en', path.resolve(__dirname, '..', 'ui-locales'));
|
|
22
|
+
loadTranslations( 'en', path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class I18nSummaryReporter {
|
|
@@ -54,7 +54,7 @@ class I18nSummaryReporter {
|
|
|
54
54
|
this.config = baseConfig;
|
|
55
55
|
|
|
56
56
|
const uiLanguage = this.config.uiLanguage || 'en';
|
|
57
|
-
loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'ui-locales'));
|
|
57
|
+
loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));
|
|
58
58
|
|
|
59
59
|
this.sourceDir = this.config.sourceDir;
|
|
60
60
|
|
|
@@ -112,12 +112,12 @@ class I18nSummaryReporter {
|
|
|
112
112
|
|
|
113
113
|
// Get all available languages
|
|
114
114
|
getAvailableLanguages() {
|
|
115
|
-
if (!
|
|
115
|
+
if (!SecurityUtils.safeExistsSync(this.config.sourceDir, this.config.sourceDir)) {
|
|
116
116
|
return [];
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
// Check for monolith JSON files (en.json, es.json, etc.)
|
|
120
|
-
const files =
|
|
120
|
+
const files = SecurityUtils.safeReaddirSync(this.config.sourceDir, this.config.sourceDir) || [];
|
|
121
121
|
const languages = files
|
|
122
122
|
.filter(file => file.endsWith('.json'))
|
|
123
123
|
.map(file => path.basename(file, '.json'));
|
|
@@ -126,7 +126,8 @@ class I18nSummaryReporter {
|
|
|
126
126
|
const directories = fs.readdirSync(this.config.sourceDir)
|
|
127
127
|
.filter(item => {
|
|
128
128
|
const itemPath = path.join(this.config.sourceDir, item);
|
|
129
|
-
|
|
129
|
+
const stats = SecurityUtils.safeStatSync(itemPath, this.config.sourceDir);
|
|
130
|
+
return stats && stats.isDirectory() &&
|
|
130
131
|
!item.startsWith('.') &&
|
|
131
132
|
item !== 'node_modules';
|
|
132
133
|
});
|
|
@@ -138,11 +139,11 @@ class I18nSummaryReporter {
|
|
|
138
139
|
getLanguageFiles(language) {
|
|
139
140
|
const languageDir = path.join(this.config.sourceDir, language);
|
|
140
141
|
|
|
141
|
-
if (!
|
|
142
|
+
if (!SecurityUtils.safeExistsSync(languageDir, this.config.sourceDir)) {
|
|
142
143
|
return [];
|
|
143
144
|
}
|
|
144
145
|
|
|
145
|
-
return
|
|
146
|
+
return SecurityUtils.safeReaddirSync(languageDir, this.config.sourceDir) || []
|
|
146
147
|
.filter(file => {
|
|
147
148
|
return this.config.supportedExtensions.some(ext => file.endsWith(ext)) &&
|
|
148
149
|
!this.config.excludeFiles.includes(file);
|
|
@@ -153,7 +154,7 @@ class I18nSummaryReporter {
|
|
|
153
154
|
// Get file size information
|
|
154
155
|
getFileSize(filePath) {
|
|
155
156
|
try {
|
|
156
|
-
const stats =
|
|
157
|
+
const stats = SecurityUtils.safeStatSync(filePath, this.config.sourceDir);
|
|
157
158
|
return {
|
|
158
159
|
size: stats.size,
|
|
159
160
|
sizeFormatted: this.formatFileSize(stats.size),
|
|
@@ -177,10 +178,10 @@ class I18nSummaryReporter {
|
|
|
177
178
|
calculateFolderSize(folderPath) {
|
|
178
179
|
let totalSize = 0;
|
|
179
180
|
try {
|
|
180
|
-
const items =
|
|
181
|
+
const items = SecurityUtils.safeReaddirSync(folderPath, this.config.sourceDir) || [];
|
|
181
182
|
for (const item of items) {
|
|
182
183
|
const itemPath = path.join(folderPath, item);
|
|
183
|
-
const stats =
|
|
184
|
+
const stats = SecurityUtils.safeStatSync(itemPath, this.config.sourceDir);
|
|
184
185
|
if (stats.isDirectory()) {
|
|
185
186
|
totalSize += this.calculateFolderSize(itemPath);
|
|
186
187
|
} else {
|
|
@@ -340,7 +341,7 @@ class I18nSummaryReporter {
|
|
|
340
341
|
// Calculate folder sizes for each language
|
|
341
342
|
for (const language of this.stats.languages) {
|
|
342
343
|
const languageDir = path.join(this.config.sourceDir, language);
|
|
343
|
-
if (
|
|
344
|
+
if (SecurityUtils.safeExistsSync(languageDir, this.config.sourceDir)) {
|
|
344
345
|
this.stats.folderSizes[language] = this.calculateFolderSize(languageDir);
|
|
345
346
|
}
|
|
346
347
|
}
|
|
@@ -830,7 +831,7 @@ class I18nSummaryReporter {
|
|
|
830
831
|
this.config = { ...this.config, ...baseConfig };
|
|
831
832
|
|
|
832
833
|
const uiLanguage = this.config.uiLanguage || 'en';
|
|
833
|
-
loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'ui-locales'));
|
|
834
|
+
loadTranslations(uiLanguage, path.resolve(__dirname, '..', 'resources', 'i18n', 'ui-locales'));
|
|
834
835
|
if (!this.config.sourceDir) {
|
|
835
836
|
this.config.sourceDir = this.detectI18nDirectory();
|
|
836
837
|
}
|
|
@@ -865,7 +866,7 @@ class I18nSummaryReporter {
|
|
|
865
866
|
}
|
|
866
867
|
|
|
867
868
|
// Validate source directory exists
|
|
868
|
-
if (!
|
|
869
|
+
if (!SecurityUtils.safeExistsSync(this.config.sourceDir, this.config.sourceDir)) {
|
|
869
870
|
console.error(t('summary.sourceDirectoryDoesNotExist', { sourceDir: this.config.sourceDir }));
|
|
870
871
|
process.exit(1);
|
|
871
872
|
}
|
|
@@ -898,7 +899,7 @@ class I18nSummaryReporter {
|
|
|
898
899
|
|
|
899
900
|
// Create output directory if it doesn't exist
|
|
900
901
|
const outputDir = path.resolve(process.cwd(), 'i18ntk-reports');
|
|
901
|
-
if (!
|
|
902
|
+
if (!SecurityUtils.safeExistsSync(outputDir)) {
|
|
902
903
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
903
904
|
}
|
|
904
905
|
|
|
@@ -923,7 +924,7 @@ class I18nSummaryReporter {
|
|
|
923
924
|
if (args.outputFile) {
|
|
924
925
|
// Always save summary reports to i18ntk-reports
|
|
925
926
|
const reportsDir = path.resolve(process.cwd(), 'i18ntk-reports');
|
|
926
|
-
if (!
|
|
927
|
+
if (!SecurityUtils.safeExistsSync(reportsDir)) {
|
|
927
928
|
fs.mkdirSync(reportsDir, { recursive: true });
|
|
928
929
|
}
|
|
929
930
|
const outputFileName = args.outputFile ? path.basename(args.outputFile) : `summary-report-${new Date().toISOString().slice(0,10)}.txt`;
|
|
@@ -943,8 +944,8 @@ class I18nSummaryReporter {
|
|
|
943
944
|
console.log(t('summary.cleaningUpReportFiles'));
|
|
944
945
|
try {
|
|
945
946
|
const reportsDir = path.join(this.config.sourceDir, 'scripts', 'i18n', 'reports');
|
|
946
|
-
if (
|
|
947
|
-
const files =
|
|
947
|
+
if (SecurityUtils.safeExistsSync(reportsDir)) {
|
|
948
|
+
const files = SecurityUtils.safeReaddirSync(reportsDir, this.config.sourceDir) || [];
|
|
948
949
|
const reportFiles = files.filter(file =>
|
|
949
950
|
(file.endsWith('.txt') || file.endsWith('.json') || file.endsWith('.log')) &&
|
|
950
951
|
file !== path.basename(args.outputFile || '')
|
|
@@ -953,7 +954,9 @@ class I18nSummaryReporter {
|
|
|
953
954
|
let deletedCount = 0;
|
|
954
955
|
for (const file of reportFiles) {
|
|
955
956
|
try {
|
|
956
|
-
fs.unlinkSync
|
|
957
|
+
// Note: Using direct fs.unlinkSync as SecurityUtils.safeUnlinkSync doesn't exist yet
|
|
958
|
+
// This should be replaced with a secure version when available
|
|
959
|
+
fs.unlinkSync(path.join(reportsDir, file));
|
|
957
960
|
deletedCount++;
|
|
958
961
|
} catch (error) {
|
|
959
962
|
console.log(t('summary.couldNotDelete', { file, error: error.message }));
|