المستوى المطلوب: مبتدئ
لو حفظت اسم عربي في قاعدة بيانات أو ملف، ورجعت لقيته بقى رموز زي Ø£ØÙ…د أو علامات استفهام ????، المقال ده هيخلّيك تعرف السبب بالظبط وتصلّحه في دقايق. المشكلة مش في الكيبورد ولا في السيرفر. المشكلة في حاجة اسمها الترميز (encoding).
ليه النص العربي بيتحول لرموز غريبة؟
الكمبيوتر مابيعرفش حروف. هو بيعرف بايتات، يعني أرقام. عشان يخزّن كلمة "أحمد"، بيحوّلها لمجموعة بايتات بقاعدة متفق عليها. لو خزّنت بقاعدة وقريت بقاعدة تانية، بيطلعلك كلام مكسّر اسمه mojibake.
المشكلة باختصار
أي نص بيتخزّن بايتات. والبايتات لوحدها مالهاش معنى من غير ما تعرف "اتكتبت بأي ترميز". لو الترميز اللي بتقرأ بيه مختلف عن اللي خزّنت بيه، الحروف بتتفكّك غلط. ده أشهر سبب لظهور العربي كرموز في المواقع وقواعد البيانات.
مثال يقرّب الفكرة: دفتر الشفرة
تخيّل إنك بتبعت رسالة لصاحبك بشفرة. عندكوا دفتر بيقول الرقم 1 يساوي "أ"، الرقم 2 يساوي "ب"، وهكذا. انت كتبت بالدفتر بتاعك، بس صاحبك فتح دفتر تاني أرقامه مختلفة. هيقرأ نفس الأرقام، لكن يطلعله كلام ملوش معنى. الكمبيوتر بيعمل نفس الحاجة بالظبط: "الدفتر" هو الترميز، ولو الطرفين مش بنفس الدفتر، الرسالة بتتقري غلط.
المفهوم بدقة: ASCII و Unicode و UTF-8
الخلط بين التلاتة دول هو أصل المشكلة، فخلينا نفكّهم بالترتيب:
- ASCII: أقدم دفتر. بايت واحد لكل حرف، و128 حرف بس. بيغطّي الإنجليزي والأرقام، ومافيهوش عربي خالص.
- Unicode: ده مش ترميز، ده جدول عملاق بيدّي كل حرف في كل لغات الدنيا رقم ثابت اسمه code point. مثلاً حرف الألف-همزة "أ" رقمه
U+0623. Unicode فيه أكتر من 149 ألف محرف. - UTF-8: ده الترميز اللي بيحوّل الـ code point لبايتات فعلية. طوله متغيّر: من 1 لـ 4 بايت للحرف الواحد.
القاعدة العملية في UTF-8: الحرف الإنجليزي بياخد بايت واحد، الحرف العربي غالبًا بايتين، والإيموجي لحد 4 بايت. عشان كده كلمة "أحمد" (4 حروف) بتاخد 8 بايت، مش 4.
اعملها بنفسك: كود Python بيوريك المشكلة والحل
s = "أحمد"
print(len(s)) # 4 ← عدد الحروف
print(len(s.encode("utf-8"))) # 8 ← عدد البايتات في UTF-8
print(s.encode("utf-8")) # b'\xd8\xa3\xd8\xad\xd9\x85\xd8\xaf'
# الغلطة الشائعة: قراءة بايتات UTF-8 وكأنها Latin-1
wrong = s.encode("utf-8").decode("latin-1")
print(wrong) # Ø£ØÙ…د ← ده الـ mojibake
# الإصلاح: اقرأ بنفس الترميز اللي خزّنت بيه
fixed = s.encode("utf-8").decode("utf-8")
print(fixed) # أحمد
ركز في السطرين len(s) و len(s.encode("utf-8")). الأول بيعدّ الحروف، والتاني بيعدّ البايتات. الفرق بينهم (4 مقابل 8) هو لُب الموضوع كله.
السيناريو الواقعي والأرقام
الافتراض إن عندك جدول MySQL وعموده النصي charset بتاعه latin1 بدل utf8mb4. لو دخّلت فيه 50,000 صف فيهم أسماء عربية، كل الصفوف دي هترجع mojibake وقت العرض. والمشكلة مش هتبان وانت بتكتب، هتبان بعد ما البيانات تتخزّن غلط. تصليحها بعدين بيحتاج migration وممكن ياخد ساعات، وده أغلى بكتير من إنك تظبط الـ charset من أول يوم.
الحل في 3 خطوات
- خلّي كل حاجة UTF-8 من البداية للنهاية: الملفات، قاعدة البيانات (
utf8mb4في MySQL)، والـ HTTP header (Content-Type: text/html; charset=utf-8). - في الـ HTML حط
<meta charset="utf-8">كأول حاجة جوّه الـ<head>. - وانت بتقرا ملفات في الكود، حدّد الترميز صراحةً:
open("file.txt", encoding="utf-8")بدل ما تسيبه للنظام يخمّن.
الـ trade-off اللي لازم تعرفه
UTF-8 بيكسبك توافق كامل مع ASCII وحجم أصغر للنصوص الإنجليزية، بس بتخسر إن النص العربي بياخد ضعف المساحة (بايتين للحرف). لو عندك نص عربي ضخم جدًا والمساحة حرجة، فيه ترميز تاني اسمه UTF-16 بيخزّن أغلب الحروف العربية في بايتين كمان، لكنه بيخلّي الإنجليزي ياخد بايتين بدل واحد وبيكسر توافق ASCII. التوصية العملية: ابدأ بـ UTF-8 دايمًا، ومتفكّرش في UTF-16 إلا لو عندك سبب قياس حقيقي.
متى متشغّلش بالك بالموضوع
لو تطبيقك كله إنجليزي وأرقام بس، ومفيش أي إدخال من مستخدمين بلغات تانية، الفرق بين ASCII و UTF-8 مش هيأثر عليك عمليًا، فمتضيّعش وقت في تحسينات ترميز مش محتاجها. بس بمجرد ما يدخل حرف عربي واحد، الكلام ده بيبقى إجباري.
الخطوة التالية
افتح أقرب جدول قاعدة بيانات عندك وشوف الـ charset بتاع الأعمدة النصية. لو لقيته latin1 أو أي حاجة غير utf8mb4، ده تذكرة مفتوحة لازم تتقفل قبل ما تتخزّن فيه بيانات عربية. وجرّب كمان تشغّل كود الـ Python اللي فوق وشوف الفرق بين 4 و 8 بعينك.
المصادر
- The Unicode Standard, Version 15.0 — unicode.org
- RFC 3629: UTF-8, a transformation format of ISO 10646 — IETF (ietf.org)
- Python Unicode HOWTO — docs.python.org
- WHATWG Encoding Standard — encoding.spec.whatwg.org
- Joel Spolsky: "The Absolute Minimum Every Software Developer Must Know About Unicode and Character Sets" — joelonsoftware.com