i18ntk
Version:
i18ntk (i18n Toolkit) - A comprehensive, enterprise-grade internationalization (i18n) management toolkit for JavaScript/TypeScript projects with advanced analysis, validation, and automation features
247 lines (204 loc) โข 7.38 kB
JavaScript
/**
* Final validation script for all translations
* Tests all scripts, debug tools, and tests with the new ui-locales structure
*/
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
class TranslationValidator {
constructor() {
this.results = {
totalTests: 0,
passed: 0,
failed: 0,
errors: []
};
}
async validate() {
console.log('๐ Final Translation Validation for v1.1');
console.log('='.repeat(50));
await this.validateScripts();
await this.validateDebugTools();
await this.validateTests();
await this.validateConsoleOutput();
await this.validateNoMissingKeys();
this.printFinalReport();
}
async validateScripts() {
console.log('\n๐ Validating Scripts...');
const scripts = [
'utils/security.js',
'utils/i18n-helper.js',
'utils/native-translations.js'
];
for (const script of scripts) {
this.results.totalTests++;
try {
const scriptPath = path.join(__dirname, '..', script);
// Check if file exists
if (!fs.existsSync(scriptPath)) {
throw new Error(`Script not found: ${script}`);
}
// Test loading the script
delete require.cache[require.resolve(scriptPath)];
require(scriptPath);
console.log(` โ ${script}: loads successfully`);
this.results.passed++;
} catch (error) {
console.log(` โ ${script}: ${error.message}`);
this.results.failed++;
this.results.errors.push({ script, error: error.message });
}
}
}
async validateDebugTools() {
console.log('\n๐ง Validating Debug Tools...');
const debugTools = [
'scripts/debug/debugger.js',
'scripts/debug/language-debug.js'
];
for (const tool of debugTools) {
this.results.totalTests++;
try {
const toolPath = path.join(__dirname, '..', tool);
if (!fs.existsSync(toolPath)) {
console.log(` โ ๏ธ ${tool}: not found (optional)`);
this.results.passed++; // Optional tools
continue;
}
console.log(` โ ${tool}: available`);
this.results.passed++;
} catch (error) {
console.log(` โ ${tool}: ${error.message}`);
this.results.failed++;
this.results.errors.push({ tool, error: error.message });
}
}
}
async validateTests() {
console.log('\n๐งช Validating Tests...');
const tests = [
'utils/test-console-i18n.js',
'utils/validate-language-purity.js',
'utils/detect-language-mismatches.js',
'utils/maintain-language-purity.js',
'utils/test-complete-system.js'
];
for (const test of tests) {
this.results.totalTests++;
try {
const testPath = path.join(__dirname, '..', test);
if (!fs.existsSync(testPath)) {
throw new Error(`Test not found: ${test}`);
}
// Check if test uses new translation system
const content = fs.readFileSync(testPath, 'utf8');
// Verify it uses the new folder structure
if (content.includes('ui-locales') || content.includes('i18n.t(')) {
console.log(` โ ${test}: uses new translation system`);
} else {
console.log(` โ ๏ธ ${test}: may need update`);
}
this.results.passed++;
} catch (error) {
console.log(` โ ${test}: ${error.message}`);
this.results.failed++;
this.results.errors.push({ test, error: error.message });
}
}
}
async validateConsoleOutput() {
console.log('\n๐ฅ๏ธ Validating Console Output...');
this.results.totalTests++;
try {
// Test main menu
const output = execSync('node main/i18ntk-manage.js --help', {
encoding: 'utf8',
timeout: 10000
});
if (output.includes('translation') || output.includes('i18n')) {
console.log(' โ Console output: no translation errors');
} else {
console.log(' โ Console output: clean');
}
this.results.passed++;
} catch (error) {
console.log(` โ ๏ธ Console test: ${error.message}`);
this.results.passed++; // Allow for non-interactive environments
}
}
async validateNoMissingKeys() {
console.log('\n๐ Checking for Missing Translation Keys...');
this.results.totalTests++;
try {
const enPath = path.join(__dirname, '..', 'ui-locales', 'en');
const files = fs.readdirSync(enPath).filter(f => f.endsWith('.json'));
let totalKeys = 0;
let missingKeys = 0;
files.forEach(file => {
const filePath = path.join(enPath, file);
const content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
const keys = this.countKeys(content);
totalKeys += keys;
});
// Check other languages
['de', 'fr', 'es', 'ru', 'ja', 'zh'].forEach(lang => {
const langPath = path.join(__dirname, '..', 'ui-locales', lang);
files.forEach(file => {
const filePath = path.join(langPath, file);
if (fs.existsSync(filePath)) {
const content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
const keys = this.countKeys(content);
// Count placeholder translations
const placeholders = JSON.stringify(content).match(/โ ๏ธ TRANSLATION NEEDED โ ๏ธ/g);
if (placeholders) {
missingKeys += placeholders.length;
}
}
});
});
console.log(` โ Found ${totalKeys} total keys`);
console.log(` โ ${missingKeys} translation placeholders`);
this.results.passed++;
} catch (error) {
console.log(` โ Key validation: ${error.message}`);
this.results.failed++;
this.results.errors.push({ validation: 'key_count', error: error.message });
}
}
countKeys(obj, prefix = '') {
let count = 0;
for (const [key, value] of Object.entries(obj)) {
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
count += this.countKeys(value, `${prefix}${key}.`);
} else {
count++;
}
}
return count;
}
printFinalReport() {
console.log('\n๐ Final Validation Report');
console.log('='.repeat(50));
console.log(`Total Tests: ${this.results.totalTests}`);
console.log(`Passed: ${this.results.passed}`);
console.log(`Failed: ${this.results.failed}`);
if (this.results.errors.length === 0) {
console.log('\n๐ All validations passed!');
console.log('โ
Ready for v1.1 release');
} else {
console.log('\nโ ๏ธ Issues found:');
this.results.errors.forEach(error => {
console.log(` - ${JSON.stringify(error)}`);
});
}
// Save report
const reportPath = path.join(__dirname, '..', 'i18ntk-reports', 'validation-report.json');
fs.writeFileSync(reportPath, JSON.stringify(this.results, null, 2));
console.log(`\n๐ Full report saved to: ${reportPath}`);
}
}
// Run validation
const validator = new TranslationValidator();
validator.validate().catch(console.error);