محلی سازی یکی از جالب ترین زمینه ها از نظر رابط کاربری است: طول متن ممکن است بسته به زبان متفاوت باشد، ترازهای پیش فرض برای متن ممکن است متفاوت باشد، جهت خواندن می تواند آینه ای یا عمودی باشد، و بسیاری موارد مختلف دیگر. به طور خلاصه، آن یک است منبع باور نکردنی تنوع، که باعث می شود رابط های ما و کار جلویی ما قوی تر، قابل اطمینان تر و چالش برانگیزتر شوند.

نیاز به رابط های راست به چپ

بیشتر زبان‌ها، مانند فرانسوی یا انگلیسی، برای خواندن از چپ به راست (LTR) در نظر گرفته شده‌اند. با این حال، در این موارد، برخی از زبان‌ها مانند فارسی (فارسی)، عربی، و عبری جهت خواندن متفاوتی دارند – از راست به چپ (RTL).

سوال این است چگونه آیا می توانیم رابط های خود را با این تغییر عظیم تطبیق دهیم؟

قبل از CSS Logical Properties

قبل از CSS Logical Properties، می‌توانیم RTL را با روش‌های مختلف تطبیق دهیم:

  • افزودن یک فایل CSS اختصاصی فقط برای اضافه هزینه/طراحی RTL.
  • فقط بخش هایی را اضافه کنید که باید در همان CSS تطبیق داده شوند، به عنوان مثال [dir="rtl"] .float-left { float: right; }.

حتی اگر این روش ها کار را انجام می دهند – من از روش دوم برای ایجاد استفاده کردم نسخه عربی سایت Stand Up for Human Rights چند سال پیش – هر دوی آنها کاملاً کمتر از حد مطلوب هستند:

  • شما باید فایل دیگری را برای فایل اول نگهداری کنید.
  • فایل CSS برای فایل دوم کمی سنگین‌تر است و ممکن است مشکلاتی وجود داشته باشد (ویژگی، ویژگی‌های بیشتر برای افزودن و غیره).

مطمئناً، ما می‌توانیم با Sass ماشین‌آلات عظیمی برای تولید چندین بیلد ایجاد کنیم و از ابزارهایی مانند UnCSS برای حذف مواردی که لازم نیست استفاده کنیم، اما بیایید صادق باشیم: این خسته کننده است و می تواند منجر به کدهای “غیر طبیعی” شود، مانند مثال قبلی.

چرا ویژگی های منطقی CSS یک تناسب کامل / امیدوارکننده هستند؟

اینجاست که ویژگی های منطقی CSS ماژول وارد بازی میشه ایده اصلی این ماژول CSS داشتن یک انتزاع منطقی که ما را قادر می سازد یک طرح بندی را تولید کنیم که بسته به جهت متن و حالت نوشتن خود را تطبیق دهد (خواصی مانند writing-mode، direction، و text-orientation، یا dir ویژگی در HTML). این به ما امکاناتی مانند افقی راست به چپ یا چپ به راست، RTL عمودی و غیره را می دهد.

پیاده سازی در عمل

چگونه کار می کند

چند مفهوم برای درک وجود دارد که قبلا توسط راشل اندروز در اینجا در “درک خواص و ارزش های منطقی” توضیح داده شده است:

  • ما دیگر به شرایط فکر نمی کنیم left/right ولی start/end (در مورد هم همینطور top/bottom):
  • ما دیگر نمی گوییم width یا height اما به جای آن inline و block – کاملا کلاسیک (احتمالاً نام پیش فرض را شنیده اید inline یا block عناصر. 😉)

این ایده از start/end جدید نیست شما احتمالاً هر روز از آن با مواردی مانند استفاده می کنید justify-content: start.

تبریک می گویم، شما اکنون – تقریباً – همه چیز را می دانید! 🎉 بیایید چند مثال کاربردی ببینیم.

مثال ها

بیایید با اصول اولیه شروع کنیم:

املاک کلاسیک ویژگی منطقی
width inline-size
height block-size
min-width min-inline-size
min-height min-block-size
max-width max-inline-size
max-height max-block-size

حاشیه ها از همین منطق پیروی می کنند:

املاک کلاسیک ویژگی منطقی
margin-top margin-block-start
margin-bottom margin-block-end
margin-left margin-inline-start
margin-right margin-inline-end

همینطور است padding. بیایید به موقعیت یابی برویم:

املاک کلاسیک ویژگی منطقی
top inset-block-start
bottom inset-block-end
left inset-inline-start
right inset-inline-end

ساده است، اینطور نیست؟ float، text-align، و border همین مسیر را دنبال کنید:

دارایی/ارزش کلاسیک ویژگی منطقی
float: left; float: inline-start;
float: right; float: inline-end;
text-align: left; text-align: start;
text-align: right; text-align: end;
border-top border-block-start
border-bottom border-block-end
border-left border-inline-start
border-right border-inline-end

من به جزئیات برخی از موارد دیگر نمی پردازم resize یا scroll-margin-top، اما در عوض، اجازه دهید به مورد خاص نگاه کنیم border-radius:

املاک کلاسیک ویژگی منطقی
border-top-left-radius border-start-start-radius
border-top-right-radius border-start-end-radius
border-bottom-left-radius border-end-start-radius
border-bottom-right-radius border-end-end-radius

کمی متفاوت است، اما به هر حال به راحتی قابل درک است.

برخی از امکانات با مقادیر بسیار جالب هستند – می توانید برخی از نمادها را ساده کنید. در اینجا چند نمونه دیگر وجود دارد:

دارایی/ارزش کلاسیک ویژگی منطقی
margin-left: auto;
margin-right: auto;
margin-inline: auto;
margin-top: 0;
margin-bottom: 0;
margin-block: 0;
margin-top: 1em;
margin-bottom: 2em;
margin-block: 1em 2em;
top: 0;
left: 0;
bottom: 0;
right: 0;
inset: 0; 🎉
left: 10%;
right: 10%;
inset-inline: 10%;

این طلای خالص در بهترین جهان است، درست است؟ کد کمتر برای پشتیبانی کامل از زبان های RTL! 🎉

اکنون متاسفم که برخی از ستاره های چشمان شما را از بین می برم – در واقع محدودیت هایی وجود دارد.

بیشتر بعد از پرش! ادامه مطلب زیر ↓

برخی محدودیت ها

نحوهای گمشده

ویژگی‌های منطقی CSS کاملاً جدید هستند، حتی اگر پشتیبانی در مرورگرهای اخیر خوب باشد. با این حال، ماژول CSS Logical Properties به نوعی “جوان” است و به سطح 2 نیاز دارد.

برای مثال ساده: مولفه ضامن ما از تبدیل های CSS بین حالت های مختلف (بارگیری، فعال و غیره) استفاده می کند، بیشتر به این دلیل transform یک راه قابل اعتماد برای انتقال یا انیمیشن های روان است.

بنابراین، ما چیزی شبیه به این داریم:

.element {
   transform: translateX(#{$toggle-width - $toggle-width-button});
}

متاسفانه وجود دارد هیچ نحو مربوط به جریان برای transform. بنابراین، ما باید کاری مانند زیر انجام دهیم:

[dir="rtl"] .element {
    transform: translateX(-#{$toggle-width - $toggle-width-button});
}

اگر می‌خواهید درباره موارد گمشده مانند این ایده بگیرید، می‌توانید بررسی کنید مسائل مربوط به لوازم منطقی CSS را باز کرد.

مختصات مختصر

برخی از نمادهای کوتاه فعلاً پشتیبانی نمی شوند، مانند مقادیر 2، 3، یا 4 برای margin:

دارایی/ارزش کلاسیک ویژگی منطقی
margin: 1em 2em; margin-block: 1em; /* top and bottom */
margin-inline: 2em /* left and right */
margin: 1em 2em 3em; margin-block: 1em 3em; /* top, bottom */
margin-inline: 2em /* left, right */
margin: 1em 2em 3em 4em; margin-block: 1em 3em; /* top, bottom */
margin-inline: 4em 2em /* left, right */

از این مثال های کلاسیک با نیازهای منطقی استفاده نکنید. شما با مشکلاتی مواجه خواهید شد زیرا در واقع کار نمی کند. بهتر است صریح باشد. همچنین به نظر من خواندنی تر است.

نمایش برخی از مسائل واقعی و برخی از راه حل ها

تصاویری که جهت خواندن مهم است

برخی از تصاویر معنای مستقیم دارند. بیایید کارت های تم را مثال بزنیم:

تم های پروتون در LTR
تم های پروتون در LTR (پیش نمایش بزرگ)

در این مورد، اگر فقط موارد RTL را در این مورد اعمال کنیم، این را دریافت خواهیم کرد:

مضامین پروتون در RTL، اشتباه انجام شده است
مضامین پروتون در RTL، اشتباه انجام شده است. (پیش نمایش بزرگ)

ترتیب RTL است، اما هر تصویر شبیه رابط کاربری یک کاربر RTL نیست. این نسخه LTR است! در این مورد، به این دلیل است که جهت خواندن تصویر اطلاعات را منتقل می کند.

تم های پروتون در RTL
(پیش نمایش بزرگ)

ما یک کمک کننده کلاس CSS داریم که دستیابی به این اصلاح را بسیار ساده می کند:

[dir="rtl"] .on-rtl-mirror {
  transform: rotateY(180deg);
}

این همچنین برای هر تصویری که جهت خواندن دارد، مانند یک فلش یا نماد دوتایی که چیزی را نشان می دهد یا به آن اشاره می کند، صدق می کند.

سبک ها/مقادیر محاسبه شده از طریق جاوا اسکریپت

بیایید تصور کنیم پلاگینی دارید که مقداری موقعیت در جاوا اسکریپت را محاسبه می کند و مقداری را که می توانید در JS یا CSS استفاده کنید را ارائه می دهد. کتابخانه کشویی که ما از آن استفاده می کنیم، فقط این را ارائه می دهد left ارزش در هر دو زمینه RTL/LTR، و ما به CSS منتقل می کنیم با استفاده از یک ویژگی CSS Custom.

بنابراین، اگر ما از این با ویژگی های منطقی استفاده می کردیم، یعنی inset-inline-start: calc(var(--left) * 1px);، با کلیک بر روی منوی کشویی کاربر موارد زیر را دریافت خواهیم کرد:

منوی کشویی کاربر در سمت مقابل رابط باز می شود، نه در نزدیکی دکمه باز کردن آن
(پیش نمایش بزرگ)

راه حل در اینجا ساده است. ما ویژگی غیر منطقی را حفظ می کنیم:

/* stylelint-disable */
top: calc(var(--top) * 1px);
left: calc(var(--left) * 1px); // JS provide left value only
/* stylelint-enable */
منوی کشویی کاربر در نزدیکی دکمه باز کردن آن باز می شود
(پیش نمایش بزرگ)

و ما لینتینگ خود را برای این مورد خاص غیرفعال می کنیم.

ترکیب محتوای RTL و LTR

حتی با بهترین ماژول‌های CSS، هر کسی که قبلاً برخی از اقتباس‌های RTL را انجام داده باشد، می‌گوید که مخلوط کردن محتوای RTL و LTR گاهی اوقات (اغلب) چیزهای احمقانه‌ای را به همراه دارد.

بیایید یک مثال در پروتون درایو با یک جزء به نام MiddleEllipsis. هدف این مؤلفه اعمال بیضی قبل از پسوند فایل برای بدست آوردن چیزی شبیه به آن است my-filename-blahblahblah…blah.jpg.

هیچ چیز دیوانه کننده ای نیست: ما محتوا را به دو قسمت تقسیم می کنیم و اعمال می کنیم text-overflow: ellipsis در مورد اول می توانی چک کنی منبع این MiddleEllipsis جزء.

بیایید مقداری RTL خوب اعمال کنیم – سپس باید موارد زیر را دریافت کنیم:

نمایش فایل در پروتون درایو، بهتر نمایش داده می شود
(پیش نمایش بزرگ)

عجیبه، درسته؟ با این حال توضیح این موضوع ساده است:

  • MiddleEllipsis ساختار RTL است.
  • و محتوای LTR را تزریق می کنیم. (به یاد داشته باشید، ما این محتوای LTR را RTL برش دادیم.)

مرورگر تمام تلاش خود را می کند و چیزی که نمایش داده می شود از نظر آن اشتباه نیست، اما این برای شخص بی معنی است. در این مورد، ما انتخاب کردیم که صفحه نمایش LTR را برای حفظ هدف نام فایل ها حفظ کنیم، اما آن را به سمت راست تراز کردیم:

نمایش فایل در پروتون درایو، بهتر نمایش داده می شود
(پیش نمایش بزرگ)

جستجو برای الگوهای LTR بومی

را MiddleEllipsis مثال نشان داد که اگر محتوای تولید شده توسط کاربر LTR است، بهتر است آن را به صورت LTR نمایش دهید.

اما می توانیم تعجب کنیم که آیا الگوهایی وجود دارند که به طور طبیعی LTR هستند. پاسخ کوتاه بله است. در زیر می توانید یک نمونه را بیابید.

شماره تلفن

شماره تلفن ممکن است واضح‌ترین مورد در اینجا باشد زیرا معمولاً از اعداد غربی استفاده می‌کند که به معنای LTR خوانده می‌شوند.

اگر Logical props را مستقیماً روی آن اعمال کنیم، ممکن است موارد زیر را نشان دهد:

ورودی تلفن در RTL نمایش داده می شود، صفحه نمایش عجیب و غریب
(پیش نمایش بزرگ)

اگرچه از نظر فنی نادرست نیست، اما نمایش آن کمی عجیب است +33 6 12 34 56 78 مثل این. در این مورد، تصمیم گرفتیم برای جلوگیری از این نتیجه عجیب، تراز LTR را به صورت پیش فرض حفظ کنیم.

ورودی تلفن با LTR نمایش داده می شود
(پیش نمایش بزرگ)

ما همین مورد را برای ورودی 2FA با استفاده از اعداد غربی داریم. ما هنوز موردی را نداریم، اما تصور کنید یک ورودی 4 قسمتی برای وارد کردن یک آدرس IP. این منطقی نیست که آن را به طور کامل RTL همانطور که مردم درک می کنند نشان دهیم 1.0.163.192 بجای 192.163.0.1.

سازگاری

بزرگترین مشکلی که ما با آن مواجه بودیم بیشتر در رابطه با سازگاری بود. این را می توان در مشاهده کرد آیا می توانم از جداول برای لوازم منطقی استفاده کنم؟:

آیا می توانم از جداول برای لوازم منطقی استفاده کنم؟
آیا می توانم از جداول برای لوازم منطقی استفاده کنم (پیش نمایش بزرگ)

اگر هدف فقط مرورگرهای مدرن اخیر باشد، مشکلی وجود ندارد. اما اگر برای مثال نیاز به نسخه های قدیمی سافاری باشد، پشتیبانی بسیار بد است. و در این مورد، CSS Logical Properties به خوبی کاهش نمی‌یابد. بنابراین همه چیز ممکن است شکسته به نظر برسد.

چندین گزینه ممکن است:

  • یک ساخت CSS برای مرورگرهای مدرن و دیگری برای مرورگرهای قدیمی تر ارائه دهید.
  • همه چیز را برای هر مورد ترجمه کنید.

در مورد پروتون، از آنجایی که ما در هنگام ادغام یک زبان RTL کاملاً آماده نبودیم، و به دلایل دیگر، تصمیم گرفته شد همه چیز را به ویژگی‌های CSS کلاسیک خوب تبدیل کنیم. اخیراً پیدا کردیم یک راه حل برای یک مورد که نیاز به پشتیبانی RTL برای زبان فارسی (حساب VPN) داشت:

  1. ما دو فایل CSS می سازیم: یکی مدرن با لوازم منطقی و دیگری میراث.
  2. ما مدرن را بارگذاری می کنیم.
  3. ما پشتیبانی صحیح را آزمایش می کنیم border-start-start-radius;
  4. اگر پشتیبانی نشود، ما به میراث برمی گردیم.

نتیجه

حتی اگر کمال مطلق خارج از این دنیا باشد، حرکت به خصوصیات منطقی CSS است یک حرکت واقعا جالب و یک شرط خوب برای آینده: ما با این CSS Logical Props کد کمتری می نویسیم و با استفاده از آنها حجم کارهای آینده را کاهش می دهیم، بنابراین واقعاً به مسیر هیجان انگیزی می رود.

به‌عنوان آخرین پیشنهاد، و حتی اگر به کار بیشتری نیاز داشت، ما برخی از آزمایش‌های صفحه نمایش RTL عمودی را برای آزمایش ویژگی‌های منطقی CSS بیشتر انجام دادیم.

نمایشگر عمودی راست به چپ، با استفاده از حالت نوشتن
(پیش نمایش بزرگ)

خیلی جالب به نظر می رسد، اینطور نیست؟ 😉

سرمقاله Smashing
(yk, il)