مرحبًا أعضاء مجتمع إتقان.
أشارككم اليوم تفاصيل تجربة شخصية في العمل على تطوير تطبيق قرآني لترجمة القرآن الكريم إلى اللغة التركية، مع الاستفادة من تقنيات الذكاء الاصطناعي لتحسين الترجمة وتعزيزها.
خطرت لي فكرة هذا التطبيق من حياتي اليومية كأم. أولادي الذين وُلدوا وتعلّموا في تركيا يعيشون بين لغتين: العربية والتركية. كنت أحاول أن أقرّبهم من القرآن الكريم وأشرح لهم معانيه بالعربية، لكنني لاحظت أنهم يواجهون صعوبة في فهم كثير من الآيات نظرًا لأن مفرداتهم العربية لا تزال محدودة، وبحكم تخصصي في هندسة برمجيات فكرت في إنشاء تطبيق يساعدني في شرح معاني القرآن لهم باللغة التركية التي يفهمونها جيدًا.
لحسن الحظ وجدت بالبحث وجود العديد من الواجهات البرمجية APIs التي تساعدني على البدء وتوفر لي ترجمات مختلفة للقرآن الكريم باللغة التركية لكن هنا ظهرت مشكلة أخرى تتعلق بي، فهناك عدة ترجمات مختلفة لكل سورة ومعلوماتي بالتركية ليست بالمستوى الذي يمكنني من تقييم أدقها وأقربها للمعنى الأصلي، ومن هنا جاءتني فكرة أخرى لماذا لا أجمع كل هذه الترجمات في تطبيق واحد، ثم أمررها لأحد نماذج الذكاء الاصطناعي لصياغة معنى هجين يقارب بينها ويحسنها ليستخرج أفضل ترجمة من بينها.
أشارككم هنا تفاصيل تنفيذي لهذه التجربة وما استنتجته منها ابتداءً من جلب الترجمات المتوفرة، مرورًا بمعالجتها عبر النموذج اللغوي للحصول على صياغة محسّنة، وصولًا إلى اختبار جودة النتائج، ومناقشة التحديات التي واجهتني، وفتح باب النقاش حول تحسين التطبيق ورفع جودته.

التقنيات المستخدمة في التطبيق
طوّرت التطبيق باستخدام إطار العمل فلاسك Flask فهو صغير الحجم ومرن في التعامل ومن السهل ربطه بالواجهات البرمجية. ولجلب نصوص القرآن الكريم وترجماته التركية استخدمت الواجهة Quran.com API. كما اعتمدت على نموذج Llama 3 لتوليد ترجمات هجينة محسنة.
لماذا اخترت Quran.com API
تتوفر عدة واجهات برمجية جيدة توفر ترجمات جيدة للقرآن الكريم، لكني اخترت Quran.com API لهذا التطبيق لكونها واحدة من أفضل المصادر المجانية الموثوقة للنصوص القرآنية، وتتميز بشمولية المحتوى وغناه إذ توفر مئات الترجمات بمختلف اللغات، وهي تتيح خمس ترجمات مختلفة للغة التركية وحدها. إلى جانب توفير ملفات صوتية للآيات كاملة، كما توفر توثيقاً تفصيليًا وواضحًا ساعدني على فهم الواجهة البرمجية والتعامل معها بسهولة، وطلباتها مصممة بدقة وتساعد المطور في الحصول على البيانات التي يحتاجها ويقلل من حجم البيانات المنقولة للتطبيق ويسرع استجابته.
الطلبات الأساسية المستخدمة من Quran API
اعتمدت في تشغيل التطبيق على ثلاث طلبات أساسية من الواجهة وهي:
1- طلب لجلب قائمة كاملة بجميع سور القرآن الكريم من أجل عرضها كفهرس قابل للنقر في الصفحة الرئيسية للتطبيق:
GET https://api.quran.com/api/v4/chapters
2- طلب لجلب معلومات مفصلة عن سورة محددة:
GET https://api.quran.com/api/v4/chapters/{chapter_id}
3- طلب يجلب الآيات والترجمات باللغة التركية لكل سورة:
GET https://api.quran.com/api/v4/verses/by_chapter/{chapter_id}
ويحتاج هذا الطلب لتمرير عدة معاملات استعلام Query Parameters تحدد المحتوى والترجمات المطلوبة فبدلًا من جلب كل الترجمات المتاحة سأجلب الترجمات المقابلة للمعرفات IDs الخاصة باللغة التركية فقط وهي:
TURKISH_TRANSLATION_IDS = [52, 112, 124, 210, 77]
وسأحدد للواجهة بأني لا أحتاج لكافة المعلومات الخاصة بالآيات بل أريد فقط نصها بالرسم العثماني من خلال هذا المعامل:
fields=text_uthmani
ولتسريع الاستجابة لن أترجم كل كلمة من الآية على حدا بل سأترجمها بالكلية، لذا حددت قيمة معامل الاستعلام words لتكون false:
وبهذا سيجلب لي الطلب النص العربي بالخط العثماني لكل آية، ويجلب ترجماتها الخمس باللغة التركية.
بعد أن تحققت من الطلبات التي أحتاجها من الواجهة انتقلت للخطوة التالية وهي اختيار نموذج لغوي ذكي أمرر له هذه البيانات كمدخلات وأطلب منه أن يتعامل معها كخبير باللغة التركية وينشئ لي ترجمة جديدة محسنة بناء عليها.
لماذا اخترت نموذج Llama 3
استخدمت في التجربة نموذج الذكاء الاصطناعي Llama 3 وتحديدًا الإصدار 8B منه فهذا النموذج مفتوح المصدر ومتخصص في فهم النصوص وتوليدها ويمكن تشغيله محليًا عبر خادم Ollama بموارد حاسوبية مقبولة وبالمجان.
البنية البرمجية للتطبيق
يتكون الكود البرمجي للتطبيق من ثلاثة ملفات أساسية:
- index.html: الصفحة الرئيسية للتطبيق وهي صفحة بسيطة تعرض قائمة بجميع سور القرآن. عندما النقر على اسم أي سورة من بينها سينتقل إلى الصفحة التالية التي تعرض بيانات مفصلة عنها.

- surah.html: صفحة السورة التي ستعرض كل آية من آيات السورة التي اخترناها من الصفحة الرئيسية للتطبيق مع الترجمات التركية الخمسة الخاصة بها والتي جلبتها من الواجهة البرمجية Quran.com API إلى جانب ترجمة سادسة محسنة ولدها الذكاء الاصطناعي.

- quran_app.py: الملف الرئيسي للتطبيق مكتوب بلغة بايثون باستخدام إطار عمل فلاسك Flask والذي يعمل في الخلفية ليحقق كافة الوظائف المطلوبة لعمل التطبيق.
شرح الملف quran_app.py
ملف quran_app.py هو المحرك الرئيسي للتطبيق، فهو كما وضحت سابقًا يدير العمليات الأساسية في الواجهة الخلفية للتطبيق حيث يعمل على إدارة الطلبات وجلب البيانات من الواجهة Quran.com API، ثم تمريرها إلى نموذج الذكاء الاصطناعي لتحسين الترجمات. وبعد المعالجة، يرسل النتائج النهائية إلى ملفات الواجهة الأمامية ليتم عرضها للمستخدمين.
لذا فإن فهم هذا الملف ضروري لاستيعاب كيفية عمل التطبيق بالكامل وآلية تدفق البيانات داخله.
في البداية يستورد الكود المكتبات الأساسية المطلوبة وينشئ التطبيق، وأهم هذه المكتبات:
- Flask: المكتبة الأساسية لإنشاء تطبيق ويب وتشغيل خادم محلي
- requests: لإرسال طلبات HTTP والاتصال بالواجهات البرمجية APIs
- subprocess: للتواصل بين تطبيق بايثون وبين برامج أو أدوات خارجية مثل Ollama
- json: لتمثيل بيانات الآيات والترجمات بصيغة JSON وإرسالها إلى Ollama
from flask import Flask, render_template
import requests
import subprocess
import json
import time
import re
app = Flask(__name__)
كما يعرف عدة دوال سأوضحها حسب تسلسل الاستدعاء:
الدالة get_all_surahs
تستدعى هذه الدالة عند عرض الصفحة الرئيسية للتطبيق، حيث تجلب قائمة بجميع سور القرآن الكريم من واجهة Quran.com API وتستخدم هذه البيانات لعرض أسماء السور وروابطها في واجهة التطبيق الرئيسية مما يتيح للمستخدم اختيار السورة التي يريد ترجمتها:
API_BASE_URL = "https://api.quran.com/api/v4"
def get_all_surahs():
url = f"{API_BASE_URL}/chapters"
try:
response = requests.get(url, timeout=15)
response.raise_for_status()
return response.json()["chapters"], None
except requests.exceptions.RequestException as e:
return [], f"خطأ في الشبكة أثناء جلب قائمة السور: {e}"
الدالة clean_html_tags
تقوم هذه الدالة بتنظيف نصوص الترجمات من وسوم HTML غير المرغوب فيها، مثل <sup>. فقد لاحظت أن بعض الترجمات المسترجعة من واجهة Quran.com API تحتوي على هذه الوسوم، لذا استخدمت التعابير النمطية regex لإزالتها وضمان بقاء النصوص نظيفة وواضحة عند عرضها في التطبيق.
def clean_html_tags(text):
clean_text = re.sub(r"<sup.*?</sup>", "", text)
return clean_text.strip()
الدالة get_full_surah_data
تتولى هذه الدالة جلب جميع آيات السورة المحددة من واجهة Quran.com API مع الترجمات التركية الخمسة، ثم تجهز بيانات كل آية لإرسالها إلى نموذج الذكاء الاصطناعي، ليتم دمج الترجمات الناتجة وتحويلها إلى نسخة هجينة محسنة.
def get_full_surah_data(chapter_number):
translations_str = ",".join(map(str, TURKISH_TRANSLATION_IDS))
url = (
f"{API_BASE_URL}/verses/by_chapter/{chapter_number}"
f"?language=ar&words=false&translations={translations_str}&fields=text_uthmani"
)
try:
info_res = requests.get(f"{API_BASE_URL}/chapters/{chapter_number}", timeout=10)
info_res.raise_for_status()
surah_info = info_res.json()["chapter"]
verses_res = requests.get(url, timeout=30)
verses_res.raise_for_status()
verses = verses_res.json()["verses"]
combined_data, verses_for_ai = [], []
for verse in verses:
verse_num, arabic_text = verse["verse_number"], verse["text_uthmani"]
translations_map = {
t["resource_id"]: t["text"] for t in verse["translations"]
}
turkish_versions = [
clean_html_tags(translations_map.get(tid, "غير متوفرة"))
for tid in TURKISH_TRANSLATION_IDS
]
verses_for_ai.append(
{
"verse_number": verse_num,
"arabic_text": arabic_text,
"turkish_translations": turkish_versions,
}
)
combined_data.append(
{
"number": verse_num,
"arabic_text": arabic_text,
"turkish_versions": turkish_versions,
"hybrid": "جاري التوليد...",
}
)
hybrid_translations_map = call_ai_model_batch(verses_for_ai)
if hybrid_translations_map:
for item in combined_data:
item["hybrid"] = hybrid_translations_map.get(
item["number"], " فشل التوليد"
)
else:
for item in combined_data:
item["hybrid"] = " حدث خطأ أثناء الاتصال بالذكاء الاصطناعي"
return surah_info, combined_data, None
except Exception as e:
return None, None, f"حدث خطأ أثناء جلب البيانات: {e}"
الدالة call_ai_model_batch
تستدعي الدالة السابقة get_full_surah_data هذه الدالة ضمنها، فهي المسؤولة عن تمرير البيانات إلى نموذج Ollama والحصول على الترجمة الهجينة.
هذه الدالة أساسية في عمل التطبيق فهي ما يضيف الجزء المتعلق بالذكاء الاصطناعي للتطبيق، لذا سأتوسع قليلًا في شرح أهم أجزائها.
def call_ai_model_batch(verses_data):
prompt_header = (
"You are an expert in Quranic Arabic and Turkish linguistics. "
"Your task is to generate an improved, clear, and accurate hybrid Turkish translation for each Quranic verse provided. "
"Analyze the original Arabic text and the five different Turkish translations, then synthesize a final, high-quality translation. "
"Respond ONLY with a valid JSON array where each object contains 'verse_number' and 'hybrid_translation'.\n\n"
"Here is the data:\n"
)
prompt_data = json.dumps(verses_data, indent=2, ensure_ascii=False)
full_prompt = prompt_header + prompt_data
try:
print(
f" إرسال الطلب إلى نموذج Ollama المحلي (llama3) لـ {len(verses_data)} آية..."
)
start_time = time.time()
result = subprocess.run(
["ollama", "run", "llama3"],
input=full_prompt.encode("utf-8"),
capture_output=True,
check=True,
timeout=600,
)
end_time = time.time()
print(f" استجاب نموذج Ollama خلال {end_time - start_time:.2f} ثانية.")
response_text = result.stdout.decode("utf-8").strip()
json_start = response_text.find("[")
json_end = response_text.rfind("]") + 1
if json_start == -1 or json_end == 0:
print(" خطأ: لم يتم العثور على مصفوفة JSON في استجابة النموذج.")
print(f"--- الاستجابة الخام ---\n{response_text}\n--------------------")
return None
clean_json_str = response_text[json_start:json_end]
ai_translations = json.loads(clean_json_str)
return {
item["verse_number"]: item["hybrid_translation"] for item in ai_translations
}
except subprocess.TimeoutExpired:
print(f" خطأ: استغرق النموذج وقتًا أطول من المهلة المحددة (600 ثانية).")
return None
except FileNotFoundError:
print(
" خطأ: الأمر 'ollama' غير موجود. تأكد من تثبيته بشكل صحيح وإضافته إلى PATH."
)
return None
except (json.JSONDecodeError, KeyError) as e:
print(f" خطأ في تحليل استجابة النموذج: {e}")
print(f"--- الاستجابة الخام ---\n{response_text}\n--------------------")
return None
except Exception as e:
print(f" حدث خطأ غير متوقع أثناء استدعاء Ollama: {e}")
return None
تستقبل هذه الدالة البيانات القرآنية مع الترجمات التركية الخاصة بها بصيغة جيسون JSON على نحو مشابه لما يلي:
[
{
"verse_number": 1,
"arabic_text": "بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِيمِ",
"turkish_translations": ["ترجمة2", "ترجمة1", "..."]
},
...
]
ثم تمرر البيانات مع موجه prompt يطلب من النموذج أن يحلل بيانات كل آية من السورة باللغة العربية مع ترجماتها التركية الخمسة ويعيد صياغة ترجمة هجينة دقيقة لها:
prompt_header = (
"You are an expert in Quranic Arabic and Turkish linguistics. "
"Your task is to generate an improved, clear, and accurate hybrid Turkish translation for each Quranic verse provided. "
"Analyze the original Arabic text and the five different Turkish translations, then synthesize a final, high-quality translation. "
"Respond ONLY with a valid JSON array where each object contains 'verse_number' and 'hybrid_translation'.\n\n"
"Here is the data:\n"
)
prompt_data = json.dumps(verses_data, indent=2, ensure_ascii=False)
full_prompt = prompt_header + prompt_data
ملاحظة: كتبت موجه النموذج هنا باللغة الإنجليزية لأن نماذج الذكاء الاصطناعي تتعامل مع توجيهات اللغة الإنجليزية بكفاءة أعلى لأنها مدربة بشكل أساسي على بيانات باللغة الإنجليزية، ويمكن تجربة تمرير الموجه بلغة عربية أو تركية واختبار التأثير على جودة النتائج.
بعد تجهيز البيانات والموجه prompt، يقوم الكود بتشغيل برنامج Ollama الخارجي من داخل بايثون، ويمرر له الموجه بترميز UTF-8 لدعم النصوص العربية والتركية. ثم يسترجع الكود النتيجة باستخدام عملية فرعية Subprocess، مع تحديد حد أقصى للوقت قدره 600 ثانية للاستجابة.
إذا تجاوز النموذج هذا الوقت، يتوقف الكود عن العمل ويعرض رسالة خطأ، لضمان عدم تعليق التطبيق أثناء المعالجة.
result = subprocess.run(
["ollama", "run", "llama3"],
input=full_prompt.encode("utf-8"),
capture_output=True,
check=True,
timeout=600
)
ملاحظة: أحيانًا يرجع النموذج نتيجة خلال ثوانٍ وأحيانًا يتأخر لعدة دقائق، لذا حددت المهلة الزمنية لتكون 600 ثانية كإجراء احترازي، لأن استدعاء نموذج Ollama قد يستغرق وقتًا أطول عند معالجة سور طويلة، لذا اخترت مهلة أطول لتجنب أي تأخير . سأحاول تجربة عدة حلول لتحسين زمن الاستجابة مستقبلاً.
عند استدعاء نموذج Ollama للحصول على الترجمات الهجينة، قد ترجع الاستجابة أحيانًا نصوصًا إضافية مثل رسائل توضيحية أو أسطر فارغة لا نحتاجها، ما نحتاجه فقط هو مصفوفة JSON التي تحتوي على الترجمات، لذلك كان علي البحث ضمن الاستجابة عن بداية ونهاية هذه المصفوفة واستخراجها. وبعد ذلك، حولت هذه المصفوفة إلى بنية قاموس dictionary باسم ai_translations يربط كل رقم آية بالترجمة الهجينة الخاصة بها بحيث يمكن استخدامها في التطبيق.
response_text = result.stdout.decode("utf-8").strip()
json_start = response_text.find("[")
json_end = response_text.rfind("]") + 1
if json_start == -1 or json_end == 0:
print(" خطأ: لم يتم العثور على مصفوفة JSON في استجابة النموذج.")
print(f"--- الاستجابة الخام ---\n{response_text}\n--------------------")
return None
clean_json_str = response_text[json_start:json_end]
ai_translations = json.loads(clean_json_str)
return {
item["verse_number"]: item["hybrid_translation"] for item in ai_translations
}
الكود البرمجي الكامل
حتى لا يطول الشرح بالكود التفصيلي اكتفيت بعرض أهم الأجزاء وشرحها، ووفرت الكود الكامل مع جميع الملفات المساعدة على مستودع GitHub للاطلاع عليه وتجربته مباشرة.
ستجدون في هذا المستودع جميع الملفات الأساسية والمساعدة المتعلقة بالتطبيق:
quran_app.py: الكود الرئيسي لتشغيل التطبيق.
requirements.txt: قائمة المكتبات المطلوبة.
README.md: وصف شامل للتطبيق وآلية عمله.
test_ollama.py: ملف مساعد للتأكد من أن نموذج Ollama يعمل بشكل صحيح ويولد الترجمات كما هو متوقع قبل استخدامه في الكود الرئيسي.
list_languages.py: ملف مساعد لعرض كافة الترجمات التي توفرها واجهة Quran.com API.
index.html و surah.html: ملفات الواجهة موجودة داخل مجلد TEMPLATE.
لتشغيل التطبيق تحتاج إلى تثبيت لغة بايثون على جهازك، وتثبيت المكتبات الموجودة في الملف requirements.txt إلى جانب وجود نموذج Ollama مثبت ومشغل على جهازك (أو الوصول له من خلال واجهة برمجية أو عبر شبكة) ولوجود اتصال بالإنترنت للوصول إلى واجهة Quran.com API لجلب النصوص والترجمات.
تقييمي للتجربة
بعد اختبار التطبيق ومراجعة نتائج الترجمة الهجينة التي ولدها النموذج، هذا تقييمي للتجربة:
- يقدم نموذج LLaMA 3 8B ترجمات هجينة للقرآن الكريم إلى التركية بدقة جيدة بشكل عام.
- يقع النموذج أحيانًا في أخطاء لغوية أو ينتج تراكيب غير سليمة، خصوصًا عند التعامل مع الآيات ذات البنية اللغوية المعقدة.
- يصبح النموذج بطيئًا بشكل ملحوظ مع السور الطويلة مما يؤثر على تجربة الاستخدام.
بشكل عام، أرى أن التجربة جيدة وأشجع على فكرة الجمع بين الترجمات المتوفرة مع تعزيز الذكاء الاصطناعي فهذا يمكن أن يفتح آفاقًا واعدة في تطبيقات الترجمة القرآنية.
في الختام، يسرني معرفة رأيكم بهذه التجربة، وإن كان لديكم أي تساؤلات أو أفكار أو اقتراحات لتحسين جودة الترجمة أو تسريع أداء التطبيق شاركوني إياها في التعليقات.