Spaces:
Sleeping
Sleeping
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>AI Document Translator Pro</title> | |
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> | |
| <style> | |
| :root { | |
| --primary-color: #4361ee; | |
| --secondary-color: #3f37c9; | |
| --accent-color: #4cc9f0; | |
| --dark-color: #1a1a2e; | |
| --light-color: #f8f9fa; | |
| } | |
| body { | |
| background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); | |
| color: var(--dark-color); | |
| min-height: 100vh; | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| } | |
| .main-container { | |
| max-width: 800px; | |
| background: white; | |
| padding: 2rem; | |
| border-radius: 15px; | |
| box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); | |
| margin: 2rem auto; | |
| } | |
| .header { | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| position: relative; | |
| } | |
| .logo { | |
| font-size: 2.5rem; | |
| color: var(--primary-color); | |
| margin-bottom: 0.5rem; | |
| } | |
| .title { | |
| font-weight: 700; | |
| color: var(--dark-color); | |
| margin-bottom: 0.5rem; | |
| } | |
| .subtitle { | |
| color: #6c757d; | |
| font-size: 1rem; | |
| } | |
| .upload-section { | |
| background: rgba(67, 97, 238, 0.05); | |
| border: 2px dashed rgba(67, 97, 238, 0.3); | |
| border-radius: 10px; | |
| padding: 2rem; | |
| margin-bottom: 2rem; | |
| transition: all 0.3s ease; | |
| } | |
| .upload-section:hover { | |
| border-color: var(--primary-color); | |
| background: rgba(67, 97, 238, 0.1); | |
| } | |
| .file-info { | |
| background: var(--light-color); | |
| padding: 0.5rem; | |
| border-radius: 5px; | |
| font-size: 0.9rem; | |
| margin-top: 1rem; | |
| } | |
| .form-control, .form-select { | |
| border-radius: 8px; | |
| padding: 0.75rem 1rem; | |
| border: 1px solid #ced4da; | |
| transition: all 0.3s ease; | |
| } | |
| .form-control:focus, .form-select:focus { | |
| border-color: var(--primary-color); | |
| box-shadow: 0 0 0 0.25rem rgba(67, 97, 238, 0.25); | |
| } | |
| .btn-primary { | |
| background-color: var(--primary-color); | |
| border-color: var(--primary-color); | |
| border-radius: 8px; | |
| padding: 0.75rem 1.5rem; | |
| font-weight: 600; | |
| transition: all 0.3s ease; | |
| } | |
| .btn-primary:hover { | |
| background-color: var(--secondary-color); | |
| border-color: var(--secondary-color); | |
| transform: translateY(-2px); | |
| } | |
| .result-container { | |
| margin-top: 2rem; | |
| } | |
| .result-box { | |
| background: white; | |
| border: 1px solid #e9ecef; | |
| border-radius: 10px; | |
| padding: 1.5rem; | |
| min-height: 200px; | |
| max-height: 400px; | |
| overflow-y: auto; | |
| box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.05); | |
| } | |
| .result-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 1rem; | |
| padding-bottom: 0.5rem; | |
| border-bottom: 1px solid #e9ecef; | |
| } | |
| .file-preview { | |
| margin-top: 1rem; | |
| padding: 1rem; | |
| background: var(--light-color); | |
| border-radius: 8px; | |
| max-height: 200px; | |
| overflow-y: auto; | |
| } | |
| .language-selector { | |
| display: flex; | |
| gap: 1rem; | |
| margin-bottom: 1.5rem; | |
| } | |
| .language-box { | |
| flex: 1; | |
| background: white; | |
| border-radius: 10px; | |
| padding: 1rem; | |
| box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); | |
| } | |
| .language-label { | |
| font-size: 0.9rem; | |
| color: #6c757d; | |
| margin-bottom: 0.5rem; | |
| display: block; | |
| } | |
| .progress-container { | |
| margin-top: 1rem; | |
| display: none; | |
| } | |
| @media (max-width: 768px) { | |
| .main-container { | |
| padding: 1rem; | |
| margin: 1rem; | |
| } | |
| .language-selector { | |
| flex-direction: column; | |
| gap: 0.5rem; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="main-container"> | |
| <div class="header"> | |
| <div class="logo"> | |
| <i class="fas fa-language"></i> | |
| </div> | |
| <h1 class="title">AI Document Translator Pro</h1> | |
| <p class="subtitle">Traduisez vos documents en un clic avec une intelligence artificielle avancée</p> | |
| </div> | |
| <div class="upload-section text-center"> | |
| <form id="uploadForm"> | |
| <div class="mb-3"> | |
| <label for="fileInput" class="form-label"> | |
| <i class="fas fa-cloud-upload-alt fa-3x mb-3" style="color: #4361ee;"></i> | |
| <p class="text-muted">Cliquez pour parcourir vos fichiers</p> | |
| </label> | |
| <input type="file" id="fileInput" name="file" class="form-control d-none" required> | |
| <div class="file-info"> | |
| Formats supportés: <b>TXT, PDF, DOCX, PPTX, XLSX</b> (Max 10MB) | |
| </div> | |
| </div> | |
| <div class="language-selector"> | |
| <div class="language-box"> | |
| <span class="language-label">Langue source</span> | |
| <select id="src_lang" name="src_lang" class="form-select"> | |
| <option>Francais</option> | |
| <option>Anglais</option> | |
| <option>Espagnol</option> | |
| <option>Arabe</option> | |
| </select> | |
| </div> | |
| <div class="language-box"> | |
| <span class="language-label">Langue cible</span> | |
| <select id="tgt_lang" name="tgt_lang" class="form-select"> | |
| <option>Francais</option> | |
| <option>Anglais</option> | |
| <option>Espagnol</option> | |
| <option>Arabe</option> | |
| </select> | |
| </div> | |
| </div> | |
| <button type="submit" class="btn btn-primary mt-3"> | |
| <i class="fas fa-exchange-alt me-2"></i> Traduire le document | |
| </button> | |
| </form> | |
| </div> | |
| <div class="result-container"> | |
| <div class="result-header"> | |
| <h5><i class="fas fa-file-alt me-2"></i> Résultat de la traduction</h5> | |
| </div> | |
| <div class="result-box" id="result"> | |
| <div class="text-center text-muted py-5"> | |
| <i class="fas fa-language fa-3x mb-3"></i> | |
| <p>Aucun résultat pour le moment.<br>Votre traduction apparaîtra ici.</p> | |
| </div> | |
| </div> | |
| <div class="file-preview" id="filePreview" style="display: none;"> | |
| <h6><i class="fas fa-file me-2"></i> Aperçu du fichier</h6> | |
| <div id="previewContent"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| $(document).ready(function() { | |
| $('.upload-section').click(function() { | |
| $('#fileInput').click(); | |
| }); | |
| $('#fileInput').change(function() { | |
| const file = this.files[0]; | |
| if (file) { | |
| $('.file-info').html(`<i class="fas fa-file me-1"></i> ${file.name} (${formatFileSize(file.size)})`); | |
| if (file.type === "text/plain" || file.name.endsWith('.txt')) { | |
| const reader = new FileReader(); | |
| reader.onload = function(e) { | |
| $('#previewContent').text(e.target.result.substring(0, 1000)); | |
| $('#filePreview').show(); | |
| }; | |
| reader.readAsText(file); | |
| } else { | |
| $('#filePreview').hide(); | |
| } | |
| } | |
| }); | |
| $('#uploadForm').submit(async function(event) { | |
| event.preventDefault(); | |
| const formData = new FormData(this); | |
| const file = $('#fileInput')[0].files[0]; | |
| if (!file) { | |
| Swal.fire({ | |
| icon: 'error', | |
| title: 'Erreur', | |
| text: 'Veuillez sélectionner un fichier à traduire', | |
| confirmButtonColor: '#4361ee' | |
| }); | |
| return; | |
| } | |
| Swal.fire({ | |
| title: 'Traduction en cours', | |
| html: 'Votre document est en cours de traitement...', | |
| allowOutsideClick: false, | |
| didOpen: () => { | |
| Swal.showLoading(); | |
| } | |
| }); | |
| try { | |
| let response = await fetch('https://rayhane123-ai-traduction.hf.space/upload/', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| let result = await response.json(); | |
| Swal.close(); | |
| if (result.translated_text) { | |
| $('#result').html(`<div class="translated-content">${formatTranslatedText(result.translated_text)}</div>`); | |
| Swal.fire({ | |
| icon: 'success', | |
| title: 'Traduction terminée!', | |
| text: 'Votre document a été traduit avec succès', | |
| confirmButtonColor: '#4361ee' | |
| }); | |
| } else { | |
| $('#result').html(`<div class="alert alert-danger">❌ Erreur: ${result.detail || 'Une erreur est survenue lors de la traduction'}</div>`); | |
| Swal.fire({ | |
| icon: 'error', | |
| title: 'Erreur', | |
| text: result.detail || 'Une erreur est survenue lors de la traduction', | |
| confirmButtonColor: '#4361ee' | |
| }); | |
| } | |
| } catch (error) { | |
| console.error('Error:', error); | |
| Swal.fire({ | |
| icon: 'error', | |
| title: 'Erreur', | |
| text: 'Une erreur est survenue lors de la connexion au serveur', | |
| confirmButtonColor: '#4361ee' | |
| }); | |
| $('#result').html(`<div class="alert alert-danger">❌ Erreur de connexion au serveur</div>`); | |
| } | |
| }); | |
| function formatTranslatedText(text) { | |
| return text.split('\n').map(paragraph => { | |
| return paragraph.trim() ? `<p>${paragraph}</p>` : ''; | |
| }).join(''); | |
| } | |
| function formatFileSize(bytes) { | |
| if (bytes === 0) return '0 Bytes'; | |
| const k = 1024; | |
| const sizes = ['Bytes', 'KB', 'MB', 'GB']; | |
| const i = Math.floor(Math.log(bytes) / Math.log(k)); | |
| return parseFloat((bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i]; | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |