import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Mappings de traduction basés sur fr.json const translations = { // Choose phrases "Choose 12 Arcane Spells": "Choisissez 12 Sorts d'Arcane", "Choose 1 Necromancy Spell": "Choisissez 1 Sort de Nécromancie", "Choose 2 Arcane Spells": "Choisissez 2 Sorts d'Arcane", "Choose 2 Skills to add +20": "Choisissez 2 Compétences pour ajouter +20", "Choose 3 Arcane Spells": "Choisissez 3 Sorts d'Arcane", "Choose 3 from the Lore of Necromancy": "Choisissez 3 dans le Savoir de Nécromancie", "Choose 3 Petty Spells": "Choisissez 3 Sorts Mineurs", "Choose 4 Petty Spells": "Choisissez 4 Sorts Mineurs", "Choose 6 Arcane Spells": "Choisissez 6 Sorts d'Arcane", "Choose 6 Petty Spells": "Choisissez 6 Sorts Mineurs", "Choose 7 taken from any combination of spells from Colour Magic Lore, the Lore of Witchcraft, or Lore of Dark Magic": "Choisissez 7 Sorts parmi toute combinaison de Magie de Couleur, Sorcellerie ou Magie Noire", "Choose 8 Arcane Spells & Lore of Death": "Choisissez 8 Sorts d'Arcane et Savoir de la Mort", "Choose 9 Arcane Spells": "Choisissez 9 Sorts d'Arcane", "Choose a characteristic": "Choisissez une caractéristique", "Choose an appropriate Polearm or Two-Handed Weapon": "Choisissez une arme d'hast ou une arme à deux mains appropriée", "Choose Chanty": "Choisissez un Chant", "Choose Double Life Career": "Choisissez une Carrière de Double Vie", "Choose Lore": "Choisissez un Savoir", "Choose Rune": "Choisissez une Rune", "Choose Sense": "Choisissez un Sens", // Enter phrases "Enter Armour value": "Entrez la valeur d'Armure", "Enter Etiquette Group": "Entrez le Groupe d'Étiquette", "Enter Fear value": "Entrez la valeur de Peur", "Enter Hatred Group": "Entrez le Groupe de Haine", "Enter Resistance": "Entrez la Résistance", "Enter Spellcasting Lore": "Entrez le Savoir d'Incantation", "Enter Target Species": "Entrez l'Espèce Cible", "Enter Target Species (singular)": "Entrez l'Espèce Cible (singulier)", "Enter Terror value": "Entrez la valeur de Terreur", "Enter the Armoured value": "Entrez la valeur d'Armure", "Enter the number of diseases/poisons cured": "Entrez le nombre de maladies/poisons soignés", "Enter the Sturdy value": "Entrez la valeur de Robustesse", "Enter Venom Strength": "Entrez la Force du Venin", "Enter Ward value": "Entrez la valeur de Protection", "Enter Wounds Lost to gain SL": "Entrez les Blessures Perdues pour gagner DR", // Select phrases "Select Column": "Sélectionnez une Colonne", "Select Rune": "Sélectionnez une Rune", "Select Target": "Sélectionnez une Cible", "Select Target for Hatred": "Sélectionnez une Cible pour la Haine", "Select the column to roll on to determine Beast Head": "Sélectionnez la colonne de lancer pour déterminer la Tête de Bête", // Damage/Combat terms "Add Metal AP to Damage": "Ajouter PA de métal aux Dégâts", "Blunt Damage Reduction": "Réduction des Dégâts Contondants", "Critical (if successful attack)": "Critique (si attaque réussie)", "Damage Increase": "Augmentation des Dégâts", "Damage Reduction": "Réduction des Dégâts", "Remove Damage Rating": "Retirer l'Indice de Dégâts", "Double Wounds + 4": "Blessures Doublées + 4", "Double Wounds vs Dragons": "Blessures Doublées vs Dragons", // Status/Values "Armoured Value": "Valeur d'Armure", "Halved": "Divisé par deux", "Hatred Group": "Groupe de Haine", "Sturdy Value": "Valeur de Robustesse", // Equipment "Mail": "Mailles", "Mail & Leather": "Mailles et Cuir", "Two-Handed": "A deux mains", // Actions "Misfire": "Raté", "Misfire (Supercharged)": "Raté (Surchargé)", "Roll": "Lancer", // Misc "Basic": "Base", "Choice": "Choix", "Provide an tattooist Actor (close to skip Tests)": "Fournissez un Acteur tatoueur (fermer pour ignorer les Tests)", "Skill": "Compétence", "Target has Aethyric Attunement or Second Sight": "La Cible possède Harmonisation Aethyrique ou Seconde Vue", "Victory Notes for Experience Log": "Notes de Victoire pour le Journal d'Expérience" }; // Fonction pour échapper les caractères spéciaux pour regex function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } // Fonction pour traiter un fichier function translateFile(filePath) { let content = fs.readFileSync(filePath, 'utf8'); let modified = false; // Appliquer chaque traduction for (const [english, french] of Object.entries(translations)) { const escapedEnglish = escapeRegExp(english); // Patterns pour détecter les contextes (label, text, title, details, message) const patterns = [ new RegExp(`(label\\s*:\\s*["'\`])${escapedEnglish}(["'\`])`, 'g'), new RegExp(`(text\\s*:\\s*["'\`])${escapedEnglish}(["'\`])`, 'g'), new RegExp(`(title\\s*:\\s*["'\`])${escapedEnglish}(["'\`])`, 'g'), new RegExp(`(details\\s*:\\s*["'\`])${escapedEnglish}(["'\`])`, 'g'), new RegExp(`(message\\s*:\\s*["'\`])${escapedEnglish}(["'\`])`, 'g'), ]; patterns.forEach(pattern => { if (pattern.test(content)) { content = content.replace(pattern, `$1${french}$2`); modified = true; } }); } if (modified) { fs.writeFileSync(filePath, content, 'utf8'); return true; } return false; } // Fonction pour traiter récursivement un répertoire function processDirectory(dirPath) { const files = fs.readdirSync(dirPath); let stats = { total: 0, modified: 0, errors: 0 }; files.forEach(file => { const filePath = path.join(dirPath, file); const stat = fs.statSync(filePath); if (stat.isDirectory()) { const subStats = processDirectory(filePath); stats.total += subStats.total; stats.modified += subStats.modified; stats.errors += subStats.errors; } else if (file.endsWith('.js')) { stats.total++; try { if (translateFile(filePath)) { stats.modified++; console.log(`✓ ${path.relative(process.cwd(), filePath)}`); } } catch (error) { stats.errors++; console.error(`✗ ${path.relative(process.cwd(), filePath)}: ${error.message}`); } } }); return stats; } // Main console.log('Début de la traduction des scripts...\n'); const scriptsDir = path.join(__dirname, 'scripts'); const stats = processDirectory(scriptsDir); console.log('\n' + '='.repeat(60)); console.log('Traduction terminée !'); console.log('='.repeat(60)); console.log(`Fichiers traités : ${stats.total}`); console.log(`Fichiers modifiés : ${stats.modified}`); console.log(`Erreurs : ${stats.errors}`); console.log('='.repeat(60));