i18ntk 1.4.1 ā 1.4.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/CHANGELOG.md +9 -1
- package/README.md +8 -2
- package/main/i18ntk-manage.js +5 -5
- package/package.json +4 -4
- package/scripts/debug/README.md +34 -0
- package/scripts/debug/complete-console-translations.js +295 -0
- package/scripts/debug/console-key-checker.js +408 -0
- package/scripts/debug/console-translations.js +335 -0
- package/scripts/debug/debug-security.js +0 -0
- package/scripts/debug/debug-translation.js +56 -0
- package/scripts/debug/debugger.js +476 -0
- package/scripts/debug/export-missing-keys.js +432 -0
- package/scripts/debug/final-normalize.js +236 -0
- package/scripts/debug/find-extra-keys.js +68 -0
- package/scripts/debug/normalize-locales.js +153 -0
- package/scripts/debug/refactor-locales.js +240 -0
- package/scripts/debug/reorder-locales.js +85 -0
- package/scripts/debug/replace-hardcoded-console.js +378 -0
- package/scripts/prepublish.js +2 -2
- package/scripts/validate-all-translations.js +2 -2
- package/utils/test-complete-system.js +1 -1
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* i18nTK Debugger
|
|
5
|
+
* Main debugging script for identifying and fixing issues in the i18n toolkit
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
const SecurityUtils = require('../../utils/security');
|
|
12
|
+
|
|
13
|
+
class I18nDebugger {
|
|
14
|
+
constructor(projectRoot = null) {
|
|
15
|
+
// Validate and sanitize project root path
|
|
16
|
+
let defaultRoot;
|
|
17
|
+
|
|
18
|
+
if (projectRoot) {
|
|
19
|
+
defaultRoot = projectRoot;
|
|
20
|
+
} else {
|
|
21
|
+
// Find the actual project root by walking up from current directory
|
|
22
|
+
defaultRoot = this.findProjectRoot();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const validatedRoot = SecurityUtils.validatePath(defaultRoot, process.cwd());
|
|
26
|
+
if (!validatedRoot) {
|
|
27
|
+
throw new Error('Invalid project root path provided');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this.projectRoot = validatedRoot;
|
|
31
|
+
this.issues = [];
|
|
32
|
+
this.warnings = [];
|
|
33
|
+
this.logFile = path.join(__dirname, 'logs', `debug-${new Date().toISOString().replace(/[:.]/g, '-')}.log`);
|
|
34
|
+
|
|
35
|
+
// Ensure logs directory exists
|
|
36
|
+
const logsDir = path.dirname(this.logFile);
|
|
37
|
+
if (!fs.existsSync(logsDir)) {
|
|
38
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
log(message, level = 'INFO') {
|
|
43
|
+
const timestamp = new Date().toISOString();
|
|
44
|
+
const logMessage = `[${timestamp}] [${level}] ${message}`;
|
|
45
|
+
console.log(logMessage);
|
|
46
|
+
fs.appendFileSync(this.logFile, logMessage + '\n');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
findProjectRoot() {
|
|
50
|
+
// Start from the current working directory and walk up to find project root
|
|
51
|
+
let currentDir = process.cwd();
|
|
52
|
+
|
|
53
|
+
// First, check if we're running from within node_modules/i18ntk
|
|
54
|
+
const nodeModulesPattern = /[\/\\]node_modules[\/\\]i18ntk/;
|
|
55
|
+
if (nodeModulesPattern.test(currentDir)) {
|
|
56
|
+
// We're running from the i18ntk package, find the actual project root
|
|
57
|
+
let projectDir = currentDir;
|
|
58
|
+
while (projectDir !== path.dirname(projectDir)) {
|
|
59
|
+
if (fs.existsSync(path.join(projectDir, 'package.json')) &&
|
|
60
|
+
!projectDir.includes('node_modules')) {
|
|
61
|
+
return projectDir;
|
|
62
|
+
}
|
|
63
|
+
projectDir = path.dirname(projectDir);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Walk up the directory tree to find package.json
|
|
68
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
69
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
70
|
+
|
|
71
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
72
|
+
try {
|
|
73
|
+
const packageContent = fs.readFileSync(packageJsonPath, 'utf8');
|
|
74
|
+
const packageData = JSON.parse(packageContent);
|
|
75
|
+
|
|
76
|
+
// Skip if this is the i18ntk package itself
|
|
77
|
+
if (packageData.name === 'i18ntk' && currentDir.includes('node_modules')) {
|
|
78
|
+
currentDir = path.dirname(currentDir);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Found a valid project package.json
|
|
83
|
+
return currentDir;
|
|
84
|
+
} catch (error) {
|
|
85
|
+
// Invalid package.json, continue searching
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
currentDir = path.dirname(currentDir);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Fallback to the original behavior if no project root found
|
|
93
|
+
return path.resolve(__dirname, '../..');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
addIssue(issue) {
|
|
97
|
+
this.issues.push(issue);
|
|
98
|
+
this.log(`ISSUE: ${issue}`, 'ERROR');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
addWarning(warning) {
|
|
102
|
+
this.warnings.push(warning);
|
|
103
|
+
this.log(`WARNING: ${warning}`, 'WARN');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
checkFileExists(filePath, description) {
|
|
107
|
+
try {
|
|
108
|
+
// Validate path before checking existence
|
|
109
|
+
const validatedPath = SecurityUtils.validatePath(filePath, this.projectRoot);
|
|
110
|
+
if (!validatedPath) {
|
|
111
|
+
this.addIssue(`Invalid file path: ${filePath}`);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const fullPath = path.resolve(this.projectRoot, filePath);
|
|
116
|
+
if (!fs.existsSync(fullPath)) {
|
|
117
|
+
this.addIssue(`Missing file: ${filePath} (${description})`);
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
this.log(`ā Found: ${filePath}`);
|
|
121
|
+
return true;
|
|
122
|
+
} catch (error) {
|
|
123
|
+
this.addIssue(`Error checking file existence: ${filePath} - ${error.message}`);
|
|
124
|
+
SecurityUtils.logSecurityEvent('File existence check failed', 'warn', { filePath, error: error.message });
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
checkOldNamingConventions() {
|
|
130
|
+
this.log('Checking for old naming conventions...');
|
|
131
|
+
const oldFiles = [
|
|
132
|
+
'00-manage-i18n.js',
|
|
133
|
+
'01-init-i18n.js',
|
|
134
|
+
'02-analyze-translations.js',
|
|
135
|
+
'03-validate-translations.js',
|
|
136
|
+
'04-check-usage.js',
|
|
137
|
+
'05-complete-translations.js',
|
|
138
|
+
'06-analyze-sizing.js',
|
|
139
|
+
'07-generate-summary.js'
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
oldFiles.forEach(file => {
|
|
143
|
+
const fullPath = path.resolve(this.projectRoot, file);
|
|
144
|
+
if (fs.existsSync(fullPath)) {
|
|
145
|
+
this.addIssue(`Old naming convention file still exists: ${file}`);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Check for references to old files in code
|
|
150
|
+
this.checkForOldReferences();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async checkForOldReferences() {
|
|
154
|
+
this.log('Checking for old file references in code...');
|
|
155
|
+
const filesToCheck = [
|
|
156
|
+
'i18ntk-complete.js',
|
|
157
|
+
'i18ntk-usage.js',
|
|
158
|
+
'i18ntk-validate.js',
|
|
159
|
+
'package.json'
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
const oldReferences = [
|
|
163
|
+
'04-check-usage.js',
|
|
164
|
+
'00-manage-i18n.js',
|
|
165
|
+
'01-init-i18n.js',
|
|
166
|
+
'02-analyze-translations.js',
|
|
167
|
+
'03-validate-translations.js',
|
|
168
|
+
'05-complete-translations.js',
|
|
169
|
+
'06-analyze-sizing.js',
|
|
170
|
+
'07-generate-summary.js'
|
|
171
|
+
];
|
|
172
|
+
|
|
173
|
+
for (const file of filesToCheck) {
|
|
174
|
+
const fullPath = path.resolve(this.projectRoot, file);
|
|
175
|
+
if (fs.existsSync(fullPath)) {
|
|
176
|
+
try {
|
|
177
|
+
const content = await SecurityUtils.safeReadFile(fullPath, this.projectRoot);
|
|
178
|
+
if (content) {
|
|
179
|
+
oldReferences.forEach(oldRef => {
|
|
180
|
+
if (content.includes(oldRef)) {
|
|
181
|
+
this.addIssue(`Old reference '${oldRef}' found in ${file}`);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
} catch (error) {
|
|
186
|
+
this.addIssue(`Error reading file ${fullPath}: ${error.message}`);
|
|
187
|
+
SecurityUtils.logSecurityEvent('File read failed during reference check', 'error', { filePath: fullPath, error: error.message });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async checkTranslationKeys() {
|
|
194
|
+
this.log('Checking for missing translation keys...');
|
|
195
|
+
const uiLocalesDir = path.resolve(this.projectRoot, 'ui-locales');
|
|
196
|
+
|
|
197
|
+
if (!fs.existsSync(uiLocalesDir)) {
|
|
198
|
+
this.addIssue('ui-locales directory not found');
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const languages = ['en', 'de', 'es', 'fr', 'ja', 'ru', 'zh'];
|
|
203
|
+
const availableLanguages = [];
|
|
204
|
+
|
|
205
|
+
for (const lang of languages) {
|
|
206
|
+
const langDir = path.join(uiLocalesDir, lang);
|
|
207
|
+
const commonFile = path.join(langDir, 'common.json');
|
|
208
|
+
if (fs.existsSync(commonFile)) {
|
|
209
|
+
availableLanguages.push(lang);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (availableLanguages.length === 0) {
|
|
214
|
+
this.addIssue('No locale files found in ui-locales directory');
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Load English as reference
|
|
219
|
+
const enPath = path.join(uiLocalesDir, 'en', 'common.json');
|
|
220
|
+
if (!fs.existsSync(enPath)) {
|
|
221
|
+
this.addIssue('English locale file (en/common.json) not found');
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
const enContent = await SecurityUtils.safeReadFile(enPath, this.projectRoot);
|
|
227
|
+
if (!enContent) {
|
|
228
|
+
this.addIssue('Failed to read en.json file');
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const enLocale = SecurityUtils.safeParseJSON(enContent);
|
|
233
|
+
if (!enLocale) {
|
|
234
|
+
this.addIssue('Failed to parse en.json file');
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const requiredKeys = this.extractAllKeys(enLocale);
|
|
239
|
+
|
|
240
|
+
for (const language of availableLanguages) {
|
|
241
|
+
const filePath = path.join(uiLocalesDir, language, 'common.json');
|
|
242
|
+
try {
|
|
243
|
+
const content = await SecurityUtils.safeReadFile(filePath, this.projectRoot);
|
|
244
|
+
if (!content) {
|
|
245
|
+
this.addIssue(`Failed to read ${language}/common.json`);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const locale = SecurityUtils.safeParseJSON(content);
|
|
250
|
+
if (!locale) {
|
|
251
|
+
this.addIssue(`Failed to parse ${language}/common.json`);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const existingKeys = this.extractAllKeys(locale);
|
|
256
|
+
|
|
257
|
+
const missingKeys = requiredKeys.filter(key => !existingKeys.includes(key));
|
|
258
|
+
if (missingKeys.length > 0) {
|
|
259
|
+
this.addIssue(`Missing translation keys in ${language}/common.json: ${missingKeys.join(', ')}`);
|
|
260
|
+
}
|
|
261
|
+
} catch (error) {
|
|
262
|
+
this.addIssue(`Error processing ${language}/common.json: ${error.message}`);
|
|
263
|
+
SecurityUtils.logSecurityEvent('Translation file processing failed', 'error', { file: `${language}/common.json`, error: error.message });
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
} catch (error) {
|
|
267
|
+
this.addIssue(`Error processing en.json: ${error.message}`);
|
|
268
|
+
SecurityUtils.logSecurityEvent('English translation file processing failed', 'error', { error: error.message });
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
extractAllKeys(obj, prefix = '') {
|
|
273
|
+
let keys = [];
|
|
274
|
+
for (const key in obj) {
|
|
275
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
276
|
+
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
|
|
277
|
+
keys = keys.concat(this.extractAllKeys(obj[key], fullKey));
|
|
278
|
+
} else {
|
|
279
|
+
keys.push(fullKey);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return keys;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
async checkUserConfig() {
|
|
286
|
+
this.log('Checking user configuration...');
|
|
287
|
+
|
|
288
|
+
// Check i18ntk-config.json
|
|
289
|
+
const configPath = path.resolve(this.projectRoot, 'settings', 'i18ntk-config.json');
|
|
290
|
+
if (this.checkFileExists('settings/i18ntk-config.json', 'Main configuration file')) {
|
|
291
|
+
try {
|
|
292
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
293
|
+
const config = JSON.parse(content);
|
|
294
|
+
|
|
295
|
+
this.log('Configuration file found and valid');
|
|
296
|
+
|
|
297
|
+
// Check directory paths
|
|
298
|
+
if (config.directories) {
|
|
299
|
+
const dirs = ['sourceDir', 'outputDir', 'uiLocalesDir'];
|
|
300
|
+
dirs.forEach(dir => {
|
|
301
|
+
if (config.directories[dir]) {
|
|
302
|
+
const dirPath = path.resolve(this.projectRoot, config.directories[dir]);
|
|
303
|
+
if (!fs.existsSync(dirPath)) {
|
|
304
|
+
this.addWarning(`Configured directory does not exist: ${config.directories[dir]}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
} catch (error) {
|
|
310
|
+
this.addIssue(`Error processing i18ntk-config.json: ${error.message}`);
|
|
311
|
+
SecurityUtils.logSecurityEvent('User config processing failed', 'error', { error: error.message });
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
checkPackageJson() {
|
|
317
|
+
this.log('Checking package configuration...');
|
|
318
|
+
this.checkFileExists('package.json', 'Package configuration');
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
checkCoreFiles() {
|
|
322
|
+
this.log('Checking core i18nTK files...');
|
|
323
|
+
const coreFiles = [
|
|
324
|
+
'main/i18ntk-manage.js',
|
|
325
|
+
'main/i18ntk-init.js',
|
|
326
|
+
'main/i18ntk-analyze.js',
|
|
327
|
+
'main/i18ntk-validate.js',
|
|
328
|
+
'main/i18ntk-usage.js',
|
|
329
|
+
'main/i18ntk-complete.js',
|
|
330
|
+
'main/i18ntk-sizing.js',
|
|
331
|
+
'main/i18ntk-summary.js'
|
|
332
|
+
];
|
|
333
|
+
|
|
334
|
+
coreFiles.forEach(file => {
|
|
335
|
+
this.checkFileExists(file, 'Core i18nTK script');
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
checkDependencies() {
|
|
340
|
+
this.log('Checking dependencies...');
|
|
341
|
+
try {
|
|
342
|
+
const packageJson = JSON.parse(fs.readFileSync(path.resolve(this.projectRoot, 'package.json'), 'utf8'));
|
|
343
|
+
const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
344
|
+
|
|
345
|
+
// Check if node_modules exists in project root
|
|
346
|
+
const nodeModulesPath = path.resolve(this.projectRoot, 'node_modules');
|
|
347
|
+
if (!fs.existsSync(nodeModulesPath)) {
|
|
348
|
+
// Also check parent directories for node_modules (monorepo support)
|
|
349
|
+
let currentDir = this.projectRoot;
|
|
350
|
+
let foundNodeModules = false;
|
|
351
|
+
|
|
352
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
353
|
+
const parentNodeModules = path.join(currentDir, 'node_modules');
|
|
354
|
+
if (fs.existsSync(parentNodeModules)) {
|
|
355
|
+
this.log(`Found node_modules in: ${parentNodeModules}`);
|
|
356
|
+
foundNodeModules = true;
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
currentDir = path.dirname(currentDir);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (!foundNodeModules) {
|
|
363
|
+
const depCount = Object.keys(dependencies).length;
|
|
364
|
+
if (depCount > 0) {
|
|
365
|
+
this.addWarning(`node_modules directory not found in project or parent directories. Run 'npm install' in ${this.projectRoot}`);
|
|
366
|
+
} else {
|
|
367
|
+
this.log('No dependencies found in package.json');
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
} else {
|
|
371
|
+
this.log(`Found node_modules in: ${nodeModulesPath}`);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
this.log(`Found ${Object.keys(dependencies).length} dependencies`);
|
|
375
|
+
} catch (error) {
|
|
376
|
+
this.addIssue(`Could not check dependencies: ${error.message}`);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async generateReport() {
|
|
381
|
+
const timestamp = new Date().toLocaleString();
|
|
382
|
+
let summary = '';
|
|
383
|
+
|
|
384
|
+
summary += '\n' + '='.repeat(60) + '\n';
|
|
385
|
+
summary += ' i18nTK DEBUG REPORT\n';
|
|
386
|
+
summary += '='.repeat(60) + '\n';
|
|
387
|
+
summary += `Generated: ${timestamp}\n`;
|
|
388
|
+
summary += `Project Root: ${this.projectRoot}\n`;
|
|
389
|
+
summary += '-'.repeat(60) + '\n';
|
|
390
|
+
summary += `š Summary: ${this.issues.length} issue(s), ${this.warnings.length} warning(s)\n`;
|
|
391
|
+
summary += '-'.repeat(60) + '\n';
|
|
392
|
+
|
|
393
|
+
if (this.issues.length > 0) {
|
|
394
|
+
summary += '\nšØ CRITICAL ISSUES:\n';
|
|
395
|
+
this.issues.forEach((issue, index) => {
|
|
396
|
+
summary += ` ${index + 1}. ā ${issue}\n`;
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (this.warnings.length > 0) {
|
|
401
|
+
summary += '\nā ļø WARNINGS:\n';
|
|
402
|
+
this.warnings.forEach((warning, index) => {
|
|
403
|
+
summary += ` ${index + 1}. ā ļø ${warning}\n`;
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (this.issues.length === 0 && this.warnings.length === 0) {
|
|
408
|
+
summary += '\nā
EXCELLENT! No issues found.\n';
|
|
409
|
+
summary += ' The i18nTK project appears to be healthy.\n';
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
summary += '\n' + '='.repeat(60) + '\n';
|
|
413
|
+
summary += `š Full debug log: ${this.logFile}\n`;
|
|
414
|
+
summary += '='.repeat(60) + '\n';
|
|
415
|
+
|
|
416
|
+
console.log(summary);
|
|
417
|
+
|
|
418
|
+
// Save report to file securely
|
|
419
|
+
const reportPath = path.join(path.dirname(this.logFile), 'debug-report.txt');
|
|
420
|
+
const success = await SecurityUtils.safeWriteFile(reportPath, summary, this.projectRoot);
|
|
421
|
+
if (!success) {
|
|
422
|
+
console.warn('Warning: Could not save debug report due to security restrictions');
|
|
423
|
+
SecurityUtils.logSecurityEvent('Debug report save failed', 'warn', { reportPath });
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return {
|
|
427
|
+
issues: this.issues,
|
|
428
|
+
warnings: this.warnings,
|
|
429
|
+
summary: summary,
|
|
430
|
+
reportPath: reportPath,
|
|
431
|
+
logFile: this.logFile
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
async run() {
|
|
436
|
+
this.log('Starting i18nTK Debug Analysis...');
|
|
437
|
+
this.log(`Project Root: ${this.projectRoot}`);
|
|
438
|
+
this.log(`Working Directory: ${process.cwd()}`);
|
|
439
|
+
this.log(`Debug Tool Directory: ${__dirname}`);
|
|
440
|
+
|
|
441
|
+
SecurityUtils.logSecurityEvent('Debug analysis started', 'info', { projectRoot: this.projectRoot });
|
|
442
|
+
|
|
443
|
+
try {
|
|
444
|
+
this.checkCoreFiles();
|
|
445
|
+
await this.checkUserConfig();
|
|
446
|
+
this.checkPackageJson();
|
|
447
|
+
this.checkOldNamingConventions();
|
|
448
|
+
await this.checkTranslationKeys();
|
|
449
|
+
this.checkDependencies();
|
|
450
|
+
|
|
451
|
+
SecurityUtils.logSecurityEvent('Debug analysis completed', 'info', {
|
|
452
|
+
issuesFound: this.issues.length,
|
|
453
|
+
warningsFound: this.warnings.length
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
return await this.generateReport();
|
|
457
|
+
} catch (error) {
|
|
458
|
+
this.addIssue(`Debug analysis failed: ${error.message}`);
|
|
459
|
+
SecurityUtils.logSecurityEvent('Debug analysis failed', 'error', { error: error.message });
|
|
460
|
+
return await this.generateReport();
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Run debugger if called directly
|
|
466
|
+
if (require.main === module) {
|
|
467
|
+
const debugTool = new I18nDebugger();
|
|
468
|
+
debugTool.run().then(result => {
|
|
469
|
+
process.exit(result.issues.length > 0 ? 1 : 0);
|
|
470
|
+
}).catch(error => {
|
|
471
|
+
console.error('Debugger failed:', error);
|
|
472
|
+
process.exit(1);
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
module.exports = I18nDebugger;
|