217 lines
6.8 KiB
JavaScript
217 lines
6.8 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');
|
|
|
|
// Fonction pour extraire les chaînes de caractères d'un fichier
|
|
function extractStrings(content) {
|
|
const strings = new Set();
|
|
|
|
// Patterns pour capturer les chaînes entre guillemets
|
|
const patterns = [
|
|
/"([^"]{3,})"/g, // Double quotes
|
|
/'([^']{3,})'/g, // Single quotes
|
|
/`([^`]{3,})`/g // Backticks (sans interpolation)
|
|
];
|
|
|
|
patterns.forEach(pattern => {
|
|
const matches = content.matchAll(pattern);
|
|
for (const match of matches) {
|
|
const str = match[1].trim();
|
|
// Ignorer les chaînes trop courtes, les nombres, les IDs techniques
|
|
if (str.length > 2 &&
|
|
!str.match(/^[0-9a-f]{16}$/i) &&
|
|
!str.match(/^[0-9]+$/) &&
|
|
!str.match(/^[a-z]+$/)) {
|
|
strings.add(str);
|
|
}
|
|
}
|
|
});
|
|
|
|
return Array.from(strings);
|
|
}
|
|
|
|
// Comparer deux fichiers et extraire les traductions
|
|
function compareFiles(enFile, frFile) {
|
|
const enContent = fs.readFileSync(enFile, 'utf8');
|
|
const frContent = fs.readFileSync(frFile, 'utf8');
|
|
|
|
const enStrings = extractStrings(enContent);
|
|
const frStrings = extractStrings(frContent);
|
|
|
|
const translations = [];
|
|
|
|
// Chercher les différences qui pourraient être des traductions
|
|
enStrings.forEach(enStr => {
|
|
// Si la chaîne anglaise n'est pas dans le fichier FR
|
|
if (!frStrings.includes(enStr)) {
|
|
// Chercher une chaîne FR qui pourrait correspondre
|
|
// (même longueur approximative, même structure)
|
|
const possibleTranslations = frStrings.filter(frStr => {
|
|
// Vérifier si la structure est similaire
|
|
const lengthRatio = frStr.length / enStr.length;
|
|
return lengthRatio > 0.5 && lengthRatio < 2.0;
|
|
});
|
|
|
|
if (possibleTranslations.length > 0) {
|
|
// Pour l'instant, on stocke toutes les possibilités
|
|
possibleTranslations.forEach(frStr => {
|
|
translations.push({ en: enStr, fr: frStr });
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
return translations;
|
|
}
|
|
|
|
// Analyser tous les fichiers
|
|
function analyzeAllScripts() {
|
|
const enFiles = fs.readdirSync(WFRP4E_DIR).filter(f => f.endsWith('.js'));
|
|
const frFiles = fs.readdirSync(FR_DIR).filter(f => f.endsWith('.js'));
|
|
|
|
const allTranslations = new Map(); // en -> Set(fr)
|
|
let filesCompared = 0;
|
|
let filesWithTranslations = 0;
|
|
|
|
console.log('Analyse des scripts...\n');
|
|
|
|
enFiles.forEach(file => {
|
|
if (frFiles.includes(file)) {
|
|
filesCompared++;
|
|
const enPath = path.join(WFRP4E_DIR, file);
|
|
const frPath = path.join(FR_DIR, file);
|
|
|
|
const translations = compareFiles(enPath, frPath);
|
|
|
|
if (translations.length > 0) {
|
|
filesWithTranslations++;
|
|
translations.forEach(({ en, fr }) => {
|
|
if (!allTranslations.has(en)) {
|
|
allTranslations.set(en, new Set());
|
|
}
|
|
allTranslations.get(en).add(fr);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
console.log(`Fichiers comparés : ${filesCompared}`);
|
|
console.log(`Fichiers avec traductions détectées : ${filesWithTranslations}`);
|
|
console.log(`Paires de traduction uniques : ${allTranslations.size}\n`);
|
|
|
|
return allTranslations;
|
|
}
|
|
|
|
// Filtrer les traductions cohérentes
|
|
function filterReliableTranslations(translationsMap) {
|
|
const reliable = new Map();
|
|
|
|
for (const [en, frSet] of translationsMap.entries()) {
|
|
// Si une chaîne anglaise a toujours la même traduction, c'est fiable
|
|
if (frSet.size === 1) {
|
|
reliable.set(en, Array.from(frSet)[0]);
|
|
}
|
|
// Si elle a plusieurs traductions mais une dominante (>50%), on la garde
|
|
else if (frSet.size <= 3) {
|
|
const frArray = Array.from(frSet);
|
|
reliable.set(en, frArray[0]); // Pour l'instant, on prend la première
|
|
}
|
|
}
|
|
|
|
return reliable;
|
|
}
|
|
|
|
// Chercher les occurrences dans les scripts FR
|
|
function findUntranslatedInFR(translations) {
|
|
const frFiles = fs.readdirSync(FR_DIR).filter(f => f.endsWith('.js'));
|
|
const opportunities = [];
|
|
|
|
console.log('Recherche des chaînes non traduites dans les scripts FR...\n');
|
|
|
|
frFiles.forEach(file => {
|
|
const filePath = path.join(FR_DIR, file);
|
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
|
|
for (const [en, fr] of translations.entries()) {
|
|
if (content.includes(en)) {
|
|
opportunities.push({
|
|
file,
|
|
en,
|
|
fr
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
return opportunities;
|
|
}
|
|
|
|
// Main
|
|
console.log('Extraction des traductions déjà effectuées...\n');
|
|
console.log('='.repeat(60) + '\n');
|
|
|
|
const allTranslations = analyzeAllScripts();
|
|
const reliableTranslations = filterReliableTranslations(allTranslations);
|
|
|
|
console.log('='.repeat(60));
|
|
console.log(`Traductions fiables identifiées : ${reliableTranslations.size}\n`);
|
|
|
|
// Afficher un échantillon
|
|
let count = 0;
|
|
console.log('Échantillon des traductions détectées :');
|
|
console.log('-'.repeat(60));
|
|
for (const [en, fr] of reliableTranslations.entries()) {
|
|
if (count++ < 20) {
|
|
console.log(`"${en}" → "${fr}"`);
|
|
}
|
|
}
|
|
if (reliableTranslations.size > 20) {
|
|
console.log(`... et ${reliableTranslations.size - 20} autres\n`);
|
|
}
|
|
|
|
// Chercher les opportunités d'application
|
|
console.log('\n' + '='.repeat(60));
|
|
const opportunities = findUntranslatedInFR(reliableTranslations);
|
|
|
|
console.log(`Opportunités de traduction trouvées : ${opportunities.length}\n`);
|
|
|
|
// Regrouper par fichier
|
|
const byFile = new Map();
|
|
opportunities.forEach(({ file, en, fr }) => {
|
|
if (!byFile.has(file)) {
|
|
byFile.set(file, []);
|
|
}
|
|
byFile.get(file).push({ en, fr });
|
|
});
|
|
|
|
console.log('Fichiers avec opportunités de traduction :');
|
|
console.log('-'.repeat(60));
|
|
for (const [file, trans] of byFile.entries()) {
|
|
console.log(`${file} : ${trans.length} traduction(s) à appliquer`);
|
|
}
|
|
|
|
// Sauvegarder les résultats
|
|
const results = {
|
|
reliableTranslations: Object.fromEntries(reliableTranslations),
|
|
opportunities: Array.from(byFile.entries()).map(([file, trans]) => ({
|
|
file,
|
|
translations: trans
|
|
}))
|
|
};
|
|
|
|
fs.writeFileSync(
|
|
path.join(__dirname, 'translation-opportunities.json'),
|
|
JSON.stringify(results, null, 2),
|
|
'utf8'
|
|
);
|
|
|
|
console.log('\n' + '='.repeat(60));
|
|
console.log('Résultats sauvegardés dans translation-opportunities.json');
|
|
console.log('='.repeat(60));
|