import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const FR_DIR = path.join(__dirname, 'scripts'); // Mots anglais communs pour détecter du texte en anglais const englishWords = [ 'the', 'and', 'or', 'to', 'from', 'with', 'without', 'has', 'have', 'had', 'is', 'are', 'was', 'were', 'been', 'being', 'will', 'would', 'should', 'can', 'could', 'may', 'might', 'must', 'shall', 'this', 'that', 'these', 'those', 'what', 'which', 'who', 'when', 'where', 'not', 'all', 'any', 'each', 'every', 'some', 'other', 'another', 'gain', 'gained', 'lose', 'lost', 'add', 'added', 'remove', 'removed', 'take', 'taken', 'give', 'given', 'make', 'made', 'find', 'found', 'get', 'got', 'set', 'put', 'use', 'used', 'using', 'apply', 'applied', 'test', 'tested', 'roll', 'rolled', 'if', 'else', 'while', 'for', 'return', // Mots-clés JS à ignorer dans le code 'failed', 'passed', 'success', 'failure', 'check', 'checked', 'attack', 'damage', 'heal', 'healed', 'wound', 'wounded', 'spell', 'cast', 'casting', 'magic', 'effect', 'affected', 'target', 'targets', 'hit', 'miss', 'critical', 'weapon', 'armour', 'armor', 'shield', 'equipped', 'skill', 'talent', 'trait', 'ability', 'bonus', 'enter', 'choose', 'select', 'click', 'press', 'must', 'need', 'require', 'required', 'cannot', 'unable', 'ignore', 'ignored', 'prevent', 'prevented', 'resist', 'resisted', 'duration', 'permanent', 'temporary', 'condition', 'status', 'character', 'actor', 'creature', 'enemy', 'ally', 'during', 'until', 'after', 'before', 'when', 'while' ]; // Patterns de textes techniques à ignorer (clés, IDs, etc.) const technicalPatterns = [ /^[a-z]+$/, // Tout en minuscules (probablement une clé) /^[0-9]+$/, // Que des chiffres /^[0-9a-f]{16}$/i, // Hash/ID /^[a-z_]+$/, // snake_case (clé technique) /^[a-z][a-zA-Z]+$/, // camelCase (clé technique) /^\$\{.*\}$/, // Template literal variable /^system\./, // Chemin système /^wfrp4e/, // Préfixe système /^@/, // Référence (ex: @Condition) /^[A-Z]{2,}$/, // Acronymes courts /^[\w-]{1,10}$/, // Clés courtes ]; // Fonction pour extraire les chaînes d'un fichier function extractStrings(content) { const strings = new Set(); // Patterns pour capturer les chaînes entre guillemets // On évite les template literals complexes avec interpolation const patterns = [ /"([^"]{3,})"/g, // Double quotes /'([^']{3,})'/g, // Single quotes ]; patterns.forEach(pattern => { const matches = content.matchAll(pattern); for (const match of matches) { const str = match[1].trim(); if (str.length > 2) { strings.add(str); } } }); // Pour les template literals, on cherche ceux sans interpolation ou simples const backtickPattern = /`([^`\$]{3,})`/g; const backtickMatches = content.matchAll(backtickPattern); for (const match of backtickMatches) { const str = match[1].trim(); if (str.length > 2) { strings.add(str); } } return Array.from(strings); } // Fonction pour détecter si une chaîne est probablement du texte en anglais function isEnglishText(str) { // Ignorer les patterns techniques for (const pattern of technicalPatterns) { if (pattern.test(str)) { return false; } } // Ignorer les chaînes trop courtes if (str.length < 3) { return false; } // Convertir en minuscules pour la comparaison const lowerStr = str.toLowerCase(); // Vérifier la présence de mots anglais const words = lowerStr.split(/\W+/); const englishWordCount = words.filter(word => englishWords.includes(word) && word.length > 1 ).length; // Si au moins 1 mot anglais significatif est trouvé, c'est probablement de l'anglais if (englishWordCount > 0) { return true; } // Patterns de phrases anglaises typiques const englishPhrases = [ /\b(the|a|an)\s+\w+/i, /\b(cannot|can't|won't|don't|doesn't)\b/i, /\b(must|should|will|would)\s+\w+/i, /\b(has|have|had)\s+(been|gained|lost|acquired)/i, /\b(enter|choose|select)\s+\w+/i, /\b(rolled?|passed?|failed?)\b/i, ]; for (const pattern of englishPhrases) { if (pattern.test(str)) { return true; } } return false; } // Fonction pour filtrer les faux positifs évidents function shouldIgnore(str) { // Ignorer les chemins et références système if (str.includes('Compendium.') || str.includes('UUID[')) { return true; } // Ignorer les noms de propriétés système if (str.match(/^(system|flags|data|items|effects|actor|token)\./)) { return true; } // Ignorer les expressions JavaScript if (str.match(/^(let|const|var|function|return|if|else|for|while)\b/)) { return true; } return false; } // Analyser tous les fichiers function analyzeScripts() { const files = fs.readdirSync(FR_DIR).filter(f => f.endsWith('.js')); const results = []; console.log(`Analyse de ${files.length} fichiers...\n`); files.forEach(file => { const filePath = path.join(FR_DIR, file); const content = fs.readFileSync(filePath, 'utf8'); const strings = extractStrings(content); const englishStrings = strings.filter(str => { if (shouldIgnore(str)) return false; return isEnglishText(str); }); if (englishStrings.length > 0) { results.push({ file, count: englishStrings.length, strings: englishStrings }); } }); return results; } // Main console.log('Recherche des textes anglais dans les scripts FR...\n'); console.log('='.repeat(60)); const results = analyzeScripts(); console.log('\n' + '='.repeat(60)); console.log(`Fichiers avec du texte anglais : ${results.length}\n`); // Trier par nombre de chaînes anglaises (décroissant) results.sort((a, b) => b.count - a.count); // Afficher les résultats let totalStrings = 0; results.forEach(({ file, count, strings }) => { totalStrings += count; console.log(`\n${file} (${count} texte(s) anglais) :`); console.log('-'.repeat(60)); strings.forEach(str => { // Limiter la longueur affichée const displayStr = str.length > 80 ? str.substring(0, 77) + '...' : str; console.log(` • ${displayStr}`); }); }); console.log('\n' + '='.repeat(60)); console.log('Résumé :'); console.log('-'.repeat(60)); console.log(`Fichiers avec texte anglais : ${results.length}/${fs.readdirSync(FR_DIR).filter(f => f.endsWith('.js')).length}`); console.log(`Total de textes anglais détectés : ${totalStrings}`); console.log('='.repeat(60)); // Sauvegarder dans un fichier JSON const outputFile = path.join(__dirname, 'english-texts-found.json'); fs.writeFileSync(outputFile, JSON.stringify(results, null, 2), 'utf8'); console.log(`\nRésultats sauvegardés dans : english-texts-found.json`);