Spaces:
Running
Running
| <html lang="ar" dir="rtl"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>AZIZI JAOUAD </title> | |
| <style> | |
| /* (نفس الـ CSS السابق، مع تغييرات طفيفة إذا لزم الأمر) */ | |
| body { | |
| font-family: 'Cairo', sans-serif; /* أو أي خط عربي آخر تفضله */ | |
| background: linear-gradient(135deg, #7f7fd5, #86a8e7, #91eae4); | |
| color: #333; | |
| margin: 0; | |
| padding: 0; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| min-height: 100vh; | |
| overflow-x: hidden; /* منع الشريط الأفقي */ | |
| } | |
| header { | |
| background-color: rgba(255, 255, 255, 0.9); | |
| padding: 20px 0; | |
| text-align: center; | |
| width: 100%; | |
| box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); | |
| border-bottom: 1px solid rgba(0, 0, 0, 0.05); | |
| } | |
| header h1 { | |
| margin: 0; | |
| font-size: 2.5em; | |
| color: #2c3e50; | |
| text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); | |
| white-space: nowrap; /* منع التفاف النص */ | |
| } | |
| header h1 span{ | |
| font-family: 'Noto Sans Tifinagh', sans-serif; /* إضافة خط Tifinagh */ | |
| margin-left: 0.5em; | |
| } | |
| #container { | |
| background-color: white; | |
| padding: 40px; | |
| border-radius: 15px; | |
| box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2); | |
| width: 90%; | |
| max-width: 700px; | |
| margin-top: 40px; | |
| display: flex; | |
| flex-direction: column; | |
| animation: fadeInUp 0.8s ease; /* إضافة تأثير حركي */ | |
| } | |
| /* زر التحديث */ | |
| #refresh-btn { | |
| position: absolute; /* تموضع مطلق */ | |
| top: 10px; | |
| right: 10px; | |
| background-color: transparent; | |
| border: none; | |
| font-size: 1.5em; | |
| color: #3498db; | |
| cursor: pointer; | |
| z-index: 2; /* ليكون فوق العناصر الأخرى */ | |
| transition: transform 0.5s ease; | |
| } | |
| #refresh-btn:hover{ | |
| transform: rotate(360deg); /* دوران عند التحويم */ | |
| } | |
| /* تعديل زر التحديث في حالة اللغة العربية */ | |
| [dir="rtl"] #refresh-btn{ | |
| left: 10px; /* تغيير الجهة في حالة اللغة العربية */ | |
| right: auto; /* إعادة التعيين */ | |
| } | |
| /* مجموعات الإدخال */ | |
| .input-group { | |
| margin-bottom: 25px; | |
| } | |
| .input-group label { | |
| display: block; | |
| margin-bottom: 10px; | |
| font-weight: bold; | |
| color: #555; | |
| font-size: 1.1em; | |
| } | |
| textarea, input[type="text"] { | |
| width: 100%; | |
| padding: 15px; | |
| border: none; | |
| border-radius: 8px; | |
| box-sizing: border-box; | |
| font-size: 1.05em; | |
| background-color: #f7f7f7; | |
| box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1); | |
| transition: box-shadow 0.3s ease; | |
| } | |
| textarea:focus, input[type="text"]:focus { | |
| outline: none; | |
| box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1), 0 0 8px rgba(52, 152, 219, 0.5); | |
| } | |
| /* زر الترجمة */ | |
| #translate-btn { | |
| background-color: #2ecc71; | |
| color: white; | |
| border: none; | |
| padding: 15px 30px; | |
| border-radius: 30px; | |
| cursor: pointer; | |
| font-size: 1.2em; | |
| width: 100%; | |
| transition: all 0.3s ease; | |
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); | |
| } | |
| #translate-btn:hover { | |
| background-color: #27ae60; | |
| box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); | |
| } | |
| /* تذييل الصفحة */ | |
| footer { | |
| margin-top: auto; /* ليكون في الأسفل دائمًا */ | |
| padding: 15px 0; | |
| text-align: center; | |
| width: 100%; | |
| background-color: rgba(255, 255, 255, 0.8); | |
| color: #2c3e50; | |
| font-size: 0.9em; | |
| border-top: 1px solid rgba(0, 0, 0, 0.05); | |
| /* إضافة Flexbox للتذييل */ | |
| display: flex; | |
| align-items: center; /* توسيط رأسي */ | |
| justify-content: center; /* توسيط أفقي */ | |
| } | |
| footer span{ | |
| margin-right: 15px; | |
| } | |
| footer a { | |
| color: #3498db; | |
| text-decoration: none; | |
| margin-left: 10px; | |
| display: inline-flex; /* استخدام Flexbox للرمز والنص */ | |
| align-items: center; /* محاذاة رأسية */ | |
| } | |
| [dir="rtl"] #input-text { | |
| text-align: right; | |
| } | |
| /* تعديل محاذاة مربع النتيجة في حالة اللغة العربية */ | |
| [dir="rtl"] #result-text { | |
| text-align: right; | |
| } | |
| /* تعديل الهوامش في حالة اللغة العربية */ | |
| [dir="rtl"] footer a { | |
| margin-left: 0; /* إزالة الهامش الأيسر */ | |
| margin-right: 10px; /* إضافة هامش أيمن */ | |
| } | |
| [dir="rtl"] footer span{ | |
| margin-left: 15px; | |
| margin-right: 0; | |
| } | |
| /* تأثيرات حركية */ | |
| @keyframes fadeInUp { | |
| from { | |
| opacity: 0; | |
| transform: translateY(20px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| /* رسالة الخطأ */ | |
| .error-message { | |
| color: red; | |
| margin-top: 5px; | |
| text-align: center; | |
| } | |
| /* تنسيق النتيجة */ | |
| .result-item { | |
| padding: 15px; | |
| border-bottom: 1px solid #eee; | |
| margin-bottom: 5px; | |
| background-color: #fafafa; | |
| border-radius: 4px; /* حواف دائرية */ | |
| } | |
| .result-item:last-child { | |
| border-bottom: none; /* إزالة الخط السفلي من آخر عنصر */ | |
| } | |
| .word-cell { | |
| font-weight: bold; | |
| font-size: 1.1em; | |
| margin-bottom: 5px; | |
| } | |
| .translation-cell { | |
| font-style: italic; | |
| color: #333; | |
| margin-bottom: 5px; | |
| } | |
| .additional-cell { | |
| color: #555; | |
| margin-bottom: 3px; | |
| } | |
| /* رسالة "لا توجد نتائج" */ | |
| #no-results { | |
| text-align: center; | |
| font-style: italic; | |
| color: #888; | |
| padding: 20px; | |
| } | |
| /* تنسيق خاص لكلمات Tifinagh */ | |
| .tifinagh { | |
| font-family: 'Noto Sans Tifinagh', sans-serif; | |
| } | |
| #result-text { | |
| font-weight: bold; | |
| } | |
| </style> | |
| <!-- Google Fonts --> | |
| <link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;600;700&display=swap" rel="stylesheet"> | |
| <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Tifinagh&display=swap" rel="stylesheet"> | |
| <!-- Font Awesome --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga+ri4AuTroPR5aQvXU9xC6qOPnzFeg==" crossorigin="anonymous" referrerpolicy="no-referrer" /> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> | |
| </head> | |
| <body> | |
| <header> | |
| <h1>AMAWAL-INU - <span>ⴰⵎⴰⵡⴰⵍ ⵉⵏⵓ</span></h1> | |
| </header> | |
| <div id="container"> | |
| <button id="refresh-btn" title="تحديث الواجهة"><i class="fa fa-refresh"></i></button> | |
| <div class="input-group"> | |
| <label for="input-text">النص المراد ترجمته:</label> | |
| <textarea id="input-text" placeholder="أدخل النص هنا"></textarea> | |
| </div> | |
| <div class="input-group"> | |
| <label for="result-text">النتيجة:</label> | |
| <div id="result-text"></div> | |
| </div> | |
| <div id="errorMessageContainer" class="error-message"></div> | |
| <div id="no-results" style="display: none;">لا توجد نتائج</div> | |
| <button id="translate-btn">ترجم</button> | |
| </div> | |
| <footer> | |
| <span>JAOUADAZIZI@2025-AMAWAL-INU</span> | |
| <a id="feedback-link" href="https://wa.me/message/P3DXRV6NTZ63L1" target="_blank"> | |
| <i class="fab fa-whatsapp"></i> رأيك يهمنا | |
| </a> | |
| </footer> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script> | |
| <script> | |
| // الثوابت | |
| const DICTIONARY_FILE = 'dictionary.xlsx'; | |
| // DOM العناصر | |
| const inputTextarea = document.getElementById('input-text'); | |
| const resultTextDiv = document.getElementById('result-text'); | |
| const translateBtn = document.getElementById('translate-btn'); | |
| const refreshBtn = document.getElementById('refresh-btn'); | |
| const errorMessageContainer = document.getElementById('errorMessageContainer'); | |
| const noResultsMessage = document.getElementById('no-results'); | |
| // كائن المترجم | |
| const translator = { | |
| excelData: [], | |
| // تهيئة المترجم | |
| async init() { | |
| try { | |
| await this.loadDictionary(); | |
| this.setupEventListeners(); | |
| } catch (error) { | |
| this.displayError(error.message); | |
| } | |
| }, | |
| // تحميل القاموس من ملف Excel | |
| async loadDictionary() { | |
| try { | |
| const response = await fetch(DICTIONARY_FILE); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.arrayBuffer(); | |
| this.processExcel(data); | |
| } catch (error) { | |
| console.error('Error loading dictionary file:', error); | |
| throw new Error("Failed to load dictionary file. Please ensure 'dictionary.xlsx' exists and is accessible."); | |
| } | |
| }, | |
| // معالجة بيانات Excel | |
| processExcel(data) { | |
| const workbook = XLSX.read(data, { type: 'array', raw: false }); | |
| const sheetName = workbook.SheetNames[0]; | |
| this.excelData = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName], { header: 1, raw: false }); | |
| }, | |
| // إعداد مستمعي الأحداث | |
| setupEventListeners() { | |
| translateBtn.addEventListener('click', this.translate.bind(this)); | |
| inputTextarea.addEventListener('input', this.translate.bind(this)); // الترجمة عند الإدخال | |
| refreshBtn.addEventListener('click', () => { | |
| location.reload(); // تحديث الصفحة بالكامل | |
| }); | |
| }, | |
| // تحديد لغة الإدخال | |
| detectInputLanguage(text) { | |
| // أمازيغية، لاتينية، عربية، فرنسية | |
| const amazighRegex = /[\u2D30-\u2D7F]/; // Unicode range for Tifinagh | |
| const latinRegex = /^[a-zA-Z0-9\s\u00C0-\u017F]+$/; // Basic Latin + Extended | |
| const arabicRegex = /[\u0600-\u06FF]/; | |
| const frenchRegex = /[\u00C0-\u017F]/; // Extended Latin (for French) | |
| if (amazighRegex.test(text)) { | |
| return 'amazigh'; | |
| } else if (arabicRegex.test(text)) { | |
| return 'arabic'; | |
| }else if(latinRegex.test(text)){ | |
| if (frenchRegex.test(text)) { | |
| return 'french'; | |
| } | |
| return 'latin'; | |
| } | |
| return 'unknown'; | |
| }, | |
| // الترجمة | |
| translate() { | |
| const searchTerm = inputTextarea.value.trim(); | |
| this.clearResults(); | |
| if (!searchTerm) { | |
| return; | |
| } | |
| const inputLanguage = this.detectInputLanguage(searchTerm); | |
| if (inputLanguage === 'unknown') { | |
| // لغة الإدخال غير معروفة | |
| return; | |
| } | |
| let results = {}; | |
| // البحث في القاموس | |
| for (const row of this.excelData) { | |
| let sourceColumnIndex; | |
| switch (inputLanguage) { | |
| case 'amazigh': | |
| sourceColumnIndex = 0; // A | |
| break; | |
| case 'latin': | |
| sourceColumnIndex = 1; // B | |
| break; | |
| case 'french': | |
| sourceColumnIndex = 2; // C | |
| break; | |
| case 'arabic': | |
| sourceColumnIndex = 3; // D | |
| break; | |
| } | |
| // التحقق من أن الصف يحتوي على بيانات في العمود المطلوب | |
| if (row.length > sourceColumnIndex && typeof row[sourceColumnIndex] === 'string') { | |
| //toLowerCase() البحث الدقيق (مع ) | |
| if (row[sourceColumnIndex].toLowerCase().trim() === searchTerm.toLowerCase()) { | |
| results = { | |
| amazigh: inputLanguage === 'amazigh' ? `<b>${row[0]}</b>` : row[0] , | |
| latin: inputLanguage === 'latin' ? `<b>${row[1]}</b>` : row[1], | |
| french: inputLanguage === 'french' ? `<b>${row[2]}</b>` : row[2], | |
| arabic: inputLanguage === 'arabic' ? `<b>${row[3]}</b>` : row[3], | |
| }; | |
| break; // توقف عند أول تطابق | |
| } | |
| } | |
| } | |
| // عرض النتائج | |
| if (Object.keys(results).length > 0) { | |
| let resultHTML = ''; | |
| if(results.amazigh) resultHTML += `<p><span class="tifinagh">${results.amazigh}</span></p>`; | |
| if(results.latin) resultHTML += `<p>${results.latin}</p>`; | |
| if(results.french) resultHTML += `<p>${results.french}</p>`; | |
| if(results.arabic) resultHTML += `<p>${results.arabic}</p>`; | |
| resultTextDiv.innerHTML = resultHTML; | |
| } else { | |
| noResultsMessage.style.display = 'block'; | |
| } | |
| }, | |
| // مسح النتائج السابقة ورسائل الخطأ | |
| clearResults() { | |
| resultTextDiv.innerHTML = ''; | |
| errorMessageContainer.textContent = ''; | |
| noResultsMessage.style.display = 'none'; | |
| }, | |
| // عرض رسالة خطأ | |
| displayError(message) { | |
| errorMessageContainer.textContent = message; | |
| }, | |
| }; | |
| translator.init(); // تهيئة المترجم عند تحميل الصفحة | |
| </script> | |
| </body> | |
| </html> |