tractatus/scripts/validate-implementer-i18n.js
TheFlow b289808ab3 feat(i18n): add complete German and French translations for implementer page
Add comprehensive internationalization support for implementer.html:

- Added 277 data-i18n attributes across all major sections:
  * Hero section (title, subtitle, 3 value props)
  * Quick Links navigation (8 items)
  * How It Works section
  * Architecture diagrams (3 sections)
  * Hook Architecture (~50+ elements)
  * Deployment guide
  * Core Services (6 service cards)
  * API Reference (4 examples)
  * Integration Examples & Patterns (8 items)
  * Development Roadmap (6 items + CTA)
  * Resources section

- Translation files:
  * EN: 289 keys (complete structure)
  * DE: 282 keys translated via DeepL Pro API (0 errors)
  * FR: 282 keys translated via DeepL Pro API (0 errors)
  * Validation: 100% - all 277 HTML keys present in all languages

- Added automation scripts:
  * translate-implementer-deepl.js - DeepL translation automation
  * validate-implementer-i18n.js - Translation validation

Follows successful pattern from researcher page translation.
All translations professionally formatted with proper formality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 00:57:29 +13:00

88 lines
3 KiB
JavaScript
Executable file

#!/usr/bin/env node
/**
* Validate implementer.html i18n keys against translation files
*/
const fs = require('fs');
const path = require('path');
// Read HTML file and extract data-i18n keys
const htmlPath = path.join(__dirname, '../public/implementer.html');
const html = fs.readFileSync(htmlPath, 'utf8');
const keyPattern = /data-i18n="([^"]+)"/g;
const htmlKeys = new Set();
let match;
while ((match = keyPattern.exec(html)) !== null) {
htmlKeys.add(match[1]);
}
console.log('═══════════════════════════════════════════════════════════');
console.log(' Implementer.html i18n Validation');
console.log('═══════════════════════════════════════════════════════════\n');
console.log(`📄 Total data-i18n keys in HTML: ${htmlKeys.size}`);
// Load translation files
const enPath = path.join(__dirname, '../public/locales/en/implementer.json');
const dePath = path.join(__dirname, '../public/locales/de/implementer.json');
const frPath = path.join(__dirname, '../public/locales/fr/implementer.json');
const enData = JSON.parse(fs.readFileSync(enPath, 'utf8'));
const deData = JSON.parse(fs.readFileSync(dePath, 'utf8'));
const frData = JSON.parse(fs.readFileSync(frPath, 'utf8'));
// Helper to check if nested key exists
function hasNestedKey(obj, keyPath) {
const keys = keyPath.split('.');
let current = obj;
for (const key of keys) {
if (current && typeof current === 'object' && key in current) {
current = current[key];
} else {
return false;
}
}
return typeof current === 'string' && current.length > 0;
}
// Check each language
const languages = [
{ name: 'English (EN)', code: 'en', data: enData },
{ name: 'German (DE)', code: 'de', data: deData },
{ name: 'French (FR)', code: 'fr', data: frData }
];
let allValid = true;
for (const lang of languages) {
const missingKeys = [];
for (const key of htmlKeys) {
if (!hasNestedKey(lang.data, key)) {
missingKeys.push(key);
}
}
console.log(`\n🌐 ${lang.name}`);
if (missingKeys.length === 0) {
console.log(` ✅ All ${htmlKeys.size} keys found`);
} else {
console.log(` ❌ Missing ${missingKeys.length} keys:`);
missingKeys.forEach(key => console.log(`${key}`));
allValid = false;
}
}
console.log('\n═══════════════════════════════════════════════════════════');
if (allValid) {
console.log('✅ VALIDATION PASSED: All i18n keys are properly translated');
} else {
console.log('❌ VALIDATION FAILED: Some keys are missing');
process.exit(1);
}
console.log('═══════════════════════════════════════════════════════════\n');