Kodokon kodokon.com

التدويل: lang وdir وcharset ومصائد Unicode

استخدم lang وdir وتصريح الترميز بحكمة، واهزم مصائد التطبيع والاتجاهية في Unicode.

9 دقيقة · 3 أسئلة

افتح هذا الدرس في Kodokon

السمة lang أكثر بكثير من مجرد بيانات وصفية: فهي تقود أصوات قارئات الشاشة، والفصل المقطعي (hyphens: auto لا يعمل بدونها)، واختيار محارف CJK (المحرف التصويري ذاته يُرسَم بشكل مختلف في اليابانية والصينية)، وعلامات الاقتباس التي يولّدها <q>، ومحدِّد CSS المسمّى :lang(). وهي موروثة: صرّح بها على <html> بوسم BCP 47 (en، en-GB، ja) وتجاوَزها محليًا عند كل تغيير في اللغة.

HTML
<html lang="en">
  <p>She said: <q>hello</q>.</p>
  <p lang="fr">Elle a dit : <q>bonjour</q>.</p>
</html>
علامات اقتباس q تتبع اللغة: “hello” ثم « bonjour ».

تقلب dir=rtl المحاذاة الافتراضية والترتيب البصري للمحارف ذات الاتجاهية المحايدة. أما بالنسبة لمحتوى المستخدم غير المتوقّع، فتختار dir=auto الاتجاه بناءً على أول محرف ذي اتجاهية قوية. يعزل العنصر <bdi> مقطعًا عن الخوارزمية ثنائية الاتجاه: بدونه، يرى اسم مستخدم عربي متبوع بـ ": 12 نقطة" ترقيمَه يُعاد ترتيبه إلى هراء.

HTML
<p dir="auto">مرحبا - inferred direction: RTL</p>
<ul>
  <li><bdi>مستخدم</bdi>: 12 points</li>
  <li><bdi>Alice</bdi>: 8 points</li>
</ul>
bdi يحمي التخطيط من أسماء المستخدمين ثنائية الاتجاه.

يجب أن يظهر تصريح <meta charset=utf-8> ضمن أول 1024 بايت من المستند: يُجري المتصفح مسحًا مسبقًا محدودًا بتلك النافذة قبل اختيار ترميز. بلا تصريح وبلا ترويسة HTTP، يعتمد الترميز الافتراضي على إعدادات لغة المستخدم المحلية (غالبًا windows-1252 في أوروبا الغربية) - وليس UTF-8 أبدًا. أما علامة ترتيب البايتات (BOM) في بداية الملف فتتجاوز كل شيء آخر، بما في ذلك ترويسة HTTP.

JAVASCRIPT
const composed = "\u00e9";
const decomposed = "e\u0301";
console.log(composed === decomposed); // false
const nfc = decomposed.normalize("NFC");
console.log(composed === nfc);        // true
حرفا “é” متطابقان بصريًا، لكنهما مختلفان في الذاكرة.

يخزّن macOS بعض أسماء الملفات في شكل مُفكَّك (NFD): لذا قد يختلف "é" الآتي من تحميل عن ذلك المكتوب على لوحة المفاتيح. طبّع بشكل منهجي كل مدخلات المستخدم إلى NFC قبل تخزينها أو مقارنتها. وأخيرًا، .length يحسب وحدات ترميز UTF-16، لا المحارف المُدرَكة: فرمز إيموجي عائلة يجمع أكثر من سبع منها؛ استخدم Intl.Segmenter لعدّ الرسوم الحرفية (graphemes) الحقيقية.

اختبار المعرفة

تأكّد من أنك تذكّرت النقاط الأساسية في هذا الدرس.

  1. أين يجب أن يوجد إلزاميًا تصريح <meta charset=utf-8>؟
    • في أي مكان داخل <head>
    • ضمن أول 1024 بايت من المستند
    • قبل تصريح DOCTYPE
    • ضمن أول 512 بايت من <body>
  2. كيف تحدّد dir=auto اتجاه عنصر؟
    • تفحص أول محرف ذي اتجاهية قوية في المحتوى
    • تطبّق الاتجاه المُصرَّح على عنصر <html>
    • تعدّ محارف RTL وLTR وتحتفظ بالأغلبية
  3. لماذا قد تكون سلسلتان تعرضان “é” كلتاهما مختلفتين بالنسبة لـ ===؟
    • لأن إحداهما مُرمّزة بـ UTF-8 والأخرى بـ UTF-16
    • لأن حالة الأحرف في Unicode تختلف حسب إعدادات اللغة المحلية
    • لأن إحداهما تستخدم المحرف المُركّب مسبقًا U+00E9 والأخرى تستخدم التسلسل المُفكَّك e + U+0301