Files
foundryvtt-wh4-lang-fr-fr/tools/generate-translation-report.js

194 lines
7.4 KiB
JavaScript

import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const WFRP4E_DIR = '/home/morr/work/foundryvtt/WFRP4e-FoundryVTT/scripts';
const FR_DIR = path.join(__dirname, 'scripts');
const TRANSLATIONS_FILE = path.join(__dirname, 'auto-translations-applied.json');
// Charger le mapping de traductions
const translations = JSON.parse(fs.readFileSync(TRANSLATIONS_FILE, 'utf8'));
// Fonction pour générer le diff d'un fichier
function generateFileDiff(file) {
const frPath = path.join(FR_DIR, file);
const enPath = path.join(WFRP4E_DIR, file);
if (!fs.existsSync(frPath) || !fs.existsSync(enPath)) {
return null;
}
const frContent = fs.readFileSync(frPath, 'utf8');
const enContent = fs.readFileSync(enPath, 'utf8');
const changes = [];
// Trouver les traductions appliquées dans ce fichier
for (const [en, fr] of Object.entries(translations)) {
if (frContent.includes(fr) && enContent.includes(en)) {
changes.push({ en, fr });
}
}
return {
file,
changes,
frLines: frContent.split('\n').length,
enLines: enContent.split('\n').length
};
}
// Générer le rapport
console.log('Génération du rapport de traduction...\n');
const modifiedFiles = [];
// Lire tous les fichiers JS du répertoire FR
const files = fs.readdirSync(FR_DIR).filter(f => f.endsWith('.js'));
files.forEach(file => {
const diff = generateFileDiff(file);
if (diff && diff.changes.length > 0) {
modifiedFiles.push(diff);
}
});
// Trier par nombre de changements (décroissant)
modifiedFiles.sort((a, b) => b.changes.length - a.changes.length);
// Générer le rapport Markdown
let report = `# Rapport de Traduction Automatique\n\n`;
report += `**Date**: ${new Date().toLocaleDateString('fr-FR')}\n\n`;
report += `**Fichiers modifiés**: ${modifiedFiles.length}\n`;
report += `**Traductions uniques appliquées**: ${Object.keys(translations).length}\n\n`;
report += `---\n\n`;
// Statistiques globales
const totalChanges = modifiedFiles.reduce((sum, file) => sum + file.changes.length, 0);
report += `## Statistiques\n\n`;
report += `- **Total de fichiers analysés**: ${files.length}\n`;
report += `- **Fichiers modifiés**: ${modifiedFiles.length}\n`;
report += `- **Total de changements**: ${totalChanges}\n`;
report += `- **Moyenne de changements par fichier**: ${(totalChanges / modifiedFiles.length).toFixed(2)}\n\n`;
// Top 20 des fichiers les plus modifiés
report += `## Top 20 des fichiers les plus modifiés\n\n`;
report += `| Fichier | Changements |\n`;
report += `|---------|-------------|\n`;
modifiedFiles.slice(0, 20).forEach(({ file, changes }) => {
report += `| ${file} | ${changes.length} |\n`;
});
report += `\n`;
// Traductions les plus fréquentes
const translationFrequency = new Map();
modifiedFiles.forEach(({ changes }) => {
changes.forEach(({ en, fr }) => {
const key = `${en}${fr}`;
translationFrequency.set(key, (translationFrequency.get(key) || 0) + 1);
});
});
const sortedTranslations = Array.from(translationFrequency.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, 30);
report += `## Top 30 des traductions les plus appliquées\n\n`;
report += `| Traduction | Occurrences |\n`;
report += `|------------|-------------|\n`;
sortedTranslations.forEach(([translation, count]) => {
const [en, fr] = translation.split(' → ');
const enShort = en.length > 60 ? en.substring(0, 57) + '...' : en;
const frShort = fr.length > 60 ? fr.substring(0, 57) + '...' : fr;
report += `| \`${enShort}\`\`${frShort}\` | ${count} |\n`;
});
report += `\n`;
// Détails par fichier (exemples significatifs)
report += `## Exemples de modifications détaillées\n\n`;
report += `Voici quelques exemples de fichiers avec leurs traductions appliquées :\n\n`;
modifiedFiles.slice(0, 10).forEach(({ file, changes }) => {
report += `### ${file}\n\n`;
report += `**Nombre de traductions**: ${changes.length}\n\n`;
changes.slice(0, 5).forEach(({ en, fr }) => {
const enDisplay = en.length > 80 ? en.substring(0, 77) + '...' : en;
const frDisplay = fr.length > 80 ? fr.substring(0, 77) + '...' : fr;
report += `- ✏️ \`${enDisplay}\`\n`;
report += `\`${frDisplay}\`\n\n`;
});
if (changes.length > 5) {
report += `... et ${changes.length - 5} autre(s) traduction(s)\n\n`;
}
});
// Traductions potentiellement problématiques
report += `## ⚠️ Traductions à vérifier\n\n`;
report += `Certaines traductions automatiques peuvent nécessiter une révision manuelle :\n\n`;
const problematicPatterns = [
{ pattern: /effet\./, reason: "Vérifier que 'effect' -> 'effet' est approprié dans le contexte" },
{ pattern: /Retiré/, reason: "Vérifier l'accord (retiré/retirée/retirés/retirées)" },
{ pattern: /Ajouté/, reason: "Vérifier l'accord (ajouté/ajoutée/ajoutés/ajoutées)" },
{ pattern: /Appliqué/, reason: "Vérifier l'accord (appliqué/appliquée/appliqués/appliquées)" },
];
const filesToReview = new Map();
modifiedFiles.forEach(({ file, changes }) => {
changes.forEach(({ fr }) => {
problematicPatterns.forEach(({ pattern, reason }) => {
if (pattern.test(fr)) {
if (!filesToReview.has(reason)) {
filesToReview.set(reason, []);
}
filesToReview.get(reason).push({ file, translation: fr });
}
});
});
});
for (const [reason, items] of filesToReview.entries()) {
report += `### ${reason}\n\n`;
const uniqueItems = [...new Map(items.map(item => [item.file, item])).values()].slice(0, 10);
uniqueItems.forEach(({ file, translation }) => {
const transShort = translation.length > 80 ? translation.substring(0, 77) + '...' : translation;
report += `- **${file}**: \`${transShort}\`\n`;
});
if (items.length > 10) {
report += `\n... et ${items.length - 10} autre(s) occurrence(s)\n`;
}
report += `\n`;
}
// Recommandations
report += `## 📋 Recommandations\n\n`;
report += `1. **Vérifier les accords grammaticaux** : Les participes passés (ajouté, retiré, appliqué) doivent s'accorder avec leur sujet.\n`;
report += `2. **Vérifier les contextes** : Certains mots comme "effect" peuvent être du code (à ne pas traduire) ou du texte (à traduire).\n`;
report += `3. **Tester en jeu** : Vérifier que les messages affichés aux joueurs sont grammaticalement corrects.\n`;
report += `4. **Révision manuelle** : Consulter les fichiers avec le plus de changements pour s'assurer de la cohérence.\n\n`;
// Sauvegarder le rapport
const reportFile = path.join(__dirname, 'rapport-traduction-automatique.md');
fs.writeFileSync(reportFile, report, 'utf8');
console.log('='.repeat(60));
console.log('Rapport généré avec succès !');
console.log('='.repeat(60));
console.log(`Fichier : rapport-traduction-automatique.md`);
console.log(`\nStatistiques :`);
console.log(`- ${modifiedFiles.length} fichiers modifiés`);
console.log(`- ${totalChanges} changements au total`);
console.log(`- ${Object.keys(translations).length} traductions uniques`);
console.log('='.repeat(60));
// Afficher un aperçu du rapport
console.log('\n📄 APERÇU DU RAPPORT\n');
console.log(report.split('\n').slice(0, 50).join('\n'));
console.log('\n... (voir le fichier complet pour plus de détails)');