forked from public/foundryvtt-wh4-lang-fr-fr
Ajout de la commande /voyage et grosse MAJK de la commande /auberge
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
100
tools/analyze-english-terms.js
Normal file
100
tools/analyze-english-terms.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import fs from 'fs';
|
||||
|
||||
// Lire le fichier JSON
|
||||
const jsonData = JSON.parse(fs.readFileSync('./compendium/wfrp4e-core.items.json', 'utf8'));
|
||||
const frJson = JSON.parse(fs.readFileSync('./fr.json', 'utf8'));
|
||||
|
||||
// Chercher les termes en anglais (labels et titres courts)
|
||||
const englishTerms = new Set();
|
||||
const termOccurrences = {};
|
||||
|
||||
// Parcourir les entrées
|
||||
jsonData.entries.forEach(entry => {
|
||||
// Vérifier le champ 'name' pour des patterns entre parenthèses
|
||||
if (entry.name && entry.name.includes('(') && entry.name.includes(')')) {
|
||||
const matches = entry.name.matchAll(/\(([^)]+)\)/g);
|
||||
|
||||
for (const match of matches) {
|
||||
const parenthesisContent = match[1];
|
||||
|
||||
// Liste de termes français connus à exclure
|
||||
const frenchTerms = [
|
||||
'Mineure', 'Majeure', 'Accessible', 'Complexe', 'Difficile',
|
||||
'Facile', 'Intermédiaire', 'Type', 'Domaine', 'Arme de jet',
|
||||
'Arme de mêlée', 'Compétence avancée', 'Compétence de base'
|
||||
];
|
||||
|
||||
// Détecter si c'est potentiellement de l'anglais
|
||||
// - Contient des mots anglais courants (et, the, or, of)
|
||||
// - Ne contient pas de caractères français (é, è, à, ô, etc.)
|
||||
const hasEnglishWords = /\b(and|the|or|of|to|in|a|is)\b/i.test(parenthesisContent);
|
||||
const hasNoFrenchChars = !/[àâäéèêëïîôùûüÿæœç]/i.test(parenthesisContent);
|
||||
const notInFrenchList = !frenchTerms.some(term =>
|
||||
parenthesisContent.toLowerCase().includes(term.toLowerCase())
|
||||
);
|
||||
|
||||
if ((hasEnglishWords || (hasNoFrenchChars && notInFrenchList)) &&
|
||||
parenthesisContent.length > 2) {
|
||||
englishTerms.add(parenthesisContent);
|
||||
|
||||
if (!termOccurrences[parenthesisContent]) {
|
||||
termOccurrences[parenthesisContent] = [];
|
||||
}
|
||||
|
||||
termOccurrences[parenthesisContent].push({
|
||||
id: entry.id,
|
||||
name: entry.name
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Afficher les résultats
|
||||
console.log('Termes anglais détectés dans les noms (entre parenthèses):');
|
||||
console.log('==========================================================\n');
|
||||
|
||||
const sortedTerms = Array.from(englishTerms).sort();
|
||||
sortedTerms.forEach(term => {
|
||||
console.log(`${term} (${termOccurrences[term].length} occurrence(s)):`);
|
||||
termOccurrences[term].slice(0, 3).forEach(occ => {
|
||||
console.log(` - ${occ.id}: ${occ.name}`);
|
||||
});
|
||||
if (termOccurrences[term].length > 3) {
|
||||
console.log(` ... et ${termOccurrences[term].length - 3} autres`);
|
||||
}
|
||||
console.log('');
|
||||
});
|
||||
|
||||
console.log(`\nTotal: ${englishTerms.size} termes anglais différents détectés`);
|
||||
|
||||
// Chercher aussi dans d'autres champs
|
||||
console.log('\n\nAnalyse des autres champs potentiels...');
|
||||
console.log('========================================\n');
|
||||
|
||||
// Chercher des labels courts en anglais dans tous les champs
|
||||
const fieldsToCheck = ['type', 'special', 'description'];
|
||||
const englishInFields = {};
|
||||
|
||||
jsonData.entries.slice(0, 20).forEach(entry => {
|
||||
Object.keys(entry).forEach(key => {
|
||||
if (typeof entry[key] === 'string' && entry[key].length < 50) {
|
||||
const value = entry[key];
|
||||
// Détecter des mots anglais courants
|
||||
if (/\b(Rating|Target|Group|Feature|Type|Level|Rank)\b/.test(value)) {
|
||||
if (!englishInFields[key]) {
|
||||
englishInFields[key] = new Set();
|
||||
}
|
||||
englishInFields[key].add(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Object.keys(englishInFields).forEach(field => {
|
||||
console.log(`Champ '${field}':`);
|
||||
englishInFields[field].forEach(value => {
|
||||
console.log(` - "${value}"`);
|
||||
});
|
||||
console.log('');
|
||||
});
|
||||
157
tools/apply-sync.js
Normal file
157
tools/apply-sync.js
Normal file
@@ -0,0 +1,157 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const WFRP4E_SCRIPTS = '/home/morr/work/foundryvtt/WFRP4e-FoundryVTT/scripts';
|
||||
const FR_SCRIPTS = '/home/morr/work/foundryvtt/foundryvtt-wh4-lang-fr-fr/scripts';
|
||||
const DATA_FILE = path.join(__dirname, 'script-comparison-data.json');
|
||||
const LOG_FILE = path.join(__dirname, 'sync-scripts-log.txt');
|
||||
|
||||
// Charger les résultats de l'analyse
|
||||
const data = JSON.parse(fs.readFileSync(DATA_FILE, 'utf-8'));
|
||||
|
||||
const log = [];
|
||||
|
||||
function writeLog(message) {
|
||||
console.log(message);
|
||||
log.push(message);
|
||||
}
|
||||
|
||||
function deleteObsoleteScripts() {
|
||||
writeLog('\n=== SUPPRESSION DES SCRIPTS OBSOLÈTES ===\n');
|
||||
|
||||
let deleted = 0;
|
||||
data.usesLocalize.forEach(({file}) => {
|
||||
const filePath = path.join(FR_SCRIPTS, file);
|
||||
if (fs.existsSync(filePath)) {
|
||||
fs.unlinkSync(filePath);
|
||||
deleted++;
|
||||
writeLog(`✓ Supprimé: ${file}`);
|
||||
}
|
||||
});
|
||||
|
||||
writeLog(`\nTotal supprimés: ${deleted}/${data.usesLocalize.length}`);
|
||||
return deleted;
|
||||
}
|
||||
|
||||
function copyNewScripts() {
|
||||
writeLog('\n=== COPIE DES NOUVEAUX SCRIPTS ===\n');
|
||||
|
||||
let copied = 0;
|
||||
data.onlyInWFRP4E.forEach(file => {
|
||||
const sourcePath = path.join(WFRP4E_SCRIPTS, file);
|
||||
const destPath = path.join(FR_SCRIPTS, file);
|
||||
|
||||
if (fs.existsSync(sourcePath)) {
|
||||
fs.copyFileSync(sourcePath, destPath);
|
||||
copied++;
|
||||
writeLog(`✓ Copié: ${file}`);
|
||||
} else {
|
||||
writeLog(`✗ Source non trouvée: ${file}`);
|
||||
}
|
||||
});
|
||||
|
||||
writeLog(`\nTotal copiés: ${copied}/${data.onlyInWFRP4E.length}`);
|
||||
return copied;
|
||||
}
|
||||
|
||||
function deleteRemovedScripts() {
|
||||
writeLog('\n=== SUPPRESSION DES SCRIPTS RETIRÉS ===\n');
|
||||
|
||||
let deleted = 0;
|
||||
data.onlyInFR.forEach(file => {
|
||||
const filePath = path.join(FR_SCRIPTS, file);
|
||||
if (fs.existsSync(filePath)) {
|
||||
fs.unlinkSync(filePath);
|
||||
deleted++;
|
||||
writeLog(`✓ Supprimé (n'existe plus dans WFRP4E): ${file}`);
|
||||
}
|
||||
});
|
||||
|
||||
writeLog(`\nTotal supprimés: ${deleted}/${data.onlyInFR.length}`);
|
||||
return deleted;
|
||||
}
|
||||
|
||||
function updateScripts() {
|
||||
writeLog('\n=== MISE À JOUR DES SCRIPTS ===\n');
|
||||
writeLog('Ces scripts ont été modifiés dans WFRP4E mais contiennent peut-être des traductions FR.');
|
||||
writeLog('Ils nécessitent une révision manuelle.\n');
|
||||
|
||||
let updated = 0;
|
||||
let needsReview = [];
|
||||
|
||||
data.needsUpdate.forEach(item => {
|
||||
const wfrp4ePath = path.join(WFRP4E_SCRIPTS, item.file);
|
||||
const frPath = path.join(FR_SCRIPTS, item.file);
|
||||
|
||||
const wfrp4eContent = fs.readFileSync(wfrp4ePath, 'utf-8');
|
||||
const frContent = fs.readFileSync(frPath, 'utf-8');
|
||||
|
||||
// Vérifier si le script FR contient des textes en français
|
||||
const hasFrenchText = /["'`](Chargement|Impossible|Voulez-vous|Êtes-vous|créé|modifié|supprimé)/i.test(frContent);
|
||||
|
||||
if (hasFrenchText) {
|
||||
// Script avec traductions, nécessite révision manuelle
|
||||
needsReview.push({
|
||||
file: item.file,
|
||||
reason: 'Contient des textes traduits en français'
|
||||
});
|
||||
writeLog(`⚠ RÉVISION NÉCESSAIRE: ${item.file} (contient des traductions)`);
|
||||
} else {
|
||||
// Pas de traductions détectées, on peut mettre à jour automatiquement
|
||||
fs.copyFileSync(wfrp4ePath, frPath);
|
||||
updated++;
|
||||
writeLog(`✓ Mis à jour: ${item.file}`);
|
||||
}
|
||||
});
|
||||
|
||||
writeLog(`\nTotal mis à jour automatiquement: ${updated}`);
|
||||
writeLog(`Total nécessitant révision: ${needsReview.length}`);
|
||||
|
||||
// Créer un fichier avec la liste des scripts à réviser
|
||||
if (needsReview.length > 0) {
|
||||
const reviewFile = path.join(__dirname, 'scripts-to-review.json');
|
||||
fs.writeFileSync(reviewFile, JSON.stringify(needsReview, null, 2), 'utf-8');
|
||||
writeLog(`\nListe des scripts à réviser sauvegardée dans: ${reviewFile}`);
|
||||
}
|
||||
|
||||
return {updated, needsReview: needsReview.length};
|
||||
}
|
||||
|
||||
// Programme principal
|
||||
writeLog('='.repeat(60));
|
||||
writeLog('SYNCHRONISATION DES SCRIPTS WFRP4E');
|
||||
writeLog('='.repeat(60));
|
||||
writeLog(`Date: ${new Date().toISOString()}\n`);
|
||||
|
||||
writeLog('Statistiques:');
|
||||
writeLog(` - Scripts identiques: ${data.identical.length}`);
|
||||
writeLog(` - Scripts obsolètes (localize): ${data.usesLocalize.length}`);
|
||||
writeLog(` - Scripts à mettre à jour: ${data.needsUpdate.length}`);
|
||||
writeLog(` - Nouveaux scripts (WFRP4E): ${data.onlyInWFRP4E.length}`);
|
||||
writeLog(` - Scripts à supprimer (FR): ${data.onlyInFR.length}`);
|
||||
|
||||
// Demander confirmation
|
||||
console.log('\nVoulez-vous continuer ? (appuyez sur Entrée pour continuer, Ctrl+C pour annuler)');
|
||||
// Pour l'automatisation, on continue directement
|
||||
// En production, on utiliserait readline pour une confirmation interactive
|
||||
|
||||
const obsoleteDeleted = deleteObsoleteScripts();
|
||||
const removedDeleted = deleteRemovedScripts();
|
||||
const newCopied = copyNewScripts();
|
||||
const {updated, needsReview} = updateScripts();
|
||||
|
||||
writeLog('\n' + '='.repeat(60));
|
||||
writeLog('RÉSUMÉ DES OPÉRATIONS');
|
||||
writeLog('='.repeat(60));
|
||||
writeLog(`Scripts obsolètes supprimés: ${obsoleteDeleted}`);
|
||||
writeLog(`Scripts retirés supprimés: ${removedDeleted}`);
|
||||
writeLog(`Nouveaux scripts copiés: ${newCopied}`);
|
||||
writeLog(`Scripts mis à jour automatiquement: ${updated}`);
|
||||
writeLog(`Scripts nécessitant révision manuelle: ${needsReview}`);
|
||||
writeLog('='.repeat(60));
|
||||
|
||||
// Sauvegarder le log
|
||||
fs.writeFileSync(LOG_FILE, log.join('\n'), 'utf-8');
|
||||
writeLog(`\nLog sauvegardé dans: ${LOG_FILE}`);
|
||||
78
tools/apply-translations.js
Normal file
78
tools/apply-translations.js
Normal file
@@ -0,0 +1,78 @@
|
||||
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');
|
||||
const OPPORTUNITIES_FILE = path.join(__dirname, 'translation-opportunities.json');
|
||||
|
||||
// Charger les opportunités de traduction
|
||||
const data = JSON.parse(fs.readFileSync(OPPORTUNITIES_FILE, 'utf8'));
|
||||
const { reliableTranslations, opportunities } = data;
|
||||
|
||||
// Fonction pour échapper les caractères spéciaux pour regex
|
||||
function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
// Statistiques
|
||||
let stats = {
|
||||
filesProcessed: 0,
|
||||
filesModified: 0,
|
||||
replacementsMade: 0,
|
||||
errors: 0
|
||||
};
|
||||
|
||||
console.log('Application automatique des traductions...\n');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
// Traiter chaque fichier avec des opportunités
|
||||
opportunities.forEach(({ file, translations }) => {
|
||||
const filePath = path.join(FR_DIR, file);
|
||||
stats.filesProcessed++;
|
||||
|
||||
try {
|
||||
let content = fs.readFileSync(filePath, 'utf8');
|
||||
let modified = false;
|
||||
let replacementsInFile = 0;
|
||||
|
||||
// Appliquer chaque traduction
|
||||
translations.forEach(({ en, fr }) => {
|
||||
// Vérifier que la chaîne anglaise existe toujours dans le fichier
|
||||
if (content.includes(en)) {
|
||||
// Remplacement simple (pas de regex pour éviter les problèmes avec les caractères spéciaux)
|
||||
const newContent = content.split(en).join(fr);
|
||||
|
||||
if (newContent !== content) {
|
||||
const count = (content.split(en).length - 1);
|
||||
content = newContent;
|
||||
modified = true;
|
||||
replacementsInFile += count;
|
||||
stats.replacementsMade += count;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Sauvegarder si modifié
|
||||
if (modified) {
|
||||
fs.writeFileSync(filePath, content, 'utf8');
|
||||
stats.filesModified++;
|
||||
console.log(`✓ ${file} : ${replacementsInFile} remplacement(s)`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
stats.errors++;
|
||||
console.error(`✗ ${file} : ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('Application terminée !');
|
||||
console.log('='.repeat(60));
|
||||
console.log(`Fichiers traités : ${stats.filesProcessed}`);
|
||||
console.log(`Fichiers modifiés : ${stats.filesModified}`);
|
||||
console.log(`Remplacements effectués : ${stats.replacementsMade}`);
|
||||
console.log(`Erreurs : ${stats.errors}`);
|
||||
console.log('='.repeat(60));
|
||||
116
tools/auto-merge-translations.js
Normal file
116
tools/auto-merge-translations.js
Normal file
@@ -0,0 +1,116 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const WFRP4E_SCRIPTS = '/home/morr/work/foundryvtt/WFRP4e-FoundryVTT/scripts';
|
||||
const FR_SCRIPTS = '/home/morr/work/foundryvtt/foundryvtt-wh4-lang-fr-fr/scripts';
|
||||
const REVIEW_FILE = path.join(__dirname, 'scripts-to-review.json');
|
||||
|
||||
const scriptsToReview = JSON.parse(fs.readFileSync(REVIEW_FILE, 'utf-8'));
|
||||
|
||||
// Dictionnaire de traductions courantes
|
||||
const translations = {
|
||||
'Loading Spells': 'Chargement des sorts',
|
||||
'Loading': 'Chargement',
|
||||
'Could not find': 'Impossible de trouver',
|
||||
'Try Again': 'Essayez à nouveau',
|
||||
'Error': 'Erreur',
|
||||
'Success': 'Succès',
|
||||
'Warning': 'Avertissement',
|
||||
'Created': 'Créé',
|
||||
'Modified': 'Modifié',
|
||||
'Deleted': 'Supprimé',
|
||||
'Are you sure': 'Êtes-vous sûr',
|
||||
'Do you want': 'Voulez-vous',
|
||||
'Cancel': 'Annuler',
|
||||
'Confirm': 'Confirmer',
|
||||
'Yes': 'Oui',
|
||||
'No': 'Non'
|
||||
};
|
||||
|
||||
function translateText(text) {
|
||||
// Remplacer les traductions connues
|
||||
let translated = text;
|
||||
for (const [en, fr] of Object.entries(translations)) {
|
||||
translated = translated.replace(new RegExp(en, 'g'), fr);
|
||||
}
|
||||
return translated;
|
||||
}
|
||||
|
||||
function mergeScript(wfrp4eContent, frContent) {
|
||||
// Commence avec la version WFRP4E (à jour)
|
||||
let merged = wfrp4eContent;
|
||||
|
||||
// Extraire les textes traduits du script FR
|
||||
const frTexts = new Map();
|
||||
const textPattern = /["'`]([^"'`]+)["'`]/g;
|
||||
|
||||
let match;
|
||||
while ((match = textPattern.exec(frContent)) !== null) {
|
||||
const text = match[1];
|
||||
// Si le texte contient des mots français caractéristiques
|
||||
if (/Chargement|Impossible|Êtes-vous|Voulez-vous|créé|modifié|supprimé|Erreur/i.test(text)) {
|
||||
// Chercher le texte anglais correspondant dans WFRP4E
|
||||
const enMatch = wfrp4eContent.match(new RegExp(`["'\`]([^"'\`]*${text.split(' ')[0]}[^"'\`]*)["'\`]`));
|
||||
if (enMatch) {
|
||||
frTexts.set(enMatch[1], text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Appliquer les traductions connues
|
||||
for (const [en, fr] of frTexts.entries()) {
|
||||
merged = merged.replace(new RegExp(`["'\`]${en.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}["'\`]`, 'g'), `"${fr}"`);
|
||||
}
|
||||
|
||||
// Appliquer le dictionnaire de traductions
|
||||
for (const [en, fr] of Object.entries(translations)) {
|
||||
merged = merged.replace(new RegExp(`["'\`]${en}["'\`]`, 'g'), `"${fr}"`);
|
||||
}
|
||||
|
||||
// Cas spéciaux pour les template literals
|
||||
merged = merged.replace(/`Could not find \$\{([^}]+)\} spell\. Try Again`/g, '`Impossible de trouver le sort ${$1}. Essayez à nouveau`');
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
||||
console.log('Révision semi-automatique des scripts...\n');
|
||||
|
||||
let updated = 0;
|
||||
let skipped = 0;
|
||||
|
||||
scriptsToReview.forEach(({file}) => {
|
||||
const wfrp4ePath = path.join(WFRP4E_SCRIPTS, file);
|
||||
const frPath = path.join(FR_SCRIPTS, file);
|
||||
const backupPath = frPath + '.backup';
|
||||
|
||||
const wfrp4eContent = fs.readFileSync(wfrp4ePath, 'utf-8');
|
||||
const frContent = fs.readFileSync(frPath, 'utf-8');
|
||||
|
||||
// Sauvegarder l'original
|
||||
fs.copyFileSync(frPath, backupPath);
|
||||
|
||||
// Tenter la fusion
|
||||
const merged = mergeScript(wfrp4eContent, frContent);
|
||||
|
||||
// Vérifier si des traductions ont été préservées
|
||||
const hasTranslations = /Chargement|Impossible|Êtes-vous|Voulez-vous|créé|modifié|supprimé|Erreur/i.test(merged);
|
||||
|
||||
if (hasTranslations) {
|
||||
fs.writeFileSync(frPath, merged, 'utf-8');
|
||||
updated++;
|
||||
console.log(`✓ Mis à jour avec traductions: ${file}`);
|
||||
} else {
|
||||
// Restaurer l'original si aucune traduction n'a été préservée
|
||||
fs.copyFileSync(backupPath, frPath);
|
||||
skipped++;
|
||||
console.log(`⚠ Révision manuelle requise: ${file}`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`\n=== Résumé ===`);
|
||||
console.log(`Scripts mis à jour automatiquement: ${updated}`);
|
||||
console.log(`Scripts nécessitant révision manuelle: ${skipped}`);
|
||||
console.log(`\nNOTE: Les fichiers .backup contiennent les versions originales.`);
|
||||
console.log(`Vérifiez les fichiers mis à jour avant de supprimer les backups.`);
|
||||
219
tools/auto-translate-english.js
Normal file
219
tools/auto-translate-english.js
Normal file
@@ -0,0 +1,219 @@
|
||||
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');
|
||||
const ENGLISH_TEXTS_FILE = path.join(__dirname, 'english-texts-found.json');
|
||||
const FR_JSON_FILE = path.join(__dirname, 'fr.json');
|
||||
|
||||
// Charger les données
|
||||
const englishTexts = JSON.parse(fs.readFileSync(ENGLISH_TEXTS_FILE, 'utf8'));
|
||||
const frJson = JSON.parse(fs.readFileSync(FR_JSON_FILE, 'utf8'));
|
||||
|
||||
// Créer un mapping de traductions basé sur fr.json et les patterns connus
|
||||
const translations = {
|
||||
// Patterns déjà traduits dans le système
|
||||
"Choose Training": "Choisir un Entraînement",
|
||||
"Lore (Magic)": "Savoir (Magie)",
|
||||
"Dark Magic (Necromancy)": "Magie Noire (Nécromancie)",
|
||||
"Lore (Theology)": "Savoir (Théologie)",
|
||||
"Lore (Runes)": "Savoir (Runes)",
|
||||
"Sail (Skycraft)": "Voile (Aéronavale)",
|
||||
"all forms": "toutes formes",
|
||||
|
||||
// Messages utilisateur
|
||||
"Skipping Tests to apply the tattoos": "Tests ignorés pour appliquer les tatouages",
|
||||
"Apply Ward of Grimnir effect?": "Appliquer l'effet Rune de Grimnir ?",
|
||||
"No Lore (Theology) skill found, cannot pass.": "Compétence Savoir (Théologie) introuvable, impossible de continuer.",
|
||||
"No Lore (Runes) skill found, cannot pass.": "Compétence Savoir (Runes) introuvable, impossible de continuer.",
|
||||
"One or more Tests to apply the tattoos failed.": "Un ou plusieurs Tests pour appliquer les tatouages ont échoué.",
|
||||
"Must provide a Master Rune": "Doit fournir une Rune Maîtresse",
|
||||
"Must provide a Rune (non-Master)": "Doit fournir une Rune (non-Maîtresse)",
|
||||
|
||||
// Effets et conditions
|
||||
"Removed Broken": "Condition Brisé supprimée",
|
||||
"Added Bleeding": "Saignement ajouté",
|
||||
"Applied after effects": "Effets secondaires appliqués",
|
||||
"Does not need to make Peur or Terror tests": "N'a pas besoin de faire de tests de Peur ou de Terreur",
|
||||
"Automatically passes any": "Réussit automatiquement tout",
|
||||
|
||||
// Fragments de code courants (contextuels)
|
||||
"action-link critical": "action-link critical", // Classe CSS, ne pas traduire
|
||||
"></i> Critical</a>": "></i> Critique</a>",
|
||||
|
||||
// Patterns génériques
|
||||
"|| this.item.getFlag(": "|| this.item.getFlag(", // Code JS, ne pas traduire
|
||||
',"info")': ',"info")', // Code JS, ne pas traduire
|
||||
};
|
||||
|
||||
// Fonction pour obtenir la fréquence de chaque texte anglais
|
||||
function getTextFrequencies() {
|
||||
const frequencies = new Map();
|
||||
|
||||
englishTexts.forEach(({ strings }) => {
|
||||
strings.forEach(str => {
|
||||
frequencies.set(str, (frequencies.get(str) || 0) + 1);
|
||||
});
|
||||
});
|
||||
|
||||
return frequencies;
|
||||
}
|
||||
|
||||
// Fonction pour proposer des traductions automatiques
|
||||
function proposeTranslations(text) {
|
||||
// Si déjà dans le mapping, retourner
|
||||
if (translations[text]) {
|
||||
return translations[text];
|
||||
}
|
||||
|
||||
// Patterns de remplacement simples basés sur fr.json
|
||||
let translated = text;
|
||||
|
||||
// Mots courants du vocabulaire WFRP
|
||||
const vocabulary = {
|
||||
"Choose": "Choisir",
|
||||
"Select": "Sélectionner",
|
||||
"Enter": "Entrer",
|
||||
"Critical": "Critique",
|
||||
"Wounds": "Blessures",
|
||||
"Bleeding": "Saignement",
|
||||
"Broken": "Brisé",
|
||||
"Removed": "Retiré",
|
||||
"Added": "Ajouté",
|
||||
"Applied": "Appliqué",
|
||||
"Failed": "Échoué",
|
||||
"Passed": "Réussi",
|
||||
"Cannot": "Impossible de",
|
||||
"Must": "Doit",
|
||||
"Need": "Besoin",
|
||||
"Automatically": "Automatiquement",
|
||||
"any": "tout",
|
||||
"all": "tout",
|
||||
"Test": "Test",
|
||||
"Tests": "Tests",
|
||||
"Skill": "Compétence",
|
||||
"effect": "effet",
|
||||
"after effects": "effets secondaires",
|
||||
};
|
||||
|
||||
// Appliquer les remplacements de vocabulaire
|
||||
for (const [en, fr] of Object.entries(vocabulary)) {
|
||||
const regex = new RegExp(`\\b${en}\\b`, 'gi');
|
||||
translated = translated.replace(regex, (match) => {
|
||||
// Conserver la casse
|
||||
if (match[0] === match[0].toUpperCase()) {
|
||||
return fr.charAt(0).toUpperCase() + fr.slice(1);
|
||||
}
|
||||
return fr;
|
||||
});
|
||||
}
|
||||
|
||||
// Si rien n'a changé, ne pas proposer de traduction
|
||||
if (translated === text) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return translated;
|
||||
}
|
||||
|
||||
// Analyser et créer le mapping complet
|
||||
console.log('Création du mapping de traductions...\n');
|
||||
|
||||
const frequencies = getTextFrequencies();
|
||||
const autoTranslations = new Map();
|
||||
|
||||
// Trier par fréquence décroissante
|
||||
const sortedTexts = Array.from(frequencies.entries())
|
||||
.sort((a, b) => b[1] - a[1]);
|
||||
|
||||
let proposedCount = 0;
|
||||
let existingCount = 0;
|
||||
|
||||
sortedTexts.forEach(([text, freq]) => {
|
||||
if (translations[text]) {
|
||||
autoTranslations.set(text, translations[text]);
|
||||
existingCount++;
|
||||
} else {
|
||||
const proposed = proposeTranslations(text);
|
||||
if (proposed && proposed !== text) {
|
||||
autoTranslations.set(text, proposed);
|
||||
proposedCount++;
|
||||
if (proposedCount <= 10) {
|
||||
console.log(`"${text}" → "${proposed}" (${freq}x)`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`\n${existingCount} traductions existantes`);
|
||||
console.log(`${proposedCount} traductions proposées automatiquement`);
|
||||
console.log(`${sortedTexts.length - existingCount - proposedCount} textes ignorés (code/technique)`);
|
||||
|
||||
// Appliquer les traductions
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('Application des traductions...\n');
|
||||
|
||||
let stats = {
|
||||
filesProcessed: 0,
|
||||
filesModified: 0,
|
||||
replacementsMade: 0,
|
||||
errors: 0
|
||||
};
|
||||
|
||||
englishTexts.forEach(({ file, strings }) => {
|
||||
const filePath = path.join(FR_DIR, file);
|
||||
stats.filesProcessed++;
|
||||
|
||||
try {
|
||||
let content = fs.readFileSync(filePath, 'utf8');
|
||||
let modified = false;
|
||||
let replacementsInFile = 0;
|
||||
|
||||
strings.forEach(text => {
|
||||
const translation = autoTranslations.get(text);
|
||||
if (translation && content.includes(text)) {
|
||||
// Remplacement simple
|
||||
const newContent = content.split(text).join(translation);
|
||||
|
||||
if (newContent !== content) {
|
||||
const count = content.split(text).length - 1;
|
||||
content = newContent;
|
||||
modified = true;
|
||||
replacementsInFile += count;
|
||||
stats.replacementsMade += count;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (modified) {
|
||||
fs.writeFileSync(filePath, content, 'utf8');
|
||||
stats.filesModified++;
|
||||
console.log(`✓ ${file} : ${replacementsInFile} remplacement(s)`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
stats.errors++;
|
||||
console.error(`✗ ${file} : ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('Traduction automatique terminée !');
|
||||
console.log('='.repeat(60));
|
||||
console.log(`Fichiers traités : ${stats.filesProcessed}`);
|
||||
console.log(`Fichiers modifiés : ${stats.filesModified}`);
|
||||
console.log(`Remplacements effectués : ${stats.replacementsMade}`);
|
||||
console.log(`Erreurs : ${stats.errors}`);
|
||||
console.log('='.repeat(60));
|
||||
|
||||
// Sauvegarder le mapping de traductions
|
||||
const mappingFile = path.join(__dirname, 'auto-translations-applied.json');
|
||||
fs.writeFileSync(
|
||||
mappingFile,
|
||||
JSON.stringify(Object.fromEntries(autoTranslations), null, 2),
|
||||
'utf8'
|
||||
);
|
||||
console.log(`\nMapping de traductions sauvegardé dans : auto-translations-applied.json`);
|
||||
251
tools/auto-translations-applied.json
Normal file
251
tools/auto-translations-applied.json
Normal file
@@ -0,0 +1,251 @@
|
||||
{
|
||||
"+ this.effect.name\n\nawait this.actor.update(updateObj)\nthis.actor.createEmbeddedDocuments(": "+ this.effet.name\n\nawait this.actor.update(updateObj)\nthis.actor.createEmbeddedDocuments(",
|
||||
"+ this.effect.name\n\nawait this.actor.update(updateObj)\nconsole.log(": "+ this.effet.name\n\nawait this.actor.update(updateObj)\nconsole.log(",
|
||||
"Added Bleeding": "Saignement ajouté",
|
||||
", {skipTargets: true, appendTitle : ` - ${this.effect.name}`, fields : {difficulty :": ", {skipTargets: true, appendTitle : ` - ${this.effet.name}`, fields : {difficulty :",
|
||||
"Fatigued added to": "Fatigued Ajouté to",
|
||||
"which cannot be removed until the Malaise symptom is gone.": "which Impossible de be Retiré until the Malaise symptom is gone.",
|
||||
")}!`}));\n\nthis.effect.updateSource({": ")}!`}));\n\nthis.effet.updateSource({",
|
||||
"Lore (Magic)": "Savoir (Magie)",
|
||||
")}) \n}\n\n// Notify of lingering effects when mask is removed\nelse if (!args.equipped)\n{\n await this.item.effects.contents[0].delete();\n await this.item.update({name : this.item.name +=": ")}) \n}\n\n// Notify of lingering effects when mask is Retiré\nelse if (!args.equipped)\n{\n await this.item.effects.contents[0].delete();\n await this.item.update({name : this.item.name +=",
|
||||
"})\n this.script.message(`<strong>${this.item.name}</strong> on ${this.actor.name} has been taken off and loses its properties. However, the effects last for [[1d10+4]] days, after which they should be manually removed.`, \n {whisper: ChatMessage.getWhisperRecipients(": "})\n this.script.message(`<strong>${this.item.name}</strong> on ${this.actor.name} has been taken off and loses its properties. However, the effects last for [[1d10+4]] days, after which they should be manually Retiré.`, \n {whisper: ChatMessage.getWhisperRecipients(",
|
||||
",\n {whisper: ChatMessage.getWhisperRecipients(\"GM\")}) \n}\n\n// Notify of lingering effects when mask is removed\nelse if (!args.equipped)\n{\n await this.item.effects.contents[0].delete();\n await this.item.update({name : this.item.name += \" (Used)\"})\n this.script.message(": ",\n {whisper: ChatMessage.getWhisperRecipients(\"GM\")}) \n}\n\n// Notify of lingering effects when mask is Retiré\nelse if (!args.equipped)\n{\n await this.item.effects.contents[0].delete();\n await this.item.update({name : this.item.name += \" (Used)\"})\n this.script.message(",
|
||||
"+ this.effect.name, context : {failure:": "+ this.effet.name, context : {failure:",
|
||||
"Choose Characteristic": "Choisir Characteristic",
|
||||
": this.item.system.tests.value.replace(": ": this.item.system.Tests.value.replace(",
|
||||
") || this.item.system.tests.value.includes(": ") || this.item.system.Tests.value.includes(",
|
||||
") || this.item.system.tests.value.toLowerCase().includes(": ") || this.item.system.Tests.value.toLowerCase().includes(",
|
||||
"))\n{\n let tests = this.item.system.tests.value\n let name = this.item.name\n\n // If name already specifies, make sure tests value reflects that\n if (name.includes(": "))\n{\n let Tests = this.item.system.Tests.value\n let name = this.item.name\n\n // If name already specifies, make sure Tests value reflects that\n if (name.includes(",
|
||||
",\n skipTargets: true,\n fields: {difficulty: 'easy'},\n characteristic: 'wp',\n});\nawait test.roll();\n\nif (!test.succeeded) {\n test.result.other.push(": ",\n skipTargets: true,\n fields: {difficulty: 'easy'},\n characteristic: 'wp',\n});\nawait Test.roll();\n\nif (!Test.succeeded) {\n Test.result.other.push(",
|
||||
"Dark Magic (Necromancy)": "Magie Noire (Nécromancie)",
|
||||
"action-link critical": "action-link critical",
|
||||
"all forms": "toutes formes",
|
||||
")})\n}\n\n// Notify of lingering effects when mask is removed\nelse if (!args.equipped)\n{\n await this.item.effects.contents[0].delete();\n await this.item.update({name : this.item.name +=": ")})\n}\n\n// Notify of lingering effects when mask is Retiré\nelse if (!args.equipped)\n{\n await this.item.effects.contents[0].delete();\n await this.item.update({name : this.item.name +=",
|
||||
";\nconst test = 'Maintenance Crew Test';\nconst difficulty = 'hard';\nconst target = 80;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Maintenance Crew Test';\nconst difficulty = 'hard';\nconst target = 80;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
"}})\nawait test.roll();\nif (test.failed)\n{\n args.actor.addCondition(": "}})\nawait Test.roll();\nif (Test.Échoué)\n{\n args.actor.addCondition(",
|
||||
"}})\nawait test.roll();\nif (test.failed)\n{\n this.actor.addCondition(": "}})\nawait Test.roll();\nif (Test.Échoué)\n{\n this.actor.addCondition(",
|
||||
"Choose a Condition": "Choisir a Condition",
|
||||
"<p>\n Select your choice\n </p>\n <ol>\n <li>Mail</li>\n <li>Mail & Leather</li>\n <li>Plate</li>\n </ol>": "<p>\n Sélectionner your choice\n </p>\n <ol>\n <li>Mail</li>\n <li>Mail & Leather</li>\n <li>Plate</li>\n </ol>",
|
||||
"})\n await test.roll();\n if (test.failed)\n {\n this.actor.addCondition(": "})\n await Test.roll();\n if (Test.Échoué)\n {\n this.actor.addCondition(",
|
||||
"critical-roll": "Critique-roll",
|
||||
").pop())\n\nif (ones > SL)\n args.test.result.other.push(`<span class=": ").pop())\n\nif (ones > SL)\n args.Test.result.other.push(`<span class=",
|
||||
"Applied after effects": "Effets secondaires appliqués",
|
||||
"Choose Lore": "Choisir Lore",
|
||||
")\n }\n else if (this.actor.characteristics.int.bonus + args.test.result.SL < 0)\n args.test.result.other.push(": ")\n }\n else if (this.actor.characteristics.int.bonus + args.Test.result.SL < 0)\n args.Test.result.other.push(",
|
||||
"Choose Training": "Choisir un Entraînement",
|
||||
").map(i => {\n return {\n id : i.toLowerCase(),\n name : i\n }\n });\n}\n\nif (choice.length)\n{\n let changes = foundry.utils.deepClone(this.effect.changes);\n\n for(let training of choice)\n {\n switch(training.id)\n {\n case": ").map(i => {\n return {\n id : i.toLowerCase(),\n name : i\n }\n });\n}\n\nif (choice.length)\n{\n let changes = foundry.utils.deepClone(this.effet.changes);\n\n for(let training of choice)\n {\n switch(training.id)\n {\n case",
|
||||
", [territorial], {fromEffect: this.effect.id})\n foundry.utils.setProperty(args,": ", [territorial], {fromEffect: this.effet.id})\n foundry.utils.setProperty(args,",
|
||||
"})\n break;\n }\n }\n this.effect.updateSource({name : `${this.effect.name} (${choice.map(i => i.name).join(": "})\n break;\n }\n }\n this.effet.updateSource({name : `${this.effet.name} (${choice.map(i => i.name).join(",
|
||||
";\n\n let wounds = foundry.utils.duplicate(this.actor.status.wounds);\n let regenRoll = await new Roll(": ";\n\n let Blessures = foundry.utils.duplicate(this.actor.status.Blessures);\n let regenRoll = await new Roll(",
|
||||
").roll({allowInteractive : false});\n let regen = regenRoll.total;\n\n if (wounds.value >= wounds.max)\n return;\n\n if (wounds.value > 0) {\n wounds.value += Math.floor(regen / 2);\n if (wounds.value > wounds.max) {\n wounds.value = wounds.max;\n }\n message += \\`<b>\\${this.actor.name}</b> regagne \\${regen} Blessures.\\`;\n\n if (regen === 10) {\n message +=": ").roll({allowInteractive : false});\n let regen = regenRoll.total;\n\n if (Blessures.value >= Blessures.max)\n return;\n\n if (Blessures.value > 0) {\n Blessures.value += Math.floor(regen / 2);\n if (Blessures.value > Blessures.max) {\n Blessures.value = Blessures.max;\n }\n message += \\`<b>\\${this.actor.name}</b> regagne \\${regen} Blessures.\\`;\n\n if (regen === 10) {\n message +=",
|
||||
";\n }\n } else if (regen >= 8) {\n message += \\`<b>\\${this.actor.name}</b> a obtenu un \\${regen} et regagne 1 Blessure.\\`;\n wounds.value += 1;\n if (regen === 10) {\n message +=": ";\n }\n } else if (regen >= 8) {\n message += \\`<b>\\${this.actor.name}</b> a obtenu un \\${regen} et regagne 1 Blessure.\\`;\n Blessures.value += 1;\n if (regen === 10) {\n message +=",
|
||||
": wounds});\n this.script.message(message, {whisper: ChatMessage.getWhisperRecipients(": ": Blessures});\n this.script.message(message, {whisper: ChatMessage.getWhisperRecipients(",
|
||||
")});\n`\n\nawait effect.update({\n name,": ")});\n`\n\nawait effet.update({\n name,",
|
||||
";\n wounds.value += 1;\n if (regen === 10) {\n message += \"<br>De plus, il régénère une Blessure Critique.\";\n }\n } else {\n message += \\": ";\n Blessures.value += 1;\n if (regen === 10) {\n message += \"<br>De plus, il régénère une Blessure Critique.\";\n }\n } else {\n message += \\",
|
||||
";\n }\n\n await this.actor.update({\"system.status.wounds\": wounds});\n this.script.message(message, {whisper: ChatMessage.getWhisperRecipients(\"GM\")});": ";\n }\n\n await this.actor.update({\"system.status.Blessures\": Blessures});\n this.script.message(message, {whisper: ChatMessage.getWhisperRecipients(\"GM\")});",
|
||||
")\n}\n\nthis.effect.updateSource({": ")\n}\n\nthis.effet.updateSource({",
|
||||
")[0].trim()} (${resistance})`})\n this.effect.updateSource({name : this.effect.name + ` (${resistance})`})\n }\n} \nthis.item.updateSource({": ")[0].trim()} (${resistance})`})\n this.effet.updateSource({name : this.effet.name + ` (${resistance})`})\n }\n} \nthis.item.updateSource({",
|
||||
", resistance)})\n\nif (resistance && !this.effect.name.includes(": ", resistance)})\n\nif (resistance && !this.effet.name.includes(",
|
||||
"})\n this.effect.updateSource({name : this.effect.name +": "})\n this.effet.updateSource({name : this.effet.name +",
|
||||
"})\n }\n} \nthis.item.updateSource({\"system.tests.value\" : this.item.system.tests.value.replace(\"the associated Threat\", resistance)})\n\nif (resistance && !this.effect.name.includes(\"(\"))\n{\n this.effect.updateSource({name : this.effect.name +=": "})\n }\n} \nthis.item.updateSource({\"system.Tests.value\" : this.item.system.Tests.value.replace(\"the associated Threat\", resistance)})\n\nif (resistance && !this.effet.name.includes(\"(\"))\n{\n this.effet.updateSource({name : this.effet.name +=",
|
||||
")\n }\n }\n\n this.effect.updateSource({name})\n this.item.updateSource({name,": ")\n }\n }\n\n this.effet.updateSource({name})\n this.item.updateSource({name,",
|
||||
"épines\"];\n\nlet updateObj = this.actor.toObject();\n\nfor (let ch in characteristics)\n{\n updateObj.system.characteristics[ch].modifier += characteristics[ch];\n}\n\nfor (let index = 0; index < skills.length; index++)\n{\n let skill = skills[index]\n let skillItem;\n skillItem = updateObj.items.find(i => i.name == skill && i.type == \"skill\")\n if (skillItem)\n skillItem.system.advances.value += skillAdvancements[index]\n else \n {\n skillItem = await game.wfrp4e.utility.findSkill(skill)\n skillItem = skillItem.toObject();\n skillItem.system.advances.value = skillAdvancements[index];\n items.push(skillItem);\n }\n}\n\nfor (let talent of talents)\n{\n let talentItem = await game.wfrp4e.utility.findTalent(talent)\n if (talentItem)\n {\n items.push(talentItem.toObject());\n }\n else \n {\n ui.notifications.warn(`Could not find ${talent}`, {permanent : true})\n }\n}\n\nconst traitRegex = /(?:,?(.+?)(\\+?\\d{1,2}\\+?)?\\s*?(?:\\((.+?)\\)\\s*(\\+?\\d{1,2})?|,|$))/gm\nfor (let trait of traits)\n{\n let traitMatches = trait.matchAll(traitRegex).next().value\n let traitName = traitMatches[1]\n let traitVal = traitMatches[2] || traitMatches[4] // could be match 2 or 4 depending on if there": "épines\"];\n\nlet updateObj = this.actor.toObject();\n\nfor (let ch in characteristics)\n{\n updateObj.system.characteristics[ch].modifier += characteristics[ch];\n}\n\nfor (let index = 0; index < skills.length; index++)\n{\n let Compétence = skills[index]\n let skillItem;\n skillItem = updateObj.items.find(i => i.name == Compétence && i.type == \"Compétence\")\n if (skillItem)\n skillItem.system.advances.value += skillAdvancements[index]\n else \n {\n skillItem = await game.wfrp4e.utility.findSkill(Compétence)\n skillItem = skillItem.toObject();\n skillItem.system.advances.value = skillAdvancements[index];\n items.push(skillItem);\n }\n}\n\nfor (let talent of talents)\n{\n let talentItem = await game.wfrp4e.utility.findTalent(talent)\n if (talentItem)\n {\n items.push(talentItem.toObject());\n }\n else \n {\n ui.notifications.warn(`Could not find ${talent}`, {permanent : true})\n }\n}\n\nconst traitRegex = /(?:,?(.+?)(\\+?\\d{1,2}\\+?)?\\s*?(?:\\((.+?)\\)\\s*(\\+?\\d{1,2})?|,|$))/gm\nfor (let trait of traits)\n{\n let traitMatches = trait.matchAll(traitRegex).next().value\n let traitName = traitMatches[1]\n let traitVal = traitMatches[2] || traitMatches[4] // could be match 2 or 4 depending on if there",
|
||||
"Skipping Tests to apply the tattoos": "Tests ignorés pour appliquer les tatouages",
|
||||
"<p>Apply Ward of Grimnir effect?</p>": "<p>Apply Ward of Grimnir effet?</p>",
|
||||
"No Lore (Theology) skill found, cannot pass.": "Compétence Savoir (Théologie) introuvable, impossible de continuer.",
|
||||
"No Lore (Runes) skill found, cannot pass.": "Compétence Savoir (Runes) introuvable, impossible de continuer.",
|
||||
"One or more Tests to apply the tattoos failed.": "Un ou plusieurs Tests pour appliquer les tatouages ont échoué.",
|
||||
", fields : {difficulty : \"vhard\"}})\n await test.roll();\n if (test.failed)\n {\n failed = true;\n }\n}\nelse \n{\n this.script.notification(\"No Lore (Theology) skill found, cannot pass.\")\n failed = true;\n}\n\nif (this.actor.itemTags.skill.find(i => i.name == \"Lore (Runes)\"))\n {\n let test = await this.actor.setupSkill(\"Lore (Runes)\", {appendTitle :": ", fields : {difficulty : \"vhard\"}})\n await Test.roll();\n if (Test.Échoué)\n {\n Échoué = true;\n }\n}\nelse \n{\n this.script.notification(\"No Lore (Theology) Compétence found, Impossible de pass.\")\n Échoué = true;\n}\n\nif (this.actor.itemTags.Compétence.find(i => i.name == \"Lore (Runes)\"))\n {\n let Test = await this.actor.setupSkill(\"Lore (Runes)\", {appendTitle :",
|
||||
", fields : {difficulty : \"hard\"}})\n await test.roll();\n if (test.failed)\n {\n failed = true;\n }\n }\n else \n {\n this.script.notification(\"No Lore (Runes) skill found, cannot pass.\")\n failed = true;\n }\n\n\n let test = await this.actor.setupSkill(\"Art (Tattooing)\", {appendTitle :": ", fields : {difficulty : \"hard\"}})\n await Test.roll();\n if (Test.Échoué)\n {\n Échoué = true;\n }\n }\n else \n {\n this.script.notification(\"No Lore (Runes) Compétence found, Impossible de pass.\")\n Échoué = true;\n }\n\n\n let Test = await this.actor.setupSkill(\"Art (Tattooing)\", {appendTitle :",
|
||||
")\n let configBlessings = await Promise.all((game.wfrp4e.config.godBlessings[god.toLowerCase()] || []).map(fromUuid));\n if (god ==": ")\n let configBlessings = await Promise.tout((game.wfrp4e.config.godBlessings[god.toLowerCase()] || []).map(fromUuid));\n if (god ==",
|
||||
"))\n await this.actor.addEffectItems(blessings.map(i => i.uuid), this.effect)\n }\n else\n {\n this.script.scriptNotification(`Impossible de trouver des Bénédictions associées à ${god}.`)\n }\n if (this.item.name.includes(": "))\n await this.actor.addEffectItems(blessings.map(i => i.uuid), this.effet)\n }\n else\n {\n this.script.scriptNotification(`Impossible de trouver des Bénédictions associées à ${god}.`)\n }\n if (this.item.name.includes(",
|
||||
", group)})\n\tthis.effect.updateSource({name : this.effect.name + ` (${group})`})\n}\n\n\ndata.name = data.name.replace(": ", group)})\n\tthis.effet.updateSource({name : this.effet.name + ` (${group})`})\n}\n\n\ndata.name = data.name.replace(",
|
||||
", \"system.tests.value\" : this.item.system.tests.value.replace(\"Group\", group)})\n\tthis.effect.updateSource({name : this.effect.name +": ", \"system.Tests.value\" : this.item.system.Tests.value.replace(\"Group\", group)})\n\tthis.effet.updateSource({name : this.effet.name +",
|
||||
"attrait du Léviathan.`);\n loreTest.renderRollCard();\n return;\n }\n}\n\nlet test = await actor.setupSkill(": "attrait du Léviathan.`);\n loreTest.renderRollCard();\n return;\n }\n}\n\nlet Test = await actor.setupSkill(",
|
||||
", {\n appendTitle: ` – ${this.effect.name}`,\n skipTargets: true,\n fields: {difficulty:": ", {\n appendTitle: ` – ${this.effet.name}`,\n skipTargets: true,\n fields: {difficulty:",
|
||||
");\n loreTest.renderRollCard();\n return;\n }\n}\n\nlet test = await actor.setupSkill('Calme', {\n appendTitle:": ");\n loreTest.renderRollCard();\n return;\n }\n}\n\nlet Test = await actor.setupSkill('Calme', {\n appendTitle:",
|
||||
", this.effect.name)\n\nif (characteristics.has(": ", this.effet.name)\n\nif (characteristics.has(",
|
||||
", availableChoices);\n\n if (!result) return;\n\n characteristics.add(result);\n}\n\nthis.effect.setFlag(": ", availableChoices);\n\n if (!result) return;\n\n characteristics.add(result);\n}\n\nthis.effet.setFlag(",
|
||||
").roll({allowInteractive : false});\nlet regen = regenRoll.total;\n\nif (wounds.value >= wounds.max)\n return\n\nif (wounds.value > 0) \n{\n wounds.value += regen\n if (wounds.value > wounds.max)\n {\n wounds.value = wounds.max\n }\n message += `<b>${this.actor.name}</b> regains ${regen} Wounds.`\n\n if (regen == 10)\n {\n message += `<br>Additionally, they regenerate a Critical Wound.`\n }\n}\nelse if (regen >= 8) \n{\n message += `<b>${this.actor.name}</b> rolled a ${regen} and regains 1 Wound.`\n wounds.value += 1\n if (regen == 10)\n {\n message += `<br>Additionally, they regenerate a Critical Wound.`\n }\n}\nelse \n{\n message += `<b>${this.actor.name}</b> Régénération roll of ${regen} - No effect.`\n}\n\nawait this.actor.update({": ").roll({allowInteractive : false});\nlet regen = regenRoll.total;\n\nif (Blessures.value >= Blessures.max)\n return\n\nif (Blessures.value > 0) \n{\n Blessures.value += regen\n if (Blessures.value > Blessures.max)\n {\n Blessures.value = Blessures.max\n }\n message += `<b>${this.actor.name}</b> regains ${regen} Blessures.`\n\n if (regen == 10)\n {\n message += `<br>Additionally, they regenerate a Critique Wound.`\n }\n}\nelse if (regen >= 8) \n{\n message += `<b>${this.actor.name}</b> rolled a ${regen} and regains 1 Wound.`\n Blessures.value += 1\n if (regen == 10)\n {\n message += `<br>Additionally, they regenerate a Critique Wound.`\n }\n}\nelse \n{\n message += `<b>${this.actor.name}</b> Régénération roll of ${regen} - No effet.`\n}\n\nawait this.actor.update({",
|
||||
": wounds })\nthis.script.message(message, { whisper: ChatMessage.getWhisperRecipients(": ": Blessures })\nthis.script.message(message, { whisper: ChatMessage.getWhisperRecipients(",
|
||||
"wounds.value += 1\n if (regen == 10)\n {\n message +=": "Blessures.value += 1\n if (regen == 10)\n {\n message +=",
|
||||
",\n value: /^((?!\\().)*$/gm, // Remove all spells with parentheses (all arcane spells spells)\n regex: true\n },\n {\n property :": ",\n value: /^((?!\\().)*$/gm, // Remove tout spells with parentheses (tout arcane spells spells)\n regex: true\n },\n {\n property :",
|
||||
"+ this.effect.name\nawait this.actor.update(updateObj)\nthis.actor.createEmbeddedDocuments(": "+ this.effet.name\nawait this.actor.update(updateObj)\nthis.actor.createEmbeddedDocuments(",
|
||||
"></i> Critical</a>`;\n \n const test = await this.actor.setupSkill(game.i18n.localize(": "></i> Critique</a>`;\n \n const Test = await this.actor.setupSkill(game.i18n.localize(",
|
||||
"), {\n skipTargets: true,\n appendTitle: ` - ${this.effect.name}`,\n fields: {difficulty:": "), {\n skipTargets: true,\n appendTitle: ` - ${this.effet.name}`,\n fields: {difficulty:",
|
||||
"<a data-action=\"clickTable\" class=\"action-link critical\" data-table=\"crithead\" data-modifier=\"0\"><i class=\"fas fa-list\"></i> Critical</a>": "<a data-action=\"clickTable\" class=\"action-link Critique\" data-table=\"crithead\" data-modifier=\"0\"><i class=\"fas fa-list\"></i> Critique</a>",
|
||||
"Must provide a Master Rune": "Doit fournir une Rune Maîtresse",
|
||||
", title : this.effect.name, filter: (item) => item.type == \"wfrp4e-dwarfs.rune\" && item.system.master, onError: \"Must provide a Master Rune\"});\n }\n }\n else \n {\n rune = await DragDialog.create({text :": ", title : this.effet.name, filter: (item) => item.type == \"wfrp4e-dwarfs.rune\" && item.system.master, onError: \"Doit provide a Master Rune\"});\n }\n }\n else \n {\n rune = await DragDialog.create({text :",
|
||||
", title : this.effect.name, filter: (item) => item.type == \"wfrp4e-dwarfs.rune\" && item.system.master, onError: \"Must provide a Master Rune\"});\n }\n}\nelse \n{\n rune = await DragDialog.create({text :": ", title : this.effet.name, filter: (item) => item.type == \"wfrp4e-dwarfs.rune\" && item.system.master, onError: \"Doit provide a Master Rune\"});\n }\n}\nelse \n{\n rune = await DragDialog.create({text :",
|
||||
", title : this.effect.name, filter: (item) => item.type == \"wfrp4e-dwarfs.rune\" && item.system.master, onError: \"Must provide a Master Rune\"});\n}\n\nthis.actor.addEffectItems(rune.uuid, this.effect)\n\nlet talents = this.actor.itemTags.talent.filter(i => i.baseName == this.item.baseName);\nlet xpCost = talents.length * 100\n\nif (this.actor.type == \"character\" && (await foundry.applications.api.DialogV2.confirm({window: {title: this.effect.name}, content:": ", title : this.effet.name, filter: (item) => item.type == \"wfrp4e-dwarfs.rune\" && item.system.master, onError: \"Doit provide a Master Rune\"});\n}\n\nthis.actor.addEffectItems(rune.uuid, this.effet)\n\nlet talents = this.actor.itemTags.talent.filter(i => i.baseName == this.item.baseName);\nlet xpCost = talents.length * 100\n\nif (this.actor.type == \"character\" && (await foundry.applications.api.DialogV2.confirm({window: {title: this.effet.name}, content:",
|
||||
"Must provide a Rune (non-Master)": "Doit fournir une Rune (non-Maîtresse)",
|
||||
", title : this.effect.name, filter: (item) => item.type == \"wfrp4e-dwarfs.rune\" && !item.system.master, onError: \"Must provide a Rune (non-Master)\"});\n }\n }\n else \n {\n rune = await DragDialog.create({text :": ", title : this.effet.name, filter: (item) => item.type == \"wfrp4e-dwarfs.rune\" && !item.system.master, onError: \"Doit provide a Rune (non-Master)\"});\n }\n }\n else \n {\n rune = await DragDialog.create({text :",
|
||||
", title : this.effect.name, filter: (item) => item.type == \"wfrp4e-dwarfs.rune\" && !item.system.master, onError: \"Must provide a Rune (non-Master)\"});\n }\n}\nelse \n{\n rune = await DragDialog.create({text :": ", title : this.effet.name, filter: (item) => item.type == \"wfrp4e-dwarfs.rune\" && !item.system.master, onError: \"Doit provide a Rune (non-Master)\"});\n }\n}\nelse \n{\n rune = await DragDialog.create({text :",
|
||||
", title : this.effect.name, filter: (item) => item.type == \"wfrp4e-dwarfs.rune\" && !item.system.master, onError: \"Must provide a Rune (non-Master)\"});\n}\n\nthis.actor.addEffectItems(rune.uuid, this.effect)\n\nlet talents = this.actor.itemTags.talent.filter(i => i.baseName == this.item.baseName);\nlet xpCost = talents.length * 100\n\nif (this.actor.type == \"character\" && (await foundry.applications.api.DialogV2.confirm({window: {title: this.effect.name}, content:": ", title : this.effet.name, filter: (item) => item.type == \"wfrp4e-dwarfs.rune\" && !item.system.master, onError: \"Doit provide a Rune (non-Master)\"});\n}\n\nthis.actor.addEffectItems(rune.uuid, this.effet)\n\nlet talents = this.actor.itemTags.talent.filter(i => i.baseName == this.item.baseName);\nlet xpCost = talents.length * 100\n\nif (this.actor.type == \"character\" && (await foundry.applications.api.DialogV2.confirm({window: {title: this.effet.name}, content:",
|
||||
", title : this.effect.name});\n if (value)\n {\n name = `${name.split(": ", title : this.effet.name});\n if (value)\n {\n name = `${name.split(",
|
||||
")[0].trim()} (${value})`\n tests = this.item.system.tests.value.replace(": ")[0].trim()} (${value})`\n Tests = this.item.system.Tests.value.replace(",
|
||||
"}\n else\n {\n let value = await ValueDialog.create({text : \"Entrez le Groupe d'Étiquette\", title : this.effect.name});\n if (value)\n {\n name =": "}\n else\n {\n let value = await ValueDialog.create({text : \"Entrez le Groupe d'Étiquette\", title : this.effet.name});\n if (value)\n {\n name =",
|
||||
");\n}\n\nif (this.actor.items.find(i => i.type === \"extendedTest\" && i.name === this.effect.name)) {\n this.script.message(": ");\n}\n\nif (this.actor.items.find(i => i.type === \"extendedTest\" && i.name === this.effet.name)) {\n this.script.message(",
|
||||
");\n\n return;\n}\n\nconst extendedTestData = {\n name: this.effect.name,\n type: \"extendedTest\",\n img: this.effect.img,\n system: {\n SL: {\n current: 0,\n target: target.actor.system.status.wounds.value\n },\n test: {\n value: 'Strength'\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: \"challenging\"\n }\n }\n};\n\nconst extendedTests = await this.actor.createEmbeddedDocuments(\"Item\", [extendedTestData], {fromEffect: this.effect.id});\nconst extendedTest = extendedTests[0];\n\nthis.script.message(": ");\n\n return;\n}\n\nconst extendedTestData = {\n name: this.effet.name,\n type: \"extendedTest\",\n img: this.effet.img,\n system: {\n SL: {\n current: 0,\n target: target.actor.system.status.Blessures.value\n },\n Test: {\n value: 'Strength'\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: \"challenging\"\n }\n }\n};\n\nconst extendedTests = await this.actor.createEmbeddedDocuments(\"Item\", [extendedTestData], {fromEffect: this.effet.id});\nconst extendedTest = extendedTests[0];\n\nthis.script.message(",
|
||||
");\n\nlet effect = {\n name: extendedTest.name,\n img: extendedTest.img,\n system: {\n transferData : {\n type: \"document\",\n documentType: \"Item\"\n },\n scriptData: [\n {\n label: extendedTest.name,\n script:": ");\n\nlet effet = {\n name: extendedTest.name,\n img: extendedTest.img,\n system: {\n transferData : {\n type: \"document\",\n documentType: \"Item\"\n },\n scriptData: [\n {\n label: extendedTest.name,\n script:",
|
||||
");\n await effect.delete();": ");\n await effet.delete();",
|
||||
", {\n skipTargets: true, \n appendTitle: ` — ${this.effect.name}`, \n fields: {\n difficulty:": ", {\n skipTargets: true, \n appendTitle: ` — ${this.effet.name}`, \n fields: {\n difficulty:",
|
||||
",\n }\n});\n\nawait test.roll();\nif (test.failure) {\n await this.actor.addCondition(": ",\n }\n});\n\nawait Test.roll();\nif (Test.failure) {\n await this.actor.addCondition(",
|
||||
"}. Do you want to roll d10?</p>\n <p>1–6: add +1 SL</p>\n <p>7–10: lose all accrued SLs and perform next Test at –1 SL</p>\n </div>\n`;\n const choice = await foundry.applications.api.DialogV2.confirm({\n yes: {label:": "}. Do you want to roll d10?</p>\n <p>1–6: add +1 SL</p>\n <p>7–10: lose tout accrued SLs and perform next Test at –1 SL</p>\n </div>\n`;\n const choice = await foundry.applications.api.DialogV2.confirm({\n yes: {label:",
|
||||
");\n await roll.toMessage({flavor: this.effect.name});\n\n if (roll.total >= 7) {\n SL = -1;\n break;\n }\n\n SL++;\n} while (true);\n\nthis.effect.setFlag(": ");\n await roll.toMessage({flavor: this.effet.name});\n\n if (roll.total >= 7) {\n SL = -1;\n break;\n }\n\n SL++;\n} while (true);\n\nthis.effet.setFlag(",
|
||||
", { appendTitle: ` - ${this.effect.name}`, fields: { difficulty:": ", { appendTitle: ` - ${this.effet.name}`, fields: { difficulty:",
|
||||
"} })\nawait test.roll();\n\nif (test.failed) \n{\n let ageAdded = Math.ceil(CONFIG.Dice.randomUniform() * 10) + Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let ws = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let bs = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let s = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let t = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let ag = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let dex = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n\n let currentAge = parseInt(this.actor.system.details.age.value)\n\n let inline = `<a class=": "} })\nawait Test.roll();\n\nif (Test.Échoué) \n{\n let ageAdded = Math.ceil(CONFIG.Dice.randomUniform() * 10) + Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let ws = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let bs = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let s = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let t = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let ag = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let dex = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n\n let currentAge = parseInt(this.actor.system.details.age.value)\n\n let inline = `<a class=",
|
||||
", fields: { difficulty: \"challenging\" } })\nawait test.roll();\n\nif (test.failed) \n{\n let ageAdded = Math.ceil(CONFIG.Dice.randomUniform() * 10) + Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let ws = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let bs = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let s = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let t = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let ag = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let dex = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n\n let currentAge = parseInt(this.actor.system.details.age.value)\n\n let inline =": ", fields: { difficulty: \"challenging\" } })\nawait Test.roll();\n\nif (Test.Échoué) \n{\n let ageAdded = Math.ceil(CONFIG.Dice.randomUniform() * 10) + Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let ws = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let bs = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let s = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let t = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let ag = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n let dex = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n\n let currentAge = parseInt(this.actor.system.details.age.value)\n\n let inline =",
|
||||
"Choose Group": "Choisir Group",
|
||||
", this.actor).roll()\n\nroll.toMessage(this.script.getChatData({flavor : `${this.effect.name} (Durée)`}));\n\nthis.effect.updateSource({": ", this.actor).roll()\n\nroll.toMessage(this.script.getChatData({flavor : `${this.effet.name} (Durée)`}));\n\nthis.effet.updateSource({",
|
||||
",\n {whisper: ChatMessage.getWhisperRecipients(\"GM\")})\n}\n\n// Notify of lingering effects when mask is removed\nelse if (!args.equipped)\n{\n await this.item.effects.contents[0].delete();\n await this.item.update({name : this.item.name += \" (Utilisé)\"})\n this.script.message(": ",\n {whisper: ChatMessage.getWhisperRecipients(\"GM\")})\n}\n\n// Notify of lingering effects when mask is Retiré\nelse if (!args.equipped)\n{\n await this.item.effects.contents[0].delete();\n await this.item.update({name : this.item.name += \" (Utilisé)\"})\n this.script.message(",
|
||||
",\n {whisper: ChatMessage.getWhisperRecipients(\"GM\")})\n}\n\n// Notify of lingering effects when mask is removed\nelse if (!args.equipped)\n{\n await this.item.effects.contents[0].delete();\n await this.item.update({name : this.item.name += \" (Used)\"})\n this.script.message(": ",\n {whisper: ChatMessage.getWhisperRecipients(\"GM\")})\n}\n\n// Notify of lingering effects when mask is Retiré\nelse if (!args.equipped)\n{\n await this.item.effects.contents[0].delete();\n await this.item.update({name : this.item.name += \" (Used)\"})\n this.script.message(",
|
||||
"}\n});\n\nawait test.roll();\n\nif (test.failed) {\n await this.actor.addEffectItems(bloodyFluxUUID, this.effect);\n} else {\n const SL = test.result.SL;\n const heal = 1 + SL;\n await this.actor.modifyWounds(heal);\n this.script.message(": "}\n});\n\nawait Test.roll();\n\nif (Test.Échoué) {\n await this.actor.addEffectItems(bloodyFluxUUID, this.effet);\n} else {\n const SL = Test.result.SL;\n const heal = 1 + SL;\n await this.actor.modifyWounds(heal);\n this.script.message(",
|
||||
"You must control an Actor capable of performing a Strength Test": "You Doit control an Actor capable of performing a Strength Test",
|
||||
"}\n});\n\nawait test.roll();\nif (test.succeeded) {\n let SL = parseInt(test.result.SL);\n let name = this.effect.name.replace(/\\d+/, rating => parseInt(rating) - SL);\n await this.effect.update({name});\n}\n\nlet rating = parseInt(this.effect.name.match(/\\d+/)?.[0]);\nif (rating <= 1) {\n const scriptData = this.effect.system.scriptData\n scriptData[2].trigger = '';\n await this.effect.update({disabled: true,": "}\n});\n\nawait Test.roll();\nif (Test.succeeded) {\n let SL = parseInt(Test.result.SL);\n let name = this.effet.name.replace(/\\d+/, rating => parseInt(rating) - SL);\n await this.effet.update({name});\n}\n\nlet rating = parseInt(this.effet.name.match(/\\d+/)?.[0]);\nif (rating <= 1) {\n const scriptData = this.effet.system.scriptData\n scriptData[2].trigger = '';\n await this.effet.update({disabled: true,",
|
||||
", {appendTitle : ` - ${this.effect.name}`, fields : {difficulty :": ", {appendTitle : ` - ${this.effet.name}`, fields : {difficulty :",
|
||||
"}});\n\nawait test.roll();\n\nif (test.failed)\n{\n\n if (test.isCriticalFumble ==": "}});\n\nawait Test.roll();\n\nif (Test.Échoué)\n{\n\n if (Test.isCriticalFumble ==",
|
||||
", fields : {difficulty : \"difficult\"}});\n\nawait test.roll();\n\nif (test.failed)\n{\n\n if (test.isCriticalFumble == \"fumble\")\n {\n\t return this.script.message(": ", fields : {difficulty : \"difficult\"}});\n\nawait Test.roll();\n\nif (Test.Échoué)\n{\n\n if (Test.isCriticalFumble == \"fumble\")\n {\n\t return this.script.message(",
|
||||
");\n loreTest.renderRollCard();\n return;\n } \n}\n\nlet test = await actor.setupSkill('Calme', {\n appendTitle:": ");\n loreTest.renderRollCard();\n return;\n } \n}\n\nlet Test = await actor.setupSkill('Calme', {\n appendTitle:",
|
||||
", {skipTargets: true, appendTitle : ` - Used ${this.effect.name}`, fields: { difficulty:": ", {skipTargets: true, appendTitle : ` - Used ${this.effet.name}`, fields: { difficulty:",
|
||||
"} }).then(async test => {\n await test.roll()\n if (test.failed) \n {\n let toughnessLost = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n this.actor.update({": "} }).then(async Test => {\n await Test.roll()\n if (Test.Échoué) \n {\n let toughnessLost = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n this.actor.update({",
|
||||
", fields: { difficulty: \"difficult\" } }).then(async test => {\n await test.roll()\n if (test.failed) \n {\n let toughnessLost = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n this.actor.update({ \"system.characteristics.t.initial\": this.actor.characteristics.t.initial - toughnessLost })\n this.script.message(": ", fields: { difficulty: \"difficult\" } }).then(async Test => {\n await Test.roll()\n if (Test.Échoué) \n {\n let toughnessLost = Math.ceil(CONFIG.Dice.randomUniform() * 10)\n this.actor.update({ \"system.characteristics.t.initial\": this.actor.characteristics.t.initial - toughnessLost })\n this.script.message(",
|
||||
": 0\n}\nlet skills = []\nlet skillAdvancements = []\nlet talents = []\nlet trappings = []\nlet items = []\n\nlet updateObj = this.actor.toObject();\n\nfor (let ch in characteristics)\n{\n updateObj.system.characteristics[ch].modifier += characteristics[ch];\n}\n\nfor (let index = 0; index < skills.length; index++)\n{\n let skill = skills[index]\n let skillItem;\n skillItem = updateObj.items.find(i => i.name == skill && i.type ==": ": 0\n}\nlet skills = []\nlet skillAdvancements = []\nlet talents = []\nlet trappings = []\nlet items = []\n\nlet updateObj = this.actor.toObject();\n\nfor (let ch in characteristics)\n{\n updateObj.system.characteristics[ch].modifier += characteristics[ch];\n}\n\nfor (let index = 0; index < skills.length; index++)\n{\n let Compétence = skills[index]\n let skillItem;\n skillItem = updateObj.items.find(i => i.name == Compétence && i.type ==",
|
||||
")\n if (skillItem)\n skillItem.system.advances.value += skillAdvancements[index]\n else\n {\n skillItem = await game.wfrp4e.utility.findSkill(skill)\n skillItem = skillItem.toObject();\n skillItem.system.advances.value = skillAdvancements[index];\n items.push(skillItem);\n }\n}\n\nfor (let talent of talents)\n{\n let talentItem = await game.wfrp4e.utility.findTalent(talent)\n if (talentItem)\n {\n items.push(talentItem.toObject());\n }\n else\n {\n ui.notifications.warn(`Impossible de trouver ${talent}`, {permanent : true})\n }\n}\n\nfor (let trapping of trappings)\n{\n let trappingItem = await game.wfrp4e.utility.findItem(trapping)\n if (trappingItem)\n {\n trappingItem = trappingItem.toObject()\n\n trappingItem.system.equipped.value = true;\n\n items.push(trappingItem);\n }\n else\n {\n ui.notifications.warn(`Impossible de trouver ${trapping}`, {permanent : true})\n }\n}\n\n\nawait this.actor.update(updateObj)\nthis.actor.createEmbeddedDocuments(": ")\n if (skillItem)\n skillItem.system.advances.value += skillAdvancements[index]\n else\n {\n skillItem = await game.wfrp4e.utility.findSkill(Compétence)\n skillItem = skillItem.toObject();\n skillItem.system.advances.value = skillAdvancements[index];\n items.push(skillItem);\n }\n}\n\nfor (let talent of talents)\n{\n let talentItem = await game.wfrp4e.utility.findTalent(talent)\n if (talentItem)\n {\n items.push(talentItem.toObject());\n }\n else\n {\n ui.notifications.warn(`Impossible de trouver ${talent}`, {permanent : true})\n }\n}\n\nfor (let trapping of trappings)\n{\n let trappingItem = await game.wfrp4e.utility.findItem(trapping)\n if (trappingItem)\n {\n trappingItem = trappingItem.toObject()\n\n trappingItem.system.equipped.value = true;\n\n items.push(trappingItem);\n }\n else\n {\n ui.notifications.warn(`Impossible de trouver ${trapping}`, {permanent : true})\n }\n}\n\n\nawait this.actor.update(updateObj)\nthis.actor.createEmbeddedDocuments(",
|
||||
"<p>\n Select your choice\n </p>\n <ol>\n <li>Melee (Basic)</li>\n <li>Melee (Two-Handed)</li>\n </ol>": "<p>\n Sélectionner your choice\n </p>\n <ol>\n <li>Melee (Basic)</li>\n <li>Melee (Two-Handed)</li>\n </ol>",
|
||||
"Choose Qualities to add": "Choisir Qualities to add",
|
||||
"Choose Flaws to remove": "Choisir Flaws to remove",
|
||||
", {skipTargets: true, appendTitle : ` - ${this.effect.name}`})\nawait test.roll();\n\n\nlet opposedResult = test.opposedMessages[0]?.system.opposedHandler?.resultMessage?.system.opposedTest?.result\n\nif (opposedResult?.winner ==": ", {skipTargets: true, appendTitle : ` - ${this.effet.name}`})\nawait Test.roll();\n\n\nlet opposedResult = Test.opposedMessages[0]?.system.opposedHandler?.resultMessage?.system.opposedTest?.result\n\nif (opposedResult?.winner ==",
|
||||
"})\nawait test.roll();\n\n\nlet opposedResult = test.opposedMessages[0]?.system.opposedHandler?.resultMessage?.system.opposedTest?.result\n\nif (opposedResult?.winner == \"attacker\")\n{\n let spells = this.actor.itemTypes.spell;\n if (spells.length)\n {\n let chosen = spells[Math.floor(CONFIG.Dice.randomUniform() * spells.length)]\n this.script.message(": "})\nawait Test.roll();\n\n\nlet opposedResult = Test.opposedMessages[0]?.system.opposedHandler?.resultMessage?.system.opposedTest?.result\n\nif (opposedResult?.winner == \"attacker\")\n{\n let spells = this.actor.itemTypes.spell;\n if (spells.length)\n {\n let chosen = spells[Math.floor(CONFIG.Dice.randomUniform() * spells.length)]\n this.script.message(",
|
||||
"<p>Damage all Items carried?</p>": "<p>Damage tout Items carried?</p>",
|
||||
"Choose Optional Traits": "Choisir Optional Traits",
|
||||
"You must target exactly one Boat.": "You Doit target exactly one Boat.",
|
||||
": []});\n msg += `<p>${item.name} loses all Qualities</p>`\n }\n else \n {\n msg += `<p>${item.name} crumbles into dust!</p>` \n await item.update({name : item.name +": ": []});\n msg += `<p>${item.name} loses tout Qualities</p>`\n }\n else \n {\n msg += `<p>${item.name} crumbles into dust!</p>` \n await item.update({name : item.name +",
|
||||
"}});\nawait test.roll();\nCorruptionMessageModel.createCorruptionMessage(": "}});\nawait Test.roll();\nCorruptionMessageModel.createCorruptionMessage(",
|
||||
", this.script.getChatData())\n\nif (test.failed)\n{\n this.actor.addCondition(": ", this.script.getChatData())\n\nif (Test.Échoué)\n{\n this.actor.addCondition(",
|
||||
")\n\nlet value = hitloc.result\nlet desc = hitloc.description\n\nthis.effect.updateSource({": ")\n\nlet value = hitloc.result\nlet desc = hitloc.description\n\nthis.effet.updateSource({",
|
||||
"EFFECT.CreatureBackInWater": "Effet.CreatureBackInWater",
|
||||
"EFFECT.CreatureOutOfWater": "Effet.CreatureOutOfWater",
|
||||
": 5\n }\n let items = []\n\n let updateObj = this.actor.toObject();\n\n let talents = (await Promise.all([game.wfrp4e.tables.rollTable(": ": 5\n }\n let items = []\n\n let updateObj = this.actor.toObject();\n\n let talents = (await Promise.tout([game.wfrp4e.tables.rollTable(",
|
||||
";\nconst test = 'Métier (Charpentier)';\nconst difficulty = 'challenging';\nconst target = 40;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Métier (Charpentier)';\nconst difficulty = 'challenging';\nconst target = 40;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
"}\n});\n\nawait test.roll();\n\nif (test.failed) {\n args.actor.addCondition(\"poisoned\");\n const speaker = ChatMessage.getSpeaker({actor: args.actor});\n this.script.message(": "}\n});\n\nawait Test.roll();\n\nif (Test.Échoué) {\n args.actor.addCondition(\"poisoned\");\n const speaker = ChatMessage.getSpeaker({actor: args.actor});\n this.script.message(",
|
||||
")})\n if (args.test.failed && this.actor.type ==": ")})\n if (args.Test.Échoué && this.actor.type ==",
|
||||
"Set Liquid Fortification effect duration to 1 hour.": "Set Liquid Fortification effet duration to 1 hour.",
|
||||
"Reset Liquid Fortification effect duration to 1 hour.": "Reset Liquid Fortification effet duration to 1 hour.",
|
||||
"Choose Symptoms": "Choisir Symptoms",
|
||||
"&& args.test.failed && args.test.result.SL <= -3)\n{\n this.script.notification(": "&& args.Test.Échoué && args.Test.result.SL <= -3)\n{\n this.script.notification(",
|
||||
", {skipTargets: true, appendTitle : ` - ${this.effect.name}`})\nawait test.roll();\nif (test.succeeded)\n{\n this.script.message(": ", {skipTargets: true, appendTitle : ` - ${this.effet.name}`})\nawait Test.roll();\nif (Test.succeeded)\n{\n this.script.message(",
|
||||
"This Actor does not know any runes.": "This Actor does not know tout runes.",
|
||||
") return;\n\nconst SL = args.opposedTest.data.opposeResult.differenceSL;\n\nconst targetId = this.effect.getFlag(": ") return;\n\nconst SL = args.opposedTest.data.opposeResult.differenceSL;\n\nconst targetId = this.effet.getFlag(",
|
||||
");\n return await this.effect.delete();\n}\n\nif (SL > 0) {\n args.opposedTest.data.opposeResult.other.push(": ");\n return await this.effet.delete();\n}\n\nif (SL > 0) {\n args.opposedTest.data.opposeResult.other.push(",
|
||||
";\nconst test = 'Métier (Charpentier)';\nconst difficulty = 'difficult';\nconst target = 20;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Métier (Charpentier)';\nconst difficulty = 'difficult';\nconst target = 20;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
"All Effects have been used. Reset to select them again": "Tout Effects have been used. Reset to Sélectionner them again",
|
||||
"Choose Power to Gain": "Choisir Power to Gain",
|
||||
";\nconst test = 'Trade (Carpentry)';\nconst difficulty = 'easy';\nconst target = 20;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Trade (Carpentry)';\nconst difficulty = 'easy';\nconst target = 20;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
";\nconst test = 'Voile';\nconst difficulty = 'easy';\nconst target = 10;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Voile';\nconst difficulty = 'easy';\nconst target = 10;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
";\nconst test = 'Trade (Carpentry)';\nconst difficulty = 'hard';\nconst target = 30;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Trade (Carpentry)';\nconst difficulty = 'hard';\nconst target = 30;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
";\nconst test = 'Voile';\nconst difficulty = 'average';\nconst target = 30;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Voile';\nconst difficulty = 'average';\nconst target = 30;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
";\nconst test = 'Métier (Ingénieur)';\nconst difficulty = 'easy';\nconst target = 10;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Métier (Ingénieur)';\nconst difficulty = 'easy';\nconst target = 10;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
";\nconst test = 'Métier (Charpentier)';\nconst difficulty = 'difficult';\nconst target = 40;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Métier (Charpentier)';\nconst difficulty = 'difficult';\nconst target = 40;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
";\nconst test = 'Métier (Charpentier)';\nconst difficulty = 'hard';\nconst target = 40;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Métier (Charpentier)';\nconst difficulty = 'hard';\nconst target = 40;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
";\nconst test = 'Strength';\nconst difficulty = 'average';\nconst target = 10;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Strength';\nconst difficulty = 'average';\nconst target = 10;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
", {skipTargets: true, appendTitle : ` - ${this.effect.name}`, context: { failure:": ", {skipTargets: true, appendTitle : ` - ${this.effet.name}`, context: { failure:",
|
||||
"}\n});\n\nawait test.roll();\n\nif (test.failed) {\n const SL = Number(test.result.SL);\n this.script.message(": "}\n});\n\nawait Test.roll();\n\nif (Test.Échoué) {\n const SL = Number(Test.result.SL);\n this.script.message(",
|
||||
": locations})\nthis.effect.updateSource({": ": locations})\nthis.effet.updateSource({",
|
||||
";\nconst test = 'Métier (Charpentier)';\nconst difficulty = 'challenging';\nconst target = 10;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Métier (Charpentier)';\nconst difficulty = 'challenging';\nconst target = 10;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
"s name\nawait effect.update({\n name,\n \"system.scriptData\": scriptData\n});\n\n\n// update Trait": "s name\nawait effet.update({\n name,\n \"system.scriptData\": scriptData\n});\n\n\n// update Trait",
|
||||
";\nconst test = 'Trade (Tailor)';\nconst difficulty = 'difficult';\nconst target = 40;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Trade (Tailor)';\nconst difficulty = 'difficult';\nconst target = 40;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
"]\n }\n]\n\nlet arcane = await ItemDialog.createFromFilters(filters, 12, {title : this.effect.name, text :": "]\n }\n]\n\nlet arcane = await ItemDialog.createFromFilters(filters, 12, {title : this.effet.name, text :",
|
||||
";\nconst test = 'Trade (Carpentry)';\nconst difficulty = 'easy';\nconst target = 10;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Trade (Carpentry)';\nconst difficulty = 'easy';\nconst target = 10;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
";\nconst test = 'Trade (Carpentry)';\nconst difficulty = 'difficult';\nconst target = 30;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Trade (Carpentry)';\nconst difficulty = 'difficult';\nconst target = 30;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
"}})\nawait test.roll();\n\nif (!test.succeeded)\n{\n\tthis.actor.addCondition(": "}})\nawait Test.roll();\n\nif (!Test.succeeded)\n{\n\tthis.actor.addCondition(",
|
||||
"}});\nawait test.roll();\n\nif (test.failed)\n{\n await this.actor.addCondition(": "}});\nawait Test.roll();\n\nif (Test.Échoué)\n{\n await this.actor.addCondition(",
|
||||
";\nconst test = 'Strength';\nconst difficulty = 'easy';\nconst target = 10;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Strength';\nconst difficulty = 'easy';\nconst target = 10;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
"; // Put path to token image here, inbetween the quotation marks\nif (tokenImg)\n{\n if (this.effect.getFlag(": "; // Put path to token image here, inbetween the quotation marks\nif (tokenImg)\n{\n if (this.effet.getFlag(",
|
||||
";\n\t\t\targs.test.result.description =": ";\n\t\t\targs.Test.result.description =",
|
||||
"}\n\t\targs.test.result.outcome =": "}\n\t\targs.Test.result.outcome =",
|
||||
"Failed Trade (Engineering)": "Échoué Trade (Engineering)",
|
||||
";\nconst test = 'Trade (Tailor)';\nconst difficulty = 'easy';\nconst target = 20;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Trade (Tailor)';\nconst difficulty = 'easy';\nconst target = 20;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
") \n{\n if (args.test.failed)\n {\n let item = await fromUuid(": ") \n{\n if (args.Test.Échoué)\n {\n let item = await fromUuid(",
|
||||
";\nconst test = 'Trade (Carpentry)';\nconst difficulty = 'challenging';\nconst target = 20;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Trade (Carpentry)';\nconst difficulty = 'challenging';\nconst target = 20;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
";\nconst test = 'Métier (Charpentier)';\nconst difficulty = 'difficult';\nconst target = 50;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Métier (Charpentier)';\nconst difficulty = 'difficult';\nconst target = 50;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
") \n{\n if (args.test.failed)\n {\n this.actor.createEmbeddedDocuments(": ") \n{\n if (args.Test.Échoué)\n {\n this.actor.createEmbeddedDocuments(",
|
||||
"]])\n this.script.message(`Willpower Test failed, <b>${this.actor.prototypeToken.name}</b> gains @Condition[Malaise] for [[1d10]] hours`, {whisper: ChatMessage.getWhisperRecipients(": "]])\n this.script.message(`Willpower Test Échoué, <b>${this.actor.prototypeToken.name}</b> gains @Condition[Malaise] for [[1d10]] hours`, {whisper: ChatMessage.getWhisperRecipients(",
|
||||
"}\n \n args.test.result.other.push (": "}\n \n args.Test.result.other.push (",
|
||||
";\nconst test = 'Trade (Tailor)';\nconst difficulty = 'easy';\nconst target = 30;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Trade (Tailor)';\nconst difficulty = 'easy';\nconst target = 30;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
").map(i => `max(0, 1d10 - ${this.actor.system.characteristics.fel.bonus})`)\n\nlet test = new Roll(`${rolls.join(": ").map(i => `max(0, 1d10 - ${this.actor.system.characteristics.fel.bonus})`)\n\nlet Test = new Roll(`${rolls.join(",
|
||||
")\n\nlet test = new Roll(": ")\n\nlet Test = new Roll(",
|
||||
", {skipTargets: true, appendTitle : ` - ${this.effect.name}`, fields: { difficulty:": ", {skipTargets: true, appendTitle : ` - ${this.effet.name}`, fields: { difficulty:",
|
||||
"} }).then(async test => {\n await test.roll();\n if (test.failed) \n {\n await args.actor.addCondition(": "} }).then(async Test => {\n await Test.roll();\n if (Test.Échoué) \n {\n await args.actor.addCondition(",
|
||||
"}})\nawait test.roll();\nif (test.failed)\n{\n let roll = await new Roll(": "}})\nawait Test.roll();\nif (Test.Échoué)\n{\n let roll = await new Roll(",
|
||||
";\nconst test = 'Métier (Charpentier)';\nconst difficulty = 'challenging';\nconst target = 20;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Métier (Charpentier)';\nconst difficulty = 'challenging';\nconst target = 20;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
"<p>Does the vessel have a magazine or any other kind of store for blackpowder?</p>": "<p>Does the vessel have a magazine or tout other kind of store for blackpowder?</p>",
|
||||
";\nconst test = 'Voile';\nconst difficulty = 'challenging';\nconst target = 40;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Voile';\nconst difficulty = 'challenging';\nconst target = 40;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
";\nconst test = 'Métier (Charpentier)';\nconst difficulty = 'easy';\nconst target = 40;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n test: {\n value: test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:": ";\nconst Test = 'Métier (Charpentier)';\nconst difficulty = 'easy';\nconst target = 40;\n\nconst extendedTestData = {\n name: this.item.name,\n type: \"extendedTest\",\n img: this.item.img,\n system: {\n SL: {\n current: 0,\n target: target\n },\n Test: {\n value: Test\n },\n completion: {\n value: \"remove\"\n },\n difficulty: {\n value: difficulty\n }\n },\n effects: [\n {\n name:",
|
||||
"this.script.message(msg)\n\nlet test = await this.actor.setupSkill(\"Résistance\", {fields : {difficulty : \"difficult\"}, appendTitle :": "this.script.message(msg)\n\nlet Test = await this.actor.setupSkill(\"Résistance\", {fields : {difficulty : \"difficult\"}, appendTitle :",
|
||||
"Choose Location": "Choisir Location",
|
||||
"Hatred (All enemies)": "Hatred (Tout enemies)",
|
||||
", {skipTargets: true, appendTitle : ` - ${this.effect.name}`});\nawait test.roll();\nif (test.failed)\n{\n this.actor.addCondition(": ", {skipTargets: true, appendTitle : ` - ${this.effet.name}`});\nawait Test.roll();\nif (Test.Échoué)\n{\n this.actor.addCondition(",
|
||||
")\n this.actor.modifyWounds(-1 * value)\n await this.item.system.toggleEquip();\n args.test.addSL(value);\n args.test.preData.other.push(": ")\n this.actor.modifyWounds(-1 * value)\n await this.item.system.toggleEquip();\n args.Test.addSL(value);\n args.Test.preData.other.push(",
|
||||
"<p>This Talent also extends to any metal object because of <strong>Metallic Affinity</strong></p>": "<p>This Talent also extends to tout metal object because of <strong>Metallic Affinity</strong></p>",
|
||||
"Halve Damage? (Halves all damage other than fire, cold, and magic)": "Halve Damage? (Halves tout damage other than fire, cold, and magic)",
|
||||
"Choose Limb": "Choisir Limb",
|
||||
"Effect Used": "Effet Used",
|
||||
"must make a <b>Willpower</b> Test or fall @Condition[Prone].": "Doit make a <b>Willpower</b> Test or fall @Condition[Prone].",
|
||||
"Cannot remove Blinded condition.": "Impossible de remove Blinded condition.",
|
||||
"Removed Fatigued": "Retiré Fatigued",
|
||||
"})\nawait test.roll();\n\nif (test.failed) {\n \tthis.script.scriptMessage(await this.actor.applyBasicDamage(20, {suppressMsg: true}));\n this.script.scriptMessage(": "})\nawait Test.roll();\n\nif (Test.Échoué) {\n \tthis.script.scriptMessage(await this.actor.applyBasicDamage(20, {suppressMsg: true}));\n this.script.scriptMessage(",
|
||||
"Cannot move or act this Turn": "Impossible de move or act this Turn",
|
||||
"Select Wind": "Sélectionner Wind",
|
||||
")\n bleeding.delete(); \n}\nelse \n{\n this.script.notification(": ")\n Saignement.delete(); \n}\nelse \n{\n this.script.notification(",
|
||||
"Choose a Skill": "Choisir a Compétence",
|
||||
") \n{\n if (args.test.failed)\n {\n this.actor.addSystemEffect(": ") \n{\n if (args.Test.Échoué)\n {\n this.actor.addSystemEffect(",
|
||||
",\n}\n\nlet test = await args.actor.setupSkill(": ",\n}\n\nlet Test = await args.actor.setupSkill(",
|
||||
"Cannot be Surprised": "Impossible de be Surprised",
|
||||
", {skipTargets: true, appendTitle : ` - ${this.effect.name}`})\nawait test.roll();\nif (test.failed)\n{\n this.script.message(await game.wfrp4e.tables.formatChatRoll(": ", {skipTargets: true, appendTitle : ` - ${this.effet.name}`})\nawait Test.roll();\nif (Test.Échoué)\n{\n this.script.message(await game.wfrp4e.tables.formatChatRoll(",
|
||||
"}, skipTargets: true, appendTitle : ` - ${this.effect.name}`})\nawait test.roll();\nif (test.failed)\n{\n\tlet stuns = Math.max(1, Math.abs(test.result.SL))\n\tthis.actor.addCondition(": "}, skipTargets: true, appendTitle : ` - ${this.effet.name}`})\nawait Test.roll();\nif (Test.Échoué)\n{\n\tlet stuns = Math.max(1, Math.abs(Test.result.SL))\n\tthis.actor.addCondition(",
|
||||
")\n}\nelse \n{\n\tlet points = this.effect.sourceTest.result.overcast.usage.other.current;\n\tthis.actor.update({\"system.status.corruption.value\" : this.actor.system.status.corruption.value - points})\n\tthis.script.message(": ")\n}\nelse \n{\n\tlet points = this.effet.sourceTest.result.overcast.usage.other.current;\n\tthis.actor.update({\"system.status.corruption.value\" : this.actor.system.status.corruption.value - points})\n\tthis.script.message(",
|
||||
"})\nawait test.roll();\nif (test.failed)\n{\n\n let myRoll = await new Roll(\"1d10\").roll({allowInteractive : false});\n let duration = myRoll.total\n this.actor.addSystemEffect(\"nausea\");\n this.script.scriptMessage(": "})\nawait Test.roll();\nif (Test.Échoué)\n{\n\n let myRoll = await new Roll(\"1d10\").roll({allowInteractive : false});\n let duration = myRoll.total\n this.actor.addSystemEffect(\"nausea\");\n this.script.scriptMessage(",
|
||||
"Choose the Critical Wounds to heal (cannot reattach body parts)": "Choisir the Critique Blessures to heal (Impossible de reattach body parts)",
|
||||
"Choose Taille": "Choisir Taille",
|
||||
"Cannot attack targets that are not Entangled": "Impossible de attack targets that are not Entangled",
|
||||
").pop())\n\n if (ones == 0) {\n ones = 10;\n }\n\n if (ones > SL) {\n args.test.data.result.SL =": ").pop())\n\n if (ones == 0) {\n ones = 10;\n }\n\n if (ones > SL) {\n args.Test.data.result.SL =",
|
||||
"Gained 2 Bleeding Conditions": "Gained 2 Saignement Conditions",
|
||||
"Choose a Disease": "Choisir a Disease",
|
||||
"});\nawait test.roll();\nif (test.failed)\n{\n\tawait this.actor.addCondition(\"blinded\");\n}\n\nlet msg =": "});\nawait Test.roll();\nif (Test.Échoué)\n{\n\tawait this.actor.addCondition(\"blinded\");\n}\n\nlet msg =",
|
||||
")\n }\n else if (this.actor.characteristics.int.bonus + Number(args.test.result.SL) < 0)\n {\n args.test.result.other.push(": ")\n }\n else if (this.actor.characteristics.int.bonus + Number(args.Test.result.SL) < 0)\n {\n args.Test.result.other.push(",
|
||||
"});\nawait test.roll();\n\nif (test.failed) {\n this.actor.addCondition('stunned');\n}\n\nthis.script.scriptNotification(": "});\nawait Test.roll();\n\nif (Test.Échoué) {\n this.actor.addCondition('stunned');\n}\n\nthis.script.scriptNotification(",
|
||||
"Added Fatigued": "Ajouté Fatigued",
|
||||
"t use this.effect because it thinks it": "t use this.effet because it thinks it",
|
||||
"Halve Damage? (Halves Damage from all fire)": "Halve Damage? (Halves Damage from tout fire)",
|
||||
"Can only be applied to River Troll.": "Can only be Appliqué to River Troll.",
|
||||
"+ parseInt(this.effect.sourceTest.result.SL)": "+ parseInt(this.effet.sourceTest.result.SL)",
|
||||
")\nthis.item.setFlag(\"wfrp4e\", \"uses\", uses);\nif (uses >= 3)\n{\n\tthis.effect.update({\"system.transferData.type\" : \"other\"})\n\tthis.script.notification(": ")\nthis.item.setFlag(\"wfrp4e\", \"uses\", uses);\nif (uses >= 3)\n{\n\tthis.effet.update({\"system.transferData.type\" : \"other\"})\n\tthis.script.notification(",
|
||||
"Wounds Healed": "Blessures Healed",
|
||||
"Choose a Weapon": "Choisir a Weapon",
|
||||
"ambre\";\n amberTalons.img = this.effect.img;\n amberTalons.system.damage.value = \"SB + WPB\"\n amberTalons.system.equipped = true;\n amberTalons.system.qualities.value.push({name : \"magical\"})\n amberTalons.effects.push({\n name : \"Serres d": "ambre\";\n amberTalons.img = this.effet.img;\n amberTalons.system.damage.value = \"SB + WPB\"\n amberTalons.system.equipped = true;\n amberTalons.system.qualities.value.push({name : \"magical\"})\n amberTalons.effects.push({\n name : \"Serres d",
|
||||
")\n args.test.preData.reversal = {allowed: true, if:": ")\n args.Test.preData.reversal = {allowed: true, if:",
|
||||
", {skipTargets: true, appendTitle : ` - ${this.effect.name}`, fields : {difficulty :": ", {skipTargets: true, appendTitle : ` - ${this.effet.name}`, fields : {difficulty :",
|
||||
"}});\nawait test.roll();\nif (test.failed)\n{\n\tawait this.actor.addCondition(\"blinded\");\n}\n\nlet msg =": "}});\nawait Test.roll();\nif (Test.Échoué)\n{\n\tawait this.actor.addCondition(\"blinded\");\n}\n\nlet msg =",
|
||||
"Can roll on the @Table[crithead]{Head Critical Hits} instead of the normal hit location": "Can roll on the @Table[crithead]{Head Critique Hits} instead of the normal hit location",
|
||||
"hast)\",\n diff : {\n system : {\n advances : {\n value : 20\n }\n }\n }\n }\n]\n\nlet choice3 = [\n {\n type : \"skill\",\n name : \"Mêlée (Deux mains)\",\n diff : {\n system : {\n advances : {\n value : 20\n }\n }\n }\n }\n]\n\nlet choice = await foundry.applications.api.DialogV2.wait({\n window : {title : \"Choix\"},\n content :\n `<p>\n Sélectionnez votre choix\n </p>\n <ol>\n <li>Mêlée (Base)</li>\n <li>Mêlée (Arme d": "hast)\",\n diff : {\n system : {\n advances : {\n value : 20\n }\n }\n }\n }\n]\n\nlet choice3 = [\n {\n type : \"Compétence\",\n name : \"Mêlée (Deux mains)\",\n diff : {\n system : {\n advances : {\n value : 20\n }\n }\n }\n }\n]\n\nlet choice = await foundry.applications.api.DialogV2.wait({\n window : {title : \"Choix\"},\n content :\n `<p>\n Sélectionnez votre choix\n </p>\n <ol>\n <li>Mêlée (Base)</li>\n <li>Mêlée (Arme d",
|
||||
"<b>Rune of Goblin Bane</b>: Impact Added": "<b>Rune of Goblin Bane</b>: Impact Ajouté",
|
||||
"Enter Grim value": "Entrer Grim value",
|
||||
", {skipTargets: true, appendTitle : ` - ${this.effect.name}`})\nawait test.roll();\n\n// Kind of insane but whatever\nlet opposedResult = test.opposedMessages[0]?.system.opposedHandler?.resultMessage?.system.opposedTest?.result\n\nreturn opposedResult?.winner ==": ", {skipTargets: true, appendTitle : ` - ${this.effet.name}`})\nawait Test.roll();\n\n// Kind of insane but whatever\nlet opposedResult = Test.opposedMessages[0]?.system.opposedHandler?.resultMessage?.system.opposedTest?.result\n\nreturn opposedResult?.winner ==",
|
||||
"Cannot suffer Critical Wounds": "Impossible de suffer Critique Blessures",
|
||||
"Rolled and applied mutations": "Rolled and Appliqué mutations",
|
||||
")\n }\n else if (this.actor.characteristics.int.bonus + Number(args.test.result.SL) < 0)\n {\n args.test.result.other.push(": ")\n }\n else if (this.actor.characteristics.int.bonus + Number(args.Test.result.SL) < 0)\n {\n args.Test.result.other.push(",
|
||||
").pop())\n\n if (ones > SL) {\n args.test.data.result.SL =": ").pop())\n\n if (ones > SL) {\n args.Test.data.result.SL =",
|
||||
"Cannot be surprised": "Impossible de be surprised",
|
||||
"Removed 1 Bleeding Condition": "Retiré 1 Saignement Condition",
|
||||
"}, skipTargets: true, appendTitle : \" - \" + this.effect.name, fields : {difficulty : \"average\"}})\nawait test.roll();\n\n\nif (location && test.failed)\n{\n let dropped = this.item.system.weaponsAtLocation;\n\n if (dropped.length)\n {\n this.script.notification(": "}, skipTargets: true, appendTitle : \" - \" + this.effet.name, fields : {difficulty : \"average\"}})\nawait Test.roll();\n\n\nif (location && Test.Échoué)\n{\n let dropped = this.item.system.weaponsAtLocation;\n\n if (dropped.length)\n {\n this.script.notification(",
|
||||
").pop())\n\n if (ones == 0) {\n ones = 10;\n }\n\n\n if (ones > SL) {\n args.test.data.result.SL =": ").pop())\n\n if (ones == 0) {\n ones = 10;\n }\n\n\n if (ones > SL) {\n args.Test.data.result.SL =",
|
||||
", fields : {difficulty : \"difficult\", slBonus : -1 * this.effect.sourceTest.result.SL}})\nawait test.roll();\nif (test.succeeded)\n{\n\tthis.script.notification(": ", fields : {difficulty : \"difficult\", slBonus : -1 * this.effet.sourceTest.result.SL}})\nawait Test.roll();\nif (Test.succeeded)\n{\n\tthis.script.notification(",
|
||||
"Target has higher Willpower, no effect": "Target has higher Willpower, no effet",
|
||||
"Choose a disease to heal (must be naturally occuring)": "Choisir a disease to heal (Doit be naturally occuring)",
|
||||
"|| this.item.getFlag(": "|| this.item.getFlag(",
|
||||
"Removed Broken": "Condition Brisé supprimée",
|
||||
"Does not need to make Peur or Terror tests": "N'a pas besoin de faire de tests de Peur ou de Terreur",
|
||||
",\"info\")\n}\n\nconst runesOfRestoration = this.item.effects.contents.filter(e => e.name == this.effect.name)\nconst restorationWounds = parseInt(runesOfRestoration.length * this.actor.system.characteristics.t.bonus)\n\nthis.actor.modifyWounds(restorationWounds)\nthis.script.message(": ",\"info\")\n}\n\nconst runesOfRestoration = this.item.effects.contents.filter(e => e.name == this.effet.name)\nconst restorationWounds = parseInt(runesOfRestoration.length * this.actor.system.characteristics.t.bonus)\n\nthis.actor.modifyWounds(restorationWounds)\nthis.script.message(",
|
||||
"Automatically passes any": "Réussit automatiquement tout"
|
||||
}
|
||||
2675
tools/english-texts-found.json
Normal file
2675
tools/english-texts-found.json
Normal file
File diff suppressed because it is too large
Load Diff
216
tools/extract-translations.js
Normal file
216
tools/extract-translations.js
Normal file
@@ -0,0 +1,216 @@
|
||||
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));
|
||||
216
tools/find-english-texts.js
Normal file
216
tools/find-english-texts.js
Normal file
@@ -0,0 +1,216 @@
|
||||
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`);
|
||||
103
tools/generate-review-report.js
Normal file
103
tools/generate-review-report.js
Normal file
@@ -0,0 +1,103 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const WFRP4E_SCRIPTS = '/home/morr/work/foundryvtt/WFRP4e-FoundryVTT/scripts';
|
||||
const FR_SCRIPTS = '/home/morr/work/foundryvtt/foundryvtt-wh4-lang-fr-fr/scripts';
|
||||
const REVIEW_FILE = path.join(__dirname, 'scripts-to-review.json');
|
||||
const REPORT_FILE = path.join(__dirname, 'review-comparison.md');
|
||||
|
||||
const scriptsToReview = JSON.parse(fs.readFileSync(REVIEW_FILE, 'utf-8'));
|
||||
|
||||
let report = `# Scripts nécessitant révision manuelle\n\n`;
|
||||
report += `Total de scripts: ${scriptsToReview.length}\n\n`;
|
||||
report += `Ces scripts contiennent des traductions en français mais ont été modifiés dans WFRP4E.\n`;
|
||||
report += `Ils nécessitent une révision manuelle pour intégrer les changements tout en préservant les traductions.\n\n`;
|
||||
report += `---\n\n`;
|
||||
|
||||
scriptsToReview.forEach(({file}, index) => {
|
||||
const wfrp4ePath = path.join(WFRP4E_SCRIPTS, file);
|
||||
const frPath = path.join(FR_SCRIPTS, file);
|
||||
|
||||
const wfrp4eContent = fs.readFileSync(wfrp4ePath, 'utf-8');
|
||||
const frContent = fs.readFileSync(frPath, 'utf-8');
|
||||
|
||||
report += `## ${index + 1}. ${file}\n\n`;
|
||||
|
||||
// Extraire les différences notables
|
||||
const wfrp4eLines = wfrp4eContent.split('\n').length;
|
||||
const frLines = frContent.split('\n').length;
|
||||
|
||||
report += `- **Lignes WFRP4E**: ${wfrp4eLines}\n`;
|
||||
report += `- **Lignes FR**: ${frLines}\n`;
|
||||
report += `- **Différence**: ${wfrp4eLines - frLines} lignes\n\n`;
|
||||
|
||||
// Extraire les textes notables
|
||||
const wfrp4eTexts = extractNotableTexts(wfrp4eContent);
|
||||
const frTexts = extractNotableTexts(frContent);
|
||||
|
||||
if (wfrp4eTexts.length > 0 || frTexts.length > 0) {
|
||||
report += `### Textes identifiés\n\n`;
|
||||
|
||||
if (wfrp4eTexts.length > 0) {
|
||||
report += `**WFRP4E (anglais)**:\n`;
|
||||
wfrp4eTexts.forEach(text => {
|
||||
report += `- \`${text}\`\n`;
|
||||
});
|
||||
report += `\n`;
|
||||
}
|
||||
|
||||
if (frTexts.length > 0) {
|
||||
report += `**FR (français)**:\n`;
|
||||
frTexts.forEach(text => {
|
||||
report += `- \`${text}\`\n`;
|
||||
});
|
||||
report += `\n`;
|
||||
}
|
||||
}
|
||||
|
||||
// Afficher le code côte à côte si court
|
||||
if (wfrp4eLines < 30 && frLines < 30) {
|
||||
report += `### Code WFRP4E\n\n\`\`\`javascript\n${wfrp4eContent}\n\`\`\`\n\n`;
|
||||
report += `### Code FR\n\n\`\`\`javascript\n${frContent}\n\`\`\`\n\n`;
|
||||
}
|
||||
|
||||
report += `### Actions recommandées\n\n`;
|
||||
report += `- [ ] Vérifier les changements structurels dans WFRP4E\n`;
|
||||
report += `- [ ] Intégrer les modifications tout en gardant les traductions FR\n`;
|
||||
report += `- [ ] Tester le script après modification\n\n`;
|
||||
report += `---\n\n`;
|
||||
});
|
||||
|
||||
function extractNotableTexts(content) {
|
||||
const texts = new Set();
|
||||
|
||||
// Patterns pour extraire les textes
|
||||
const patterns = [
|
||||
/ui\.notifications\.(info|warn|error|notify)\s*\(\s*["'`]([^"'`]+)["'`]/g,
|
||||
/this\.script\.(scriptNotification|scriptMessage|notification)\s*\(\s*["'`]([^"'`]+)["'`]/g,
|
||||
/["'`](Loading|Could not find|Chargement|Impossible de trouver|créé|modifié|supprimé)[^"'`]*["'`]/gi
|
||||
];
|
||||
|
||||
patterns.forEach(pattern => {
|
||||
const matches = content.matchAll(pattern);
|
||||
for (const match of matches) {
|
||||
const text = match[2] || match[1];
|
||||
if (text && text.length > 3 && text.length < 100) {
|
||||
texts.add(text);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Array.from(texts);
|
||||
}
|
||||
|
||||
fs.writeFileSync(REPORT_FILE, report, 'utf-8');
|
||||
|
||||
console.log(`\nRapport de révision généré: ${REPORT_FILE}`);
|
||||
console.log(`\nNombre de scripts à réviser: ${scriptsToReview.length}`);
|
||||
console.log(`\nOuvrez le fichier avec votre éditeur préféré pour réviser les scripts.`);
|
||||
console.log(`Vous pouvez aussi utiliser un outil de diff comme 'meld' ou 'kdiff3' pour comparer:`);
|
||||
console.log(`\nExemple:`);
|
||||
console.log(` meld ${FR_SCRIPTS}/${scriptsToReview[0].file} ${WFRP4E_SCRIPTS}/${scriptsToReview[0].file}`);
|
||||
193
tools/generate-translation-report.js
Normal file
193
tools/generate-translation-report.js
Normal file
@@ -0,0 +1,193 @@
|
||||
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)');
|
||||
154
tools/replace-review-scripts.js
Normal file
154
tools/replace-review-scripts.js
Normal file
@@ -0,0 +1,154 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const WFRP4E_SCRIPTS = '/home/morr/work/foundryvtt/WFRP4e-FoundryVTT/scripts';
|
||||
const FR_SCRIPTS = '/home/morr/work/foundryvtt/foundryvtt-wh4-lang-fr-fr/scripts';
|
||||
const REVIEW_FILE = path.join(__dirname, 'scripts-to-review.json');
|
||||
const OUTPUT_FILE = path.join(__dirname, 'scripts-replaced-list.md');
|
||||
|
||||
const scriptsToReview = JSON.parse(fs.readFileSync(REVIEW_FILE, 'utf-8'));
|
||||
|
||||
console.log(`\n=== REMPLACEMENT DES SCRIPTS PAR LES VERSIONS SYSTÈME ===\n`);
|
||||
console.log(`Nombre de scripts à remplacer: ${scriptsToReview.length}\n`);
|
||||
|
||||
let replaced = 0;
|
||||
let errors = [];
|
||||
const replacedList = [];
|
||||
|
||||
scriptsToReview.forEach(({file, reason}, index) => {
|
||||
const wfrp4ePath = path.join(WFRP4E_SCRIPTS, file);
|
||||
const frPath = path.join(FR_SCRIPTS, file);
|
||||
const backupPath = frPath + '.fr-backup';
|
||||
|
||||
try {
|
||||
// Sauvegarder la version FR avec traductions
|
||||
if (fs.existsSync(frPath)) {
|
||||
fs.copyFileSync(frPath, backupPath);
|
||||
}
|
||||
|
||||
// Remplacer par la version WFRP4E
|
||||
if (fs.existsSync(wfrp4ePath)) {
|
||||
fs.copyFileSync(wfrp4ePath, frPath);
|
||||
replaced++;
|
||||
|
||||
// Extraire les textes traduits de la sauvegarde pour référence
|
||||
const frContent = fs.readFileSync(backupPath, 'utf-8');
|
||||
const translations = extractTranslations(frContent);
|
||||
|
||||
replacedList.push({
|
||||
index: index + 1,
|
||||
file,
|
||||
translations
|
||||
});
|
||||
|
||||
console.log(`✓ [${index + 1}/${scriptsToReview.length}] ${file}`);
|
||||
} else {
|
||||
errors.push(`Source non trouvée: ${file}`);
|
||||
console.log(`✗ [${index + 1}/${scriptsToReview.length}] ${file} - Source non trouvée`);
|
||||
}
|
||||
} catch (error) {
|
||||
errors.push(`${file}: ${error.message}`);
|
||||
console.log(`✗ [${index + 1}/${scriptsToReview.length}] ${file} - Erreur: ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
function extractTranslations(content) {
|
||||
const translations = [];
|
||||
|
||||
// Patterns pour extraire les textes en français
|
||||
const patterns = [
|
||||
/ui\.notifications\.(info|warn|error|notify)\s*\(\s*["'`]([^"'`]+)["'`]/g,
|
||||
/this\.script\.(scriptNotification|scriptMessage|notification)\s*\(\s*["'`]([^"'`]+)["'`]/g,
|
||||
/["'`](Chargement|Impossible|Êtes-vous|Voulez-vous|créé|modifié|supprimé|Erreur)[^"'`]*["'`]/gi,
|
||||
/warhammer\.utility\.findAllItems\([^,]+,\s*["'`]([^"'`]+)["'`]/g
|
||||
];
|
||||
|
||||
patterns.forEach(pattern => {
|
||||
const regex = new RegExp(pattern.source, pattern.flags);
|
||||
let match;
|
||||
while ((match = regex.exec(content)) !== null) {
|
||||
const text = match[2] || match[1];
|
||||
if (text && text.length > 3 && /[a-zàâäéèêëïîôöùûüÿçœæ]/i.test(text)) {
|
||||
if (!translations.includes(text)) {
|
||||
translations.push(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return translations;
|
||||
}
|
||||
|
||||
// Générer le rapport
|
||||
let report = `# Scripts remplacés par les versions système\n\n`;
|
||||
report += `Date: ${new Date().toISOString()}\n\n`;
|
||||
report += `## Résumé\n\n`;
|
||||
report += `- **Scripts remplacés**: ${replaced}\n`;
|
||||
report += `- **Erreurs**: ${errors.length}\n\n`;
|
||||
report += `Tous les scripts ont été remplacés par leurs versions du système WFRP4E.\n`;
|
||||
report += `Les versions françaises avec traductions sont sauvegardées avec l'extension \`.fr-backup\`.\n\n`;
|
||||
|
||||
if (errors.length > 0) {
|
||||
report += `## Erreurs\n\n`;
|
||||
errors.forEach(error => {
|
||||
report += `- ${error}\n`;
|
||||
});
|
||||
report += `\n`;
|
||||
}
|
||||
|
||||
report += `## Scripts à revoir manuellement\n\n`;
|
||||
report += `Pour chaque script, vous devez :\n`;
|
||||
report += `1. Comparer la version actuelle (système) avec le backup (.fr-backup)\n`;
|
||||
report += `2. Identifier les textes à traduire\n`;
|
||||
report += `3. Appliquer les traductions nécessaires\n\n`;
|
||||
|
||||
report += `| # | Fichier | Traductions trouvées |\n`;
|
||||
report += `|---|---------|----------------------|\n`;
|
||||
|
||||
replacedList.forEach(({index, file, translations}) => {
|
||||
const translationsText = translations.length > 0
|
||||
? translations.slice(0, 3).join(', ') + (translations.length > 3 ? '...' : '')
|
||||
: 'Aucune';
|
||||
report += `| ${index} | \`${file}\` | ${translationsText} |\n`;
|
||||
});
|
||||
|
||||
report += `\n## Commandes utiles\n\n`;
|
||||
report += `### Comparer un script avec son backup\n\n`;
|
||||
report += `\`\`\`bash\n`;
|
||||
report += `# Avec meld\n`;
|
||||
report += `meld scripts/<fichier> scripts/<fichier>.fr-backup\n\n`;
|
||||
report += `# Avec diff\n`;
|
||||
report += `diff -u scripts/<fichier>.fr-backup scripts/<fichier>\n`;
|
||||
report += `\`\`\`\n\n`;
|
||||
|
||||
report += `### Exemples de scripts\n\n`;
|
||||
if (replacedList.length > 0) {
|
||||
const example = replacedList[0];
|
||||
report += `Premier script: \`${example.file}\`\n\n`;
|
||||
report += `\`\`\`bash\n`;
|
||||
report += `meld scripts/${example.file} scripts/${example.file}.fr-backup\n`;
|
||||
report += `\`\`\`\n\n`;
|
||||
|
||||
if (example.translations.length > 0) {
|
||||
report += `Traductions à réappliquer:\n`;
|
||||
example.translations.forEach(t => {
|
||||
report += `- "${t}"\n`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fs.writeFileSync(OUTPUT_FILE, report, 'utf-8');
|
||||
|
||||
console.log(`\n=== RÉSUMÉ ===`);
|
||||
console.log(`Scripts remplacés: ${replaced}/${scriptsToReview.length}`);
|
||||
console.log(`Erreurs: ${errors.length}`);
|
||||
console.log(`\nBackups créés avec extension: .fr-backup`);
|
||||
console.log(`Liste détaillée: ${OUTPUT_FILE}`);
|
||||
|
||||
console.log(`\n=== PROCHAINES ÉTAPES ===`);
|
||||
console.log(`1. Consulter: ${OUTPUT_FILE}`);
|
||||
console.log(`2. Pour chaque script, comparer avec son .fr-backup`);
|
||||
console.log(`3. Réappliquer les traductions nécessaires`);
|
||||
console.log(`4. Supprimer les .fr-backup une fois terminé\n`);
|
||||
1489
tools/review-comparison.md
Normal file
1489
tools/review-comparison.md
Normal file
File diff suppressed because it is too large
Load Diff
6591
tools/script-comparison-data.json
Normal file
6591
tools/script-comparison-data.json
Normal file
File diff suppressed because it is too large
Load Diff
713
tools/script-comparison-report.md
Normal file
713
tools/script-comparison-report.md
Normal file
@@ -0,0 +1,713 @@
|
||||
# Rapport de comparaison des scripts
|
||||
|
||||
Date: 2026-01-06T18:58:40.637Z
|
||||
|
||||
## Résumé
|
||||
|
||||
- **Total de fichiers communs**: 1505
|
||||
- **Scripts identiques**: 671
|
||||
- **Scripts nécessitant mise à jour**: 473
|
||||
- **Scripts utilisant localize() (obsolètes)**: 361
|
||||
- **Scripts uniquement dans FR**: 2
|
||||
- **Scripts uniquement dans WFRP4E**: 394
|
||||
|
||||
## Scripts obsolètes (utilisant localize() dans WFRP4E)
|
||||
|
||||
Ces scripts peuvent être supprimés du module FR car le système utilise maintenant les fichiers de localisation.
|
||||
|
||||
- `0FNOq4J1AdPd2A0q.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `0YKQGbsKdHSmYGE7.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `0mrUnxzufYgsR0Ph.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `1A87vGLh2PXH0rG0.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `1LDSzXeO5CzXgTOc.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `1kB2su7hLRYDhZ2H.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `1mNkLj9JYNr3ofC6.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `1wKVvxRTHOyV4Qdv.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `22bW97lkvCqisfHX.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `23HgjCB1oecxANvA.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `2AdSBXw7IwCiqawQ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `2NLINicPQWbuvp2n.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `2VNnVrtktdGUqXEV.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `2W9uMTT6iJhfQ044.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `2WSN306tL4apjRtD.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `2hzDv8ROulOe1elK.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `2sDH6RvoOAR40oqH.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `2vTVR0quRZQtjNfQ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `3JEzEzF1SeYA9lsV.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `3hfMQkUKYI4rCuBy.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `3plV9WFqs2prfAdp.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `3sfD1nedXLzuYoXJ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `454x3Q95pLvZm0Kx.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `4FGKZk2f0xrmIDnp.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `4ZR7p8G3OzOBWx0L.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `4fnTKgl0HW9ZrWyJ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `4iuTz0uInAfMaoGl.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `4pQW4WLyhjbZR85k.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `4rb7LfMq9CTnlrpn.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `52mwb33mGrQjq89B.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `5Fe1ELaS6Gnvy0Cj.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `5o1XiceC4rutjMms.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `5sI9iYh5j2nx2XyT.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `6JrUjs3g5x6bFnj3.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `6V3qHON3mcerlBlB.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `6ZS1rQLkNvMDO0Fp.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `6fElmBxTjdAaubbK.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `6qUKKep5vhFYmo1J.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `6tjn0RH4VyOPFneS.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `715G1Bf0haOHvmYQ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `7Ck0fkzE4WQ62qVe.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `7H6wYyJ6cpaoc2QQ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `7VAhXHov6pR1SkgD.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `7e8FgQUF2oANANmx.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `7szLG4VALuuy1cPm.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `84IB8CWa55XzoAkv.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `86ivOsBQAuu0UmFg.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `8ByuHnUZ4RNTdGVv.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `8N3Uqjq1ZxPxo4pk.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `8RNziYGGb4sp3BGQ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `8ZAUBSH9CM9OTpTL.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `93K85NnVwjVNXlZq.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `9EVj4bmZJex45Mt7.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `9JnPK1jNUEso7Pv8.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `9RFoasDcFnYZ1txR.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `9fK07tqqZyPg7dpx.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `A3fvV69RS1lYgma0.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `ACgKpKrEEHoNGG0h.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `AHZ8f7dfN8jNsYk6.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `ALuPRzf85dmkEfLo.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `AMxezwtYnWCF6Oza.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `AV2Kj6jgmIc45zKi.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `B6ZbY3bxTPg6nCng.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `B950b0XnIUYCdVwu.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `BAOv7moTxsKlT3JS.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `BNJRV66jlrp51qZK.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `BtyFhdGMKiMamGhM.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `C4LZnaX0MYgwrszj.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `CCK1iIfPmB398ziT.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `CiFeduksZJ6PRulx.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `CkE8NZOhzPkuRrKJ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `DTiHS6RfwhF4THbf.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `DsE6rTSzxEn6uWMz.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `DuM5l2Yb4bdvDeaG.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `DxQnamsb2AuW0p2e.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `E4CHDe1xfmcV3oGv.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `E6DMqfDeczqmVMFV.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `E7D4bxz8gy4e1wL7.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `EDAMEOzdBfkoKHxP.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `EGWF3LHav3e2zFL4.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `EQ5dtGW5kQhtAb87.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `EU5j0hnDTG9Z6d1e.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `EVBSHEC5nmmj2X41.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `EmXwcuycEH8slEn5.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `EmmG49pMOPHRwDzR.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Ew3C2WmLCtc1KT46.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `FXuyiJoXdAh6WhRK.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `FYUPfYyTYZkxRLFT.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `FkTwk8hfHpRLbAp2.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `FmLx9pwOkzqqU7Ph.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Fvlc4RkeF4dHjW3m.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `GOq4TcnWbfyfCo2V.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `GZFsuynUhgZqwTGo.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `GbPEy22VuCNzlNv2.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Gc8S5TYlVdV8NnOT.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `H2CJvApKMnfGNNoo.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `HASsi6wYHVALExWq.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `HKhyn0kijKfzW6cw.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `HMC6hPND9DWLFfZE.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `HUKzssLxeQo1wbx9.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Hcpn1gU58DIKIhty.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `HdTuY2IGhdlMDOy3.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `HfCxNd7mFGZH4s9Y.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `HfZAQWoY8n3clLlo.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `HiMBS6GeOwEydWYN.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `HrOBAXsEX073ReKl.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `I7ieW0hNYvvX0KFg.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `I9QAPKbaXwMMMBT4.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `ID8mCcjkl7PCQhDq.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `IPPDvZdE8kn3H9z7.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `IR5URcjnCuWBFMoN.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `IsLAvY9ikR1cOJWw.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `J0IWUhxada2ONowP.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `JBoKPBr27C3PMoSD.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `JEbs0WlqhKNDOo5A.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `JQruHprM5R5vZ9DA.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `JeThJbOf6Xmbtgo1.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `JgCcgDVZX54slrWx.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `JhCMYHHYA860Kka8.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `JibNjuQrJRnY0yf9.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Jk7OHqx06oCUVAzb.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `JstrA46EYSEuRSy5.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `JyTxUG5dNW670Sf7.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `KIoVBinAZK8sMOqD.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `KPQfupKuaf4LCv4R.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `KSjsDlsx3DD6cT16.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `KTBVDHUndI3qDOXM.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `KUx0deSF3xNzMucL.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `KkjkYAGI9Em1NgiQ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `KyUPYV1RXJxPOfyA.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `L9eAtDyaoHvqryk4.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `LeKLtvEDrWh4yHsx.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Lg1oRg4oNRvucsvi.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `LjfScVGBf0Egr70E.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Lpv2N9LK9loeumiW.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Lrb1S2aK7SFVD0C7.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Lu27iXtJVkrJ8bOx.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `M0XhKnWjG14pk3iH.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `M2FshTX4PjKFVU8y.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `M9VgeYGiUO97ZUW4.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `MJB6WbZSF6Briz30.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `MMv2B8TH7jxNCtdl.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `MMx8f5uJ15XOgJGg.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `MSJWJEUrX7ZmMvAD.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Mp8UjuCLa9jdzhBS.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `N9kA46ZQ9LiRjy6T.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `NDvNGATDM2xPFJK0.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `NkqtQaLEGYst0PUO.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `NnA4zpuO6iUXKhH7.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `NnDq4miIPNEtZUWb.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Np8P8IPT2GYlrh6G.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `OeCgX3hIsfLfmGvC.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `OgSI0Z6SHjYuqKIz.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `OqLKL0PiCvYH2QxW.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `P29tT1eMMdAw3CPF.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `PMISUsaEDBA7D3od.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `PMNjdEAusVBfam09.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `PVjaKAHTKDA0rA9J.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `PdClojv7yNgQpOUc.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `PoNnT5EqvLj2r5yf.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Q4EQgP4gZR8TTm7S.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Q5gh5Y9dCdclcwsD.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Q9EmlWmuDac83cJw.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `QPVVDPcJ4Xi5FmQl.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `QQ2gHThZHdO4yLLX.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `QfTBRGXVfwQSghmd.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `RDtJXji3hgcKnEBk.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `RHyBLYT5oHf7EPnG.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `RNr9CwyvLhlnwD2h.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `RprZWlnopSqZt7KZ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `RrchOMpEdIvceJxl.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `SNjG7IvgQzvCGczR.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `SrCHfOJFZwDickqa.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `T3RfSt3VMEat3iDD.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `TOyQLrugFGzwc5nY.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `TU2xjbJ0zFtytF3J.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `TdjlJro0RRVSh8g8.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `ToKlHDAjJOsC51ag.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Tq45Nd8J3eTvHT41.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `TrIYdcG3jDER4WgY.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `TwwKxFjK6TNGKbRB.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `U4A8FDNmwBGTuQZO.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `U78c4oUjKwyUu6jT.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `U7lRf56BFaTfsC6B.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `U9xh2wriSqCosugW.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `UC6G3pFQwzUhrw6F.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `UTlgF4azrGQZsoDv.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `UaImulhbPURkLJg2.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `UsAHQecRlWL5PhP6.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `UvycHOjSPm5Zv9KJ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `VAs1nXvicdQK18Do.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `VCnNWmRBH28Rx0JH.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `VNOKTzCrFbZ6PJUj.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `VQaC6ynouW5EQCbC.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `VbL0TgaBAmYjrezZ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `VlFUDaKUYoBYKYn0.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `VlHuDIAvPr8JM1P5.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Vns6WrafVq8NjX7t.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `VqTrKPtxv9hpn0Hr.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `VurA2XNqC0d9U49C.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `VzO0ZDcTWvaBn4vm.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `WTRYAEzwxRuGENyI.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Wqff6ICWYzvLDYC8.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `XClTZOjuhcxWLF51.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Xf4FcZ4ZLdWmOXBa.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `XuFxKPYheYF4WMmQ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `YDqpKJVy8ijEKdLX.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `YEBw2CzHYxsTpTy5.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `YFSgWRXel0bWE3EE.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `YMaxpXnml01bLGpO.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `YhhiWEQbox3WZA3Q.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Z6OmmC0irJzxSnMH.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `ZLspFT2I3ZdWWr2H.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `ZNW3ubbKIYXAyE48.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `Ze9E2zR1GFGWGMVH.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `ZgF1sYdbAKaOuHmK.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `ZvbBM4gTJHPdU8jU.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `a0YU3whUm16wGBNu.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `a4Aza4a9v8JMU8dC.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `a6gacHsvgwtsIFSQ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `aAvJrAKLzXhS9qN6.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `afdmOvPGMpEdZvCb.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `b5prg1FLjCAvBjLy.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `bh2qDCKiAIWM0UPi.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `bhXUW7IJtEaUGAoV.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `bwx9wuEOJPF7btD1.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `c3KA1knL2NYNUEww.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `cAKqUBuJBsU85erO.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `cTYNaKbepMwqYsZ8.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `cV9JiAgUPOeUHKnS.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `cqYgZQk1C3kMARy5.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `dAMtbn3uQwF8KpKU.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `dSmRhZ6o1bUcOSF9.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `dXGosSxdoYbET2O8.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `dfEgat3jz4EtWszH.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `dfnCK8jCPXNLM7Gh.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `dkiNmwFXztIVbuxg.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `dsXGavzXLerXR8Xg.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `dtFvpY96RPzNnphq.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `dwSgcFxKN3S0hLJL.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `eGQAyzCFZAEQhyJl.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `f062aa2BNClx08D6.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `f3rXusHh6VIpVPUl.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `f5Mp3kXwCFdPkW6N.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `fKzlu6fFE2th9uIJ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `fP2edYbj6QjPPAjL.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `fYLSe6CrYciap5y8.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `g07HI7vyqiFXPB0o.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `gFUXBbTskQBKjxqm.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `gKPL3t4vlZAsvtGr.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `gnVpxOeBZpNF4HIF.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `gqZLfIr6svrtdwdC.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `gu72JaTs9GrSiVTd.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `h0DfPwUUOBjyAHMZ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `h1XKoMuVnS0bagRO.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `hDC6lroDEPVBituR.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `hR1qD2kpFHF8JT8h.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `hnsmzvcuiUYB065I.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `iM6JLF8jDXMViReZ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `iT0h3VZLEBQnn5Bx.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `iT3C15fMyQrj1RmG.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `jRSgPhpfN7MH7TTp.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `jgO1Kf60Ctt6R0qO.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `jpcU8FFWSlQ3gD0L.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `k3FqFgsF6a3TkxAD.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `k8TC0yzp4xfOXD2n.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `kEaBLoIHt1FpQVKq.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `kMSdRskYDI2J1gnp.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `kWynO1lQzjiSs8RK.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `kYiDBPRKIokFkr4Z.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `kYmscP2HuXjDovBD.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `kkC5EhqA05U6U0gU.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `kmsGLWGxCY8Z8jVG.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `l1ntrpa8RE3Lg5xE.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `l8qFKSnMpy4P7XQR.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `lPudo1grrVp05i7a.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `lYYkGzqNshiYc7WI.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `lhemR8EP5tGNKout.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `mTnmPcjWmvScIBWY.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `mYL4i1vNlMl4vFYy.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `mr8qm5Bg6k1idZ6Q.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `mziJBUYcsrhkdcCJ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `nD2QVg3DrPK3foMf.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `nEaF3jbCiVYD8jia.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `nIOeK0BrtdZeZW8X.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `ncIjDE6TFx88IQA1.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `nvrFhHHVq3KzirlR.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `o3JUBKLvE6bBxK2n.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `oEsUsI74yGTZ9CwU.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `oGdsGPgJWcyWkiWl.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `oWM43EdUiyHgUlfW.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `obIXhQXKFyyQoNNV.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `p222EiR8RRtlPm31.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `p7NJB1PsY6X5q8OO.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `pAgiAGyaLJY10894.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `pHyXdPnWwoFrUA5n.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `pNPjXEoQGHLKzq0r.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `pq1YQffxtOcqCRTn.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `pzknBcJtZWeliE27.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `qTk96NKh14YOIShf.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `qaVde0sTuMBRi2nl.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `qijgjcOBCDmhglRX.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `quPcuKsq2fcild4a.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `qzGPJflVW7c2Ciim.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `rXMylpnEtZpwou6x.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `red2bt4PGgIWAdTR.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `rlTvhnDpj4lzfusf.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `rnioLwiJP7ps5Jwy.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `roKvPHDSpX4IV11C.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `rr4htuVq45onXdRG.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `rxB1AqfVMDqTRieE.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `s7gJQdzuM3fz2zQK.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `sSMg43ZjnNmpytfj.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `sUHuj00IpoZ7Gd03.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `sWyO1DNaqb2EdHoW.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `sagKJM6oDFlw4ED2.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `sgS9rblPkQB36C8S.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `syBgPp7rOymCZejX.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `t56mnblo1kv3gM1M.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `tDrs0aNIYmZPsOoS.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `tG1qGqzBLmAR3WHm.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `tcZug8ehU6lyYBd9.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `tn6SwmjAuNzqE6dx.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `tnE8LF6E3svIlLca.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `tnilBagajWM8UGQt.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `tolkNN5P7oOC8GKZ.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `tuIsytv3jl2yAIb2.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `uACa6u4JLNMRgFlr.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `uSwkYENTOcnfRrqA.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `upfK6GM33qZCZjll.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `uwdQvZtzy2HVeEzx.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `ux3jaLpAUhZ5YqA6.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `v6LIG7EwWYALxCpP.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `vj3zArmX27vCxYJW.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `vvdo1NxjmGVkmFCT.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `vzMxIDjRlQSxXtCW.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `w4JKuTECFmu3YmTR.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `wS6OIR3QN4mOUHn0.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `wsqNM4NHnwaAAQym.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `wzkxiKjxVEeNS1di.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `x2RLUUNB7BiIDYCP.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `x8XK2fzzXCnSwfjt.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `xRd6oA1QWLVpfoBm.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `xS2su09zcza9du09.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `xVYVegD692CCv8Yl.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `xWPgIZOQLba5nZ23.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `xobGBJbgFjQCrwvq.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `xvH4PKJasHcehOZz.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `yIGItnshXI4W46cp.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `yRRzSKlcN3L7rEEe.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `yXUPiWuQ5o0JBY4i.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `yatUu0cd7iKs50rq.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `z5HfNUrHy5MS3K7a.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `zA6TDttpwMSMl7D8.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `zFYCaGR0wbFWjl4T.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `zLBLEDl3aGcAxai2.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `zR4WAjzXHTZuiu5G.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `zY4ZjY7uyKIKMYmX.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `ziG9H5Kdb7xC3dFE.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `zsiV6XEHlCNGLLPl.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
- `zzk2uRSFjFHB5kjw.js` - Le système utilise maintenant localize() - script FR obsolète
|
||||
|
||||
## Scripts nécessitant une mise à jour
|
||||
|
||||
### 03mJu59V4iByWlsO.js
|
||||
|
||||
- Taille WFRP4E: 1153 octets
|
||||
- Taille FR: 1201 octets
|
||||
- Textes FR: <p><strong>${this.actor.prototypeToken.name}</strong> :
|
||||
<ul>
|
||||
<li>Reçoit 3 états Empoisonnés, sans Test de Résistance possible</li>
|
||||
<li>Récupère ${this.actor.system.characteristics.t.bonus} Blessures</li>
|
||||
<li>Acuiert le Trait de Creature Régénération.</li>
|
||||
</ul>
|
||||
C
|
||||
|
||||
### 0BP5l7bIkf744G1k.js
|
||||
|
||||
- Taille WFRP4E: 70 octets
|
||||
- Taille FR: 70 octets
|
||||
|
||||
### 0FWto1oEr3jbWggw.js
|
||||
|
||||
- Taille WFRP4E: 789 octets
|
||||
- Taille FR: 766 octets
|
||||
- Textes WFRP4E: Could not find ${lore} spell. Try Again
|
||||
- Textes FR: Impossible de trouver le sort ${lore}. Essayez à nouveau
|
||||
|
||||
### 0R0QAr3D024kWPfo.js
|
||||
|
||||
- Taille WFRP4E: 552 octets
|
||||
- Taille FR: 589 octets
|
||||
- Textes WFRP4E: Mutation table not found, please ensure a table with the , Item could not be found: , ${item.name} added
|
||||
- Textes FR: La table des Mutations n, L, ${item.name} added
|
||||
|
||||
### 0Uly7OmkH0zqYbxQ.js
|
||||
|
||||
- Taille WFRP4E: 584 octets
|
||||
- Taille FR: 585 octets
|
||||
- Textes WFRP4E: Dropped ${dropped.map(i => i.name).join(
|
||||
- Textes FR: Lache ${dropped.map(i => i.name).join(
|
||||
|
||||
### 0abwNjpzo3SbEOeO.js
|
||||
|
||||
- Taille WFRP4E: 267 octets
|
||||
- Taille FR: 270 octets
|
||||
|
||||
### 0yyofYHeDRQlFliO.js
|
||||
|
||||
- Taille WFRP4E: 68 octets
|
||||
- Taille FR: 68 octets
|
||||
|
||||
### 11uCC0mK2uL783al.js
|
||||
|
||||
- Taille WFRP4E: 134 octets
|
||||
- Taille FR: 133 octets
|
||||
|
||||
### 190PHSHKGaJ74wsR.js
|
||||
|
||||
- Taille WFRP4E: 1169 octets
|
||||
- Taille FR: 1060 octets
|
||||
|
||||
### 1BT0MWM2cbhlEnrn.js
|
||||
|
||||
- Taille WFRP4E: 1169 octets
|
||||
- Taille FR: 1176 octets
|
||||
- Textes WFRP4E: Could not find ${talent}
|
||||
- Textes FR: Impossible de trouver ${talent}
|
||||
|
||||
### 1CeYp5MlPcH68UIw.js
|
||||
|
||||
- Taille WFRP4E: 2481 octets
|
||||
- Taille FR: 2498 octets
|
||||
- Textes WFRP4E: Could not find ${talent}, Could not find ${trapping}
|
||||
- Textes FR: Impossible de trouver ${talent}, Impossible de trouver ${trapping}
|
||||
|
||||
### 1JwxZujbDcueLWBL.js
|
||||
|
||||
- Taille WFRP4E: 162 octets
|
||||
- Taille FR: 168 octets
|
||||
|
||||
### 1OpT3CXs07XFWWCT.js
|
||||
|
||||
- Taille WFRP4E: 30 octets
|
||||
- Taille FR: 30 octets
|
||||
|
||||
### 1ZArMNUI8qqH6zkX.js
|
||||
|
||||
- Taille WFRP4E: 247 octets
|
||||
- Taille FR: 242 octets
|
||||
|
||||
### 1exiWlVUHsXDLLAH.js
|
||||
|
||||
- Taille WFRP4E: 62 octets
|
||||
- Taille FR: 70 octets
|
||||
- Textes WFRP4E: Cannot enter ${this.effect.name}!
|
||||
- Textes FR: Ne peut saisir ${this.effect.name}!
|
||||
|
||||
### 1fQr1Dg7DX0vfz3r.js
|
||||
|
||||
- Taille WFRP4E: 134 octets
|
||||
- Taille FR: 145 octets
|
||||
- Textes FR: Soins de ${healed} Blessures
|
||||
|
||||
### 1jQq9v8fXK8zuEBU.js
|
||||
|
||||
- Taille WFRP4E: 853 octets
|
||||
- Taille FR: 863 octets
|
||||
|
||||
### 1l7Jz2ZHbAWko7Vm.js
|
||||
|
||||
- Taille WFRP4E: 33 octets
|
||||
- Taille FR: 33 octets
|
||||
|
||||
### 1wrPvP6lJwIAfmsl.js
|
||||
|
||||
- Taille WFRP4E: 362 octets
|
||||
- Taille FR: 371 octets
|
||||
|
||||
### 1yOvw74jzFfaI87b.js
|
||||
|
||||
- Taille WFRP4E: 27 octets
|
||||
- Taille FR: 27 octets
|
||||
|
||||
### 23vWiHUjxtRQ3Efz.js
|
||||
|
||||
- Taille WFRP4E: 219 octets
|
||||
- Taille FR: 218 octets
|
||||
|
||||
### 2AOo7KUyzMrgIlgM.js
|
||||
|
||||
- Taille WFRP4E: 137 octets
|
||||
- Taille FR: 129 octets
|
||||
|
||||
### 2Qi1hwLYhdE6v6Hs.js
|
||||
|
||||
- Taille WFRP4E: 243 octets
|
||||
- Taille FR: 258 octets
|
||||
- Textes WFRP4E: Cannot Dodge!
|
||||
- Textes FR: Impossible d
|
||||
|
||||
### 2cKarG9ToyW2ptCd.js
|
||||
|
||||
- Taille WFRP4E: 338 octets
|
||||
- Taille FR: 340 octets
|
||||
- Textes WFRP4E: None left!
|
||||
- Textes FR: Vide !
|
||||
|
||||
### 2rzxQlL7A9ujZ9uK.js
|
||||
|
||||
- Taille WFRP4E: 315 octets
|
||||
- Taille FR: 316 octets
|
||||
- Textes WFRP4E: <b>${this.effect.name}</b>: Gained ${this.item.Advances} Advantage
|
||||
- Textes FR: <b>${this.effect.name}</b>: Gain de ${this.item.Advances} Avantages
|
||||
|
||||
### 2yctEihGmdCfTTVx.js
|
||||
|
||||
- Taille WFRP4E: 88 octets
|
||||
- Taille FR: 63 octets
|
||||
|
||||
### 2zeP2nMSURjxrqYz.js
|
||||
|
||||
- Taille WFRP4E: 282 octets
|
||||
- Taille FR: 302 octets
|
||||
- Textes WFRP4E: No effect at 0 Wounds, Healed ${this.actor.characteristics.t.bonus} Wounds
|
||||
- Textes FR: Aucun effet à 0 Blessures, Soin de ${this.actor.characteristics.t.bonus} Blessures
|
||||
|
||||
### 33US8YRgaMqYu2We.js
|
||||
|
||||
- Taille WFRP4E: 29 octets
|
||||
- Taille FR: 29 octets
|
||||
|
||||
### 37UN17gb8suFeZIW.js
|
||||
|
||||
- Taille WFRP4E: 133 octets
|
||||
- Taille FR: 139 octets
|
||||
|
||||
### 3D5ImpMgpOTPucvv.js
|
||||
|
||||
- Taille WFRP4E: 379 octets
|
||||
- Taille FR: 379 octets
|
||||
|
||||
### 3IGO7xEjRjat937X.js
|
||||
|
||||
- Taille WFRP4E: 232 octets
|
||||
- Taille FR: 241 octets
|
||||
- Textes WFRP4E: Removing Fatigued Condition, disabled effect
|
||||
- Textes FR: Suppression de l
|
||||
|
||||
### 3eSaX0BeaUalNkEP.js
|
||||
|
||||
- Taille WFRP4E: 26 octets
|
||||
- Taille FR: 26 octets
|
||||
|
||||
### 3jm0NoYpgB6ZuUSl.js
|
||||
|
||||
- Taille WFRP4E: 38 octets
|
||||
- Taille FR: 38 octets
|
||||
|
||||
### 3l7MQSa10Kve2K3P.js
|
||||
|
||||
- Taille WFRP4E: 215 octets
|
||||
- Taille FR: 221 octets
|
||||
|
||||
### 4MQ7u4INxp51oyyR.js
|
||||
|
||||
- Taille WFRP4E: 1932 octets
|
||||
- Taille FR: 1952 octets
|
||||
- Textes WFRP4E: Could not find ${talent}, Could not find ${trapping}
|
||||
- Textes FR: Impossible de trouver ${talent}, Impossible de trouver ${trapping}
|
||||
|
||||
### 4ylzjgUdHY5D0yVh.js
|
||||
|
||||
- Taille WFRP4E: 3410 octets
|
||||
- Taille FR: 3359 octets
|
||||
- Textes WFRP4E: Could not find ${talent}, Could not find ${trapping}
|
||||
- Textes FR: Impossible de trouver ${talent}, Impossible de trouver ${trapping}
|
||||
|
||||
### 58rFc9HiBoX66J6p.js
|
||||
|
||||
- Taille WFRP4E: 444 octets
|
||||
- Taille FR: 453 octets
|
||||
|
||||
### 5DI6cHAg1LHo54Yv.js
|
||||
|
||||
- Taille WFRP4E: 420 octets
|
||||
- Taille FR: 426 octets
|
||||
- Textes FR: 1 Point de Fortune volé à <strong>${this.actor.name}</strong>
|
||||
|
||||
### 5JWC0l3JEpOsqbR9.js
|
||||
|
||||
- Taille WFRP4E: 1767 octets
|
||||
- Taille FR: 1783 octets
|
||||
- Textes WFRP4E: Could not find ${talent}, Could not find ${trapping}
|
||||
- Textes FR: Impossible de trouver ${talent}, Impossible de trouver ${trapping}
|
||||
|
||||
### 5JvKJZPcd6Hz5zvn.js
|
||||
|
||||
- Taille WFRP4E: 1886 octets
|
||||
- Taille FR: 1906 octets
|
||||
- Textes WFRP4E: Could not find ${talent}, Could not find ${trapping}
|
||||
- Textes FR: Impossible de trouver ${talent}, Impossible de trouver ${trapping}
|
||||
|
||||
### 5M6IgCUncCwyxHok.js
|
||||
|
||||
- Taille WFRP4E: 1217 octets
|
||||
- Taille FR: 1197 octets
|
||||
|
||||
### 5MxRDXzUBPfp2KKD.js
|
||||
|
||||
- Taille WFRP4E: 38 octets
|
||||
- Taille FR: 38 octets
|
||||
|
||||
### 5ScjIdRUOxblHdWS.js
|
||||
|
||||
- Taille WFRP4E: 1217 octets
|
||||
- Taille FR: 1212 octets
|
||||
|
||||
### 5dR7Erj3nwsxLAV7.js
|
||||
|
||||
- Taille WFRP4E: 1954 octets
|
||||
- Taille FR: 1976 octets
|
||||
- Textes WFRP4E: Could not find ${talent}, Could not find ${trapping}
|
||||
- Textes FR: Impossible de trouver ${talent}, Impossible de trouver ${trapping}
|
||||
|
||||
### 62Ky6bC1EnTllSJA.js
|
||||
|
||||
- Taille WFRP4E: 253 octets
|
||||
- Taille FR: 259 octets
|
||||
|
||||
### 65xE9OV5sA1ZWT7j.js
|
||||
|
||||
- Taille WFRP4E: 377 octets
|
||||
- Taille FR: 377 octets
|
||||
|
||||
### 6Aqq4F4Xui923sc6.js
|
||||
|
||||
- Taille WFRP4E: 779 octets
|
||||
- Taille FR: 754 octets
|
||||
- Textes FR: <p><strong>${this.actor.prototypeToken.name}</strong> reçoit le Trait de Créatuer A Sang Froid et peut inverser n
|
||||
|
||||
### 6BmvV9c03FkfisnE.js
|
||||
|
||||
- Taille WFRP4E: 1069 octets
|
||||
- Taille FR: 1107 octets
|
||||
- Textes FR: ${this.actor.name} porte le <strong>${this.item.name}</strong>. <br>
|
||||
Il gagne +1 Point de Corruption point si un Test de Corruption est échoué, à appliquer manuellement.<br>Si le personnage porte le masque pendant plus d, <strong>${this.item.name}</strong> de ${this.actor.name} a été enlevé et a perdu ses propriétés. Cependant, les effets perdurent pendant [[1d10+4]] jours, après quoi ils devront être manuellement supprimés.
|
||||
|
||||
### 6H6vNjzvMGl2ZqCR.js
|
||||
|
||||
- Taille WFRP4E: 285 octets
|
||||
- Taille FR: 305 octets
|
||||
- Textes FR: <b>Lame de Nurglitch: ${args.actor.name}</b> doit réussir un <b>Test d
|
||||
|
||||
### 6QZUX7ZrFxOzqI0b.js
|
||||
|
||||
- Taille WFRP4E: 252 octets
|
||||
- Taille FR: 268 octets
|
||||
|
||||
|
||||
... et 423 autres fichiers
|
||||
|
||||
## Scripts uniquement dans WFRP4E (394)
|
||||
|
||||
Ces scripts existent dans WFRP4E mais pas dans le module FR.
|
||||
|
||||
- 07tvKnPT8ICtv2us.js
|
||||
- 0H2syk6qc0sCY0pj.js
|
||||
- 0IAc5VFR2ogXOaGE.js
|
||||
- 0NAD1LNcVyAZ1fC7.js
|
||||
- 0PzfGjGhHQbxEwlb.js
|
||||
- 0amHqfjTRp5ff6Op.js
|
||||
- 0hAbiNR1nFkpFMRz.js
|
||||
- 0hgTyeaEhMBLwzUn.js
|
||||
- 0kUalAsb4OhtYbaJ.js
|
||||
- 0uUxvBLJC76WIIBC.js
|
||||
- 0wR0LWpfhLFA240I.js
|
||||
- 0wmIC2MssUX6LW3N.js
|
||||
- 1Du4e27M8WgP2iui.js
|
||||
- 1PPh4vHd5sPKtudZ.js
|
||||
- 1UvL0XA1EpQtjDNn.js
|
||||
- 20fvE9nJmcfGYVzw.js
|
||||
- 22PMOW0G5MWiBQmg.js
|
||||
- 2EAYX5G9Fh3HJwiP.js
|
||||
- 2Ej6LUqn8frTRURo.js
|
||||
- 2IPTF0akWw9y48br.js
|
||||
|
||||
... et 374 autres
|
||||
|
||||
## Scripts uniquement dans FR (2)
|
||||
|
||||
Ces scripts existent dans le module FR mais plus dans WFRP4E (probablement supprimés).
|
||||
|
||||
- ZingXNvYyZ2BEvfY.js
|
||||
- tfdKU6nmvUtEjXE2.js
|
||||
|
||||
93
tools/scripts-replaced-list.md
Normal file
93
tools/scripts-replaced-list.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# Scripts remplacés par les versions système
|
||||
|
||||
Date: 2026-01-06T19:07:20.939Z
|
||||
|
||||
## Résumé
|
||||
|
||||
- **Scripts remplacés**: 46
|
||||
- **Erreurs**: 0
|
||||
|
||||
Tous les scripts ont été remplacés par leurs versions du système WFRP4E.
|
||||
Les versions françaises avec traductions sont sauvegardées avec l'extension `.fr-backup`.
|
||||
|
||||
## Scripts à revoir manuellement
|
||||
|
||||
Pour chaque script, vous devez :
|
||||
1. Comparer la version actuelle (système) avec le backup (.fr-backup)
|
||||
2. Identifier les textes à traduire
|
||||
3. Appliquer les traductions nécessaires
|
||||
|
||||
| # | Fichier | Traductions trouvées |
|
||||
|---|---------|----------------------|
|
||||
| 1 | `0FWto1oEr3jbWggw.js` | Impossible de trouver le sort ${lore}. Essayez à nouveau, Chargement, Impossible... |
|
||||
| 2 | `1BT0MWM2cbhlEnrn.js` | Impossible de trouver ${talent}, Impossible |
|
||||
| 3 | `1CeYp5MlPcH68UIw.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 4 | `2Qi1hwLYhdE6v6Hs.js` | Impossible d, Impossible |
|
||||
| 5 | `4MQ7u4INxp51oyyR.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 6 | `4ylzjgUdHY5D0yVh.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 7 | `5JWC0l3JEpOsqbR9.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 8 | `5JvKJZPcd6Hz5zvn.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 9 | `5dR7Erj3nwsxLAV7.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 10 | `6jcTzK1XEuWqAacN.js` | Impossible d, Impossible |
|
||||
| 11 | `6xTtJEhRc4OjcDTf.js` | Impossible de mettre à jour la Fortune, Impossible |
|
||||
| 12 | `A1odAcuRbq9797ZB.js` | Impossible de trouver ${talent}, Impossible |
|
||||
| 13 | `I1J2m5uud84N50Lk.js` | Impossible d, Impossible |
|
||||
| 14 | `IslMfFgpgQq2brpu.js` | Impossible de supprimer l, Impossible |
|
||||
| 15 | `IupskvzvoGyD2H5o.js` | Adding , Impossible de trouver any Blessings associated with ${god}., Impossible... |
|
||||
| 16 | `KICZPwLvbUSxbDrE.js` | Impossible de trouver la table des Mutations Mentales, Impossible de trouver l, ${item.name} added... |
|
||||
| 17 | `N8hA6ysHCTlLd8Kj.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 18 | `RvipIYj9H7n4UDMe.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 19 | `TCtXPvDpbfz1yrVZ.js` | Impossible de trouver ${talent}, Impossible |
|
||||
| 20 | `TwgdEucxcHloc4cX.js` | Impossible de trouver ${c.name}, Impossible |
|
||||
| 21 | `U1UpSRJOSjPpO4HS.js` | Ajout ${mutations[roll].name}, Chargement, Chargement des mutations |
|
||||
| 22 | `ULmZMLezDamerN04.js` | Chargement, Chargement des sorts |
|
||||
| 23 | `UQtXuQmUlTyDKqhe.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 24 | `UnqnWi0dZYLf5fTT.js` | Impossible de trouver ${c.name}, Impossible |
|
||||
| 25 | `V9zm2hKUVLVZtAcN.js` | Impossible de trouver ${talent}, Impossible de trouver ${trait}, Impossible de trouver ${trapping}... |
|
||||
| 26 | `WO5n7Vbx8AgoVrwC.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 27 | `YN8719gme9AxYtyY.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 28 | `Z6jNlyZMECkW4Hon.js` | Chargement, Chargement des sorts |
|
||||
| 29 | `aeBetniKqq5SD9Ou.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 30 | `bEVlJOOA1kLlzpWx.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 31 | `ePPgxQOqL1Uhz2k9.js` | Impossible de trouver ${talent}, Impossible |
|
||||
| 32 | `h766UvswLCsxcMow.js` | Impossible de trouver ${talent}, Impossible de trouver ${trait}, Impossible de trouver ${trapping}... |
|
||||
| 33 | `hhv7PrRdlf9sfC82.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 34 | `hpwJRAhCsXTp9bd9.js` | Impossible de trouver ${talent}, Impossible |
|
||||
| 35 | `iuSoKntfJ4eAPafQ.js` | Chargement, Chargement des sorts |
|
||||
| 36 | `jHgxpe6TJDlP3oTn.js` | Chargement, Chargement des sorts |
|
||||
| 37 | `lII4KMRblqwFBlsV.js` | Impossible de trouver ${talent}, Impossible de trouver ${trait}, Impossible de trouver ${trapping}... |
|
||||
| 38 | `oTXPA6rbPnYOKNmo.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 39 | `okW06V9UiPC4Vcrn.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 40 | `svCqdytEOtqFXCcs.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 41 | `sz0PqS1kroMOzUZk.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 42 | `v5xrDWcrTNFJkyQB.js` | Impossible de trouver ${talent}, Impossible |
|
||||
| 43 | `whUSkaR1yem21bXp.js` | Impossible de trouver ${talent}, Impossible de trouver ${trait}, Impossible de trouver ${trapping}... |
|
||||
| 44 | `y3F1K1sYBymPZCjz.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 45 | `z8mwLihZQu0JtUHY.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
| 46 | `zadppy7FEbXvgUON.js` | Impossible de trouver ${talent}, Impossible de trouver ${trapping}, Impossible |
|
||||
|
||||
## Commandes utiles
|
||||
|
||||
### Comparer un script avec son backup
|
||||
|
||||
```bash
|
||||
# Avec meld
|
||||
meld scripts/<fichier> scripts/<fichier>.fr-backup
|
||||
|
||||
# Avec diff
|
||||
diff -u scripts/<fichier>.fr-backup scripts/<fichier>
|
||||
```
|
||||
|
||||
### Exemples de scripts
|
||||
|
||||
Premier script: `0FWto1oEr3jbWggw.js`
|
||||
|
||||
```bash
|
||||
meld scripts/0FWto1oEr3jbWggw.js scripts/0FWto1oEr3jbWggw.js.fr-backup
|
||||
```
|
||||
|
||||
Traductions à réappliquer:
|
||||
- "Impossible de trouver le sort ${lore}. Essayez à nouveau"
|
||||
- "Chargement"
|
||||
- "Impossible"
|
||||
- "Chargement des sorts"
|
||||
186
tools/scripts-to-review.json
Normal file
186
tools/scripts-to-review.json
Normal file
@@ -0,0 +1,186 @@
|
||||
[
|
||||
{
|
||||
"file": "0FWto1oEr3jbWggw.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "1BT0MWM2cbhlEnrn.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "1CeYp5MlPcH68UIw.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "2Qi1hwLYhdE6v6Hs.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "4MQ7u4INxp51oyyR.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "4ylzjgUdHY5D0yVh.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "5JWC0l3JEpOsqbR9.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "5JvKJZPcd6Hz5zvn.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "5dR7Erj3nwsxLAV7.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "6jcTzK1XEuWqAacN.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "6xTtJEhRc4OjcDTf.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "A1odAcuRbq9797ZB.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "I1J2m5uud84N50Lk.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "IslMfFgpgQq2brpu.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "IupskvzvoGyD2H5o.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "KICZPwLvbUSxbDrE.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "N8hA6ysHCTlLd8Kj.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "RvipIYj9H7n4UDMe.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "TCtXPvDpbfz1yrVZ.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "TwgdEucxcHloc4cX.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "U1UpSRJOSjPpO4HS.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "ULmZMLezDamerN04.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "UQtXuQmUlTyDKqhe.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "UnqnWi0dZYLf5fTT.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "V9zm2hKUVLVZtAcN.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "WO5n7Vbx8AgoVrwC.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "YN8719gme9AxYtyY.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "Z6jNlyZMECkW4Hon.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "aeBetniKqq5SD9Ou.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "bEVlJOOA1kLlzpWx.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "ePPgxQOqL1Uhz2k9.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "h766UvswLCsxcMow.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "hhv7PrRdlf9sfC82.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "hpwJRAhCsXTp9bd9.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "iuSoKntfJ4eAPafQ.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "jHgxpe6TJDlP3oTn.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "lII4KMRblqwFBlsV.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "oTXPA6rbPnYOKNmo.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "okW06V9UiPC4Vcrn.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "svCqdytEOtqFXCcs.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "sz0PqS1kroMOzUZk.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "v5xrDWcrTNFJkyQB.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "whUSkaR1yem21bXp.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "y3F1K1sYBymPZCjz.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "z8mwLihZQu0JtUHY.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
},
|
||||
{
|
||||
"file": "zadppy7FEbXvgUON.js",
|
||||
"reason": "Contient des textes traduits en français"
|
||||
}
|
||||
]
|
||||
196
tools/sync-scripts.js
Normal file
196
tools/sync-scripts.js
Normal file
@@ -0,0 +1,196 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const WFRP4E_SCRIPTS = '/home/morr/work/foundryvtt/WFRP4e-FoundryVTT/scripts';
|
||||
const FR_SCRIPTS = '/home/morr/work/foundryvtt/foundryvtt-wh4-lang-fr-fr/scripts';
|
||||
const REPORT_FILE = '/home/morr/work/foundryvtt/foundryvtt-wh4-lang-fr-fr/tools/script-comparison-report.md';
|
||||
|
||||
// Recherche des patterns qui indiquent du texte localisé
|
||||
const LOCALIZE_PATTERNS = [
|
||||
/game\.i18n\.localize\(/g,
|
||||
/game\.i18n\.format\(/g,
|
||||
/game\.wfrp4e\.i18n\./g
|
||||
];
|
||||
|
||||
// Patterns de textes en dur qui ont probablement été traduits
|
||||
const HARDCODED_TEXT_PATTERNS = [
|
||||
/ui\.notifications\.(info|warn|error|notify)\s*\(\s*["'`]([^"'`]+)["'`]/g,
|
||||
/this\.script\.(scriptNotification|scriptMessage|notification)\s*\(\s*["'`]([^"'`]+)["'`]/g
|
||||
];
|
||||
|
||||
function analyzeScript(filePath) {
|
||||
const content = fs.readFileSync(filePath, 'utf-8');
|
||||
|
||||
// Vérifie si le fichier utilise localize()
|
||||
const hasLocalize = LOCALIZE_PATTERNS.some(pattern => pattern.test(content));
|
||||
|
||||
// Extrait les textes en dur
|
||||
const hardcodedTexts = [];
|
||||
HARDCODED_TEXT_PATTERNS.forEach(pattern => {
|
||||
const matches = content.matchAll(pattern);
|
||||
for (const match of matches) {
|
||||
hardcodedTexts.push(match[2] || match[1]);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
hasLocalize,
|
||||
hardcodedTexts,
|
||||
content,
|
||||
size: content.length
|
||||
};
|
||||
}
|
||||
|
||||
function compareScripts() {
|
||||
const wfrp4eFiles = fs.readdirSync(WFRP4E_SCRIPTS).filter(f => f.endsWith('.js'));
|
||||
const frFiles = fs.readdirSync(FR_SCRIPTS).filter(f => f.endsWith('.js'));
|
||||
|
||||
const results = {
|
||||
identical: [],
|
||||
needsUpdate: [],
|
||||
usesLocalize: [],
|
||||
onlyInFR: [],
|
||||
onlyInWFRP4E: [],
|
||||
total: 0
|
||||
};
|
||||
|
||||
// Fichiers présents seulement dans le module FR
|
||||
frFiles.forEach(file => {
|
||||
if (!wfrp4eFiles.includes(file)) {
|
||||
results.onlyInFR.push(file);
|
||||
}
|
||||
});
|
||||
|
||||
// Fichiers présents seulement dans WFRP4E
|
||||
wfrp4eFiles.forEach(file => {
|
||||
if (!frFiles.includes(file)) {
|
||||
results.onlyInWFRP4E.push(file);
|
||||
}
|
||||
});
|
||||
|
||||
// Comparaison des fichiers communs
|
||||
const commonFiles = wfrp4eFiles.filter(f => frFiles.includes(f));
|
||||
results.total = commonFiles.length;
|
||||
|
||||
commonFiles.forEach(file => {
|
||||
const wfrp4ePath = path.join(WFRP4E_SCRIPTS, file);
|
||||
const frPath = path.join(FR_SCRIPTS, file);
|
||||
|
||||
const wfrp4e = analyzeScript(wfrp4ePath);
|
||||
const fr = analyzeScript(frPath);
|
||||
|
||||
// Si WFRP4E utilise localize(), le script FR n'est plus nécessaire
|
||||
if (wfrp4e.hasLocalize) {
|
||||
results.usesLocalize.push({
|
||||
file,
|
||||
details: 'Le système utilise maintenant localize() - script FR obsolète'
|
||||
});
|
||||
}
|
||||
// Si les contenus sont identiques
|
||||
else if (wfrp4e.content === fr.content) {
|
||||
results.identical.push(file);
|
||||
}
|
||||
// Si différents, besoin de mise à jour
|
||||
else {
|
||||
results.needsUpdate.push({
|
||||
file,
|
||||
wfrp4eSize: wfrp4e.size,
|
||||
frSize: fr.size,
|
||||
wfrp4eTexts: wfrp4e.hardcodedTexts,
|
||||
frTexts: fr.hardcodedTexts
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function generateReport(results) {
|
||||
let report = `# Rapport de comparaison des scripts\n\n`;
|
||||
report += `Date: ${new Date().toISOString()}\n\n`;
|
||||
report += `## Résumé\n\n`;
|
||||
report += `- **Total de fichiers communs**: ${results.total}\n`;
|
||||
report += `- **Scripts identiques**: ${results.identical.length}\n`;
|
||||
report += `- **Scripts nécessitant mise à jour**: ${results.needsUpdate.length}\n`;
|
||||
report += `- **Scripts utilisant localize() (obsolètes)**: ${results.usesLocalize.length}\n`;
|
||||
report += `- **Scripts uniquement dans FR**: ${results.onlyInFR.length}\n`;
|
||||
report += `- **Scripts uniquement dans WFRP4E**: ${results.onlyInWFRP4E.length}\n\n`;
|
||||
|
||||
if (results.usesLocalize.length > 0) {
|
||||
report += `## Scripts obsolètes (utilisant localize() dans WFRP4E)\n\n`;
|
||||
report += `Ces scripts peuvent être supprimés du module FR car le système utilise maintenant les fichiers de localisation.\n\n`;
|
||||
results.usesLocalize.forEach(({file, details}) => {
|
||||
report += `- \`${file}\` - ${details}\n`;
|
||||
});
|
||||
report += `\n`;
|
||||
}
|
||||
|
||||
if (results.needsUpdate.length > 0) {
|
||||
report += `## Scripts nécessitant une mise à jour\n\n`;
|
||||
results.needsUpdate.slice(0, 50).forEach(item => {
|
||||
report += `### ${item.file}\n\n`;
|
||||
report += `- Taille WFRP4E: ${item.wfrp4eSize} octets\n`;
|
||||
report += `- Taille FR: ${item.frSize} octets\n`;
|
||||
if (item.wfrp4eTexts.length > 0) {
|
||||
report += `- Textes WFRP4E: ${item.wfrp4eTexts.join(', ')}\n`;
|
||||
}
|
||||
if (item.frTexts.length > 0) {
|
||||
report += `- Textes FR: ${item.frTexts.join(', ')}\n`;
|
||||
}
|
||||
report += `\n`;
|
||||
});
|
||||
if (results.needsUpdate.length > 50) {
|
||||
report += `\n... et ${results.needsUpdate.length - 50} autres fichiers\n\n`;
|
||||
}
|
||||
}
|
||||
|
||||
if (results.onlyInWFRP4E.length > 0) {
|
||||
report += `## Scripts uniquement dans WFRP4E (${results.onlyInWFRP4E.length})\n\n`;
|
||||
report += `Ces scripts existent dans WFRP4E mais pas dans le module FR.\n\n`;
|
||||
results.onlyInWFRP4E.slice(0, 20).forEach(file => {
|
||||
report += `- ${file}\n`;
|
||||
});
|
||||
if (results.onlyInWFRP4E.length > 20) {
|
||||
report += `\n... et ${results.onlyInWFRP4E.length - 20} autres\n`;
|
||||
}
|
||||
report += `\n`;
|
||||
}
|
||||
|
||||
if (results.onlyInFR.length > 0) {
|
||||
report += `## Scripts uniquement dans FR (${results.onlyInFR.length})\n\n`;
|
||||
report += `Ces scripts existent dans le module FR mais plus dans WFRP4E (probablement supprimés).\n\n`;
|
||||
results.onlyInFR.slice(0, 20).forEach(file => {
|
||||
report += `- ${file}\n`;
|
||||
});
|
||||
if (results.onlyInFR.length > 20) {
|
||||
report += `\n... et ${results.onlyInFR.length - 20} autres\n`;
|
||||
}
|
||||
report += `\n`;
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
console.log('Analyse des scripts en cours...');
|
||||
const results = compareScripts();
|
||||
const report = generateReport(results);
|
||||
|
||||
fs.writeFileSync(REPORT_FILE, report, 'utf-8');
|
||||
|
||||
console.log(`\nRapport généré: ${REPORT_FILE}`);
|
||||
console.log(`\nRésumé:`);
|
||||
console.log(` Identiques: ${results.identical.length}`);
|
||||
console.log(` À mettre à jour: ${results.needsUpdate.length}`);
|
||||
console.log(` Obsolètes (localize): ${results.usesLocalize.length}`);
|
||||
console.log(` Uniquement FR: ${results.onlyInFR.length}`);
|
||||
console.log(` Uniquement WFRP4E: ${results.onlyInWFRP4E.length}`);
|
||||
|
||||
// Export des résultats pour utilisation ultérieure
|
||||
fs.writeFileSync(
|
||||
path.join(path.dirname(REPORT_FILE), 'script-comparison-data.json'),
|
||||
JSON.stringify(results, null, 2),
|
||||
'utf-8'
|
||||
);
|
||||
81
tools/translate-ids.js
Normal file
81
tools/translate-ids.js
Normal file
@@ -0,0 +1,81 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
// Lire et parser le JSON
|
||||
const jsonPath = './compendium/wfrp4e-core.items.json';
|
||||
console.log('Lecture du fichier JSON...');
|
||||
const jsonData = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
|
||||
|
||||
// Créer le mapping id -> name
|
||||
const idToName = {};
|
||||
jsonData.entries.forEach(entry => {
|
||||
if (entry.id && entry.name) {
|
||||
idToName[entry.id] = entry.name;
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Nombre d'entrées trouvées: ${Object.keys(idToName).length}`);
|
||||
|
||||
// Fonction pour échapper les regex
|
||||
function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
// Parcourir tous les fichiers .js dans scripts/
|
||||
const scriptsDir = './scripts/';
|
||||
console.log('Analyse des fichiers dans', scriptsDir);
|
||||
const files = fs.readdirSync(scriptsDir).filter(f => f.endsWith('.js'));
|
||||
console.log(`${files.length} fichiers .js trouvés`);
|
||||
|
||||
let totalReplacements = 0;
|
||||
let filesModified = 0;
|
||||
const modifications = {};
|
||||
|
||||
files.forEach(file => {
|
||||
const filePath = path.join(scriptsDir, file);
|
||||
let content = fs.readFileSync(filePath, 'utf8');
|
||||
let originalContent = content;
|
||||
let fileReplacements = 0;
|
||||
|
||||
// Pour chaque ID, chercher et remplacer les occurrences entre guillemets
|
||||
Object.entries(idToName).forEach(([id, name]) => {
|
||||
// Chercher l'ID entre guillemets simples ou doubles
|
||||
const pattern1 = new RegExp('"' + escapeRegExp(id) + '"', 'g');
|
||||
const pattern2 = new RegExp("'" + escapeRegExp(id) + "'", 'g');
|
||||
|
||||
const matches1 = (content.match(pattern1) || []).length;
|
||||
const matches2 = (content.match(pattern2) || []).length;
|
||||
|
||||
if (matches1 > 0 || matches2 > 0) {
|
||||
content = content.replace(pattern1, '"' + name + '"');
|
||||
content = content.replace(pattern2, "'" + name + "'");
|
||||
|
||||
if (!modifications[file]) modifications[file] = [];
|
||||
modifications[file].push(` ${id} -> ${name} (${matches1 + matches2} fois)`);
|
||||
fileReplacements += matches1 + matches2;
|
||||
}
|
||||
});
|
||||
|
||||
if (content !== originalContent) {
|
||||
fs.writeFileSync(filePath, content, 'utf8');
|
||||
filesModified++;
|
||||
totalReplacements += fileReplacements;
|
||||
}
|
||||
});
|
||||
|
||||
console.log('\n===== RÉSULTAT =====');
|
||||
console.log(`Fichiers modifiés: ${filesModified} / ${files.length}`);
|
||||
console.log(`Total de remplacements: ${totalReplacements}`);
|
||||
|
||||
if (filesModified > 0) {
|
||||
console.log('\n===== DÉTAILS DES MODIFICATIONS =====');
|
||||
Object.entries(modifications).forEach(([file, changes]) => {
|
||||
console.log(`\n${file}:`);
|
||||
changes.slice(0, 10).forEach(change => console.log(change));
|
||||
if (changes.length > 10) {
|
||||
console.log(` ... et ${changes.length - 10} autres remplacements`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
console.log('\n✓ Traitement terminé !');
|
||||
177
tools/translate-scripts.js
Normal file
177
tools/translate-scripts.js
Normal file
@@ -0,0 +1,177 @@
|
||||
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));
|
||||
1196
tools/translation-opportunities.json
Normal file
1196
tools/translation-opportunities.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user