ساختن رابط فارسی فقط اضافهکردن dir="rtl" به تگ html نیست. اگر کارتان همینجا تمام شود، نتیجه رابطی است که فنی درست است اما فارسی به نظر نمیرسد: فاصلهها نامتوازناند، آیکونها سمت اشتباهاند و اعداد وسط جمله میشکنند.
این چیزهایی است که در پروژههای فارسی یاد گرفتهایم.
بهجای left و right، از start و end استفاده کنید
مهمترین عادتی که باید تغییر کند. در Tailwind بهجای ml-4 بنویسید ms-4 و بهجای pr-6 بنویسید pe-6. همین برای text-left/text-start، border-l/border-s و rounded-tl/rounded-ts هم صدق میکند.
مزیتش فقط تمیزی کد نیست: با این کار کل چیدمان با تغییر dir خودش برمیگردد و لازم نیست برای حالت راستبهچپ استایل جداگانه بنویسید. اگر روزی نسخهی انگلیسی هم بخواهید، هیچ کاری لازم نیست.
استثنا هم دارد. چیزهایی که باید همیشه چپبهراست بمانند — بلوک کد، شماره تلفن، نشانی ایمیل و عنوانهای لاتین — باید صراحتاً dir="ltr" بگیرند، وگرنه علائم انتهایشان جابهجا نمایش داده میشود.
فونت: نصف کیفیت رابط فارسی همین است
فونت فارسی را همیشه محلی سرو کنید. وابستهبودن به CDN خارجی برای کاربر ایرانی یعنی تأخیر و گاهی اصلاً بارگذارینشدن.
با next/font/local فونتها را بهصورت woff2 بارگذاری کنید و برای هر وزن فایل جدا بدهید. یک نکته که زیاد فراموش میشود: font-display را روی swap بگذارید. در غیر این صورت متن تا آمادهشدن فونت نامرئی میماند و کاربر روی اینترنت کند، چند لحظه صفحهی خالی میبیند.
نکتهی دیگر ارتفاع خط است. فونتهای فارسی بهخاطر زیرنویسها و کشیدگیها به فضای عمودی بیشتری نیاز دارند؛ مقدارهای پیشفرض که برای فونتهای لاتین تنظیم شدهاند، متن فارسی را فشرده نشان میدهند.
اعداد
سه تصمیم که باید یکبار بگیرید و همهجا رعایت کنید:
ارقام فارسی یا لاتین؟ برای متنهای محتوایی و شمارهگذاری، ارقام فارسی طبیعیتر است. برای دادههای فنی، شمارهی سفارش و مقادیری که کاربر ممکن است کپی کند، ارقام لاتین بهتر است. یک تابع کمکی ساده کافی است:
const PERSIAN_DIGITS = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
export function toPersianDigits(value: string | number) {
return String(value).replace(/\d/g, (digit) => PERSIAN_DIGITS[Number(digit)]);
}
اعداد در جدولها باید با font-variant-numeric: tabular-nums رندر شوند تا ستونها زیر هم بمانند و ارقام موقع تغییر عدد نلرزند.
فیلدهای ورودی عددی را با inputMode="numeric" مشخص کنید تا روی موبایل صفحهکلید عددی باز شود. کاربر نباید برای وارد کردن شماره تلفن بین صفحهکلیدها جابهجا شود.
آیکونهای جهتدار
فلشها معنایشان در راستبهچپ برعکس میشود. «بعدی» در فارسی یعنی فلش رو به چپ، نه راست. آیکونهای غیرجهتدار مثل ذرهبین و سطل زباله نباید بچرخند.
راه ساده این است که آیکون درست را انتخاب کنید (ArrowLeft بهجای ArrowRight) نه اینکه با CSS آینهاش کنید؛ چون آینهکردن روی آیکونهایی که متن یا سایه دارند نتیجهی عجیبی میدهد.
فرمها و پیامهای خطا
پیام خطا را زیر همان فیلد و با aria-describedby به آن وصل کنید تا صفحهخوان آن را بخواند. متن خطا را هم به فارسی روشن بنویسید — «مقدار نامعتبر» به کاربر نمیگوید چه کار کند، اما «شماره تماس باید ۱۱ رقم باشد و با ۰۹ شروع شود» میگوید.
برای اعتبارسنجی، پیامهای فارسی را در همان شمای اعتبارسنجی تعریف کنید تا سمت سرور و سمت کاربر یک متن واحد بدهند.
چیزی که در تست دیده نمیشود
دو مورد را حتماً روی دستگاه واقعی ببینید، نه فقط در حالت responsive مرورگر:
متن بلند در فضای کم. فارسی معمولاً از انگلیسی طولانیتر است. دکمهای که با متن انگلیسی جا میشود، ممکن است با معادل فارسیاش بشکند. برای عنوانها text-balance و برای بریدن کلمههای طولانی min-w-0 روی آیتمهای flex و grid را فراموش نکنید — بدون آن، آیتمها از عرض کانتینر بیرون میزنند.
اسکرول افقی ناخواسته. در راستبهراست، عنصری که کمی از لبه بیرون بزند اسکرول افقی میسازد که در نگاه اول دیده نمیشود چون در سمت راست صفحه است. روی موبایل واقعی امتحان کنید.
دسترسپذیری را از اول جدی بگیرید
lang="fa" روی تگ html فقط برای موتور جستجو نیست؛ صفحهخوانها از آن برای انتخاب موتور تلفظ استفاده میکنند. یک لینک «پرش به محتوای اصلی» در ابتدای صفحه بگذارید و مطمئن شوید حلقهی فوکوس روی همهی عناصر تعاملی دیده میشود. اینها هرکدام چند دقیقه کار دارند و بعداً اضافهکردنشان چند برابر طول میکشد.
جمعبندی
رابط فارسی خوب از یک تنظیم بهدست نمیآید؛ از چند ده تصمیم کوچک میآید که هرکدام بهتنهایی بیاهمیت به نظر میرسند. اگر از ابتدا با start/end بنویسید، فونت را درست بارگذاری کنید و اعداد را یکدست نگه دارید، بیشتر راه را رفتهاید.
