Auto commit: 2025-11-20T12:17:08.078Z

This commit is contained in:
Flatlogic Bot 2025-11-20 12:17:08 +00:00
parent 2c882d18a4
commit 28bed0ead6
3 changed files with 160 additions and 22 deletions

View File

@ -68,38 +68,100 @@ document.addEventListener('DOMContentLoaded', function () {
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
// Try to get error message from JSON response, otherwise use status text
return response.json().then(err => {
throw new Error(err.message || response.statusText);
}).catch(() => {
throw new Error(response.statusText);
});
}
return response.json();
})
.then(data => {
if(processingMessage) {
processingMessage.style.display = 'none';
if (data.status === 'success') {
const translatedText = data.data.translatedText;
const outputContainer = document.getElementById('translation-output-container');
const outputElement = document.getElementById('translation-output');
if (outputElement && outputContainer) {
outputElement.textContent = translatedText;
outputContainer.style.display = 'block';
}
if(responseMessageDiv){
const alertClass = data.status === 'success' ? 'alert-success' : 'alert-danger';
responseMessageDiv.innerHTML = `<div class="alert ${alertClass}" role="alert">${data.message}</div>`;
responseMessageDiv.innerHTML = `<div class="alert alert-success" role="alert">${data.message}</div>`;
responseMessageDiv.style.display = 'block';
} else {
responseMessageDiv.innerHTML = `<div class="alert alert-danger" role="alert"><strong>Error:</strong> ${data.message}</div>`;
responseMessageDiv.style.display = 'block';
}
if(translateBtn) {
translateBtn.disabled = false;
translateBtn.innerHTML = 'Translate';
}
})
.catch(error => {
if(processingMessage) {
processingMessage.style.display = 'none';
}
if(responseMessageDiv){
responseMessageDiv.innerHTML = `<div class="alert alert-danger" role="alert">An error occurred during the upload. Please try again.</div>`;
responseMessageDiv.innerHTML = `<div class="alert alert-danger" role="alert">An unexpected error occurred: ${error.message}</div>`;
responseMessageDiv.style.display = 'block';
}
console.error('Fetch Error:', error);
})
.finally(() => {
if(translateBtn) {
translateBtn.disabled = false;
translateBtn.innerHTML = 'Translate';
translateBtn.innerHTML = '<i class="bi bi-stars"></i> Translate';
}
console.error('Error:', error);
});
});
}
// Handle copy and download buttons
const copyBtn = document.getElementById('copy-btn');
const downloadBtn = document.getElementById('download-btn');
const translationOutput = document.getElementById('translation-output');
if (copyBtn) {
copyBtn.addEventListener('click', () => {
if (translationOutput && navigator.clipboard) {
navigator.clipboard.writeText(translationOutput.textContent).then(() => {
const originalText = copyBtn.innerHTML;
copyBtn.innerHTML = '<i class="bi bi-check-lg"></i> Copied!';
copyBtn.classList.add('btn-success');
copyBtn.classList.remove('btn-secondary');
setTimeout(() => {
copyBtn.innerHTML = originalText;
copyBtn.classList.remove('btn-success');
copyBtn.classList.add('btn-secondary');
}, 2000);
}).catch(err => {
console.error('Failed to copy text: ', err);
alert('Failed to copy text. Please try again.');
});
}
});
}
if (downloadBtn) {
downloadBtn.addEventListener('click', () => {
if (translationOutput && window.jspdf) {
try {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
// Set font that supports a wide range of characters
doc.setFont('Helvetica');
doc.setFontSize(12);
const text = translationOutput.textContent;
const lines = doc.splitTextToSize(text, 180);
doc.text(lines, 15, 20);
doc.save('translation.pdf');
} catch (error) {
console.error('Failed to generate PDF:', error);
alert('Failed to generate PDF. An error occurred.');
}
} else if (!window.jspdf) {
alert('The PDF generation library is not loaded.');
}
});
}
});

View File

@ -58,11 +58,20 @@
<label for="source-lang" class="form-label">2. Source Language</label>
<select class="form-select" id="source-lang" required>
<option selected disabled value="">Choose...</option>
<option value="auto">Auto-detect</option>
<option value="en">English</option>
<option value="es">Spanish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="auto">Auto-detect</option>
<option value="it">Italian</option>
<option value="pt">Portuguese</option>
<option value="nl">Dutch</option>
<option value="ru">Russian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="zh">Chinese (Simplified)</option>
<option value="ar">Arabic</option>
<option value="hi">Hindi</option>
</select>
</div>
<div class="col-md-6">
@ -73,6 +82,15 @@
<option value="es">Spanish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="it">Italian</option>
<option value="pt">Portuguese</option>
<option value="nl">Dutch</option>
<option value="ru">Russian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="zh">Chinese (Simplified)</option>
<option value="ar">Arabic</option>
<option value="hi">Hindi</option>
</select>
</div>
</div>
@ -92,6 +110,19 @@
<span>Processing your document... This may take a moment.</span>
</div>
</div>
<div id="translation-output-container" class="card mt-4" style="display: none;">
<div class="card-header fw-bold">
<i class="bi bi-check-circle-fill text-success me-2"></i>Translation Result
</div>
<div class="card-body">
<pre id="translation-output" class="mb-0" style="white-space: pre-wrap; font-family: inherit; font-size: 1rem;"></pre>
</div>
<div class="card-footer bg-light text-end">
<button id="copy-btn" class="btn btn-secondary btn-sm"><i class="bi bi-clipboard me-1"></i> Copy Text</button>
<button id="download-btn" class="btn btn-primary btn-sm"><i class="bi bi-download me-1"></i> Download PDF</button>
</div>
</div>
</div>
</div>
</div>
@ -104,6 +135,7 @@
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
</body>
</html>

View File

@ -47,8 +47,52 @@ $target_path = $upload_dir . $file_name;
// Move the file to the uploads directory
if (move_uploaded_file($file['tmp_name'], $target_path)) {
json_response('success', 'File uploaded successfully.', ['filePath' => 'uploads/' . $file_name]);
// AI Translation Step
try {
require_once __DIR__ . '/ai/LocalAIApi.php';
$source_lang = $_POST['source_lang'] ?? 'auto-detect';
$target_lang = $_POST['target_lang'] ?? 'English';
$file_path_for_ai = 'uploads/' . $file_name; // The path relative to the project root
$prompt = "You are an expert document translator. Please perform the following tasks:\n"
. "1. **OCR Extraction:** Analyze the document located at the following path: `{$file_path_for_ai}`. Extract all visible text from it.\n"
. "2. **Translation:** Translate the extracted text from `{$source_lang}` to `{$target_lang}`.\n"
. "3. **Output:** Return ONLY the translated text as a single block of plain text. Do not include any explanations, apologies, or introductory phrases. Just the translation.";
$resp = LocalAIApi::createResponse(
[
'input' => [
['role' => 'system', 'content' => 'You are a document translation service.'],
['role' => 'user', 'content' => $prompt],
],
]
);
if (!empty($resp['success'])) {
$translated_text = LocalAIApi::extractText($resp);
if ($translated_text === '') {
// Handle cases where the AI returns a non-text response or empty text
$decoded = LocalAIApi::decodeJsonFromResponse($resp);
$error_details = $decoded ? json_encode($decoded, JSON_PRETTY_PRINT) : 'AI returned an empty or invalid response.';
json_response('error', 'AI processing failed. Details: ' . $error_details);
} else {
json_response('success', 'File translated successfully.', [
'filePath' => $file_path_for_ai,
'translatedText' => $translated_text
]);
}
} else {
$error_message = $resp['error'] ?? 'Unknown AI error.';
json_response('error', 'Failed to get response from AI service: ' . $error_message);
}
} catch (Exception $e) {
json_response('error', 'An exception occurred during AI processing: ' . $e->getMessage());
}
} else {
json_response('error', 'Failed to move uploaded file.');
}
?>