File size: 45,889 Bytes
d9e7bdd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 |
"""
وحدة الترجمة - نظام تحليل المناقصات
"""
import streamlit as st
import pandas as pd
import numpy as np
import os
import sys
from pathlib import Path
import re
import datetime
# إضافة مسار المشروع للنظام
sys.path.append(str(Path(__file__).parent.parent))
# استيراد محسن واجهة المستخدم
from styling.enhanced_ui import UIEnhancer
class TranslationApp:
"""تطبيق الترجمة"""
def __init__(self):
"""تهيئة تطبيق الترجمة"""
self.ui = UIEnhancer(page_title="الترجمة - نظام تحليل المناقصات", page_icon="🌐")
self.ui.apply_theme_colors()
# قائمة اللغات المدعومة
self.supported_languages = {
"ar": "العربية",
"en": "الإنجليزية",
"fr": "الفرنسية",
"de": "الألمانية",
"es": "الإسبانية",
"it": "الإيطالية",
"zh": "الصينية",
"ja": "اليابانية",
"ru": "الروسية",
"tr": "التركية"
}
# بيانات نموذجية للمصطلحات الفنية
self.technical_terms = [
{"ar": "كراسة الشروط", "en": "Terms and Conditions Document", "category": "مستندات"},
{"ar": "جدول الكميات", "en": "Bill of Quantities (BOQ)", "category": "مستندات"},
{"ar": "المواصفات الفنية", "en": "Technical Specifications", "category": "مستندات"},
{"ar": "ضمان ابتدائي", "en": "Bid Bond", "category": "ضمانات"},
{"ar": "ضمان حسن التنفيذ", "en": "Performance Bond", "category": "ضمانات"},
{"ar": "ضمان دفعة مقدمة", "en": "Advance Payment Guarantee", "category": "ضمانات"},
{"ar": "ضمان صيانة", "en": "Maintenance Bond", "category": "ضمانات"},
{"ar": "مناقصة عامة", "en": "Public Tender", "category": "أنواع المناقصات"},
{"ar": "مناقصة محدودة", "en": "Limited Tender", "category": "أنواع المناقصات"},
{"ar": "منافسة", "en": "Competition", "category": "أنواع المناقصات"},
{"ar": "أمر شراء", "en": "Purchase Order", "category": "عقود"},
{"ar": "عقد إطاري", "en": "Framework Agreement", "category": "عقود"},
{"ar": "عقد زمني", "en": "Time-based Contract", "category": "عقود"},
{"ar": "عقد تسليم مفتاح", "en": "Turnkey Contract", "category": "عقود"},
{"ar": "مقاول من الباطن", "en": "Subcontractor", "category": "أطراف"},
{"ar": "استشاري", "en": "Consultant", "category": "أطراف"},
{"ar": "مالك المشروع", "en": "Project Owner", "category": "أطراف"},
{"ar": "مدير المشروع", "en": "Project Manager", "category": "أطراف"},
{"ar": "مهندس الموقع", "en": "Site Engineer", "category": "أطراف"},
{"ar": "مراقب الجودة", "en": "Quality Control", "category": "أطراف"},
{"ar": "أعمال مدنية", "en": "Civil Works", "category": "أعمال"},
{"ar": "أعمال كهربائية", "en": "Electrical Works", "category": "أعمال"},
{"ar": "أعمال ميكانيكية", "en": "Mechanical Works", "category": "أعمال"},
{"ar": "أعمال معمارية", "en": "Architectural Works", "category": "أعمال"},
{"ar": "أعمال تشطيبات", "en": "Finishing Works", "category": "أعمال"},
{"ar": "غرامة تأخير", "en": "Delay Penalty", "category": "شروط"},
{"ar": "مدة التنفيذ", "en": "Execution Period", "category": "شروط"},
{"ar": "فترة الضمان", "en": "Warranty Period", "category": "شروط"},
{"ar": "شروط الدفع", "en": "Payment Terms", "category": "شروط"},
{"ar": "تسوية النزاعات", "en": "Dispute Resolution", "category": "شروط"}
]
# بيانات نموذجية للمستندات المترجمة
self.translated_documents = [
{
"id": "TD001",
"name": "كراسة الشروط - مناقصة إنشاء مبنى إداري",
"source_language": "ar",
"target_language": "en",
"original_file": "specs_v2.0_ar.pdf",
"translated_file": "specs_v2.0_en.pdf",
"translation_date": "2025-03-15",
"translated_by": "أحمد محمد",
"status": "مكتمل",
"pages": 52,
"related_entity": "T-2025-001"
},
{
"id": "TD002",
"name": "جدول الكميات - مناقصة إنشاء مبنى إداري",
"source_language": "ar",
"target_language": "en",
"original_file": "boq_v1.1_ar.xlsx",
"translated_file": "boq_v1.1_en.xlsx",
"translation_date": "2025-02-25",
"translated_by": "سارة عبدالله",
"status": "مكتمل",
"pages": 22,
"related_entity": "T-2025-001"
},
{
"id": "TD003",
"name": "المخططات - مناقصة إنشاء مبنى إداري",
"source_language": "ar",
"target_language": "en",
"original_file": "drawings_v2.0_ar.pdf",
"translated_file": "drawings_v2.0_en.pdf",
"translation_date": "2025-03-20",
"translated_by": "محمد علي",
"status": "مكتمل",
"pages": 35,
"related_entity": "T-2025-001"
},
{
"id": "TD004",
"name": "كراسة الشروط - مناقصة صيانة طرق",
"source_language": "ar",
"target_language": "en",
"original_file": "specs_v1.1_ar.pdf",
"translated_file": "specs_v1.1_en.pdf",
"translation_date": "2025-03-25",
"translated_by": "فاطمة أحمد",
"status": "مكتمل",
"pages": 34,
"related_entity": "T-2025-002"
},
{
"id": "TD005",
"name": "جدول الكميات - مناقصة صيانة طرق",
"source_language": "ar",
"target_language": "en",
"original_file": "boq_v1.0_ar.xlsx",
"translated_file": "boq_v1.0_en.xlsx",
"translation_date": "2025-03-10",
"translated_by": "خالد عمر",
"status": "مكتمل",
"pages": 15,
"related_entity": "T-2025-002"
},
{
"id": "TD006",
"name": "كراسة الشروط - مناقصة توريد معدات",
"source_language": "en",
"target_language": "ar",
"original_file": "specs_v1.0_en.pdf",
"translated_file": "specs_v1.0_ar.pdf",
"translation_date": "2025-02-15",
"translated_by": "أحمد محمد",
"status": "مكتمل",
"pages": 28,
"related_entity": "T-2025-003"
},
{
"id": "TD007",
"name": "عقد توريد - مناقصة توريد معدات",
"source_language": "en",
"target_language": "ar",
"original_file": "contract_v1.0_en.pdf",
"translated_file": "contract_v1.0_ar.pdf",
"translation_date": "2025-03-05",
"translated_by": "سارة عبدالله",
"status": "مكتمل",
"pages": 20,
"related_entity": "T-2025-003"
},
{
"id": "TD008",
"name": "كراسة الشروط - مناقصة تجهيز مختبرات",
"source_language": "ar",
"target_language": "en",
"original_file": "specs_v1.0_ar.pdf",
"translated_file": "specs_v1.0_en.pdf",
"translation_date": "2025-03-28",
"translated_by": "محمد علي",
"status": "قيد التنفيذ",
"pages": 30,
"related_entity": "T-2025-004"
}
]
# بيانات نموذجية للنصوص المترجمة
self.sample_translations = {
"text1": {
"ar": """
# كراسة الشروط والمواصفات
## مناقصة إنشاء مبنى إداري
### 1. مقدمة
تدعو شركة شبه الجزيرة للمقاولات الشركات المتخصصة للتقدم بعروضها لتنفيذ مشروع إنشاء مبنى إداري في مدينة الرياض.
### 2. نطاق العمل
يشمل نطاق العمل تصميم وتنفيذ مبنى إداري مكون من 6 طوابق بمساحة إجمالية 6000 متر مربع، ويشمل ذلك:
- أعمال الهيكل الإنشائي
- أعمال التشطيبات الداخلية والخارجية
- أعمال الكهرباء والميكانيكا
- أعمال تنسيق الموقع
- أعمال أنظمة الأمن والسلامة
- أعمال أنظمة المباني الذكية
""",
"en": """
# Terms and Conditions Document
## Administrative Building Construction Tender
### 1. Introduction
Peninsula Contracting Company invites specialized companies to submit their offers for the implementation of an administrative building construction project in Riyadh.
### 2. Scope of Work
The scope of work includes the design and implementation of a 6-floor administrative building with a total area of 6000 square meters, including:
- Structural works
- Interior and exterior finishing works
- Electrical and mechanical works
- Site coordination works
- Security and safety systems works
- Smart building systems works
"""
},
"text2": {
"ar": """
### 3. المواصفات الفنية
#### 3.1 أعمال الخرسانة
- يجب أن تكون الخرسانة المسلحة بقوة لا تقل عن 40 نيوتن/مم²
- يجب استخدام حديد تسليح مطابق للمواصفات السعودية
- يجب استخدام إضافات للخرسانة لزيادة مقاومتها للعوامل الجوية
#### 3.2 أعمال التشطيبات
- يجب استخدام مواد عالية الجودة للتشطيبات الداخلية
- يجب أن تكون الواجهات الخارجية مقاومة للعوامل الجوية
- يجب استخدام زجاج عاكس للحرارة للواجهات
- يجب استخدام مواد صديقة للبيئة
""",
"en": """
### 3. Technical Specifications
#### 3.1 Concrete Works
- Reinforced concrete must have a strength of not less than 40 Newton/mm²
- Reinforcement steel must comply with Saudi specifications
- Concrete additives must be used to increase its resistance to weather conditions
#### 3.2 Finishing Works
- High-quality materials must be used for interior finishes
- Exterior facades must be weather-resistant
- Heat-reflective glass must be used for facades
- Environmentally friendly materials must be used
"""
}
}
def run(self):
"""تشغيل تطبيق الترجمة"""
# إنشاء قائمة العناصر
menu_items = [
{"name": "لوحة المعلومات", "icon": "house"},
{"name": "المناقصات والعقود", "icon": "file-text"},
{"name": "تحليل المستندات", "icon": "file-earmark-text"},
{"name": "نظام التسعير", "icon": "calculator"},
{"name": "حاسبة تكاليف البناء", "icon": "building"},
{"name": "الموارد والتكاليف", "icon": "people"},
{"name": "تحليل المخاطر", "icon": "exclamation-triangle"},
{"name": "إدارة المشاريع", "icon": "kanban"},
{"name": "الخرائط والمواقع", "icon": "geo-alt"},
{"name": "الجدول الزمني", "icon": "calendar3"},
{"name": "الإشعارات", "icon": "bell"},
{"name": "مقارنة المستندات", "icon": "files"},
{"name": "الترجمة", "icon": "translate"},
{"name": "المساعد الذكي", "icon": "robot"},
{"name": "التقارير", "icon": "bar-chart"},
{"name": "الإعدادات", "icon": "gear"}
]
# إنشاء الشريط الجانبي
selected = self.ui.create_sidebar(menu_items)
# إنشاء ترويسة الصفحة
self.ui.create_header("الترجمة", "أدوات ترجمة المستندات والنصوص")
# إنشاء علامات تبويب للوظائف المختلفة
tabs = st.tabs(["ترجمة النصوص", "ترجمة المستندات", "قاموس المصطلحات", "المستندات المترجمة"])
# علامة تبويب ترجمة النصوص
with tabs[0]:
self.translate_text()
# علامة تبويب ترجمة المستندات
with tabs[1]:
self.translate_documents()
# علامة تبويب قاموس المصطلحات
with tabs[2]:
self.technical_terms_dictionary()
# علامة تبويب المستندات المترجمة
with tabs[3]:
self.show_translated_documents()
def translate_text(self):
"""ترجمة النصوص"""
st.markdown("### ترجمة النصوص")
# اختيار لغات الترجمة
col1, col2 = st.columns(2)
with col1:
source_language = st.selectbox(
"لغة المصدر",
options=list(self.supported_languages.keys()),
format_func=lambda x: self.supported_languages[x],
index=0 # العربية كلغة افتراضية
)
with col2:
# استبعاد لغة المصدر من خيارات لغة الهدف
target_languages = {k: v for k, v in self.supported_languages.items() if k != source_language}
target_language = st.selectbox(
"لغة الهدف",
options=list(target_languages.keys()),
format_func=lambda x: self.supported_languages[x],
index=0 # أول لغة متاحة
)
# خيارات الترجمة
st.markdown("#### خيارات الترجمة")
col1, col2, col3 = st.columns(3)
with col1:
translation_engine = st.radio(
"محرك الترجمة",
options=["OpenAI", "Google Translate", "Microsoft Translator", "محلي"]
)
with col2:
use_technical_terms = st.checkbox("استخدام قاموس المصطلحات الفنية", value=True)
with col3:
preserve_formatting = st.checkbox("الحفاظ على التنسيق", value=True)
# إدخال النص المراد ترجمته
st.markdown("#### النص المراد ترجمته")
# إضافة أمثلة نصية
examples = st.expander("أمثلة نصية")
with examples:
if st.button("مثال 1: مقدمة كراسة الشروط"):
source_text = self.sample_translations["text1"][source_language] if source_language in self.sample_translations["text1"] else self.sample_translations["text1"]["ar"]
elif st.button("مثال 2: المواصفات الفنية"):
source_text = self.sample_translations["text2"][source_language] if source_language in self.sample_translations["text2"] else self.sample_translations["text2"]["ar"]
else:
source_text = ""
if "source_text" not in locals():
source_text = ""
source_text = st.text_area(
"أدخل النص المراد ترجمته",
value=source_text,
height=200
)
# زر الترجمة
if st.button("ترجمة النص", use_container_width=True):
if not source_text:
st.error("يرجى إدخال النص المراد ترجمته")
else:
# في تطبيق حقيقي، سيتم استدعاء واجهة برمجة التطبيقات للترجمة
# هنا نستخدم النصوص النموذجية المحددة مسبقاً للعرض
with st.spinner("جاري الترجمة..."):
# محاكاة تأخير الترجمة
import time
time.sleep(1)
# التحقق من وجود ترجمة نموذجية
if source_language == "ar" and target_language == "en" and source_text.strip() in [self.sample_translations["text1"]["ar"].strip(), self.sample_translations["text2"]["ar"].strip()]:
if source_text.strip() == self.sample_translations["text1"]["ar"].strip():
translated_text = self.sample_translations["text1"]["en"]
else:
translated_text = self.sample_translations["text2"]["en"]
elif source_language == "en" and target_language == "ar" and source_text.strip() in [self.sample_translations["text1"]["en"].strip(), self.sample_translations["text2"]["en"].strip()]:
if source_text.strip() == self.sample_translations["text1"]["en"].strip():
translated_text = self.sample_translations["text1"]["ar"]
else:
translated_text = self.sample_translations["text2"]["ar"]
else:
# ترجمة نموذجية للعرض فقط
translated_text = f"[هذا نص مترجم نموذجي من {self.supported_languages[source_language]} إلى {self.supported_languages[target_language]}]\n\n{source_text}"
# عرض النص المترجم
st.markdown("#### النص المترجم")
st.text_area(
"النص المترجم",
value=translated_text,
height=200
)
# أزرار إضافية
col1, col2, col3 = st.columns(3)
with col1:
if st.button("نسخ النص المترجم", use_container_width=True):
st.success("تم نسخ النص المترجم إلى الحافظة")
with col2:
if st.button("حفظ الترجمة", use_container_width=True):
st.success("تم حفظ الترجمة بنجاح")
with col3:
if st.button("تصدير كملف", use_container_width=True):
st.success("تم تصدير الترجمة كملف بنجاح")
# عرض إحصائيات الترجمة
st.markdown("#### إحصائيات الترجمة")
col1, col2, col3, col4 = st.columns(4)
with col1:
self.ui.create_metric_card(
"عدد الكلمات",
str(len(source_text.split())),
None,
self.ui.COLORS['primary']
)
with col2:
self.ui.create_metric_card(
"عدد الأحرف",
str(len(source_text)),
None,
self.ui.COLORS['secondary']
)
with col3:
self.ui.create_metric_card(
"وقت الترجمة",
"1.2 ثانية",
None,
self.ui.COLORS['success']
)
with col4:
self.ui.create_metric_card(
"المصطلحات الفنية",
"5",
None,
self.ui.COLORS['accent']
)
def translate_documents(self):
"""ترجمة المستندات"""
st.markdown("### ترجمة المستندات")
# اختيار لغات الترجمة
col1, col2 = st.columns(2)
with col1:
source_language = st.selectbox(
"لغة المصدر",
options=list(self.supported_languages.keys()),
format_func=lambda x: self.supported_languages[x],
index=0, # العربية كلغة افتراضية
key="doc_source_lang"
)
with col2:
# استبعاد لغة المصدر من خيارات لغة الهدف
target_languages = {k: v for k, v in self.supported_languages.items() if k != source_language}
target_language = st.selectbox(
"لغة الهدف",
options=list(target_languages.keys()),
format_func=lambda x: self.supported_languages[x],
index=0, # أول لغة متاحة
key="doc_target_lang"
)
# تحميل المستند
st.markdown("#### تحميل المستند")
uploaded_file = st.file_uploader("اختر المستند المراد ترجمته", type=["pdf", "docx", "xlsx", "txt"])
if uploaded_file is not None:
st.success(f"تم تحميل الملف: {uploaded_file.name}")
# عرض معلومات الملف
file_details = {
"اسم الملف": uploaded_file.name,
"نوع الملف": uploaded_file.type,
"حجم الملف": f"{uploaded_file.size / 1024:.1f} كيلوبايت"
}
st.json(file_details)
# خيارات الترجمة
st.markdown("#### خيارات الترجمة")
col1, col2 = st.columns(2)
with col1:
translation_engine = st.radio(
"محرك الترجمة",
options=["OpenAI", "Google Translate", "Microsoft Translator", "محلي"],
key="doc_engine"
)
use_technical_terms = st.checkbox("استخدام قاموس المصطلحات الفنية", value=True, key="doc_terms")
with col2:
preserve_formatting = st.checkbox("الحفاظ على التنسيق", value=True, key="doc_format")
translate_images = st.checkbox("ترجمة النصوص في الصور", value=False)
maintain_layout = st.checkbox("الحفاظ على تخطيط المستند", value=True)
# معلومات إضافية
st.markdown("#### معلومات إضافية")
col1, col2 = st.columns(2)
with col1:
document_name = st.text_input("اسم المستند")
with col2:
related_entity = st.text_input("الكيان المرتبط (مثل: رقم المناقصة أو المشروع)")
# زر بدء الترجمة
if st.button("بدء ترجمة المستند", use_container_width=True):
if uploaded_file is None:
st.error("يرجى تحميل المستند المراد ترجمته")
else:
# في تطبيق حقيقي، سيتم إرسال المستند إلى خدمة الترجمة
# هنا نعرض محاكاة لعملية الترجمة
progress_bar = st.progress(0)
status_text = st.empty()
# محاكاة تقدم الترجمة
import time
for i in range(101):
progress_bar.progress(i)
if i < 10:
status_text.text("جاري تحليل المستند...")
elif i < 30:
status_text.text("جاري استخراج النصوص...")
elif i < 70:
status_text.text("جاري ترجمة المحتوى...")
elif i < 90:
status_text.text("جاري إعادة بناء المستند...")
else:
status_text.text("جاري إنهاء الترجمة...")
time.sleep(0.05)
# عرض نتيجة الترجمة
st.success("تمت ترجمة المستند بنجاح!")
# إنشاء اسم الملف المترجم
file_name_parts = uploaded_file.name.split('.')
translated_file_name = f"{'.'.join(file_name_parts[:-1])}_{target_language}.{file_name_parts[-1]}"
# عرض معلومات الملف المترجم
st.markdown("#### معلومات الملف المترجم")
col1, col2 = st.columns(2)
with col1:
st.markdown(f"**اسم الملف:** {translated_file_name}")
st.markdown(f"**لغة المصدر:** {self.supported_languages[source_language]}")
st.markdown(f"**لغة الهدف:** {self.supported_languages[target_language]}")
with col2:
st.markdown(f"**محرك الترجمة:** {translation_engine}")
st.markdown(f"**تاريخ الترجمة:** {datetime.datetime.now().strftime('%Y-%m-%d')}")
st.markdown(f"**حالة الترجمة:** مكتمل")
# أزرار إضافية
col1, col2, col3 = st.columns(3)
with col1:
if st.button("تنزيل الملف المترجم", use_container_width=True):
st.success("تم بدء تنزيل الملف المترجم")
with col2:
if st.button("حفظ في المستندات المترجمة", use_container_width=True):
st.success("تم حفظ الملف في المستندات المترجمة")
with col3:
if st.button("مشاركة الملف", use_container_width=True):
st.success("تم نسخ رابط مشاركة الملف")
# عرض إحصائيات الترجمة
st.markdown("#### إحصائيات الترجمة")
col1, col2, col3, col4 = st.columns(4)
with col1:
self.ui.create_metric_card(
"عدد الصفحات",
"12",
None,
self.ui.COLORS['primary']
)
with col2:
self.ui.create_metric_card(
"عدد الكلمات",
"2,450",
None,
self.ui.COLORS['secondary']
)
with col3:
self.ui.create_metric_card(
"وقت الترجمة",
"45 ثانية",
None,
self.ui.COLORS['success']
)
with col4:
self.ui.create_metric_card(
"المصطلحات الفنية",
"28",
None,
self.ui.COLORS['accent']
)
def technical_terms_dictionary(self):
"""قاموس المصطلحات الفنية"""
st.markdown("### قاموس المصطلحات الفنية")
# إضافة مصطلح جديد
with st.expander("إضافة مصطلح جديد"):
with st.form("add_term_form"):
col1, col2, col3 = st.columns(3)
with col1:
term_ar = st.text_input("المصطلح بالعربية")
with col2:
term_en = st.text_input("المصطلح بالإنجليزية")
with col3:
term_category = st.selectbox(
"الفئة",
options=["مستندات", "ضمانات", "أنواع المناقصات", "عقود", "أطراف", "أعمال", "شروط", "أخرى"]
)
# زر إضافة المصطلح
submit_button = st.form_submit_button("إضافة المصطلح")
if submit_button:
if not term_ar or not term_en:
st.error("يرجى ملء جميع الحقول المطلوبة")
else:
# في تطبيق حقيقي، سيتم إضافة المصطلح إلى قاعدة البيانات
st.success("تمت إضافة المصطلح بنجاح")
# البحث في المصطلحات
st.markdown("#### البحث في المصطلحات")
col1, col2, col3 = st.columns(3)
with col1:
search_term = st.text_input("البحث عن مصطلح")
with col2:
search_language = st.radio(
"لغة البحث",
options=["الكل", "العربية", "الإنجليزية"],
horizontal=True
)
with col3:
category_filter = st.selectbox(
"تصفية حسب الفئة",
options=["الكل", "مستندات", "ضمانات", "أنواع المناقصات", "عقود", "أطراف", "أعمال", "شروط", "أخرى"]
)
# تطبيق الفلاتر
filtered_terms = self.technical_terms
if search_term:
if search_language == "العربية":
filtered_terms = [term for term in filtered_terms if search_term.lower() in term["ar"].lower()]
elif search_language == "الإنجليزية":
filtered_terms = [term for term in filtered_terms if search_term.lower() in term["en"].lower()]
else:
filtered_terms = [term for term in filtered_terms if search_term.lower() in term["ar"].lower() or search_term.lower() in term["en"].lower()]
if category_filter != "الكل":
filtered_terms = [term for term in filtered_terms if term["category"] == category_filter]
# عرض المصطلحات
st.markdown("#### المصطلحات الفنية")
if not filtered_terms:
st.info("لا توجد مصطلحات تطابق معايير البحث")
else:
# تحويل البيانات إلى DataFrame
terms_df = pd.DataFrame(filtered_terms)
# إعادة تسمية الأعمدة
terms_df = terms_df.rename(columns={
"ar": "المصطلح بالعربية",
"en": "المصطلح بالإنجليزية",
"category": "الفئة"
})
# عرض الجدول
st.dataframe(
terms_df,
use_container_width=True,
hide_index=True
)
# أزرار إضافية
col1, col2 = st.columns([1, 5])
with col1:
if st.button("تصدير القاموس", use_container_width=True):
st.success("تم تصدير القاموس بنجاح")
# عرض إحصائيات القاموس
st.markdown("#### إحصائيات القاموس")
# حساب عدد المصطلحات في كل فئة
category_counts = {}
for term in self.technical_terms:
if term["category"] not in category_counts:
category_counts[term["category"]] = 0
category_counts[term["category"]] += 1
# عرض الإحصائيات
col1, col2 = st.columns(2)
with col1:
st.markdown("##### عدد المصطلحات حسب الفئة")
# تحويل البيانات إلى DataFrame
category_df = pd.DataFrame({
"الفئة": list(category_counts.keys()),
"العدد": list(category_counts.values())
})
# عرض الرسم البياني
st.bar_chart(category_df.set_index("الفئة"))
with col2:
st.markdown("##### إحصائيات عامة")
total_terms = len(self.technical_terms)
categories_count = len(category_counts)
st.markdown(f"**إجمالي المصطلحات:** {total_terms}")
st.markdown(f"**عدد الفئات:** {categories_count}")
st.markdown(f"**متوسط المصطلحات لكل فئة:** {total_terms / categories_count:.1f}")
st.markdown(f"**آخر تحديث للقاموس:** {datetime.datetime.now().strftime('%Y-%m-%d')}")
def show_translated_documents(self):
"""عرض المستندات المترجمة"""
st.markdown("### المستندات المترجمة")
# إنشاء فلاتر للمستندات
col1, col2, col3 = st.columns(3)
with col1:
entity_filter = st.selectbox(
"تصفية حسب الكيان",
options=["الكل"] + list(set([doc["related_entity"] for doc in self.translated_documents]))
)
with col2:
language_pair_filter = st.selectbox(
"تصفية حسب زوج اللغات",
options=["الكل"] + list(set([f"{doc['source_language']} -> {doc['target_language']}" for doc in self.translated_documents]))
)
with col3:
status_filter = st.selectbox(
"تصفية حسب الحالة",
options=["الكل", "مكتمل", "قيد التنفيذ"]
)
# تطبيق الفلاتر
filtered_docs = self.translated_documents
if entity_filter != "الكل":
filtered_docs = [doc for doc in filtered_docs if doc["related_entity"] == entity_filter]
if language_pair_filter != "الكل":
source_lang, target_lang = language_pair_filter.split(" -> ")
filtered_docs = [doc for doc in filtered_docs if doc["source_language"] == source_lang and doc["target_language"] == target_lang]
if status_filter != "الكل":
filtered_docs = [doc for doc in filtered_docs if doc["status"] == status_filter]
# عرض المستندات المترجمة
if not filtered_docs:
st.info("لا توجد مستندات مترجمة تطابق معايير التصفية")
else:
# تحويل البيانات إلى DataFrame
docs_df = pd.DataFrame(filtered_docs)
# تحويل رموز اللغات إلى أسماء اللغات
docs_df["source_language"] = docs_df["source_language"].map(self.supported_languages)
docs_df["target_language"] = docs_df["target_language"].map(self.supported_languages)
# إعادة ترتيب الأعمدة وتغيير أسمائها
display_df = docs_df[[
"id", "name", "source_language", "target_language", "translation_date", "status", "pages", "related_entity"
]].rename(columns={
"id": "الرقم",
"name": "اسم المستند",
"source_language": "لغة المصدر",
"target_language": "لغة الهدف",
"translation_date": "تاريخ الترجمة",
"status": "الحالة",
"pages": "عدد الصفحات",
"related_entity": "الكيان المرتبط"
})
# عرض الجدول
st.dataframe(
display_df,
use_container_width=True,
hide_index=True
)
# عرض تفاصيل المستند المحدد
st.markdown("#### تفاصيل المستند المترجم")
selected_doc_id = st.selectbox(
"اختر مستنداً لعرض التفاصيل",
options=[doc["id"] for doc in filtered_docs],
format_func=lambda x: next((f"{doc['id']} - {doc['name']}" for doc in filtered_docs if doc["id"] == x), "")
)
# العثور على المستند المحدد
selected_doc = next((doc for doc in filtered_docs if doc["id"] == selected_doc_id), None)
if selected_doc:
col1, col2 = st.columns(2)
with col1:
st.markdown(f"**اسم المستند:** {selected_doc['name']}")
st.markdown(f"**لغة المصدر:** {self.supported_languages[selected_doc['source_language']]}")
st.markdown(f"**لغة الهدف:** {self.supported_languages[selected_doc['target_language']]}")
st.markdown(f"**تاريخ الترجمة:** {selected_doc['translation_date']}")
with col2:
st.markdown(f"**الملف الأصلي:** {selected_doc['original_file']}")
st.markdown(f"**الملف المترجم:** {selected_doc['translated_file']}")
st.markdown(f"**المترجم:** {selected_doc['translated_by']}")
st.markdown(f"**الحالة:** {selected_doc['status']}")
# أزرار الإجراءات
col1, col2, col3 = st.columns(3)
with col1:
if st.button("تنزيل الملف الأصلي", use_container_width=True):
st.success("تم بدء تنزيل الملف الأصلي")
with col2:
if st.button("تنزيل الملف المترجم", use_container_width=True):
st.success("تم بدء تنزيل الملف المترجم")
with col3:
if st.button("مشاركة الملف المترجم", use_container_width=True):
st.success("تم نسخ رابط مشاركة الملف المترجم")
# عرض إحصائيات الترجمة
st.markdown("#### إحصائيات الترجمة")
col1, col2, col3 = st.columns(3)
with col1:
# إحصائيات حسب زوج اللغات
language_pairs = {}
for doc in self.translated_documents:
pair = f"{self.supported_languages[doc['source_language']]} -> {self.supported_languages[doc['target_language']]}"
if pair not in language_pairs:
language_pairs[pair] = 0
language_pairs[pair] += 1
st.markdown("##### المستندات حسب زوج اللغات")
# تحويل البيانات إلى DataFrame
language_df = pd.DataFrame({
"زوج اللغات": list(language_pairs.keys()),
"العدد": list(language_pairs.values())
})
# عرض الرسم البياني
st.bar_chart(language_df.set_index("زوج اللغات"))
with col2:
# إحصائيات حسب الكيان المرتبط
entity_counts = {}
for doc in self.translated_documents:
if doc["related_entity"] not in entity_counts:
entity_counts[doc["related_entity"]] = 0
entity_counts[doc["related_entity"]] += 1
st.markdown("##### المستندات حسب الكيان المرتبط")
# تحويل البيانات إلى DataFrame
entity_df = pd.DataFrame({
"الكيان المرتبط": list(entity_counts.keys()),
"العدد": list(entity_counts.values())
})
# عرض الرسم البياني
st.bar_chart(entity_df.set_index("الكيان المرتبط"))
with col3:
# إحصائيات عامة
total_docs = len(self.translated_documents)
completed_docs = len([doc for doc in self.translated_documents if doc["status"] == "مكتمل"])
in_progress_docs = len([doc for doc in self.translated_documents if doc["status"] == "قيد التنفيذ"])
total_pages = sum([doc["pages"] for doc in self.translated_documents])
st.markdown("##### إحصائيات عامة")
st.markdown(f"**إجمالي المستندات المترجمة:** {total_docs}")
st.markdown(f"**المستندات المكتملة:** {completed_docs}")
st.markdown(f"**المستندات قيد التنفيذ:** {in_progress_docs}")
st.markdown(f"**إجمالي الصفحات المترجمة:** {total_pages}")
st.markdown(f"**متوسط الصفحات لكل مستند:** {total_pages / total_docs:.1f}")
# تشغيل التطبيق
if __name__ == "__main__":
translation_app = TranslationApp()
translation_app.run()
|