تبدأ أغلب المجلات العلمية في الجامعات ببريد إلكتروني: يرسل الباحث بحثه إلى بريد المجلة، فيعيد المحرر إرساله إلى محكمين اثنين بعد أن يحذف الأسماء من الملف بيده، ثم تتجمع الردود في صندوق البريد، وبعد سنة يصبح السؤال «من حكم هذا البحث؟ ومتى أرسلنا له التذكير؟» سؤالاً لا يجيب عليه أحد، وقد يكتشف المحرر أن اسم الباحث بقي في خصائص ملف Word الذي وصل إلى المحكم. وفي مقال الأنظمة التي تحتاجها الجامعة ذكرنا أن النشر العلمي جزء من مرحلة التعلم والبحث، وفي هذا المقال سوف نشغل Open Journal Systems واختصاراً OJS، وهو النظام المفتوح المصدر الذي يطوره مشروع المعرفة العامة PKP لإدارة المجلات المحكمة، وسوف نتناول ما يلي:
- ما الذي يحتاجه OJS 3.5، ومختبر على Docker من الـ Docker Image الرسمي مع MariaDB، ومشكلتان واجهتنا في التثبيت وسببهما.
- إنشاء المجلة والمستخدمين والأدوار، وتقديم بحث كما يفعل المؤلف.
- التحكيم مزدوج التعمية Double-Anonymous Review خطوة بخطوة: ماذا يرى المحرر، وماذا يرى المحكم، وما الذي لا يحميه البرنامج.
- قرار المحرر Editorial Decision، ثم الإنتاج والنشر في عدد Issue.
- المعرف الرقمي الدائم DOI، والفهرسة في Google Scholar وعبر بروتوكول OAI-PMH، والنسخ الاحتياطي والترقية.
والصورة التالية تبين الطريق الذي يمر به البحث داخل المجلة، وهو الطريق نفسه الذي سوف نمشي فيه في المختبر:

ما الذي يحتاجه OJS 3.5؟
الإصدار الحالي هو 3.5.0-5، وهو إصدار دعم طويل LTS صدر في 30 يونيو 2026، وفي الصفحة نفسها أن الإصدار القديم 3.3 ما زال مدعوماً حتى 1 يناير 2027 على الأقل، فإذا كانت مجلتك على 3.3 فهذا وقت التخطيط للترقية. ودليل مدير النظام يحدد المتطلبات كما يلي:
- PHP: الإصدار 8.2 أو أحدث مع الإضافات mbstring وxml وintl.
- قاعدة البيانات Database: MySQL أو MariaDB أو PostgreSQL.
- مجلد الملفات Files Directory: مجلد تحفظ فيه ملفات الأبحاث المقدمة، والدليل يشترط أن يكون خارج المجلد الذي يصل إليه المتصفح، لأن فيه أبحاثاً لم تنشر بعد وملفات المحكمين.
- البريد Email: خادم SMTP أو sendmail، لأن كل خطوة في التحكيم ترسل بريداً، وسوف نعود إليه.
وأما الموارد ففي مختبرنا بعد انتهاء الدورة كاملة كان الـ Container الخاص بالتطبيق يستخدم 206MB من الذاكرة، وقاعدة MariaDB تستخدم 214MB، وهي أرقام مجلة واحدة فيها بحث واحد، ولكنها تبين أن OJS خفيف ويعمل على سيرفر صغير، وأن الذي يكبر مع الوقت هو مجلد الملفات وليس الذاكرة.
التجربة العملية: OJS على Docker
ينشر فريق PKP الـ Docker Image الرسمي pkpofficial/ojs من مستودع pkp/containers، وهو Apache مع PHP 8.3 وكود OJS، ولكل إصدار وسمان: وسم ثابت فيه رقم البناء، ووسم قصير مثل 3_5_0-5 يشير دائماً إلى آخر بناء لهذا الإصدار. وفي المختبر ثبتنا الوسم القصير بالبصمة @sha256 حتى لا يتغير تحتنا.
ملفات المختبر
أنشئ مجلداً للمختبر، وضع فيه compose.yaml التالي:
name: edu4-ojs
services:
db:
image: mariadb:11.8.9
container_name: edu4-ojs-db
mem_limit: 1g
restart: unless-stopped
environment:
MARIADB_DATABASE: ojs
MARIADB_USER: ojs
MARIADB_PASSWORD: change-me-db
MARIADB_ROOT_PASSWORD: change-me-root
command: ["--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
volumes:
- db:/var/lib/mysql
app:
image: pkpofficial/ojs:3_5_0-5@sha256:d1530e533f2eac070e221d5480f41b6a8580ea83a83d94a133a974488c20353f
container_name: edu4-ojs-app
mem_limit: 1g
restart: unless-stopped
depends_on: [db]
environment:
SERVERNAME: localhost
ports:
- "127.0.0.1:30081:80"
volumes:
- ./config.inc.php:/var/www/html/config.inc.php
- files:/var/www/files
- public:/var/www/html/public
volumes:
db:
name: edu4-ojs-db
files:
name: edu4-ojs-files
public:
name: edu4-ojs-publicفي الإعداد أعلاه لاحظ التالي:
- ثلاثة أشياء تحفظ: قاعدة البيانات، ومجلد الملفات
/var/www/filesالذي فيه الأبحاث وملفات المحكمين، ومجلدpublicالذي فيه شعار المجلة وصور الأعداد، وكل منها في Volume مستقل. - ملف الإعداد config.inc.php: هو الملف الذي يكتب فيه المثبت إعدادات قاعدة البيانات وحالة التثبيت، لذلك نربطه من خارج الـ Container حتى لا يضيع عند تحديث الـ Image، وسوف نرى بعد قليل أن هذا الربط له شرط.
- الترميز utf8mb4: ضبطناه في MariaDB من البداية، لأن العناوين والملخصات بالعربية، ولا تقم بتغيير ترميز قاعدة بيانات فيها بيانات حقيقية بعد التشغيل.
- المنفذ Port: على
127.0.0.1فقط، وفي الإنتاج يكون أمامه Reverse Proxy بشهادة HTTPS كما في قسم النطاق والشهادة.
تجهيز ملف الإعداد قبل التشغيل
خذ الملف من الـ Image نفسه، ثم عدل فيه ثلاثة أسطر قبل أول تشغيل:
docker run --rm --entrypoint cat pkpofficial/ojs:3_5_0-5 /var/www/html/config.inc.php > config.inc.php
sed -i 's|^base_url = .*|base_url = "http://127.0.0.1:30081"|; s|^restful_urls = Off|restful_urls = On|; s|^files_dir = files|files_dir = /var/www/files|' config.inc.php
docker compose up -dوقد يتساءل البعض: لماذا نعدل files_dir بأيدينا والمثبت يسأل عنه؟ والإجابة أن هذا ما واجهناه في المحاولة الأولى، وهو الموضوع التالي.
MSYS_NO_PATHCONV=1 قبل الأمر docker run أعلاه، وإلا حول Git Bash المسار /var/www/html/config.inc.php إلى مسار Windows وفشل الأمر برسالة No such file or directory.معالج التثبيت بالعربية
افتح http://127.0.0.1:30081، فيحولك OJS إلى معالج التثبيت، وهو مترجم إلى العربية، وفيه اسم المدير وكلمة المرور، واللغة الرئيسية للموقع واللغات الإضافية، والمنطقة الزمنية، ومجلد الملفات، وإعدادات قاعدة البيانات، ومعرف المستودع الذي يظهر في OAI-PMH. والصورة التالية للجزء الأخير منه:

اخترنا العربية لغة رئيسية والإنجليزية لغة إضافية، والمنطقة الزمنية Asia/Riyadh، وتركنا خيار المرشد Beacon غير محدد، وهو خيار يرسل إلى PKP معرف الموقع وعنوان OAI لأغراض إحصائية كما يذكر النص تحته.
ماذا يحدث إذا بقي مجلد الملفات نسبياً؟
في المحاولة الأولى تركنا files_dir = files كما هو في الملف، وكتبنا المسار الصحيح في حقل المعالج فقط، فانتهى الضغط على زر التثبيت بخطأ HTTP 500، وفي سجل الـ Container السطران التاليان:
PHP Warning: mkdir(): Permission denied in /var/www/html/lib/pkp/classes/file/FileManager.php on line 424
PHP Fatal error: Uncaught AssertionError: assert(false) in /var/www/html/lib/pkp/classes/scheduledTask/ScheduledTask.php:67
#2 [internal function]: PKP\install\Installer->updateRorRegistryDataset(Object(APP\install\Install), Array)والسبب أن المثبت في أثناء عمله يشغل مهمة تنزيل بيانات المؤسسات البحثية ROR، وهذه المهمة تنشئ مجلداً لسجلاتها داخل مجلد الملفات المكتوب في config.inc.php وليس المكتوب في المعالج، لأن الملف لم يكتب بعد، والمسار النسبي files يقع داخل مجلد الكود الذي لا يكتب فيه المستخدم www-data. والنتيجة قاعدة بيانات نصف مثبتة، لذلك حذفنا الـ Volumes وبدأنا من جديد بعد تصحيح السطر، ومن هنا جاء التعديل الذي في القسم السابق.
وفي المحاولة الثانية اكتمل التثبيت في قاعدة البيانات، فقد أنشأ المثبت 132 جدولاً وحساب المدير، ولكن الموقع بقي يحولنا إلى صفحة التثبيت، وفي الملف بقي السطر installed = Off. والسبب أن المثبت لم يستطع الكتابة في config.inc.php المربوط من خارج الـ Container، وتأكدنا من ذلك بمحاولة كتابة مباشرة بالمستخدم نفسه:
docker exec -u www-data edu4-ojs-app php -r '$f="/var/www/html/config.inc.php"; var_dump(is_writable($f)); var_dump(file_put_contents($f, file_get_contents($f)));'bool(true)
PHP Warning: file_put_contents(/var/www/html/config.inc.php): Failed to open stream: Permission denied in Command line code on line 1
bool(false)لاحظ أن PHP يقول إن الملف قابل للكتابة ثم يفشل في فتحه، وهذا سلوك ربط ملف من Windows عبر Docker Desktop، والحل على سيرفر Linux هو ما يذكره ملف pkp/containers: أن تجعل مالك الملفات المربوطة المستخدم 33 وهو www-data داخل الـ Image:
sudo chown 33:33 config.inc.phpوعلى جهاز التطوير الذي لا يقبل ذلك، أكمل الملف بنفسك بالقيم نفسها التي كان المثبت سيكتبها: installed = On، ومفتاح التطبيق app_key بقيمة عشوائية بالصيغة base64:، وhost = db وكلمة مرور قاعدة البيانات، وsalt وapi_key_secret بقيم عشوائية، وrepository_id في قسم OAI، وهذا ما فعلناه في المختبر. والقاعدة العامة هنا: إذا رأيت معالج تثبيت يعود إلى بدايته بعد أن نجح، فابحث أولاً عن ملف إعداد لم يكتب.
إنشاء المجلة
الموقع الواحد في OJS يستضيف أكثر من مجلة، ولكل مجلة رابط قصير وإعدادات ومحررون خاصون بها، وتنشئها من الإدارة ثم المجلات المستضافة Hosted Journals ثم إنشاء مجلة. وفي المختبر أنشأناها عبر واجهة REST API بالحقول نفسها التي في النموذج: الرابط jcs، والاسم «مجلة علوم الحاسب» بالعربية و«Journal of Computer Science» بالإنجليزية، واللغة الرئيسية العربية، واللغات المدعومة العربية والإنجليزية. ثم قرأنا إعدادات المجلة الجديدة من الواجهة نفسها، وأهم ما فيها لموضوعنا:
defaultReviewMode=2
numWeeksPerReview=4
enableDois=true
doiPrefix=null
enableOai=trueوالقيمة 2 في defaultReviewMode هي الثابت SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS في كود OJS، أي أن المجلة الجديدة تبدأ بالتحكيم مزدوج التعمية افتراضياً، والمحكم له أربعة أسابيع، والـ DOI مفعل ولكن دون بادئة Prefix، وOAI-PMH مفعل.
المستخدمون والأدوار Roles
كل شخص في OJS حساب واحد، والأدوار تعطى لكل مجلة على حدة، فالأستاذ نفسه قد يكون مؤلفاً في مجلة ومحكماً في أخرى. والأدوار التي تهمنا في التحكيم كما يلي:
| الدور | ما الذي يفعله | ماذا يرى في التحكيم مزدوج التعمية |
|---|---|---|
| مدير المجلة Journal Manager | الإعدادات والمستخدمون، ويستطيع العمل محرراً | كل شيء |
| المحرر Editor | يستقبل البحث، ويختار المحكمين، ويتخذ القرار | اسم المؤلف وأسماء المحكمين |
| المحكم Reviewer | يقرأ البحث ويكتب التحكيم والتوصية | العنوان والملخص والملف، دون اسم المؤلف |
| المؤلف Author | يقدم البحث ويرفع التعديلات | حالة البحث، دون أسماء المحكمين |
في المختبر سجلنا ثلاثة حسابات من صفحة التسجيل العامة في المجلة: الباحثة «سارة»، والمحكمان «خالد» و«ريم»، وفي صفحة التسجيل خيار يطلب فيه الشخص دور المحكم، فأعطاهما النظام هذا الدور مباشرة، وأما المؤلف فيأخذ دوره عندما يبدأ أول تقديم. وعمل حساب المدير محرراً في هذه الدورة.
تقديم البحث Submission
قدمت الباحثة بحثاً بعنوان «أثر التخزين المؤقت على زمن استجابة تطبيقات الويب» بالعربية، مع ملخص وكلمتين مفتاحيتين وملف PDF، والملف نفسه نسخة للتحكيم ليس فيها اسمها، وهذا ما يطلبه التحكيم مزدوج التعمية من المؤلف. ومعالج التقديم في OJS 3.5 يعمل كله عبر REST API، فالمتصفح ينشئ التقديم ثم يرفع الملف ثم يرسل التقديم، وقد استخدمنا هذه الطلبات نفسها من سكربت، وبعد الإرسال ظهر البحث في لوحة المحرر في قائمة «تحتاج محرر».
ولاحظ أن OJS أنشأ من حساب الباحثة سجل المؤلف في البحث تلقائياً: الاسم والبريد والمؤسسة «جامعة المثال»، وهذه البيانات تظهر للقارئ بعد النشر، ولا تظهر للمحكم قبله كما سوف نرى.
التحكيم مزدوج التعمية خطوة بخطوة
في التحكيم المزدوج لا يعرف المحكم من هو المؤلف، ولا يعرف المؤلف من هم المحكمون، والهدف أن يحكم المحكم على البحث وليس على اسم صاحبه أو جامعته. وفي OJS ثلاثة أنواع للتحكيم، يختار المحرر واحداً منها لكل محكم، وأسماؤها في الواجهة العربية كما يلي:
| الاسم في الواجهة العربية | الاسم في التوثيق | المعنى |
|---|---|---|
| محكم مجهول/مؤلف مجهول | Anonymous Reviewer/Anonymous Author | التحكيم مزدوج التعمية |
| محكم سري/مؤلف مكشوف | Anonymous Reviewer/Disclosed Author | المحكم يعرف المؤلف، والمؤلف لا يعرف المحكم |
| علني | Open | كل طرف يعرف الآخر |
قبل الإرسال: ملف بلا أسماء
هناك مشكلة رئيسية في التحكيم المزدوج لا يحلها أي برنامج، وهي الملف نفسه، ودليل التحكيم في OJS يقولها صراحة: OJS يخفي اسم المؤلف داخل النظام، ولكن الاسم قد يبقى في صفحة العنوان، وفي نص البحث والحواشي والمراجع، وفي خصائص الملف التي يكتبها برنامج التحرير، وضمان التعمية مسؤولية المحرر. لذلك اتفق مع مجلتك على قاعدة واضحة: المؤلف يرفع نسخة بلا أسماء، والمحرر يفتح خصائص الملف قبل أن يرسله.
بعد قرار «أرسل للتحكيم»، يختار المحرر الملفات التي سوف يراها المحكمون، فهي لا تنتقل وحدها، ففي مختبرنا ظهرت جولة التحكيم الأولى وقائمة «الملفات المعدة للتحكيم» فارغة، فاخترنا الملف من «رفع/إختيار الملفات» مع خيار إظهار الملفات من كل المراحل.
اختيار المحكمين
من «إضافة محكم» تظهر قائمة المحكمين المسجلين في المجلة، والصورة التالية لها كما ظهرت لنا:

لاحظ الشارة «نفس مؤسسة المؤلف» بجانب المحكمين، فقد سجلنا الثلاثة بالمؤسسة نفسها، وOJS قارن مؤسسة المحكم بمؤسسة المؤلف ونبه المحرر، وهذا تعارض مصالح Conflict of Interest حقيقي في مجلة جامعية، لأن المحكم من القسم نفسه قد يعرف البحث من أسلوبه أو من موضوعه حتى لو لم ير الاسم. والقاعدة هنا: اجعل نصف المحكمين على الأقل من خارج الجامعة، والسبب أن التعمية تحمي الاسم ولا تحمي المعرفة الشخصية.
بعد «إختر المحكم» يظهر نموذج الإرسال، وفيه رسالة الدعوة، وتاريخ الرد وتاريخ تسليم التحكيم، والملفات، ونوع التحكيم:

أضفنا المحكمين بالنوع الافتراضي، وتأكدنا من قاعدة البيانات أن كل تكليف حفظ بالنوع 2:
review_id reviewer_id review_method date_assigned
1 3 2 2026-10-21 16:05:53
2 4 2 2026-10-21 16:11:53ماذا يرى المحكم؟
دخلنا بحساب المحكم «خالد» وفتحنا الدعوة، والصورة التالية للخطوة الأولى من الخطوات الأربع للتحكيم:

قبل المحكم الدعوة، ثم قرأ الإرشادات، ثم كتب تعليقين: تعليقاً للمؤلف والمحرر، وتعليقاً للمحرر فقط، واختار توصيته من القائمة، ثم سلم التحكيم. فاختار «خالد» التوصية «أعد التقديم للتحكيم»، واختارت «ريم» «التنقيحات مطلوبة»، والتوصيات الست في الكود كما يلي: القبول، والتنقيحات مطلوبة، وأعد التقديم للتحكيم، وأعد التقديم إلى مكان آخر، والرفض، وانظر التعليقات.
ماذا يرى المحرر؟

التوصيتان مختلفتان، وهذا طبيعي، والقرار للمحرر وليس للتصويت، فاتخذنا القرار «إلتماس التنقيحات»، فرأت الباحثة في لوحتها أن التنقيحات مطلوبة، دون أي اسم للمحكمين، فرفعت نسخة معدلة في قائمة «التنقيحات قد رفعت» في الجولة نفسها. وبعد ذلك اتخذنا القرار «قبول طلب النشر»، فانتقل البحث إلى مرحلة التدقيق Copyediting، ثم «الإرسال إلى الإنتاج». والقرارات المتاحة للمحرر في مرحلة التحكيم كما أعادتها واجهة REST API:
[{"stageId":3,"id":4,"label":"إلتماس التنقيحات"},{"stageId":3,"id":5,"label":"إعادة التقديم للتحكيم"},{"stageId":3,"id":2,"label":"قبول طلب النشر"},{"stageId":3,"id":14,"label":"جولة تحكيم جديدة"},{"stageId":3,"id":6,"label":"رفض المؤلَّف"}]ولاحظ الفرق بين «إلتماس التنقيحات» و«إعادة التقديم للتحكيم»: الأول يعني أن المحرر سوف يراجع التعديلات بنفسه، والثاني يعني أن النسخة المعدلة تعود إلى المحكمين في جولة جديدة، وهو ما أوصى به «خالد». وفي مجلة حقيقية اكتب في السياسة متى تكفي مراجعة المحرر ومتى تلزم جولة ثانية، حتى لا يختلف القرار من محرر إلى آخر.
الإنتاج والنشر في عدد
في مرحلة الإنتاج Production يرفع المحرر أو مصمم الصفحات النسخة النهائية التي سوف يقرؤها الناس، وهنا يعود اسم المؤلف إلى الملف، ويسمى هذا الملف في OJS «اللوح الطباعي» Galley. وفي المختبر قمنا بما يلي:
- أنشأنا عدداً مستقبلياً Future Issue: المجلد 1، العدد 1، سنة 2026، بعنوان «العدد الأول».
- أضفنا Galley بعنوان PDF ولغة عربية، ورفعنا فيه النسخة النهائية التي فيها اسم الباحثة ومؤسستها.
- ربطنا البحث بالعدد، وكتبنا الصفحات 1-6، ثم نشرناه، فأصبحت حالته «مجدول» لأن العدد لم ينشر بعد.
- نشرنا العدد، فنشر معه كل ما فيه، وأصبح تاريخ النشر 2026-10-21.
والصورة التالية لصفحة البحث كما يراها الزائر بعد النشر:

المعرف الرقمي الدائم DOI
المعرف الرقمي الدائم Digital Object Identifier هو رقم مثل 10.5555/mncq0351 يشير إلى البحث مهما تغير رابطه، فإذا نقلت المجلة إلى نطاق جديد بعد خمس سنوات يبقى الاستشهاد بالبحث صحيحاً. وأوله البادئة Prefix التي تعطيها لك وكالة تسجيل مثل Crossref، وآخره اللاحقة Suffix التي يولدها OJS. ودليل مدير المجلة يبين أن إدارة الـ DOI أصبحت جزءاً من OJS منذ 3.4، وأن الخطوات أربع: ضبط البادئة وما يأخذ DOI، ثم التعيين Assign، ثم الإيداع Deposit لدى الوكالة، ثم التحديث عند تغيير البيانات.
في المختبر وضعنا البادئة 10.5555 كمثال، وعينا DOI للبحث، فأعاد النظام:
assign 200 {"failedDoiActions":[]}
doi {"contextId":1,"doi":"10.5555/mncq0351","id":1,"registrationAgency":null,"resolvingUrl":"https://doi.org/10.5555/mncq0351","status":1}
وهنا تحذير مهم: صفحة البحث عرضت الرابط https://doi.org/10.5555/mncq0351 مباشرة بعد التعيين، والحالة في صفحة المعرفات «غير مسجلة» (status 1)، أي أن الرابط لن يعمل لأحد حتى يودع لدى Crossref. لذلك لا تقم بتفعيل DOI في مجلة حقيقية قبل أن تكون لديك عضوية وبادئة حقيقية، والسبب أن الباحثين سوف ينسخون الرابط في استشهاداتهم من اليوم الأول.
والعضوية في Crossref لها رسوم، وهي كما في صفحة الرسوم في 21 أكتوبر 2026:
| البند | الرسم |
|---|---|
| العضوية السنوية لجهة إيرادات النشر أو مصروفاته بين 1000 ومليون دولار | 275 دولاراً في السنة |
| العضوية السنوية إذا كانت أقل من 1000 دولار | 200 دولار في السنة |
| تسجيل مقالة حديثة (السنة الحالية والسنتان قبلها) | 1.00 دولار للمقالة |
| تسجيل مقالة أقدم | 0.15 دولار للمقالة |
والصفحة نفسها تذكر أن أغلب أسعار التسجيل تنخفض للمحتوى المسجل من 1 يناير 2027، وأن تسجيل المحتوى القديم يصبح دون رسوم، فراجعها قبل أن تحسب الميزانية. وبعد العضوية تكتب بيانات الحساب في إعدادات التسجيل في OJS، وتفعل الإيداع التلقائي، فيتولاه النظام عند النشر.
الفهرسة: Google Scholar وOAI-PMH
بيانات Google Scholar
لا يوجد تسجيل للمجلة في Google Scholar، ودليل PKP للفهرسة في Google Scholar يذكر أنه يزحف إلى الموقع بنفسه ويقرأ بيانات وصفية في رأس صفحة كل بحث، وهذه البيانات التي وجدناها في صفحة بحثنا:
curl -s http://127.0.0.1:30081/jcs/ar/article/view/1 | grep -o '<meta name="citation[^>]*>'<meta name="citation_journal_title" content="مجلة علوم الحاسب"/>
<meta name="citation_author" content="سارة الباحثة"/>
<meta name="citation_author_institution" content="جامعة المثال"/>
<meta name="citation_title" content="أثر التخزين المؤقت على زمن استجابة تطبيقات الويب"/>
<meta name="citation_language" content="ar"/>
<meta name="citation_date" content="2026/10/21"/>
<meta name="citation_volume" content="1"/>
<meta name="citation_issue" content="1"/>
<meta name="citation_firstpage" content="1"/>
<meta name="citation_lastpage" content="6"/>
<meta name="citation_doi" content="10.5555/mncq0351"/>
<meta name="citation_pdf_url" content="http://127.0.0.1:30081/jcs/article/download/1/1"/>والنصيحة الأهم في دليل PKP للمجلات العربية: لغة واحدة في كل وسم، ولغة الوسم هي لغة نص البحث، والاسم مكتوب بالطريقة نفسها في كل الأبحاث. فلا تقم بكتابة العنوان العربي والإنجليزي معاً في حقل واحد، والسبب أن Google Scholar يقرأ الوسم كما هو فيخلط العنوانين. ولاحظ أن الوسم citation_pdf_url يشير إلى ملف الـ Galley، فإذا كانت المجلة تنشر HTML فقط فلن يجد Google Scholar النص الكامل بالطريقة نفسها.
بروتوكول OAI-PMH
بروتوكول حصاد البيانات الوصفية OAI-PMH هو الطريقة التي تقرأ بها المجمعات والفهارس الوطنية والدولية بيانات المجلة دفعة واحدة، وفي OJS يعمل على الرابط /oai لكل مجلة:
curl -sL "http://127.0.0.1:30081/jcs/oai?verb=Identify"<Identify>
<repositoryName>مجلة علوم الحاسب</repositoryName>
<baseURL>http://127.0.0.1:30081/jcs/ar/oai</baseURL>
<protocolVersion>2.0</protocolVersion>
<adminEmail>[email protected]</adminEmail>
<earliestDatestamp>2026-10-21T20:29:55Z</earliestDatestamp>
<deletedRecord>persistent</deletedRecord>
...
<sampleIdentifier>oai:journal.example.com:article/1</sampleIdentifier>ثم سجل البحث بصيغة Dublin Core:
curl -sL "http://127.0.0.1:30081/jcs/oai?verb=ListRecords&metadataPrefix=oai_dc"<identifier>oai:journal.example.com:article/1</identifier>
<setSpec>jcs:ART</setSpec>
...
<dc:title xml:lang="ar">أثر التخزين المؤقت على زمن استجابة تطبيقات الويب</dc:title>
<dc:creator xml:lang="ar">الباحثة, سارة</dc:creator>
<dc:subject xml:lang="ar">التخزين المؤقت</dc:subject>
<dc:publisher xml:lang="en">Journal of Computer Science</dc:publisher>
<dc:type>info:eu-repo/semantics/article</dc:type>
<dc:identifier>10.5555/mncq0351</dc:identifier>
<dc:source xml:lang="ar">مجلة علوم الحاسب; مجلد 1 عدد 1 (2026); 1-6</dc:source>في المخرج أعلاه لاحظ التالي:
- المعرف
oai:journal.example.com:article/1مبني على معرف المستودع الذي كتبناه في معالج التثبيت، والمجمعات تحفظه، فاختر النطاق الحقيقي للمجلة من البداية ولا تغيره. - الاسم في
dc:creatorبالصيغة «العائلة, الاسم»، أي «الباحثة, سارة»، وهي الصيغة المتعارف عليها في الفهارس، لذلك اطلب من المؤلفين تعبئة حقل اسم العائلة والاسم الأول كل في مكانه. - الرابط في
baseURLفيه رمز اللغةar، لأن OJS 3.5 يضع اللغة في الروابط، وقد طلبنا/jcs/oaiفحولنا إليه.
والمستودع العلمي للجامعة يعمل بالبروتوكول نفسه، وقد شرحناه في دليل المستودع المؤسسي مع DSpace.
العربية في OJS بصراحة
الواجهة العربية تعمل من معالج التثبيت إلى صفحة القارئ، والاتجاه من اليمين إلى اليسار سليم في كل الصفحات التي فتحناها، ولكن أثناء التجربة وجدنا ما يلي:
- مفتاح ترجمة ظاهر: في لوحة المحرر زر نصه
##common.help##، أي أن مفتاح الترجمة نفسه ظهر بدلاً من كلمة «مساعدة». - أخطاء إملائية في الترجمة: مثل «إقفز إلى المحتوى الرئيسي»، و«إختر المحكم»، و«تأريخ رفعه».
- مصطلح غير مألوف: البحث المقدم يسمى في الترجمة «المؤلف» بمعنى العمل المؤلف، فيظهر زر «رفض المؤلف» الذي يفهمه المحرر لأول وهلة رفضاً للشخص وليس للبحث.
- Galley: مترجمة «الألواح الطباعية»، وهي ترجمة لن يفهمها أغلب أعضاء هيئة التحرير دون شرح.
وكلها نصوص يمكن تعديلها من ملفات اللغة أو من إضافة تخصيص الترجمة، وهي لا تمنع التشغيل، ولكن اجمعها في قائمة واحدة قبل تدريب هيئة التحرير.
البريد والمهام المجدولة
كل خطوة في التحكيم ترسل بريداً: دعوة المحكم، وتذكيره، وإبلاغ المؤلف بالقرار، والمجلة التي لا يصل بريدها لا يعمل فيها التحكيم. وفي المختبر لم نضبط خادماً للبريد، فبقي الإعداد الافتراضي default = sendmail ولم تخرج أي رسالة، وفي الإنتاج اضبط قسم [email] في config.inc.php بخادم SMTP كما في البريد التفاعلي Transactional Email، ودليل البريد في OJS يطلب سجل SPF للنطاق، ومرسلاً من نطاق المجلة نفسه حتى يمر البريد من فحص DMARC، وقد شرحناهما في شرح SPF وDKIM وDMARC.
وأما التذكيرات وإيداع الـ DOI التلقائي فهي مهام مجدولة Scheduled Tasks، وهذه قائمتها كما في المختبر:
docker exec edu4-ojs-app sh -c 'cd /var/www/html && php lib/pkp/tools/scheduler.php list' * * * * * PKP\task\ProcessQueueJobs ........ Next Due: 27 seconds from now
0 0 * * * PKP\task\ReviewReminder ............. Next Due: 3 hours from now
0 0 * * * PKP\task\DepositDois ................ Next Due: 3 hours from now
0 0 1 * * PKP\task\UpdateRorRegistryDataset .... Next Due: 1 week from now
0 0 * * * APP\tasks\UsageStatsLoader .......... Next Due: 3 hours from now
...ودليل المهام المجدولة يذكر أن OJS 3.5 فيه مشغل مهام داخلي يعمل مع طلبات الزوار، وهو مفعل في الإعداد الافتراضي task_runner = On، وأنه قد لا يناسب المواقع الكبيرة، وينصح حينها بأن يشغلها Cron كل دقيقة ثم يوقف المشغل الداخلي:
* * * * * php lib/pkp/tools/scheduler.php run >> /dev/null 2>&1ولاحظ أن ملف التشغيل في الـ Docker Image يترك سطر تشغيل Cron معلقاً، فإذا قررت إيقاف المشغل الداخلي فأضف Container أو مهمة Cron على السيرفر تشغل الأمر أعلاه داخل Container التطبيق، وإلا توقفت التذكيرات دون أن ينبهك أحد.
النطاق والشهادة
في الإنتاج ضع OJS خلف Reverse Proxy بشهادة HTTPS كما في تثبيت Caddy، ثم عدل base_url في config.inc.php إلى النطاق الحقيقي، مثل https://journal.example.com، والسبب أن OJS يبني من هذه القيمة كل الروابط في الصفحات والبريد وOAI والوسوم التي يقرؤها Google Scholar. وفي دليل تأمين النظام إعدادات أخرى، أهمها allowed_hosts الذي يحدد النطاقات المقبولة للطلبات، وهو فارغ في الملف الافتراضي.
هذا القسم لم نختبره في المختبر المحلي، لأنه يحتاج نطاقاً حقيقياً وشهادة حقيقية.
التحقق من النجاح
- الصفحة الرئيسية للمجلة تفتح بالعربية، ولا يحولك الموقع إلى صفحة التثبيت.
- بحث تجريبي يمر بكل المراحل، والمحكم لا يرى اسم المؤلف في صفحة التحكيم ولا في الملف.
- بريد دعوة المحكم يصل فعلاً إلى صندوق خارجي، وليس إلى مجلد الرسائل المزعجة.
- الطلب
/oai?verb=Identifyيعيد اسم المجلة والنطاق الحقيقي. - صفحة البحث المنشور فيها وسوم
citation_، وفيها DOI مسجل يفتح منdoi.org.
النسخ الاحتياطي والاستعادة
النسخة الكاملة أربعة أشياء: قاعدة البيانات، ومجلد الملفات، ومجلد public، وملف config.inc.php، والأخير مهم لأن فيه مفتاح التطبيق app_key. وهذه الأوامر التي أخذنا بها النسخة في المختبر:
docker exec edu4-ojs-db sh -c 'mariadb-dump -uojs -pchange-me-db --single-transaction ojs | gzip > /tmp/ojs.sql.gz && ls -la /tmp/ojs.sql.gz'
docker exec edu4-ojs-app sh -c 'tar czf /tmp/ojs-files.tgz -C /var/www files html/public && ls -la /tmp/ojs-files.tgz; du -sh /var/www/files /var/www/html/public'-rw-r--r-- 1 root root 9179637 Oct 21 20:32 /tmp/ojs.sql.gz
-rw-r--r-- 1 www-data www-data 61255077 Oct 21 20:32 /tmp/ojs-files.tgz
122M /var/www/files
16K /var/www/html/publicقد يبدو الرقم من الوهلة الأولى غريباً، فمجلة فيها بحث واحد مجلد ملفاتها 122MB، ولكن عند البحث وجدنا أن أغلبه في المجلد usageStats، وهو بيانات المواقع الجغرافية التي ينزلها OJS لإحصاءات القراءة، وأن مجلد المجلة نفسه 140KB فقط. لذلك لا تحكم على نمو المجلة من أول نسخة، وراقب المجلد journals داخل مجلد الملفات. ثم انقل النسخ خارج السيرفر واختبر استعادتها كما في النسخ الاحتياطي بقاعدة 3-2-1 واختبار الاستعادة، والاستعادة بالعكس: قاعدة البيانات بالأمر mariadb، والملفات في الـ Volumes، وملف الإعداد في مكانه.
التحديث إلى إصدار أحدث
- خذ نسخة كاملة كما في القسم السابق، وجرب الترقية على نسخة من الموقع أولاً.
- غير وسم الـ Image إلى الإصدار الجديد، واحتفظ بملف
config.inc.phpوالـ Volumes كما هي. - شغل أداة الفحص ثم الترقية داخل الـ Container:
php tools/upgrade.php checkثمphp tools/upgrade.php upgrade. - افتح لوحة المحرر وبحثاً منشوراً، وتأكد من OAI-PMH قبل أن تعلن انتهاء الترقية.
ولا تقم بالقفز من 3.3 إلى 3.5 على الموقع الحقيقي مباشرة، والسبب أن الترقية تغير بنية قاعدة البيانات، ولا رجوع عنها إلا من النسخة الاحتياطية.
مشكلات شائعة وحلولها
| العرض | السبب | الحل |
|---|---|---|
خطأ 500 عند زر التثبيت، وفي السجل mkdir(): Permission denied | files_dir نسبي في ملف الإعداد | اكتب المسار الكامل /var/www/files في الملف قبل التثبيت، وابدأ بقاعدة بيانات فارغة |
| الموقع يعود إلى صفحة التثبيت بعد نجاحه | المثبت لم يستطع الكتابة في config.inc.php | chown 33:33 للملف على Linux، أو أكمل الملف بنفسك |
| المحكمون لا يرون أي ملف | الملف لم يختر في «الملفات المعدة للتحكيم» | اختره من «رفع/إختيار الملفات» قبل إضافة المحكمين |
| رابط DOI على صفحة البحث لا يفتح | الـ DOI معين وغير مسجل | أودعه من صفحة المعرفات، وتأكد أن الحالة «مسجلة» |
| لا تصل دعوات التحكيم | sendmail دون خادم بريد، أو مرسل لا يطابق النطاق | SMTP في [email] وسجلات SPF وDMARC للنطاق |
تنظيف المختبر
docker compose down -v Volume edu4-ojs-files Removed
Volume edu4-ojs-public Removed
Volume edu4-ojs-db Removed
Network edu4-ojs_default Removedثم احذف الـ Image بالأمر docker image rm pkpofficial/ojs:3_5_0-5 إذا لم تعد تحتاجه، وحجمه في مختبرنا 2.3GB.
تدريب عملي
- أنشئ ملف Word فيه اسمك في خصائص الملف Author، وارفعه في تقديم تجريبي، ثم افتحه بحساب المحكم وابحث عن اسمك في خصائصه، وستعرف لماذا يتحمل المحرر مسؤولية التعمية.
- غير نوع التحكيم لمحكم واحد إلى «محكم سري/مؤلف مكشوف»، وقارن ما يراه في الخطوة الأولى بما رآه «خالد».
الخلاصة
وصلنا لنهاية الموضوع، وأهم ما فيه:
- OJS 3.5.0-5 إصدار LTS، يحتاج PHP 8.2 وقاعدة MariaDB أو PostgreSQL، واستهلك في المختبر نحو 420MB من الذاكرة للتطبيق وقاعدة البيانات معاً.
- جهز
config.inc.phpقبل التثبيت: المسار الكامل لمجلد الملفات، وملف يستطيع المستخدم 33 الكتابة فيه. - المجلة الجديدة تبدأ بالتحكيم مزدوج التعمية، والمحكم لا يرى اسم المؤلف داخل النظام، ولكن تعمية الملف نفسه مسؤولية المحرر.
- OJS ينبه إلى المحكم من مؤسسة المؤلف، فاستفد من هذا التنبيه واختر محكمين من خارج الجامعة.
- الـ DOI يظهر على الصفحة بمجرد تعيينه، ولا يعمل حتى يودع لدى Crossref، فلا تفعله قبل العضوية.
- Google Scholar يقرأ وسوم
citation_والمجمعات تقرأ OAI-PMH، وكلاهما يعمل في OJS دون إضافات.
سجل التحديثات
- أكتوبر 2026: كتابة الدليل وتجربته على OJS 3.5.0-5 من الـ Docker Image الرسمي (PHP 8.3.31) مع MariaDB 11.8.9.