// Global variables let sourceText = ""; let targetText = ""; let sourceFile = null; let targetFile = null; let sourceFileType = ""; let targetFileType = ""; let documentType = "regular"; // Default document type: "regular" or "official" let analysis = null; let correctedSourceText = ""; // For storing corrected text in case of official documents let detectedCountry = ""; // For storing detected country from document // Initialize when DOM is loaded document.addEventListener("DOMContentLoaded", function() { initializeApp(); }); // Initialize application function initializeApp() { // Initialize document type selector initDocumentTypeSelector(); // Initialize file upload listeners initFileUploadListeners(); // Initialize text area listeners initTextAreaListeners(); // Initialize button listeners initButtonListeners(); // Initialize display options initDisplayOptions(); // Initialize filter options initFilterOptions(); } // Initialize document type selector function initDocumentTypeSelector() { // Create document type selector (radio buttons) const selectorHtml = `

نوع الملف:

`; // Insert before source file upload section const sourceFileSection = document.querySelector("#sourceFileSection"); sourceFileSection.insertAdjacentHTML('beforebegin', selectorHtml); // Add event listeners to the radio buttons document.querySelectorAll('input[name="documentType"]').forEach(radio => { radio.addEventListener('change', function() { documentType = this.value; console.log(`Document type changed to: ${documentType}`); }); }); } // Initialize file upload listeners function initFileUploadListeners() { // Source file upload const sourceFileInput = document.getElementById("sourceFileInput"); if (sourceFileInput) { sourceFileInput.addEventListener("change", function(e) { handleFileUpload(e, "source"); }); } // Target file upload const targetFileInput = document.getElementById("targetFileInput"); if (targetFileInput) { targetFileInput.addEventListener("change", function(e) { handleFileUpload(e, "target"); }); } // Drag and drop zones initDragAndDropZones(); } // Initialize drag and drop zones function initDragAndDropZones() { const sourceDropZone = document.getElementById("sourceDropZone"); const targetDropZone = document.getElementById("targetDropZone"); // Source drop zone if (sourceDropZone) { ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { sourceDropZone.addEventListener(eventName, preventDefaults, false); }); ['dragenter', 'dragover'].forEach(eventName => { sourceDropZone.addEventListener(eventName, function() { this.classList.add('bg-blue-100'); }, false); }); ['dragleave', 'drop'].forEach(eventName => { sourceDropZone.addEventListener(eventName, function() { this.classList.remove('bg-blue-100'); }, false); }); sourceDropZone.addEventListener('drop', function(e) { const dt = e.dataTransfer; if (dt.files.length) { document.getElementById('sourceFileInput').files = dt.files; handleFileUpload({ target: { files: dt.files } }, "source"); } }, false); } // Target drop zone if (targetDropZone) { ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { targetDropZone.addEventListener(eventName, preventDefaults, false); }); ['dragenter', 'dragover'].forEach(eventName => { targetDropZone.addEventListener(eventName, function() { this.classList.add('bg-blue-100'); }, false); }); ['dragleave', 'drop'].forEach(eventName => { targetDropZone.addEventListener(eventName, function() { this.classList.remove('bg-blue-100'); }, false); }); targetDropZone.addEventListener('drop', function(e) { const dt = e.dataTransfer; if (dt.files.length) { document.getElementById('targetFileInput').files = dt.files; handleFileUpload({ target: { files: dt.files } }, "target"); } }, false); } } // Prevent default behavior for drag and drop function preventDefaults(e) { e.preventDefault(); e.stopPropagation(); } // Initialize text area listeners function initTextAreaListeners() { const sourceTextArea = document.getElementById("sourceTextArea"); const targetTextArea = document.getElementById("targetTextArea"); if (sourceTextArea) { sourceTextArea.addEventListener("input", function() { sourceText = this.value; }); } if (targetTextArea) { targetTextArea.addEventListener("input", function() { targetText = this.value; }); } } // Initialize button listeners function initButtonListeners() { // Analyze button const analyzeBtn = document.getElementById("analyzeBtn"); if (analyzeBtn) { analyzeBtn.addEventListener("click", startAnalysis); } // Export report button const exportReportBtn = document.getElementById("exportReportBtn"); if (exportReportBtn) { exportReportBtn.addEventListener("click", exportReport); } // Clear all button const clearAllBtn = document.getElementById("clearAllBtn"); if (clearAllBtn) { clearAllBtn.addEventListener("click", clearAll); } } // Initialize display options function initDisplayOptions() { // Remove classic display option as per requirements const displayOptions = document.querySelectorAll('.display-option'); displayOptions.forEach(option => { if (option.dataset.display === 'classic') { option.remove(); } }); // Set split view as default const splitViewOption = document.querySelector('.display-option[data-display="split"]'); if (splitViewOption) { splitViewOption.classList.add('active'); setDisplayMode('split'); } // Add display option listeners document.querySelectorAll('.display-option').forEach(option => { option.addEventListener('click', function() { document.querySelectorAll('.display-option').forEach(opt => opt.classList.remove('active')); this.classList.add('active'); setDisplayMode(this.dataset.display); }); }); } // Initialize filter options function initFilterOptions() { document.querySelectorAll('.filter-option').forEach(option => { option.addEventListener('click', function() { this.classList.toggle('active'); applyFilters(); }); }); } // Handle file upload function handleFileUpload(event, type) { const file = event.target.files[0]; if (!file) return; // Store file if (type === "source") { sourceFile = file; document.getElementById("sourceFileName").textContent = file.name; } else { targetFile = file; document.getElementById("targetFileName").textContent = file.name; } // Process file based on type processFile(file, type); } // Process file based on file extension async function processFile(file, textType) { const fileExtension = file.name.split('.').pop().toLowerCase(); const fileType = file.type; // Show loading indicator toggleLoading(true, textType); try { let extractedText = ""; // Process based on file extension/type if (fileType.includes('pdf') || fileExtension === 'pdf') { extractedText = await processPDF(file); } else if (fileType.includes('image') || ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(fileExtension)) { extractedText = await processImage(file); } else if (fileExtension === 'docx' || fileExtension === 'doc') { extractedText = await processDocx(file); } else if (['xlsx', 'xls', 'csv'].includes(fileExtension)) { extractedText = await processExcel(file); } else if (fileType.includes('text') || fileExtension === 'txt') { extractedText = await processTextFile(file); } else { throw new Error("Unsupported file format. Please use PDF, image, Word, Excel, or text files."); } // If document type is "official", correct the fixed terms if (documentType === "official" && textType === "source") { showNotification("جاري تصحيح الثوابت في المستند الرسمي...", "info"); correctedSourceText = await correctOfficialDocument(extractedText); // Update extracted text with corrected text extractedText = correctedSourceText; showNotification("تم تصحيح الثوابت بنجاح", "success"); } // Update UI with extracted text if (textType === "source") { sourceText = extractedText; sourceFileType = fileExtension; document.getElementById("sourceTextArea").value = extractedText; } else { targetText = extractedText; targetFileType = fileExtension; document.getElementById("targetTextArea").value = extractedText; } // Show preview if it's a PDF if (fileType.includes('pdf') || fileExtension === 'pdf') { showPDFPreview(file, textType); } // Show OCR results showOCRResults(extractedText, textType); // Enable analyze button if both texts are available if (sourceText && targetText) { document.getElementById("analyzeBtn").disabled = false; } } catch (error) { console.error("Error processing file:", error); showNotification(`خطأ في معالجة الملف: ${error.message}`, "error"); } finally { // Hide loading indicator toggleLoading(false, textType); } } // Process PDF file async function processPDF(file) { return new Promise((resolve, reject) => { const fileReader = new FileReader(); fileReader.onload = async function() { try { const typedArray = new Uint8Array(this.result); // Load the PDF using pdf.js const pdf = await pdfjsLib.getDocument({ data: typedArray }).promise; let text = ""; // Extract text from all pages for (let i = 1; i <= pdf.numPages; i++) { const page = await pdf.getPage(i); const textContent = await page.getTextContent(); const pageText = textContent.items.map(item => item.str).join(' '); text += pageText + "\n"; } resolve(text); } catch (error) { console.error("Error extracting text from PDF:", error); reject(error); } }; fileReader.onerror = function() { reject(new Error("Error reading the PDF file.")); }; fileReader.readAsArrayBuffer(file); }); } // Process image using OCR async function processImage(file) { return new Promise((resolve, reject) => { const fileReader = new FileReader(); fileReader.onload = async function() { try { // Here we would typically call an OCR API // For now, we'll simulate it with a placeholder showNotification("جاري استخراج النص من الصورة...", "info"); // This is where you would call your OCR API // For example, using Tesseract.js or a cloud OCR API // Simulate OCR processing delay await new Promise(res => setTimeout(res, 2000)); // Placeholder for OCR result // In a real implementation, replace this with actual OCR API call const ocrResult = "هذا نص تم استخراجه من الصورة باستخدام تقنية OCR.\nيمكنك استبدال هذا النص بنتائج OCR الفعلية من API الخاص بك."; resolve(ocrResult); } catch (error) { console.error("Error processing image:", error); reject(error); } }; fileReader.onerror = function() { reject(new Error("Error reading the image file.")); }; fileReader.readAsDataURL(file); }); } // Process Word document async function processDocx(file) { return new Promise((resolve, reject) => { const fileReader = new FileReader(); fileReader.onload = async function() { try { // Use mammoth.js to extract text from DOCX const arrayBuffer = this.result; const result = await mammoth.extractRawText({ arrayBuffer }); resolve(result.value); } catch (error) { console.error("Error extracting text from DOCX:", error); reject(error); } }; fileReader.onerror = function() { reject(new Error("Error reading the Word document.")); }; fileReader.readAsArrayBuffer(file); }); } // Process Excel file async function processExcel(file) { return new Promise((resolve, reject) => { const fileReader = new FileReader(); fileReader.onload = async function() { try { const data = new Uint8Array(this.result); const workbook = XLSX.read(data, { type: 'array' }); // Extract text from all sheets let text = ""; workbook.SheetNames.forEach(sheetName => { const worksheet = workbook.Sheets[sheetName]; const sheetText = XLSX.utils.sheet_to_txt(worksheet); text += `[Sheet: ${sheetName}]\n${sheetText}\n\n`; }); resolve(text); } catch (error) { console.error("Error extracting text from Excel:", error); reject(error); } }; fileReader.onerror = function() { reject(new Error("Error reading the Excel file.")); }; fileReader.readAsArrayBuffer(file); }); } // Process text file async function processTextFile(file) { return new Promise((resolve, reject) => { const fileReader = new FileReader(); fileReader.onload = function() { try { resolve(this.result); } catch (error) { console.error("Error reading text file:", error); reject(error); } }; fileReader.onerror = function() { reject(new Error("Error reading the text file.")); }; fileReader.readAsText(file); }); } // Correct official document using DeepSeek API async function correctOfficialDocument(text) { try { // First, detect the country from the document detectedCountry = await detectCountryFromDocument(text); console.log("Detected country:", detectedCountry); // Prepare the prompt for DeepSeek API based on the detected country const prompt = prepareFixedTermsPrompt(text, detectedCountry); // Call DeepSeek API for correction const correctionResponse = await callDeepSeekAPI(prompt, "correction"); // Extract the corrected text from the response return extractCorrectedText(correctionResponse, text); } catch (error) { console.error("Error correcting official document:", error); showNotification("حدث خطأ أثناء تصحيح المستند الرسمي", "error"); return text; // Return original text if correction fails } } // Detect country from document text async function detectCountryFromDocument(text) { try { const prompt = ` أنت خبير في تحليل المستندات الرسمية. قم بتحليل النص التالي وتحديد الدولة التي ينتمي إليها هذا المستند بناءً على المحتوى، الصياغة، المصطلحات المستخدمة، أو أي مؤشرات أخرى. أعطني اسم الدولة فقط دون أي توضيح إضافي. النص: ${text} `; // Call DeepSeek API for country detection const response = await callDeepSeekAPI(prompt, "country-detection"); // Process the response to extract just the country name let country = response.trim(); // If multiple lines, take the first line if (country.includes('\n')) { country = country.split('\n')[0]; } return country; } catch (error) { console.error("Error detecting country:", error); return "غير محدد"; // Default if detection fails } } // Prepare prompt for fixed terms correction based on country function prepareFixedTermsPrompt(text, country) { return ` أنت خبير في تصحيح المستندات الرسمية للدولة: ${country}. مهمتك هي تصحيح المصطلحات الثابتة فقط في المستند الرسمي التالي، مع الحفاظ على البيانات المتغيرة كما هي تماماً. قواعد التصحيح: 1. صحح فقط المصطلحات والعبارات الثابتة مثل "الاسم"، "تاريخ الميلاد"، "الجنسية"، "الرقم القومي"، "رقم الهوية". 2. لا تغير أبداً البيانات المتغيرة مثل أسماء الأشخاص، التواريخ، الأرقام، إلخ. 3. حافظ على التنسيق الأصلي للنص. 4. أعد النص كاملاً بعد التصحيح. على سبيل المثال: - إذا كان النص يحتوي على "الأثم: محمد أحمد"، قم بتصحيحه إلى "الاسم: محمد أحمد" - إذا كان النص يحتوي على "تاريخ الميلات: 1990/05/15"، قم بتصحيحه إلى "تاريخ الميلاد: 1990/05/15" النص المراد تصحيحه: ${text} أعد النص كاملاً بعد التصحيح دون أي توضيحات إضافية. `; } // Extract corrected text from API response function extractCorrectedText(response, originalText) { // This function should parse the API response to extract just the corrected text // If the API returns explanations or other content, strip those out // For now, we'll just return the response as is, assuming it's clean return response; } // Call DeepSeek API async function callDeepSeekAPI(prompt, type) { // This function would typically make an API call to DeepSeek // For now, we'll simulate it with a placeholder response console.log(`Calling DeepSeek API for ${type} with prompt:`, prompt); // Simulate API delay await new Promise(res => setTimeout(res, 3000)); // Simulate different responses based on the type of request if (type === "correction") { // Simulate a corrected document return prompt.replace("الأثم:", "الاسم:") .replace("تاريخ الميلات:", "تاريخ الميلاد:") .replace("الجنسيه:", "الجنسية:") .replace("رقم القومى:", "الرقم القومي:"); } else if (type === "country-detection") { // Simulate country detection return "مصر"; } else if (type === "analysis") { // Simulate analysis response return { differences: [ { sourceText: "هذا النص الأصلي يحتوي على خطأ.", targetText: "هذا النص المترجم يحتوي على خطأ مختلف.", errorType: "grammar", explanation: "الجملة في النص المترجم تحتوي على خطأ نحوي.", severity: "medium" }, // More differences... ], summary: "تم العثور على 5 اختلافات بين النصين، منها 2 خطأ نحوي و3 أخطاء إملائية." }; } return "عذراً، حدث خطأ في معالجة طلبك."; } // Start analysis of texts async function startAnalysis() { if (!sourceText || !targetText) { showNotification("يرجى إدخال أو تحميل النصين المصدر والهدف", "error"); return; } try { // Show loading indicator toggleLoading(true, "analysis"); showNotification("جاري تحليل النصوص...", "info"); // Prepare prompt for analysis const analysisPrompt = ` قم بتحليل النصين التاليين ومقارنتهما لتحديد الاختلافات والأخطاء: النص المصدر: ${sourceText} النص الهدف: ${targetText} قم بتحديد الاختلافات التالية: 1. الأخطاء النحوية 2. الأخطاء الإملائية 3. الاختلافات في المعنى 4. الكلمات أو العبارات المفقودة 5. الإضافات غير الضرورية لكل اختلاف، قدم: - النص المصدر - النص الهدف - نوع الخطأ - شرح الخطأ - مستوى خطورة الخطأ (منخفض، متوسط، مرتفع) `; // Call DeepSeek API for analysis const apiResponse = await callDeepSeekAPI(analysisPrompt, "analysis"); // Process the analysis results analysis = apiResponse; // In a real implementation, this would parse the API response // Display analysis results displayAnalysisResults(analysis); // Enable report export document.getElementById("exportReportBtn").disabled = false; showNotification("تم الانتهاء من التحليل بنجاح", "success"); } catch (error) { console.error("Error during analysis:", error); showNotification(`خطأ في التحليل: ${error.message}`, "error"); } finally { // Hide loading indicator toggleLoading(false, "analysis"); } } // Display analysis results with improved highlighting and explanation function displayAnalysisResults(analysis) { const resultsContainer = document.getElementById("resultsContainer"); resultsContainer.innerHTML = ""; // Create summary section const summarySection = document.createElement("div"); summarySection.className = "mb-6 p-4 bg-gray-50 rounded-lg"; summarySection.innerHTML = `

ملخص التحليل

${analysis.summary}

`; resultsContainer.appendChild(summarySection); // Create differences section with improved display const differencesSection = document.createElement("div"); differencesSection.className = "differences-section"; // Group differences by paragraphs for better organization const groupedDifferences = groupDifferencesByParagraph(analysis.differences); // Create each paragraph section let paragraphIndex = 1; for (const [paragraph, differences] of Object.entries(groupedDifferences)) { const paragraphSection = document.createElement("div"); paragraphSection.className = "paragraph-section mb-8 p-4 bg-white rounded-lg shadow"; paragraphSection.innerHTML = `

فقرة ${paragraphIndex}

${highlightDifferencesInParagraph(paragraph, differences)}

الاختلافات المكتشفة:

`; differencesSection.appendChild(paragraphSection); paragraphIndex++; } resultsContainer.appendChild(differencesSection); // Show results container document.getElementById("resultsSection").classList.remove("hidden"); // Add tooltip popups to highlighted differences addTooltipsToHighlights(); } // Group differences by paragraph for better organization function groupDifferencesByParagraph(differences) { const paragraphMap = {}; differences.forEach(diff => { // Use the source text to determine the paragraph const paragraph = extractParagraphFromText(diff.sourceText, sourceText); if (!paragraphMap[paragraph]) { paragraphMap[paragraph] = []; } paragraphMap[paragraph].push(diff); }); return paragraphMap; } // Extract the paragraph containing the given text function extractParagraphFromText(snippet, fullText) { // Split the full text into paragraphs const paragraphs = fullText.split(/\n\s*\n/); // Find the paragraph containing the snippet for (const paragraph of paragraphs) { if (paragraph.includes(snippet)) { return paragraph; } } // If not found, return the snippet itself return snippet; } // Highlight differences in paragraph function highlightDifferencesInParagraph(paragraph, differences) { let highlightedText = paragraph; // Sort differences by their position in the paragraph (to handle overlaps correctly) differences.sort((a, b) => { const posA = paragraph.indexOf(a.sourceText); const posB = paragraph.indexOf(b.sourceText); return posA - posB; }); // Apply highlights to each difference let offset = 0; differences.forEach(diff => { const diffId = `diff-${Math.random().toString(36).substr(2, 9)}`; const originalText = diff.sourceText; const startPos = paragraph.indexOf(originalText, offset); if (startPos !== -1) { // Find the sentence containing the difference const sentenceMatch = findSentenceContaining(paragraph, startPos, originalText.length); if (sentenceMatch) { const { start, end } = sentenceMatch; const sentence = paragraph.substring(start, end); // Create highlighted version of the sentence const highlightedSentence = `${sentence}`; // Replace the sentence in the text highlightedText = highlightedText.substring(0, start) + highlightedSentence + highlightedText.substring(end); // Update offset to account for the added HTML offset = end + (highlightedSentence.length - sentence.length); // Store difference details for the tooltip window.diffDetails = window.diffDetails || {}; window.diffDetails[diffId] = diff; } } }); return highlightedText; } // Find the sentence containing the difference function findSentenceContaining(text, position, length) { // Look for sentence boundaries (period, question mark, exclamation mark followed by space or newline) const sentenceEnders = ['. ', '? ', '! ', '.\n', '?\n', '!\n']; let start = position; while (start > 0) { let foundBoundary = false; for (const ender of sentenceEnders) { const endPos = text.lastIndexOf(ender, start); if (endPos !== -1 && endPos + ender.length <= start) { start = endPos + ender.length; foundBoundary = true; break; } } if (foundBoundary || start === 0) break; start--; } let end = position + length; while (end < text.length) { let foundBoundary = false; for (const ender of sentenceEnders) { const endPos = text.indexOf(ender, end - ender.length + 1); if (endPos !== -1 && endPos >= end - ender.length + 1) { end = endPos + ender.length; foundBoundary = true; break; } } if (foundBoundary || end === text.length) break; end++; } return { start, end }; } // Add tooltips to highlighted differences function addTooltipsToHighlights() { document.querySelectorAll('.highlighted-sentence').forEach(el => { el.addEventListener('click', function() { const diffId = this.dataset.diffId; const diff = window.diffDetails[diffId]; if (diff) { showDifferencePopup(diff, this); } }); }); } // Show popup with difference details function showDifferencePopup(diff, element) { // Remove any existing popups const existingPopup = document.getElementById('difference-popup'); if (existingPopup) { existingPopup.remove(); } // Create popup element const popup = document.createElement('div'); popup.id = 'difference-popup'; popup.className = 'fixed bg-white rounded-lg shadow-lg p-4 max-w-md z-50'; popup.style.maxWidth = '90vw'; // Create popup content popup.innerHTML = `

${getErrorTypeLabel(diff.errorType)}

${getSeverityLabel(diff.severity)}
النص الأصلي:

${diff.sourceText}

النص المترجم:

${diff.targetText}

الشرح:

${diff.explanation}

`; // Position the popup near the element document.body.appendChild(popup); positionPopup(popup, element); // Add close button event listener document.getElementById('close-popup').addEventListener('click', function() { popup.remove(); }); // Close popup when clicking outside document.addEventListener('click', function closePopup(e) { if (!popup.contains(e.target) && e.target !== element) { popup.remove(); document.removeEventListener('click', closePopup); } }); } // Position popup near the target element function positionPopup(popup, element) { const rect = element.getBoundingClientRect(); const popupRect = popup.getBoundingClientRect(); // Default position below the element let top = rect.bottom + window.scrollY + 10; let left = rect.left + window.scrollX; // Check if popup would go below viewport if (top + popupRect.height > window.innerHeight + window.scrollY) { // Position above the element instead top = rect.top + window.scrollY - popupRect.height - 10; } // Ensure popup doesn't go off-screen horizontally if (left + popupRect.width > window.innerWidth) { left = window.innerWidth - popupRect.width - 10; } popup.style.top = `${top}px`; popup.style.left = `${left}px`; } // Set display mode function setDisplayMode(mode) { const resultsContainer = document.getElementById("resultsContainer"); // Remove existing display mode classes resultsContainer.classList.remove('display-classic', 'display-split', 'display-side-by-side'); // Add new display mode class resultsContainer.classList.add(`display-${mode}`); } // Apply filters to displayed results function applyFilters() { const activeFilters = Array.from(document.querySelectorAll('.filter-option.active')) .map(el => el.dataset.filter); // Show all differences initially document.querySelectorAll('.difference-item').forEach(item => { item.classList.remove('hidden'); }); // If no filters are active, show all if (activeFilters.length === 0) { return; } // Hide differences that don't match active filters document.querySelectorAll('.difference-item').forEach(item => { const errorType = item.querySelector('.error-type').textContent; const severity = item.querySelector('.severity-badge').textContent; const matchesFilter = activeFilters.some(filter => { if (filter.startsWith('type-')) { return errorType === filter.replace('type-', ''); } else if (filter.startsWith('severity-')) { return severity === filter.replace('severity-', ''); } return false; }); if (!matchesFilter) { item.classList.add('hidden'); } }); } // Export analysis report function exportReport() { if (!analysis) { showNotification("لا توجد نتائج تحليل للتصدير", "error"); return; } try { // Create report content const reportContent = generateReportContent(); // Create blob and download link const blob = new Blob([reportContent], { type: 'text/plain;charset=utf-8' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `تقرير_تحليل_الترجمة_${new Date().toISOString().slice(0, 10)}.txt`; a.click(); URL.revokeObjectURL(url); showNotification("تم تصدير التقرير بنجاح", "success"); } catch (error) { console.error("Error exporting report:", error); showNotification("حدث خطأ أثناء تصدير التقرير", "error"); } } // Generate report content function generateReportContent() { let content = "تقرير تحليل الترجمة\n"; content += "===================\n\n"; // Add date and time content += `تاريخ التحليل: ${new Date().toLocaleString('ar-EG')}\n\n`; // Add summary content += "ملخص التحليل:\n"; content += "-------------\n"; content += analysis.summary + "\n\n"; // Add detailed differences content += "تفاصيل الاختلافات:\n"; content += "------------------\n\n"; analysis.differences.forEach((diff, index) => { content += `${index + 1}. ${getErrorTypeLabel(diff.errorType)} (${getSeverityLabel(diff.severity)})\n`; content += ` النص الأصلي: ${diff.sourceText}\n`; content += ` النص المترجم: ${diff.targetText}\n`; content += ` الشرح: ${diff.explanation}\n\n`; }); // Add footer content += "تم إنشاء هذا التقرير بواسطة نظام تحليل الترجمة - شركة الريحان للترجمة"; return content; } // Clear all inputs and results function clearAll() { // Clear text areas document.getElementById("sourceTextArea").value = ""; document.getElementById("targetTextArea").value = ""; // Clear file names document.getElementById("sourceFileName").textContent = "لم يتم اختيار ملف"; document.getElementById("targetFileName").textContent = "لم يتم اختيار ملف"; // Clear OCR results document.getElementById("sourceOCRResults").innerHTML = ""; document.getElementById("targetOCRResults").innerHTML = ""; // Clear analysis results document.getElementById("resultsContainer").innerHTML = ""; document.getElementById("resultsSection").classList.add("hidden"); // Reset PDF previews document.getElementById("sourcePDFPreview").innerHTML = ""; document.getElementById("targetPDFPreview").innerHTML = ""; document.getElementById("sourcePDFSection").classList.add("hidden"); document.getElementById("targetPDFSection").classList.add("hidden"); // Reset global variables sourceText = ""; targetText = ""; sourceFile = null; targetFile = null; sourceFileType = ""; targetFileType = ""; analysis = null; correctedSourceText = ""; detectedCountry = ""; // Reset document type to "regular" document.querySelector('input[name="documentType"][value="regular"]').checked = true; documentType = "regular"; // Disable buttons document.getElementById("analyzeBtn").disabled = true; document.getElementById("exportReportBtn").disabled = true; showNotification("تم مسح جميع البيانات", "info"); } // Show PDF preview function showPDFPreview(file, type) { const previewSection = document.getElementById(`${type}PDFSection`); const previewContainer = document.getElementById(`${type}PDFPreview`); // Clear previous preview previewContainer.innerHTML = ""; // Create PDF viewer const viewer = document.createElement("div"); viewer.className = "pdf-viewer"; // Create PDF embed const embed = document.createElement("embed"); embed.src = URL.createObjectURL(file); embed.type = "application/pdf"; embed.width = "100%"; embed.height = "500px"; viewer.appendChild(embed); previewContainer.appendChild(viewer); // Show preview section previewSection.classList.remove("hidden"); } // Show OCR results function showOCRResults(text, type) { const resultsContainer = document.getElementById(`${type}OCRResults`); // Create results display resultsContainer.innerHTML = `
${text}
`; } // Show notification function showNotification(message, type = "info") { // Create notification element if it doesn't exist let notification = document.getElementById("notification"); if (!notification) { notification = document.createElement("div"); notification.id = "notification"; notification.className = "fixed bottom-4 right-4 p-4 rounded-lg shadow-lg transform transition-opacity duration-300 opacity-0"; document.body.appendChild(notification); } // Set notification type notification.className = notification.className.replace(/bg-\w+-\d+/g, ""); switch (type) { case "success": notification.classList.add("bg-green-500", "text-white"); break; case "error": notification.classList.add("bg-red-500", "text-white"); break; case "warning": notification.classList.add("bg-yellow-500", "text-white"); break; default: notification.classList.add("bg-blue-500", "text-white"); } // Set message notification.textContent = message; // Show notification notification.classList.replace("opacity-0", "opacity-100"); // Hide notification after 3 seconds setTimeout(() => { notification.classList.replace("opacity-100", "opacity-0"); }, 3000); } // Toggle loading indicator function toggleLoading(show, section) { const loadingIndicators = { "source": document.getElementById("sourceLoadingIndicator"), "target": document.getElementById("targetLoadingIndicator"), "analysis": document.getElementById("analysisLoadingIndicator") }; const indicator = loadingIndicators[section]; if (indicator) { if (show) { indicator.classList.remove("hidden"); } else { indicator.classList.add("hidden"); } } } // Helper functions for displaying error types and severity function getErrorTypeLabel(errorType) { const labels = { "grammar": "خطأ نحوي", "spelling": "خطأ إملائي", "meaning": "اختلاف في المعنى", "missing": "نص مفقود", "addition": "إضافة غير ضرورية", "terminology": "مصطلح غير دقيق" }; return labels[errorType] || errorType; } function getSeverityLabel(severity) { const labels = { "low": "منخفض", "medium": "متوسط", "high": "مرتفع" }; return labels[severity] || severity; } function getSeverityColor(severity) { const colors = { "low": "yellow", "medium": "orange", "high": "red" }; return colors[severity] || "gray"; }