من خصائص اللغة العربية أن النص فيها يُكتب ويُقرأ من اليمين إلى اليسار. يجب أن تنعكس واجهة المستخدم للغة العربية أفقيًا (ولكن ليس كل شيء وليس دائمًا - هناك تفاصيل دقيقة) ، افتح قائمة السياق على يسار المؤشر ، إلخ.
تحت المقطع - حول كيفية دعمنا RTL (من اليمين إلى اليسار) في عميل الويب لمنصة 1C: Enterprise ، وأيضًا إحدى الفرضيات التي تشرح سبب قيام العالم العربي بالكتابة من اليمين إلى اليسار.
القليل من التاريخ
تعودنا الكتابة من اليسار إلى اليمين. يتم إنشاء هذا الاتجاه في الكتابة إلى حد كبير من حقيقة أنه عند كتابة نص على الورق ، فإن أصحاب اليد اليمنى (ووفقًا للإحصاءات ، حوالي 85 ٪ منهم) يرون ما تم كتابته بالفعل - الكتابة (اليمنى) لا تغطي النص المكتوب. يجب أن يعاني اليساريون.
تبدو إحدى الفرضيات "لماذا تكتب اللغة العربية من اليمين إلى اليسار" هكذا. نشأت اللغات التي نشأت منها اللغة العربية في تلك الأيام التي لم يكن فيها ورق ونظائرها (البردى ، المخطوطات ، إلخ). لم يكن هناك سوى طريقة واحدة لتسجيل المعلومات - لنحت الحروف على الحجر. وكيف سيكون من الأنسب أن يستخدم اليد اليمنى مطرقة وإزميل؟ بالطبع ، يحمل إزميلًا في يده اليسرى ويطرق عليه بمطرقة مثبتة في يمينه. وفي هذه الحالة يكون من الأنسب الكتابة من اليمين إلى اليسار.
والآن - حول كيفية تعاملنا مع إرث القرون هذا.
كيف بدأنا المهمة؟
لم يتحدث أي من مطوري المنصات العربية ولم يكن لديه خبرة في تطوير واجهات RTL. لقد قمنا بتجريف الكثير من المقالات حول موضوع RTL (أود بشكل خاص أن أشكر شركة 2GIS على العمل المنجز والمقالات المعدة بعناية: المادة 1 ، المادة 2 ). عندما درست المادة ، أدركت أنه لا يمكننا الاستغناء عن متحدث أصلي. لذلك ، بالتزامن مع البحث عن مترجمين إلى اللغة العربية ، بدأنا في البحث عن موظف - يمكن للمتحدث باللغة العربية ، والذي سيكون لديه الخبرة التي نحتاجها ، تقديم النصح لنا بشأن المواصفات العربية للواجهات. بعد مراجعة العديد من المرشحين ، وجدنا مثل هذا الشخص وانطلقنا إلى العمل.
هيا نلعب مع الخطوط
بشكل افتراضي ، نستخدم خط النظام الأساسي Arial ، 10pt. يمكن لمطور تكوين معين تغيير الخط لمعظم عناصر الواجهة ، ولكن ، كما تظهر الممارسة ، نادرًا ما يتم ذلك. أولئك. في معظم الحالات ، يرى مستخدمو برامج 1C نقوشًا كتبها Arial على شاشاتهم.
يعرض Arial 21 لغة جيدًا (بما في ذلك الصينية والفيتنامية). ولكن ، كما اتضح بفضل زميلنا العربي ، فإن النص العربي المعروض بهذا الخط صغير جدًا ويصعب قراءته:
100٪:
يميل المستخدمون العرب إلى العمل في زيادة DPI - 125٪ ، 150٪. يتحسن الوضع في DPI هذا ، ولكن لا يزال Arial صعب القراءة بسبب طبيعة الخط.
125٪:
150٪:
نظرنا في عدة خيارات لحل هذه المشكلة:
- Arial , , ( ).
- Arial 11pt RTL-.
- Arial , LTR- Arial.
عند اختيار حل ، كان علينا أن نأخذ في الاعتبار أن خط Arial 10pt قد تم استخدامه في 1C: منصة Enterprise لفترة طويلة جدًا ، على النظام الأساسي ، أنشأنا وشركاؤنا أكثر من 1300 إصدار من الحلول ، وفي كل منهم أظهر خط Arial 10pt نفسه جيدًا على جميع أنظمة التشغيل المدعومة (Windows و Linux و macOS من إصدارات مختلفة) ، وكذلك في المتصفحات. قد يعني تغيير الخط و / أو حجمه إجراء اختبارات مكثفة لواجهة المستخدم ، ولا يمكن أتمتة الكثير من هذه الاختبارات. قد يعني تغيير الخط أيضًا تغيير الواجهة المألوفة للبرامج للمستخدمين الحاليين.
علاوة على ذلك ، لم نتمكن من العثور على خط عالمي يمثل جميع اللغات بشكل جيد ، بما في ذلك اللغة العربية. على سبيل المثال ، يعرض خط Segoe UI اللغة العربية بشكل جيد حتى عند 10 نقاط ، لكنه لا يدعم اللغة الصينية ، كما أنه غير مدعوم في بعض أنظمة التشغيل. تعتبر Tahoma جيدة في عرض النص العربي عند 10 نقاط ، ولكن لديها مشاكل مع دعم Linux و "جريء جدًا" لاتينية / سيريلية للخط العريض (تبدو اللغة العربية جريئة جيدة). إلخ.
زيادة حجم الخط الافتراضي إلى 11 نقطة في واجهة RTL يعني قدرًا كبيرًا من اختبار واجهة المستخدم - علينا التأكد من تقديم كل شيء بشكل صحيح ، ووضع جميع الملصقات في المساحة المخصصة ، إلخ. وحتى في 11 نقطة ، لا يعرض Arial الأحرف العربية بشكل مثالي.
نتيجة لذلك ، تبين أن الطريقة الثالثة هي الطريقة المثلى من حيث تكاليف العمالة والتأثير المحقق: نستمر في استخدام Arial لجميع الأحرف باستثناء اللغة العربية. وللحروف العربية ، نستخدم خطًا مناسبًا تمامًا لهذا - المراعي . للقيام بذلك ، أضف إلى CSS:
@font-face {
font-family: 'Almarai';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('Almarai'),
local('Almarai-Regular'),
url(https://fonts.gstatic.com/s/almarai/v2/tsstApxBaigK_hnnQ1iFo0C3.woff2)
format('woff2');
unicode-range:
U+0600-06FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE80-FEFC;
}
ثم أينما كنت تريد استخدام الخط الافتراضي ، اضبط الخط بهذه الطريقة:
font-family: 'Almarai', Arial, sans-serif;
يكمن جمال هذا الأسلوب في أنه إذا لم يكن هناك حرف واحد في الواجهة يقع ضمن نطاق unicode ، فلن يتم تحميل هذا الخط حتى. ولكن بمجرد ظهور هذا الرمز ، سيقوم المتصفح بتنزيل الخط نفسه (أو استخدام نسخته المحلية) وعرض الرمز بالخط المطلوب.
واجهة "انعكاس"
كما قد تتوقع ، لم يكن تخطيط HTML لعميل الويب جاهزًا للانعكاس. بعد اتخاذ الخطوة الأولى ، وضبط سمة dir = ”rtl” على عنصر الجذر وإضافة أسلوب html [dir = rtl] {text-align: right؛} ، بدأنا العمل الشاق. في سياق هذا العمل ، قمنا بتطوير عدد من الممارسات التي نريد مشاركتها هنا.
تناظر
لنلق نظرة على مثال الأزرار. يمكن أن تحتوي الأزرار الموجودة في النظام الأساسي على صورة ونص وعلامة قائمة منسدلة. وكل هذا في أي تكوين حسب تقدير مطوري الحلول التطبيقية القائمة على المنصة.
يمثل العمود "قبل اليمين من اليسار إلى اليمين" المساحة المتروكة الأولية لعناصر الأزرار بشكل رسومي. إن اعتماد مقدار المسافات البادئة على وجود العناصر في الزر ، وكذلك على تسلسل ترتيبها ، أمر واضح. إذا كانت هناك صورة ، فلن يحتاج النص إلى مسافة بادئة يسرى ، وإذا كانت الصورة على اليمين ، فإن الصورة بها إزاحة سالبة ، وإذا كانت هناك علامة في القائمة المنسدلة ، فإن الحاوية التي تحتوي على النص بها مسافة بادئة أكبر على اليمين ، وإذا كانت العلامة بعد الصورة مباشرة ، فلا يزال بها مسافة بادئة على اليمين. يوجد عدد كبير جدًا من ifs ، باستثناء زر نص فقط مع حشوة متناسقة. متماثل! إذا قمت بتوزيع المسافات البادئة بشكل متماثل ، فلا يوجد شيء تقلبه. أصبحت هذه الفكرة الرئيسية.
يُظهر العمود "بعد RTL" المسافات البادئة المتماثلة الجديدة على نفس الأزرار. يبقى حل الفروق الدقيقة مع المسافة البادئة بين الصورة وعلامة القائمة. كنت أرغب في حل شامل لأي اتجاه. المثلث نفسه مرسوم بالحد العلوي على العنصر الزائف ، ولا يحتاج إلى مسافة بادئة إلا إذا كان بعد الصورة. في ظل هذا الشرط ، يتم إضافة عنصر زائف آخر بعرض المسافة البادئة المطلوبة. سيتم تبديل المثلث والحشو عندما يتم تغيير الاتجاه.
ملحوظة. جميع الأمثلة الواردة أدناه هي افتراضيًا لواجهة LTR. لمعرفة الشكل الذي يبدو عليه المثال في واجهة RTL ، قم بتغيير dir = "ltr" إلى dir = "rtl".
<!DOCTYPE html>
<html dir="ltr">
<head>
<style>
.button {
display: inline-flex;
align-items: center;
border: 1px solid #A0A0A0;
border-radius: 3px;
height: 26px;
padding: 0 8px;
}
.buttonImg {
background: #A0A0A0;
width: 16px;
height: 16px;
}
.buttonBox {
margin: 0 8px;
}
.buttonDrop {
display: flex;
}
.buttonDrop:after {
content: '';
display: block;
border-width: 3px 3px 0;
border-style: solid;
border-left-color: transparent;
border-right-color: transparent;
}
.buttonImg + .buttonDrop::before {
content: '';
display: block;
width: 8px;
overflow: hidden;
}
</style>
</head>
<body>
<a class="button">
<span class="buttonImg"></span>
<span class="buttonBox"></span>
<span class="buttonDrop"></span>
</a>
<a class="button">
<span class="buttonImg"></span>
<span class="buttonDrop"></span>
</a>
</body>
</html>
نحاول تجنب العناصر غير الضرورية والعناصر الزائفة والأغلفة. ولكن ، بالاختيار في هذه الحالة بين زيادة الشروط في CSS وإضافة عنصر زائف ، فاز الحل بعنصر زائف بسبب تعدد استخداماته. لا يوجد الكثير من هذه الأزرار في النموذج ، وبالتالي فإن الأداء عند إضافة العناصر لن يتأثر حتى في Internet Explorer.
ثبت أن مبدأ التناظر مفيد في تمرير لوحاتنا أيضًا. لنقل المحتوى أفقيًا ، قمنا مسبقًا بتطبيق خاصية margin-left واحدة : -Npx؛ ...
يتم الآن تعيين القيمة على الهامش المتماثل : 0 -Npx؛ ، بمعنى آخر. لليسار واليمين في وقت واحد ، وأين تتحرك - المتصفح نفسه يعرف ، اعتمادًا على الاتجاه المحدد.
الطبقات الذرية
من إمكانيات منصتنا القدرة على تغيير المحتوى ديناميكيًا وموقعه على النموذج "سريع الحركة" حسب ذوق كل مستخدم. من الحالات الشائعة للتغييرات المحاذاة الأفقية للنص: إلى اليسار أو اليمين أو الوسط. يتم تحقيق ذلك ببساطة عن طريق محاذاة النص مع القيمة المناسبة. قد يعني انعكاس الاتجاه من اليمين إلى اليسار توسيع الشروط في البرامج النصية والأنماط لكل عنصر تحكم ولكل حالة من حالات تحديد موضعه. تكلفة الحل الأدنى 4 خطوط:
.taStart {
text-align: left;
}
html[dir=rtl] .taStart {
text-align: right;
}
.taEnd {
text-align: right;
}
html[dir=rtl] .taEnd {
text-align: left;
}
وبالتالي ، في الأماكن الضرورية ، يتم تثبيت الفصل بالمحاذاة اللازمة واستبدالها بسهولة ، إذا لزم الأمر. يبقى فقط استبدال إعداد المحاذاة بالنمط = "محاذاة النص: ..." بالفئة المناسبة.
يتم استخدام نفس المبدأ لتعيين نوع آخر من المحاذاة - عائم .
.floatStart {
float: left;
}
html[dir=rtl] .floatStart {
float: right;
}
.floatEnd {
float: right;
}
html[dir=rtl] .floatEnd {
float: left;
}
وبدونها ، هناك فئة للنسخ المتطابق ، على سبيل المثال ، الرموز ، والتي يتم تثبيتها أيضًا في أي حاويات تحتاج إلى انعكاس في واجهة RTL.
html[dir=rtl] .rtlScale {
transform: scaleX(-1);
}
نطاق المكافحة
بعد التعامل مع العناصر الخطية "البسيطة" ، حان الوقت للانتقال إلى العناصر "المعقدة". يوجد أيضًا بعض في نظامنا الأساسي ، على سبيل المثال ، مفاتيح التبديل. يمكن أن تكون ذات أشكال هندسية مختلفة. تعامل المتصفح مع ترتيب العناصر ، وكانت المسافات البادئة في مفاتيح التبديل الخاصة بنا متماثلة في البداية. إذا ما هي المشكلة؟ المشكلة في تقريب الإطارات.
يتم حساب تقريب الإطارات لكل عنصر تبديل ، اعتمادًا على موضعه. "Left-top" و "right-top" و "right-top و right-bottom" - الاختلافات مختلفة.
يمكنك قلب الحاوية بالكامل باستخدام مفتاح التبديل ، ولكن ماذا عن النص الذي ينقلب أيضًا؟ أطلقنا على هذه التقنية اسم "مقياس المقاومة" . أضف الفئة الذرية rtlScale إلى الحاوية التي تحتاج إلى عكسها، وإضافة خاصية التحويل الميراث إلى عنصرها الفرعي: الميراث ؛ ... في واجهة LTR ، سيتم تجاهل هذه الطريقة ، ولكن بالنسبة لواجهة RTL ، سيتم عرض النص المقلوب مرتين حسب الحاجة.
<!DOCTYPE html>
<html dir="ltr">
<head>
<style>
html[dir=rtl] .rtlScale {
transform: scaleX(-1);
}
.tumbler {
display: inline-flex;
border-radius: 4px 0 0 4px;
border: 1px solid #A0A0A0;
padding: 4px 8px;
}
.tumblerBox {
transform: inherit;
}
</style>
</head>
<body>
<div class="tumbler rtlScale">
<div class="tumblerBox"> </div>
</div>
</body>
</html>
فليكس بوكس
بالطبع للأسف لم نتوصل إلى هذه التقنية المذهلة ، ولكن بكل سرور استخدمنا إمكانياتها لأغراضنا. على سبيل المثال ، في لوحة القسم. لا تشغل أزرار التمرير في هذه اللوحة مساحة ؛ فهي تظهر أعلى اللوحة عندما يكون من الممكن التمرير في اتجاه أو آخر. تطبيق منطقي تمامًا للموقف: مطلق ؛ يمين / يسار: 0 ؛ تبين أنها ليست عالمية ، لذلك تخلينا عنها. نتيجة لذلك ، بدأ الحل العام في الظهور على النحو التالي: اضبط الحاوية الرئيسية لزر التمرير على عرض صفري بحيث لا تشغل مساحة ، وتم تغيير اتجاه زر التمرير الموجود في النهاية من خلال الاتجاه المرن: عكس الصف ؛ ...
وهكذا ، يتم الضغط على الزر الموجود في نهاية السطر مقابل نهاية خط الحاوية ذات العرض الصفري ويتم عرضه "للخلف" فوق اللوحة.
<!DOCTYPE html>
<html dir="ltr">
<head>
<style>
.panel {
display: inline-flex;
background: #fbed9e;
height: 64px;
width: 250px;
}
.content {
width: 100%;
}
.scroll {
display: flex;
position: relative;
width: 0;
}
.scrollBack {
order: -1;
}
.scrollNext {
flex-direction: row-reverse;
}
.scroll div {
display: flex;
flex: 0 0 auto;
justify-content: center;
align-items: center;
background: rgba(255,255,255,0.5);
width: 75px;
}
</style>
</head>
<body>
<div class="panel">
<div class="content"> </div>
<div class="scroll scrollBack">
<div></div>
</div>
<div class="scroll scrollNext">
<div></div>
</div>
</div>
</body>
</html>
بالمناسبة ، تبين أن فكرة العرض الصفري مفيدة لحل المشكلات الأخرى أيضًا. تُستخدم العناصر المنسدلة (قوائم السياق ، القوائم المنسدلة ، إلخ) على نطاق واسع في النظام الأساسي. يعد حساب تحديد الموضع معقدًا ودقيقًا ، وبالتالي يتطلب الانعكاس مزيدًا من التعقيد والدقة.
الحل هو وضع القائمة المنسدلة في حاوية ذات حجم صفري (تسمى المرساة). يتم وضع المرساة تمامًا عند النقطة المطلوبة للواجهة ، ويتم الضغط على محتواها بحافة البداية على حافة بداية المرساة ، مع وضع المحتوى في الاتجاه المطلوب.
<!DOCTYPE html>
<html dir="ltr">
<head>
<style>
.anchor {
border: 1px solid red;
position: absolute;
width: 100px;
height: 50px;
max-width: 0;
max-height: 0;
top: 25%;
left: 50%;
}
.anchorContent {
background: #FFF;
border: 1px solid #A0A0A0;
width: inherit;
height: inherit;
padding: 4px 8px;
}
</style>
</head>
<body>
<div class="anchor">
<div class="anchorContent"> </div>
</div>
</body>
</html>
عناصر متوضعة تمامًا
حيث لا يمكن تجنب تحديد الموضع المطلق للعناصر ( النمط = ”position: Absolute؛” or style = ”position: fixed؛” ) ، dir = ”rtl” يكون عاجزًا. يأتي النهج للإنقاذ عندما يتم تطبيق الإحداثي الأفقي ليس على النمط الأيسر ، ولكن على النمط الأيمن .
علاوة على ذلك ، إذا كان في JS ، عند حساب الإحداثيات ، هناك نداء إلى خصائص العناصر scrollLeft و offsetLeft ، فإن استخدام هذه الخصائص مباشرة في واجهة RTL يمكن أن يؤدي إلى عواقب غير متوقعة. تحتاج إلى حساب قيمة هذه الخصائص بطريقة مختلفة. أثبت تطبيق هذه الوظيفة في مكتبة Google Closure Library ، التي نستخدمها في عميل الويب ، أنه جيد: see.https://github.com/google/closure-library/blob/master/closure/goog/style/bidi.js .
في النهاية
لقد فعلناها! قمنا بتسليم شفرة المصدر الخاصة بنا وحفظناها في إصدار واحد لواجهات LTR و RTL. لم تظهر الحاجة بعد ، ولكن إذا رغبت في ذلك ، يمكننا عرض شكلين من الاتجاهات المختلفة في وقت واحد على صفحة واحدة. وبالمناسبة ، باستخدام تقنياتنا ، انتهى بنا المطاف بملف CSS النهائي بنسبة 25٪ أخف.
لقد قمنا أيضًا بدعم RTL في عميل 1C رفيع (أصلي) يعمل على أنظمة تشغيل Windows و Linux و macOS ، ولكن هذا موضوع لمقال منفصل.