Spaces:
Running
Running
<html lang="fr"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>DocTranslator Pro - Traduction Intelligente</title> | |
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"> | |
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet"> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"> | |
<style> | |
:root { | |
--primary-color: #4361ee; | |
--secondary-color: #f8f9fc; | |
--accent-color: #3a0ca3; | |
--success-color: #2ecc71; | |
--warning-color: #f39c12; | |
--dark-color: #2c3e50; | |
} | |
body { | |
padding: 20px; | |
background-color: var(--secondary-color); | |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
min-height: 100vh; | |
} | |
.container { | |
max-width: 900px; | |
margin-top: 30px; | |
margin-bottom: 50px; | |
} | |
.card { | |
border-radius: 12px; | |
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1); | |
border: none; | |
background: linear-gradient(145deg, #ffffff, #f0f2f5); | |
transition: transform 0.3s ease; | |
overflow: hidden; | |
} | |
.card:hover { | |
transform: translateY(-5px); | |
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15); | |
} | |
.card-header { | |
background-color: var(--primary-color); | |
color: white; | |
font-weight: 600; | |
padding: 15px 20px; | |
} | |
.result-area { | |
margin-top: 30px; | |
padding: 30px; | |
background-color: white; | |
border-radius: 12px; | |
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1); | |
border: 1px solid rgba(0, 0, 0, 0.05); | |
} | |
.loading { | |
display: none; | |
text-align: center; | |
margin: 40px 0; | |
} | |
.text-display { | |
height: 350px; | |
overflow-y: auto; | |
white-space: pre-wrap; | |
background-color: var(--secondary-color); | |
padding: 20px; | |
border-radius: 8px; | |
border: 1px solid #e3e6f0; | |
font-size: 0.95rem; | |
line-height: 1.8; | |
transition: all 0.3s ease; | |
} | |
.text-display:hover { | |
box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.05); | |
} | |
#downloadBtn { | |
transition: all 0.3s ease; | |
font-weight: 600; | |
padding: 10px 20px; | |
border-radius: 8px; | |
} | |
#downloadBtn:hover { | |
transform: translateY(-3px); | |
box-shadow: 0 5px 15px rgba(46, 204, 113, 0.3); | |
} | |
.file-info { | |
font-size: 0.85rem; | |
color: #6c757d; | |
margin-top: 8px; | |
padding: 8px 12px; | |
background-color: rgba(108, 117, 125, 0.05); | |
border-radius: 6px; | |
} | |
.alert-warning { | |
border-left: 4px solid var(--warning-color); | |
background-color: rgba(243, 156, 18, 0.1); | |
} | |
.alert-info { | |
border-left: 4px solid var(--primary-color); | |
background-color: rgba(67, 97, 238, 0.1); | |
} | |
.btn-primary { | |
background-color: var(--primary-color); | |
border: none; | |
padding: 12px; | |
font-weight: 600; | |
letter-spacing: 0.5px; | |
transition: all 0.3s ease; | |
} | |
.btn-primary:hover { | |
background-color: var(--accent-color); | |
transform: translateY(-2px); | |
box-shadow: 0 5px 15px rgba(58, 12, 163, 0.3); | |
} | |
.btn-success { | |
background-color: var(--success-color); | |
border: none; | |
} | |
.spinner-border { | |
width: 3.5rem; | |
height: 3.5rem; | |
border-width: 0.3em; | |
} | |
.language-selector { | |
position: relative; | |
} | |
.language-selector::after { | |
content: "\F282"; | |
font-family: "bootstrap-icons"; | |
position: absolute; | |
right: 15px; | |
top: 50%; | |
transform: translateY(-50%); | |
pointer-events: none; | |
color: var(--primary-color); | |
} | |
.toast-notification { | |
position: fixed; | |
bottom: 20px; | |
right: 20px; | |
background: var(--dark-color); | |
color: white; | |
padding: 15px 25px; | |
border-radius: 10px; | |
box-shadow: 0 8px 20px rgba(0,0,0,0.2); | |
display: none; | |
z-index: 1000; | |
animation: fadeIn 0.5s; | |
} | |
@keyframes fadeIn { | |
from { opacity: 0; transform: translateY(20px); } | |
to { opacity: 1; transform: translateY(0); } | |
} | |
.progress-container { | |
display: none; | |
margin: 25px 0; | |
} | |
.progress { | |
height: 10px; | |
border-radius: 5px; | |
background-color: rgba(67, 97, 238, 0.1); | |
} | |
.progress-bar { | |
background-color: var(--primary-color); | |
border-radius: 5px; | |
} | |
.feature-icon { | |
font-size: 1.5rem; | |
margin-bottom: 15px; | |
color: var(--primary-color); | |
} | |
footer { | |
margin-top: 50px; | |
padding: 20px 0; | |
text-align: center; | |
color: #6c757d; | |
font-size: 0.9rem; | |
} | |
.animate-spin { | |
animation: spin 1s linear infinite; | |
} | |
@keyframes spin { | |
0% { transform: rotate(0deg); } | |
100% { transform: rotate(360deg); } | |
} | |
/* Mode mobile */ | |
@media (max-width: 768px) { | |
.container { | |
padding: 15px; | |
} | |
.text-display { | |
height: 250px; | |
} | |
.result-area { | |
padding: 20px; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container animate__animated animate__fadeIn"> | |
<header class="text-center mb-5"> | |
<div class="d-flex justify-content-center align-items-center mb-3"> | |
<i class="bi bi-translate feature-icon me-3" style="font-size: 2.5rem;"></i> | |
<h1 style="color: var(--primary-color); font-weight: 700;">DocTranslator <span class="badge bg-success">Pro</span></h1> | |
</div> | |
<p class="lead text-muted">Traduction intelligente de documents avec IA</p> | |
</header> | |
<div class="card mb-4 animate__animated animate__fadeInUp"> | |
<div class="card-header"> | |
<i class="bi bi-upload me-2"></i> Téléverser un document | |
</div> | |
<div class="card-body py-4"> | |
<form id="uploadForm"> | |
<div class="mb-4"> | |
<label for="document" class="form-label fw-bold mb-3"> | |
<i class="bi bi-file-earmark-arrow-up me-2"></i> | |
Sélectionnez votre document | |
</label> | |
<input class="form-control form-control-lg" type="file" id="document" accept=".pdf,.docx,.xlsx,.pptx" required> | |
<div class="file-info mt-2" id="fileInfo">Aucun fichier sélectionné</div> | |
</div> | |
<div class="mb-4 language-selector"> | |
<label for="targetLang" class="form-label fw-bold mb-3"> | |
<i class="bi bi-translate me-2"></i> | |
Langue de traduction | |
</label> | |
<select class="form-select form-select-lg" id="targetLang"> | |
<option value="en">Anglais 🇬🇧</option> | |
<option value="es">Espagnol 🇪🇸</option> | |
<option value="ar">Arabe 🇸🇦</option> | |
<option value="de">Allemand 🇩🇪</option> | |
</select> | |
</div> | |
<button type="submit" class="btn btn-primary w-100 py-3 mt-2"> | |
<i class="bi bi-magic me-2"></i> Traduire automatiquement | |
</button> | |
</form> | |
</div> | |
</div> | |
<!-- Zone de progression améliorée --> | |
<div class="progress-container" id="progressContainer"> | |
<div class="d-flex justify-content-between mb-2"> | |
<small class="text-muted fw-bold">Progression de la traduction</small> | |
<small class="fw-bold" id="progressPercent">0%</small> | |
</div> | |
<div class="progress"> | |
<div id="progressBar" class="progress-bar progress-bar-striped progress-bar-animated" | |
role="progressbar" style="width: 0%"></div> | |
</div> | |
</div> | |
<!-- Avertissement amélioré --> | |
<div class="alert alert-warning mt-3 animate__animated animate__fadeIn" id="sizeWarning" style="display: none;"> | |
<div class="d-flex align-items-center"> | |
<i class="bi bi-exclamation-triangle-fill me-3" style="font-size: 1.5rem;"></i> | |
<div> | |
<h6 class="alert-heading mb-1">Attention</h6> | |
<span id="warningText" class="small"></span> | |
</div> | |
</div> | |
</div> | |
<!-- Loader amélioré --> | |
<div class="loading" id="loading"> | |
<div class="spinner-border text-primary" role="status"> | |
<span class="visually-hidden">Chargement...</span> | |
</div> | |
<p class="mt-3 fw-bold" id="loadingText"> | |
<i class="bi bi-gear-fill animate-spin me-2"></i> | |
Analyse du document en cours... | |
</p> | |
<div class="progress mt-3" style="height: 6px; width: 50%; margin: 0 auto;"> | |
<div class="progress-bar bg-primary" style="width: 45%"></div> | |
</div> | |
</div> | |
<!-- Résultats améliorés --> | |
<div class="result-area animate__animated animate__fadeIn" id="resultArea" style="display: none;"> | |
<div class="d-flex justify-content-between align-items-center mb-4"> | |
<h4 class="mb-0 text-primary"> | |
<i class="bi bi-file-text me-2"></i>Résultats de la traduction | |
</h4> | |
<button id="downloadBtn" class="btn btn-success"> | |
<i class="bi bi-file-earmark-arrow-down me-2"></i>Exporter | |
</button> | |
</div> | |
<hr> | |
<div class="mb-4"> | |
<div class="d-flex align-items-center mb-2"> | |
<i class="bi bi-file-earmark-text me-2" style="font-size: 1.2rem;"></i> | |
<h5 class="mb-0 d-flex align-items-center"> | |
<span id="filename" class="fw-bold"></span> | |
<small id="fileSize" class="text-muted ms-2"></small> | |
</h5> | |
</div> | |
<div class="alert alert-info"> | |
<i class="bi bi-info-circle-fill me-2"></i> | |
<span id="infoText">Traduction effectuée avec succès</span> | |
</div> | |
</div> | |
<div class="row mt-4"> | |
<div class="col-lg-6 mb-4 mb-lg-0"> | |
<div class="d-flex align-items-center mb-3"> | |
<i class="bi bi-text-left me-2" style="font-size: 1.2rem;"></i> | |
<h5 class="mb-0">Texte original</h5> | |
</div> | |
<div class="text-display" id="originalText"></div> | |
</div> | |
<div class="col-lg-6"> | |
<div class="d-flex align-items-center mb-3"> | |
<i class="bi bi-translate me-2" style="font-size: 1.2rem;"></i> | |
<h5 class="mb-0">Texte traduit</h5> | |
</div> | |
<div class="text-display" id="translatedText"></div> | |
</div> | |
</div> | |
<div class="mt-4 pt-3 border-top"> | |
<button class="btn btn-outline-primary me-2" id="copyTranslatedBtn"> | |
<i class="bi bi-clipboard me-2"></i>Copier le texte | |
</button> | |
<button class="btn btn-outline-secondary" id="newTranslationBtn"> | |
<i class="bi bi-arrow-repeat me-2"></i>Nouvelle traduction | |
</button> | |
</div> | |
</div> | |
<!-- Notifications toast --> | |
<div class="toast-notification" id="toastNotification"> | |
<div class="d-flex align-items-center"> | |
<i class="bi bi-check-circle-fill me-3" style="font-size: 1.5rem;"></i> | |
<span id="toastMessage">Opération réussie!</span> | |
</div> | |
</div> | |
</div> | |
<footer class="text-center text-muted"> | |
<div class="container"> | |
<p class="mb-2">DocTranslator Pro - Solution de traduction IA</p> | |
<p class="small mb-0"> | |
<i class="bi bi-c-circle"></i> 2024 Tous droits réservés | |
<span class="mx-2">•</span> | |
<a href="#" class="text-decoration-none">Conditions d'utilisation</a> | |
<span class="mx-2">•</span> | |
<a href="#" class="text-decoration-none">Politique de confidentialité</a> | |
</p> | |
</div> | |
</footer> | |
<!-- Scripts --> | |
<script src="/static/script.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script> | |
<script> | |
// Affiche les infos du fichier sélectionné | |
document.getElementById('document').addEventListener('change', function(e) { | |
const file = e.target.files[0]; | |
if (file) { | |
const fileInfo = document.getElementById('fileInfo'); | |
const sizeMB = (file.size / (1024 * 1024)).toFixed(2); | |
fileInfo.innerHTML = ` | |
<i class="bi bi-file-earmark-text me-1"></i> | |
<strong>${file.name}</strong> • ${sizeMB} MB • ${file.type || 'Type inconnu'} | |
`; | |
// Animation du card | |
document.querySelector('.card').classList.add('animate__animated', 'animate__pulse'); | |
setTimeout(() => { | |
document.querySelector('.card').classList.remove('animate__animated', 'animate__pulse'); | |
}, 1000); | |
// Avertissement pour fichiers volumineux | |
const warning = document.getElementById('sizeWarning'); | |
if (file.size > 5 * 1024 * 1024) { // >5MB | |
document.getElementById('warningText').textContent = | |
`Vous avez sélectionné un fichier volumineux (${sizeMB} MB). Le traitement peut prendre plusieurs minutes.`; | |
warning.style.display = 'block'; | |
} else { | |
warning.style.display = 'none'; | |
} | |
} | |
}); | |
// Bouton nouvelle traduction | |
document.getElementById('newTranslationBtn').addEventListener('click', function() { | |
document.getElementById('document').value = ''; | |
document.getElementById('fileInfo').innerHTML = 'Aucun fichier sélectionné'; | |
document.getElementById('resultArea').style.display = 'none'; | |
document.getElementById('sizeWarning').style.display = 'none'; | |
}); | |
// Bouton copier le texte | |
document.getElementById('copyTranslatedBtn').addEventListener('click', function() { | |
const translatedText = document.getElementById('translatedText').textContent; | |
navigator.clipboard.writeText(translatedText).then(() => { | |
showToast('Texte copié dans le presse-papiers!'); | |
}); | |
}); | |
// Fonction d'affichage des notifications | |
function showToast(message) { | |
const toast = document.getElementById('toastNotification'); | |
document.getElementById('toastMessage').textContent = message; | |
toast.style.display = 'flex'; | |
setTimeout(() => { | |
toast.style.animation = 'fadeIn 0.5s reverse'; | |
setTimeout(() => { | |
toast.style.display = 'none'; | |
toast.style.animation = 'fadeIn 0.5s'; | |
}, 500); | |
}, 3000); | |
} | |
</script> | |
</body> | |
</html> |