rtl قلب اتّجاه تطبيقات الويب لتُصبح من اليمين إلى اليسار RTL – الجزء الثاني


عبد اللطيف ايمش

دفع عجلة تطوير الويب تعني جعله أفضل للمستخدمين والمطورين على حدٍ سواء، وهذا يعني محاولة حلّ المشكلات التي تواجه الويب في الوقت الراهن؛ وهذا ينطبق أيضًا على جعل المواقع متوافقة مع اتجاه RTL بسهولة ويسر.

rtl.png

قبل أن نكمل مشوارنا في الحديث عن المواضيع المتقدمة عن RTL، لنبدأ درسنا بمثالٍ عمليٍ بسيط لتتذكر فيه كيف نقلب الاتجاه إلى RTL بطريقةٍ صحيحة:

 

سنكمل حيث انتهينا في درسنا السابق، وحان الوقت الآن لنتعمّق في بعض المواضيع المتقدمة المتعلقة بتطوير واجهات من اليمين إلى اليسار. شرحنا في الدرس الأول الأساسيات، وسنشرح هنا بعض الخاصيات المُحدَثَة التي أتت حديثًا على الويب والتي ستعطينا فكرةً عن مستقبل الويب.

التقنيات الحديثة

الأساس الذي تستند عليه الواجهات ذات الاتجاه من اليمين إلى اليسار (RTL) هو خاصيات CSS، وهذه الخاصيات تتطور مع الوقت كما هو حال بقية مكوّنات الويب.
سأذكر هنا بعض خاصيات CSS التي يمكنك تجربتها على الفور في النسخ الحديثة من المتصفحات (من المحتمل أن تتغير هذه المعلومات بعد صدور تحديثات جديدة للمتصفحات).
محاذاة النص: تعودنا في الماضي على تحديد المحاذاة الأفقية للنص عبر text-align: left أو right؛ أما الآن، فلدينا القيمتان start و end. فعلى سبيل المثال text-align: start ستعطي نتيجةً مختلفةً بناءً عمّا إذا كان اتجاه المحتوى من اليمين إلى اليسار أم من اليسار إلى اليمين. القيمة start تُشير إلى اليسار في اتجاه LTR وإلى اليمين في اتجاه RTL، والعكس صحيح للقيمة end.
مثالٌ يستخدم left|right:

#content {
  text-align: left:
}
html[dir="rtl"] #content {
  text-align: right;
}

أما لو استعملنا start|end:

#content {
  text-align: start;
}

لا حاجة إلى استعمال قاعدة خاصة باتجاه RTL باستخدامنا للقيمتين start|end.
دعم المتصفح: Chrome 1.0+‎، و Safari 3.1+‎، و Firefox 3.6+‎، وأندرويد، و iOS، غير مدعومة في متصفح Internet Explorer في الوقت الراهن.
خاصيات padding و margin و border: هنالك تحسيناتٌ أُدخِلَت على تلك الخاصيات.
أصبحت كل واحدة منها تقبل لاحقةً إضافيةً هي ‎-inline-start أو ‎-inline-end، فمثلًا يمكننا أن نكتب padding-inline-end أو margin-inline-start. تعطي هذه الكلمات المحجوزة الجديدة نفس تأثير start و end في محاذاة النص: الخاصية padding-inline-start تماثِل padding-left في اتجاه LTR وتماثِل padding-right في اتجاه RTL. أما margin-inline-end تعطي نفس تأثير margin-right في اتجاه LTR و margin-left في اتجاه RTL.
مثالٌ يستعمل left|right:

#content {
  padding-left: 12px:
  margin-right: 20px;
}
html[dir="rtl"] #content {
  padding-left: 0;
  padding-right: 12px;
  margin-left: 20px;
  margin-right: 0px;
}

نفس المثال لكن باستعمال start|end:

#content {
  padding-inline-start: 12px:
  margin-inline-end: 20px;
}

أكرِّر أنَّه لا حاجة إلى قاعدة خاصة باتجاه RTL؛ فستصبح خاصية margin-inline-end وكأنها margin-right في اتجاه LTR و margin-left في اتجاه RTL.
دعم المتصفحات: Firefox 41+‎ فقط.
تحديد الموقع المطلق (absolute position) للعناصر: الخاصيتان left وright أساسيتان لتحديد الموقع المطلق، لكن قريبًا سترى استخدامًا لخاصياتٍ أذكى، ألا وهي offset-inline-startوoffset-inline-end.
يجدر بالذكر أنَّك تستطيع استعمال offset-block-startوoffset-block-end بدلًا من top و bottom على التوالي وبالترتيب.
مثالٌ يستعمل left|right:

#content {
  position: absolute;
  left: 5rem;
}
html[dir="rtl"] #content {
  left: auto;
  right: 5rem;
}

نفس المثال لكن باستعمال start|end:

#content {
  offset-inline-start: 5rem;
}

أكرر مرةً أخرى أنَّ مفهوم start|end وفَّر علينا كتابة بعض الشيفرات في ملف CSS.
دعم المتصفحات: Firefox 41+‎ فقط.
تحديد موقع العناصر باستخدام float: استعملنا float: left و float: right لوقتٍ طويل، لكنك ستتمكن قريبًا من استعمال float: inline-start و float: inline-end. خاصية inline-start ترتِّب عنصرك إلى اليسار في اتجاه LTR وإلى اليمين في اتجاه RTL.
مثالٌ يستعمل left|right:

#content {
  float: left;
}
html[dir="rtl"] #content {
  float: right;
}

نفس المثال لكن باستعمال start|end:

#content {
  float: inline-start;
}

دعم المتصفحات: Firefox 44.
Web Components (مكوِّنات الويب): وهي عناصر الواجهة الرسومية القابلة لإعادة الاستخدام. إذا تعاملت مع web components من قبل فستعلم أنَّ أنماط CSS الخاصة بها موجودة ضمن شجرة DOM فرعية (shadow DOM)، لذا لن تتمكن افتراضيًا من الحصول على اتجاه الصفحة التي تستعمل تلك المكوِّنة عبر html[dir="rtl"]، لكن شجرة DOM الفرعية (shadow DOM) تتضمن محدِّدًا جديدًا اسمه ‎:host-context()‎ الذي تستطيع استخدامه لتحديد عنصر في شجرة DOM الأساسية (host DOM).
لنحاول تبسيط الأمر عبر مثال. لنقل أنَّ لديك عنصرًا داخل شجرة DOM فرعية اسمه back. كنت ستستخدم html[dir="rtl"] .back {}‎ في حال لم تكن داخل شجرة DOM فرعية، لكنك لا تستطيع استخدام هذا المُحدِّد من داخل مكوِّن (component). المُحدِّد المكافئ للمحدِّد السابق الذي تستطيع استخدامه داخل مكوِّن هو:

.back:host-context(html[dir="rtl"]) { }

ليس من الواضح ما مدى دعم هذا النوع من المُحدِّدات، لكن يمكنك استخدام هذه الطريقة الالتفافية.
لا ترغب باستخدام الطرق الالتفافية لكنك تريد أن تجرِّب اتجاه RTL في web component في المتصفحات التي تدعمها مثل فيرفكس (بعد تفعيل الراية dom.webcomponents.enabled) ومتصفح Google Chrome؟ يمكنك فعل ذلك عبر Mutation Observers بمراقبة الخاصية document.documentElement.dir. ستبدو شيفرة المراقبة شبيهةً بالمثال الآتي:

var dirObserver = new MutationObserver(updateShadowDir);
dirObserver.observe(document.documentElement, {
  attributeFilter: ['dir'],
  attributes: true
});

لا تنسَ أن تُهيّئ دالتك لأول مرة بعد تحميل الصفحة، بعد شيفرة المراقبة مباشرةً:

updateShadowDir();

ستبدو دالة updateShadowDir()‎ كالآتي:

function updateShadowDir() {
  var internal = myInnerElement.shadowRoot.firstElementChild;
  if (document.documentElement.dir === 'rtl') {
    internal.setAttribute('dir', 'rtl');
  } else {
    internal.removeAttribute('dir');
  }
};

كل ذلك عبر JavaScript. سيملك أول «ابن» (first child) في المكوِّنة خاصية dir قابلة للتغيير، وستعتمد أنماط CSS عليه كمُحدِّد بدلًا من عنصر html. ولنقل أنَّ ذاك العنصر هو span، لذا سيكون مُحدِّدك شبيهًا بما يلي:

span[dir="rtl"] rest-of-the-selectors-chain {  }

أعلم أنَّ الأمر يبدو معقدًا، لكن –لحسن الحظ– المستقبل مشرق، لذا لنلقِ نظرةً على ما تُخبّؤه W3C لنا في المستقبل بما يخص اتجاه RTL.

مستقبل اتجاه RTL في الويب

إعلام الخادوم باتجاه النص: في الوقت الراهن نفقد قيمة اتجاه الصفحة (أو اتجاه عناصر النموذج) عند إرسال نموذج يحتوي على حقول إدخال نصية. أتت الخواديم بطرقٍ خاصةٍ بها لكي تُحدِّد اتجاه النص الُمرسَل إليها.
لحل هذه المشكلة ولإضافة معلومات حول اتجاه النص المُرسَل، ابتكرت W3C خاصيةً جديدةً ووضعتها في مواصفة نماذج HTML5 اسمها dirname، التي ستُضيفها المتصفحات في المستقبل القريب.
وكما ذَكَرَ المعيار، «تضمين خاصية dirname في حقول النموذج يُفعِّل إرسال اتجاه العنصر، ويعطي اسم الحقل الذي يحتوي على هذه القيمة أثناء عملية الإرسال. إذا حُدِّدت هذه الخاصية، فيجب ألّا تكون قيمتها فارغةً».
بعبارة أخرى: إضافة هذه الخاصية إلى حقول <input> أو <textarea> يؤدي إلى تمرير اتجاهها مع معلومات GET أو POST التي ستُرسَل إلى الخادوم. لننظر إلى مثالٍ عملي. ليكن لدينا هذا النموذج:

<form action="result.php" method="post">
<input name="comment" type="text" dirname="comment.dir"/>
<button type=submit>Send!</button>
</form>

ستحتوي عبارة POST التي ستُرسَل إلى الخادوم على حقلٍ اسمه comment، وحقلٍ آخر اسمه comment.dir. وإذا كتب المستخدم الكلمة «Hello» في الحقل النصي وأرسل النموذج، فستكون النتيجة هي:

comment=Hello&comment.dir=ltr

أما إذا كتب «مرحبا» فستكون النتيجة هكذا:

comment=%D9%85%D8%B1%D8%AD%D8%A8%D8%A7&comment.dir=rtl

يمكنك قراءة المواصفة من هنا.
ملاحظة: لكي تُعرَض المحارف العربية عرضًا صحيحًا في عناوين URL في متصفحك، فيجب أن تُرمَّز المحارف بترميز UTF-8، وكل حرف عربي يستعمل 4 محارف مفصولة فيما بينهما برمز %.
على سبيل المثال، لو كان لديك هذا الرابط؛ فسيحوله متصفحك عندما تزوره إلى هذه الصّفحة

طرق أفضل لكيفية التعامل مع الخلفيات والصور في RTL

هل سئمتَ من استخدام transform: scaleX(-1) لعكس صور الخلفية؟ قدّمَت W3C كلمةً محجوزةً جديدةً في CSS اسمها rtlflip التي تُستعمل كما يلي:

background-image: url(backbutton.png) rtlflip;

ستقلل عليك هذه الكلمة المحجوزة من عبء قلب جميع صورك عبر خاصية transform: scaleX(-1) يدويًا. من الممكن استعمالها أيضًا في قاعدة صور القوائم كما يلي:

list-style-image:url('sprite.png#xywh=10,30,60,20') rtlflip;

تقول صفحة المواصفة أيضًا أنَّ هذه الكلمة المحجوزة يمكن أن تستعمل في جميع الطرق الممكنة لتحديد الصور في CSS3. على سبيل المثال: url و sprite و image-list و linear-gradient و radial-gradient.

الواجهة البرمجية للتدويل

إليكم بعض الأجزاء غير المشهورة المتعلقة باتجاه RTL في الواجهة البرمجية للتدويل (Internationalization APIs) في JavaScript
تدعم الواجهة البرمجية للتدويل عددًا كبيرًا من اللغات مع مشتقاتها؛ فمثلًا لا تدعم هذه الواجهة البرمجية اللغة العربية فحسب، وإنما تدعم «العربية-مصر» و «العربية-تونس» وقائمة طويلة بالاشتقاقات الأخرى.
استخدام الأرقام العربية المشرقية بدلًا من الأرقام العربية الغربية: تُستخدم الأرقام العربية المشرقية (١٢٣) في بعض البلدان بدلًا من الأرقام العربية الغربية (123). تسمح لنا واجهة التدويل البرمجية بتحديد متى نريد إظهار ١٢٣ ومتى نظهر 123.

console.log(new Intl.NumberFormat('ar-EG').format(1234567890));

السطر السابق يقول أنَّنا نريد تنسيق الرقم 1234567890 بصيغة الأرقام التي تستعملها مصر (ar-EG). الناتج: ١٬٢٣٤٬٥٦٧٬٨٩٠

console.log(new Intl.NumberFormat('ar-TN').format(1234567890));

نقول هنا أننا نريد إظهار الرقم بالصيغة المعتمدة في تونس؛ ولمّا كانت تونس تستعمل الأرقام العربية الغربية، فسيكون الناتج: 1234567890
إظهار التواريخ بالتقويم الهجري بدلًا من الميلادي: هناك صفحة google.com/ramadan خاصة بإظهار معلومات حول شهر رمضان. وأحد أهم المعلومات الموجودة هي رقم اليوم في الشهر الهجري (القمري). تستخدم Google طريقة التفافية للحصول على هذه المعلومات. لكنك تستطيع الحصول على نفس المعلومات عبر الواجهة البرمجية للتدويل بسطرٍ وحيد بدلًا من مكتبة JavaScript كاملة.
هذا مثال:

console.log(new Intl.DateTimeFormat("fr-FR-u-ca-islamicc").format(new Date()));

السطر السابق يعني أنَّنا نريد أن يكون التاريخ الحالي بالتقويم الهجري وأن يُعرَض بالأرقام العربية الغربية (fr-FR). الناتج هو: 16/12/1436

console.log(new Intl.DateTimeFormat("ar-SA-u-ca-islamicc").format(new Date()));

نفس الأمر هنا، لكن التنسيق لمحليّة (locale) الخاصة بالسعودية التي تستعمل الأرقام العربية المشرقية. الناتج: ١٦‏/١٢‏/١٤٣٦

الخلاصة

رأينا في هذا الدرس بعض التقنيات المتقدمة لدعم اتجاه RTL، وأخذنا فكرةً عن مستقبل دعم RTL من معايير الويب.
ترجمة -وبتصرّف- للمقال Building RTL-Aware Web Apps & Websites: Part 2 لصاحبه أحمد نفزاوي





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن