{"id":"l-a11y-4-4","courseId":"web-accessibility","lang":"ar","kind":"lesson","summary":"اكتب نصوص Ticketly بحيث يفهمها عدد أكبر من الناس، وحدّد اللغة والاتجاه في الكود لتنطق قارئات الشاشة العربية نطقًا صحيحًا وتنعكس التخطيطات من اليمين إلى اليسار كما ينبغي.","html":"<p>يضيف Ticketly هذا العام فعالية عربية: <strong>ليالي الطرب</strong>، باسم المكان ووصفه بالعربية داخل صفحة إنجليزية في ما عدا ذلك. كان الاختبار الأول مع NVDA كارثة: حاول الصوت الإنجليزي أن ينطق الحروف العربية حرفًا حرفًا. وكانت أيقونة البطاقة العربية وحشوها ومحاذاة نصها كلها في الجهة الخطأ. للكلمات أهمية في إمكانية الوصول من ناحيتين: مدى سهولة فهمها، ومدى قدرة البرمجيات على معالجتها بشكل صحيح.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">اللغة البسيطة</h2>\n<p>ذوو الإعاقات الذهنية وصعوبات التعلّم، وعُسر القراءة، وإصابات الدماغ، وضعف الذاكرة، ومعهم كل من يقرأ بلغة ثانية أو في نهاية يوم طويل، يستفيدون من نص سهل المتابعة. المعيار الرسمي الوحيد في WCAG بشأن مستوى القراءة، 3.1.5، من المستوى AAA، لكن اللغة البسيطة تبقى من أكثر تحسينات إمكانية الوصول فاعلية.</p>\n<p>قارن سياسة الاسترداد في Ticketly قبل التعديل وبعده:</p>\n<blockquote>\n<p><strong>قبل:</strong> بصرف النظر عمّا سبق ذكره، فإن حاملي التذاكر ممّن يرتؤون التقدّم بطلب استرداد المبالغ المدفوعة بعد انقضاء المهلة المحدّدة بأربعة عشر يومًا سابقة لموعد الفعالية لا يحقّ لهم التعويض إلا في الظروف الاستثنائية.</p>\n</blockquote>\n<blockquote>\n<p><strong>بعد:</strong> يمكنك استرداد ثمن التذكرة كاملًا حتى 14 يومًا قبل المهرجان. بعد ذلك، لا نردّ المبلغ إلا إذا أُلغيت الفعالية.</p>\n</blockquote>\n<p>التقنيات سهلة الذكر وتحتاج إلى تمرين لتطبيقها:</p>\n<ul>\n<li><strong>ضع أهمّ نقطة أولًا</strong>، في العنوان وفي الجملة الأولى.</li>\n<li><strong>استخدم كلمات شائعة وجملًا قصيرة.</strong> فكرة واحدة في كل جملة.</li>\n<li><strong>استخدم الاسم نفسه للشيء نفسه</strong> في كل مكان: إن كانت «تذكرة» على البطاقة، فلا تصبح «باقة دخول» في صفحة الدفع (3.2.4 Consistent Identification).</li>\n<li><strong>اكتب تعليمات تعمل دون حاجة إلى البصر.</strong> «اضغط الزر الأخضر على اليمين» تعتمد على اللون والموضع؛ أما «اضغط Continue» فتعمل للجميع (1.3.3 Sensory Characteristics).</li>\n<li><strong>اشرح الاختصارات</strong> في أول مرة: «صالة VIP (المنطقة المسقوفة بجانب المسرح)».</li>\n</ul>\n<h2 id=\"sec-2\" tabindex=\"-1\">لغة الصفحة ولغة أجزائها</h2>\n<p>تستخدم قارئات الشاشة خاصية <code dir=\"ltr\">lang</code> لاختيار الصوت وقواعد النطق. وتستخدمها المتصفّحات أيضًا في تقسيم الكلمات عند نهاية السطر، واختيار الخط، والتدقيق الإملائي، والترجمة. ينطبق هنا معياران:</p>\n<ul>\n<li><strong>3.1.1 Language of Page ‏(A):</strong> ‏<code dir=\"ltr\">&lt;html lang=&quot;en&quot;&gt;</code> (أو <code dir=\"ltr\">ar</code> أو <code dir=\"ltr\">fr</code> وهكذا). وغياب لغة الصفحة من الإخفاقات الستة الأكثر شيوعًا على الويب.</li>\n<li><strong>3.1.2 Language of Parts ‏(AA):</strong> كل مقطع بلغة مختلفة يحصل على <code dir=\"ltr\">lang</code> خاصة به.</li>\n</ul>\n<p>هذه هي البطاقة العربية في الصفحة الإنجليزية، والعنوان «ليالي الطرب» معلَّم بأنه عربي:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"html\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">ticketly/events.html</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">html</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> lang</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"en\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">…</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> class</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"card\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h3</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> lang</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"ar\"</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> dir</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"rtl\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>…&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h3</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">> </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">&#x3C;!-- the Arabic title --></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>An evening of classic Arabic music at the old harbour.&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span></code></pre></div>\n<p>صار NVDA يتحوّل إلى صوت عربي عند العنوان ثم يعود إلى الإنجليزية عند الوصف. ولا تحتاج إلى <code dir=\"ltr\">lang</code> لأسماء العلم أو للكلمات التي دخلت الإنجليزية واستقرّت فيها مثل “café”؛ فهي مخصّصة للمقاطع التي سينطقها القارئ باللغة الأخرى.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">الاتجاه: rtl وauto وbdi</h2>\n<p>العربية والعبرية والفارسية والأردية تُكتب من اليمين إلى اليسار. وخاصية <code dir=\"ltr\">dir</code> تخبر المتصفّح بالاتجاه الأساسي لكتلة النص، وهو ما يتحكّم في الجهة التي يبدأ منها النص، والجهة التي تقع عليها علامات الترقيم، وترتيب النص حين تختلط فيه الاتجاهات.</p>\n<ul>\n<li><code dir=\"ltr\">dir=&quot;rtl&quot;</code> على <code dir=\"ltr\">&lt;html&gt;</code> لصفحة عربية، أو على عنصر لجزء عربي داخل صفحة إنجليزية.</li>\n<li><code dir=\"ltr\">dir=&quot;auto&quot;</code> حين لا تعرف الاتجاه مسبقًا، كأسماء المستخدمين والمراجعات وحقول البحث. ينظر المتصفّح إلى أول حرف ذي اتجاه قوي.</li>\n<li><code dir=\"ltr\">&lt;bdi&gt;</code> يعزل جزءًا قصيرًا من نص كتبه مستخدم داخل جملة، فلا يعيد اسم مستخدم عربي ترتيب النص الإنجليزي المحيط به: <code dir=\"ltr\">Review by &lt;bdi&gt;سارة&lt;/bdi&gt;, 5 stars</code>.</li>\n</ul>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>ضبط الاتجاه بـ CSS بدلًا من HTML</span></p>\n<p>الخاصية <code dir=\"ltr\">direction: rtl</code> في ملف الأنماط تغيّر التخطيط المرئي، لكن الاتجاه جزء من معنى المحتوى، لا من تنسيقه. إن لم يُحمَّل الـ CSS، أو نُسخ النص، أو قرأه قارئ شاشة، تضيع هذه المعلومة. ضع <code dir=\"ltr\">dir</code> في HTML؛ واستخدم CSS للتخطيط الذي ينتج عنه.</p>\n</aside>\n<h2 id=\"sec-4\" tabindex=\"-1\">تخطيط ينعكس من تلقاء نفسه</h2>\n<p>في التخطيط من اليمين إلى اليسار، ينقلب كل ما هو أفقي: الأيقونة التي كانت على يسار العنوان مكانها على يمينه، والحشو الذي كان يُبعد النص عن الحافة اليسرى يجب أن يُبعده عن اليمنى. الخصائص الفيزيائية مثل <code dir=\"ltr\">margin-left</code> و<code dir=\"ltr\">text-align: left</code> لا تنقلب. أما <strong>الخصائص المنطقية (logical properties)</strong> فتنقلب:</p>\n<div class=\"table-wrap\" role=\"region\" aria-label=\"جدول قابل للتمرير\" tabindex=\"0\"><table><thead>\n<tr>\n<th>الفيزيائية</th>\n<th>المنطقية</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code dir=\"ltr\">margin-left</code></td>\n<td><code dir=\"ltr\">margin-inline-start</code></td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">padding-right</code></td>\n<td><code dir=\"ltr\">padding-inline-end</code></td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">left: 0</code></td>\n<td><code dir=\"ltr\">inset-inline-start: 0</code></td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">text-align: left</code></td>\n<td><code dir=\"ltr\">text-align: start</code></td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">border-left</code></td>\n<td><code dir=\"ltr\">border-inline-start</code></td>\n</tr>\n</tbody>\n</table></div><div class=\"code-block\" dir=\"ltr\" data-lang=\"css\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">ticketly/card.css</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.card</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  padding-inline</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">rem</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  border-inline-start</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">4</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">px</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> solid</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> #5b3cc4</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  text-align</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">start</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.badge</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  margin-inline-end</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.5</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">rem</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">; </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">/* the gap after the icon, on whichever side that is */</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 680 200\" role=\"img\" aria-labelledby=\"l-a11y-4-4-t1\"><defs><marker id=\"arrow-l-a11y-4-4-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-a11y-4-4-t1\">بطاقة إنجليزية حدّها الملوّن وأيقونتها على اليسار والمسافة بعد الأيقونة على يمينها، بجوار بطاقة عربية حدّها وأيقونتها على اليمين والمسافة على يسار الأيقونة، وكلتاهما ناتجة عن قواعد CSS المنطقية نفسها.</title>\n  <rect class=\"d-box\" x=\"20\" y=\"40\" width=\"300\" height=\"100\" rx=\"10\"/>\n  <rect class=\"d-box-primary\" x=\"20\" y=\"40\" width=\"10\" height=\"100\"/>\n  <circle class=\"d-dot\" cx=\"60\" cy=\"80\" r=\"12\"/>\n  <text class=\"d-label\" x=\"85\" y=\"86\">Harbour Lights</text>\n  <text class=\"d-label-muted\" x=\"45\" y=\"120\">inline-start = يسار</text>\n  <rect class=\"d-box\" x=\"360\" y=\"40\" width=\"300\" height=\"100\" rx=\"10\"/>\n  <rect class=\"d-box-primary\" x=\"650\" y=\"40\" width=\"10\" height=\"100\"/>\n  <circle class=\"d-dot\" cx=\"620\" cy=\"80\" r=\"12\"/>\n  <text class=\"d-label\" x=\"595\" y=\"86\" text-anchor=\"end\">ليالي الطرب</text>\n  <text class=\"d-label-muted\" x=\"635\" y=\"120\" text-anchor=\"end\">inline-start = يمين</text>\n  <text class=\"d-code\" x=\"340\" y=\"180\" text-anchor=\"middle\">border-inline-start · margin-inline-end</text>\n</svg><figcaption>البطاقة نفسها في الاتجاهين</figcaption></figure>\n<p>ليس كل شيء يجب أن ينعكس. الشعارات والصور وأزرار مشغّل الوسائط (زر التشغيل يشير إلى اليمين دائمًا) والأرقام تبقى كما هي. أما الأسهم التي تعني «التالي» أو «رجوع» فيجب أن تنقلب؛ والـ pseudo-class ‏<code dir=\"ltr\">:dir(rtl)</code> تتيح لك استهدافها دون كلاسات إضافية.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>اختبر بمحتوى حقيقي</span></p>\n<p>النص العربي الوهمي لملء الفراغ يُخفي المشكلات. اطلب من قارئ لغته الأم العربية أن يراجع المحتوى، واستمع إليه بقارئ شاشة مضبوط على العربية. معظم أخطاء الاتجاه من اليمين إلى اليسار تظهر في أول دقيقتين من الاستخدام الحقيقي.</p>\n</aside>\n<p>بهذا يكتمل القسم 4. صار Ticketly منظّمًا، وقابلًا للتشغيل، ومقروءًا، ويُنطق بشكل صحيح. وينتقل القسم 5 إلى إثبات ذلك: الاختبار الآلي، والاختبار اليدوي بقارئات الشاشة، وتدقيق شامل.</p>\n","toc":[{"id":"sec-1","text":"اللغة البسيطة","level":2},{"id":"sec-2","text":"لغة الصفحة ولغة أجزائها","level":2},{"id":"sec-3","text":"الاتجاه: rtl وauto وbdi","level":2},{"id":"sec-4","text":"تخطيط ينعكس من تلقاء نفسه","level":2}],"takeaways":["اللغة البسيطة، والجمل القصيرة، والتعليمات التي لا تعتمد على الشكل أو اللون أو الموضع، تساعد ذوي الإعاقات الإدراكية وكل من يقرأ بلغة ثانية.","اضبط lang على عنصر html للصفحة كلها وعلى أي مقطع بلغة أخرى، لتبدّل قارئات الشاشة الصوت وقواعد النطق.","استخدم dir=“rtl” للمحتوى العربي والعبري، وdir=“auto” للنصوص التي يكتبها المستخدمون ولا يمكنك معرفة اتجاهها مسبقًا.","خصائص CSS المنطقية مثل margin-inline-start وtext-align: start تنعكس تلقائيًا في التخطيطات من اليمين إلى اليسار."],"further":[{"title":"W3C: Understanding 3.1.2 Language of Parts","url":"https://www.w3.org/WAI/WCAG22/Understanding/language-of-parts.html"},{"title":"W3C Internationalization: Structural markup and right-to-left text in HTML","url":"https://www.w3.org/International/questions/qa-html-dir"},{"title":"MDN: CSS logical properties and values","url":"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_logical_properties_and_values"}],"quiz":[{"q":"<p>تعرض صفحة Ticketly الإنجليزية عنوان الفعالية العربي «ليالي الطرب» دون خاصية lang. ماذا يفعل عادةً قارئ شاشة مضبوط على الإنجليزية؟</p>","options":[{"text":"يكتشف نظام الكتابة ويتحوّل إلى صوت عربي تلقائيًا، في كل قارئات الشاشة","why":"بعض قارئات الشاشة تحاول اكتشاف نظام الكتابة، لكن السلوك يتفاوت كثيرًا ويفشل في أحيان كثيرة. الخاصية lang هي الإشارة الموثوقة التي تشترطها WCAG."},{"text":"يتخطّى النص، لأنه لا يستطيع قراءته","why":"النص ما زال في الشجرة. المشكلة في طريقة نطقه، لا في قراءته من عدمها."},{"text":"يقرؤه بقواعد النطق الإنجليزية أو يتهجّى حروفه، فيصبح غير مفهوم","why":"صحيح. إضافة lang=“ar” ‏(3.1.2 Language of Parts) تتيح لقارئ الشاشة التحوّل إلى صوت عربي لتلك العبارة."},{"text":"يترجمه إلى الإنجليزية قبل قراءته","why":"قارئات الشاشة لا تترجم المحتوى. إنها تختار صوتًا وقواعد نطق فقط."}],"answer":2},{"q":"<p>يتيح Ticketly للحضور نشر مراجعات بالإنجليزية أو بالعربية. أيّ كود يتعامل مع اتجاه نص كل مراجعة بأفضل شكل؟</p>","options":[{"text":"<code dir=\"ltr\">&lt;p dir=&quot;rtl&quot;&gt;</code> على كل مراجعة","why":"هذا سيجعل المراجعات الإنجليزية من اليمين إلى اليسار، فتقع النقاط والأقواس في أماكن خاطئة."},{"text":"<code dir=\"ltr\">&lt;p dir=&quot;auto&quot;&gt;</code> على كل مراجعة","why":"صحيح. يضبط dir=“auto” الاتجاه بحسب أول حرف ذي اتجاه قوي، فتصبح المراجعات العربية من اليمين إلى اليسار والإنجليزية من اليسار إلى اليمين."},{"text":"بلا خاصية dir؛ فاتجاه الصفحة يكفي","why":"الصفحة من اليسار إلى اليمين، فستُعرض المراجعات العربية وعلامات الترقيم والأرقام فيها في مواضع خاطئة."}],"answer":1},{"q":"<p>أيّ تعليمة تحقّق معيار 1.3.3 Sensory Characteristics؟</p>","options":[{"text":"«اضغط الزر الأخضر الدائري على اليمين.»","why":"الشكل واللون والموضع لا معنى لها لمستخدمي قارئ الشاشة، وتتغيّر على الشاشات الصغيرة."},{"text":"«استخدم الزر أدناه للمتابعة.»","why":"كلمة «أدناه» تعتمد على الموضع البصري، الذي يتوقّف على التخطيط ولا يعرفه مستخدمو قارئ الشاشة."},{"text":"«اضغط Continue لاختيار مقاعدك.»","why":"صحيح. إنها تسمّي عنصر التحكّم بتسميته المرئية، وهذا يعمل للجميع، بمن فيهم مستخدمو التحكّم الصوتي."},{"text":"«انقر أيقونة السهم.»","why":"شكل الأيقونة خاصية حسّية، وكلمة «انقر» تستبعد مستخدمي لوحة المفاتيح والصوت."}],"answer":2},{"q":"<p>شارة أيقونة تسبق عنوان بطاقة وعليها <code dir=\"ltr\">margin-right: 8px</code>. في صفحة Ticketly العربية، تظهر المسافة في الجهة الخطأ. ما أنظف إصلاح؟</p>","options":[{"text":"استبدلها بـ <code dir=\"ltr\">margin-inline-end: 8px</code>","why":"صحيح. نهاية السطر (inline-end) هي الجهة اليمنى في النص من اليسار إلى اليمين، واليسرى في النص من اليمين إلى اليسار، فقاعدة واحدة تعمل في الحالتين."},{"text":"أضِف قاعدة تجاوز <code dir=\"ltr\">[dir=&quot;rtl&quot;] .badge { margin-left: 8px; margin-right: 0; }</code>","why":"هذا يعمل، لكنك ستحتاج إلى قواعد تجاوز كهذه لكل خاصية اتجاهية. الخصائص المنطقية تلغي هذا التكرار."},{"text":"استخدم <code dir=\"ltr\">transform: scaleX(-1)</code> على الصفحة العربية","why":"العكس بالـ transform يعكس النصوص والصور أيضًا، فيجعلها غير مقروءة."}],"answer":0}],"exercise":{"kind":"web","mode":"dom","starter":{"html":"<article class=\"card\" id=\"card-en\">\n  <h3><span class=\"badge\" aria-hidden=\"true\">★</span>Harbour Lights</h3>\n  <p>Two nights of music on the old harbour wall.</p>\n</article>\n\n<article class=\"card\" id=\"card-ar\">\n  <h3><span class=\"badge\" aria-hidden=\"true\">★</span>ليالي الطرب</h3>\n  <p>أمسية من الموسيقى العربية الكلاسيكية في الميناء القديم.</p>\n  <p class=\"note\">An evening of classic Arabic music at the old harbour.</p>\n</article>\n\n<form class=\"review\">\n  <label for=\"reviewer\">Your name</label>\n  <input id=\"reviewer\" name=\"reviewer\">\n  <label for=\"review-text\">Your review</label>\n  <textarea id=\"review-text\" name=\"review\"></textarea>\n</form>","css":".card { border: 1px solid #c9c4dc; border-left: 4px solid #5b3cc4; border-radius: 8px; padding: 8px 12px; margin-block-end: 12px; text-align: left; }\n.card h3 { margin: 0 0 4px; }\n.card p { margin: 0 0 4px; }\n.badge { color: #5b3cc4; margin-right: 8px; }\n.note { color: #595959; font-size: 0.9rem; }\n.review { display: grid; gap: 4px; max-width: 320px; }\ninput, textarea { font: inherit; padding: 6px 8px; border: 1px solid #77708f; border-radius: 6px; }\n","js":""},"solution":{"html":"<article class=\"card\" id=\"card-en\">\n  <h3><span class=\"badge\" aria-hidden=\"true\">★</span>Harbour Lights</h3>\n  <p>Two nights of music on the old harbour wall.</p>\n</article>\n\n<article class=\"card\" id=\"card-ar\">\n  <div lang=\"ar\" dir=\"rtl\">\n    <h3><span class=\"badge\" aria-hidden=\"true\">★</span>ليالي الطرب</h3>\n    <p>أمسية من الموسيقى العربية الكلاسيكية في الميناء القديم.</p>\n  </div>\n  <p class=\"note\">An evening of classic Arabic music at the old harbour.</p>\n</article>\n\n<form class=\"review\">\n  <label for=\"reviewer\">Your name</label>\n  <input id=\"reviewer\" name=\"reviewer\" dir=\"auto\">\n  <label for=\"review-text\">Your review</label>\n  <textarea id=\"review-text\" name=\"review\" dir=\"auto\"></textarea>\n</form>","css":".card { border: 1px solid #c9c4dc; border-inline-start: 4px solid #5b3cc4; border-radius: 8px; padding: 8px 12px; margin-block-end: 12px; text-align: start; }\n.card h3 { margin: 0 0 4px; }\n.card p { margin: 0 0 4px; }\n.badge { color: #5b3cc4; margin-inline-end: 8px; }\n.note { color: #595959; font-size: 0.9rem; }\n.review { display: grid; gap: 4px; max-width: 320px; }\ninput, textarea { font: inherit; padding: 6px 8px; border: 1px solid #77708f; border-radius: 6px; }\n","js":""},"checks":[{"id":"arabic-lang","test":"const arabicEls = () => { const out = new Set(); const w = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT); let n; while ((n = w.nextNode())) { if (/[\\u0600-\\u06FF]/.test(n.textContent) && !n.parentElement.closest('script, style')) out.add(n.parentElement); } return [...out]; }; const els = arabicEls(); return els.length >= 2 && els.every((el) => { const l = el.closest('[lang]'); return l && /^ar\\b/i.test(l.getAttribute('lang')); });"},{"id":"arabic-dir","test":"const arabicEls = () => { const out = new Set(); const w = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT); let n; while ((n = w.nextNode())) { if (/[\\u0600-\\u06FF]/.test(n.textContent) && !n.parentElement.closest('script, style')) out.add(n.parentElement); } return [...out]; }; const els = arabicEls(); return els.length >= 2 && els.every((el) => getComputedStyle(el).direction === 'rtl' || el.matches(':dir(rtl)'));"},{"id":"english-stays","test":"const note = $('#card-ar .note'); const l = note.closest('[lang]'); const en = !l || /^en\\b/i.test(l.getAttribute('lang')); return document.documentElement.lang === 'en' && en && getComputedStyle(note).direction === 'ltr' && getComputedStyle($('#card-en h3')).direction === 'ltr';"},{"id":"user-text-auto","test":"return $('#reviewer').getAttribute('dir') === 'auto' && $('#review-text').getAttribute('dir') === 'auto';"},{"id":"logical-css","test":"const en = getComputedStyle($('#card-en .badge')); const ar = getComputedStyle($('#card-ar .badge')); const enCard = getComputedStyle($('#card-en')); const arCard = getComputedStyle($('#card-ar h3').closest('.card')); return parseFloat(en.marginRight) > 0 && parseFloat(en.marginLeft) === 0 && parseFloat(ar.marginLeft) > 0 && parseFloat(ar.marginRight) === 0;"}],"title":"اجعل بطاقة الفعالية العربية تُنطق وتستقرّ كما ينبغي","prompt":"<p>الصفحة إنجليزية (<code dir=\"ltr\">&lt;html lang=&quot;en&quot;&gt;</code> مضبوطة أصلًا). عنوان البطاقة الثانية ووصفها بالعربية، وقد يكتب المراجعون بأيّ من اللغتين. أصلحها:</p>\n<ol>\n<li>علِّم كل نص عربي بـ <code dir=\"ltr\">lang=&quot;ar&quot;</code> وباتجاه من اليمين إلى اليسار.</li>\n<li>أبقِ الملاحظة الإنجليزية في تلك البطاقة (<code dir=\"ltr\">.note</code>) إنجليزيةً ومن اليسار إلى اليمين.</li>\n<li>اجعل حقلي اسم المراجع والمراجعة يختاران اتجاههما بحسب ما يُكتب فيهما.</li>\n<li>استبدل الـ CSS الفيزيائي لتقع مسافة الشارة بعد الأيقونة في الاتجاهين (على اليمين في الإنجليزية، وعلى اليسار في العربية).</li>\n</ol>\n","hints":["لُفّ عنصري h3 وp العربيين بعنصر واحد عليه lang=“ar” dir=“rtl”، واترك ‎.note خارجه.","dir=“auto” على حقل الإدخال والـ textarea تعالج النصوص التي يكتبها المستخدمون.","تصبح margin-right هي margin-inline-end. وما دمت هناك، يمكن أن تصبح border-left هي border-inline-start، وtext-align: left هي start."],"explanation":"<p>تجعل <code dir=\"ltr\">lang=&quot;ar&quot;</code> قارئات الشاشة تتحوّل إلى صوت عربي للعنوان والوصف (3.1.2 Language of Parts)، وتمنح <code dir=\"ltr\">dir=&quot;rtl&quot;</code> تلك الكتلة اتجاهًا أساسيًا من اليمين إلى اليسار، فيبدأ النص من اليمين وتقع علامات الترقيم في مواضعها الصحيحة. وتبقى الملاحظة الإنجليزية خارج العنصر الحاوي فتحتفظ بلغة الصفحة واتجاهها. وتتيح <code dir=\"ltr\">dir=&quot;auto&quot;</code> لكل حقل في النموذج أن يتبع أول حرف ذي اتجاه قوي فيه. وأخيرًا، تضع <code dir=\"ltr\">margin-inline-end</code> مسافة الشارة بعد الأيقونة في الاتجاهين، وتعكس بقية الخصائص المنطقية الحدّ الملوّن والمحاذاة أيضًا، وكل ذلك من مجموعة قواعد واحدة.</p>\n","checkLabels":{"arabic-lang":"كل النص العربي داخل عنصر عليه lang=“ar”","arabic-dir":"كل النص العربي معروض من اليمين إلى اليسار","english-stays":"تبقى الصفحة والملاحظة الإنجليزية بالإنجليزية ومن اليسار إلى اليمين","user-text-auto":"حقلا الاسم والمراجعة يستخدمان dir=“auto”","logical-css":"مسافة الشارة تتبع الأيقونة في البطاقتين الإنجليزية والعربية"}},"words":716,"readMinutes":4}