قالببندی عدد و تاریخ
تقویم شمسی، جداکنندهٔ عدد و مقدار مختصر — کدام تابع برای کدام کار، و کدام تلهها واقعیاند
اصل
این فارسیترین کاری است که سیستم طراحی انجام میدهد و تا امروز صفحه نداشت. دو قاعده کل ماجراست:
- رقم را تبدیل نکنید. در متن صفحه همیشه رقم لاتین (
0–9) است و ارقام فارسی از ویژگیss01فونت میآیند، فقط برای محتوای فارسی (lang="fa"؛ از 4.0). هیچ تابع سیستم طراحی رقم فارسی یا عربی تولید نمیکند، پس کسی که عددی را از صفحه کپی میکند رقم لاتین میگیرد و Excel و ماشینحساب و جستجو آن را عدد میشناسند. صفحهٔ عربی و انگلیسی رقم لاتین دارند، و شناسهها (نام کاربری، IP، URL، کد) داخل متن فارسی باLatinDigitsرقم لاتین میمانند. جزئیات و اثباتش در فارسیمحور بودن. - قالب را تبدیل کنید. جداکنندهٔ هزار، مختصرسازی و تاریخ شمسی کارِ کد است، چون آنها شکل عدد نیستند، معنای آناند.
نمونه بصری
| فراخوانی | رشتهٔ خروجی | آنچه کاربر میبیند |
|---|---|---|
| formatNumber(1234567) | 1,234,567 | 1,234,567 |
| formatNumber(1234567, 'short') | 1.2M | 1.2M |
| formatLargeNumber(1234567, 'fa') | 1.2 میلیون | 1.2 میلیون |
| formatLargeNumber(1234567, 'en') | 1.2M | 1.2M |
| formatJalaliDate(date, 'yyyy/MM/dd') | 1405/05/05 | 1405/05/05 |
| getPersianMonthName(date) | مرداد | مرداد |
| getPersianWeekdayName(date) | دوشنبه | دوشنبه |
| formatPersianDateRange(from, to) | 5 - 9 مرداد 1405 | 5 - 9 مرداد 1405 |
ستون دوم و سوم یک رشتهاند. تفاوتشان کار فونت است: ویژگی ss01 گلیف ارقام لاتین را به فارسی نگاشت میکند، بدون آنکه codepoint عوض شود. به همین دلیل کپیکردن از ستون سوم، عددِ قابلاستفاده میدهد. دقت کنید که کاما در هیچ ستونی فارسی نمیشود — ss01 فقط ارقام را میگیرد.
قوانین اجباری
برای عدد، یکی از این دو تابع
import { formatNumber, formatLargeNumber, formatPercentage } from '@partodata/ui'
formatNumber(1234567) // «1,234,567» — رقم لاتین؛ فونت آن را با رقم فارسی نشان میدهد
formatLargeNumber(1234567, 'fa') // «1.2 میلیون» — پسوند فارسی
formatLargeNumber(1234567, 'en') // «1.2M» — برای رابط لاتین
formatPercentage(12.5, 'fa') // «12.5٪» — نشانهٔ فارسی
formatPercentage(12.5, 'en') // «12.5%» — نشانهٔ لاتینحالت `'short'` را در رابط فارسی به کار نبرید
خروجیاش پسوند لاتین دارد، و چون ss01 زیر lang="fa" روشن است کاربر رقم فارسی را با پسوند لاتین کنار هم میبیند.
برای مقدار مختصر در فارسی همیشه formatLargeNumber با locale فارسی. چراییاش با اثبات، در فارسیمحور
بودن.
جداکنندهها را فونت عوض نمیکند
ss01 فقط رقمها را جانشین میکند: رقم لاتین و رقم عربی-هندی، و دیگر هیچ. این با پارس مستقیم جدول GSUB سنجیده
شده. کاما، نقطه، % و ٪ دستنخورده میمانند. پس formatNumber(1234567) با رقم فارسی و کامای لاتین دیده میشود،
نه با جداکنندهٔ فارسی «٬». اگر جداکنندهٔ فارسی میخواهید باید صریحاً بنویسیدش؛ خودبهخود نمیآید.
برای تاریخ، از توابع شمسی — نه محاسبهٔ دستی
import { formatJalaliDate, getPersianMonthName, formatPersianDateRange, jalaliToGregorian } from '@partodata/ui'
formatJalaliDate(new Date(), 'yyyy/MM/dd')
getPersianMonthName(new Date()) // «مرداد»
formatPersianDateRange(from, to) // «3 - 7 مرداد 1405»
jalaliToGregorian(1405, 5, 3) // Dateپشت همهی اینها date-fns-jalali است، و این انتخاب قفل شده: moment-jalaali از 2019
بینگهدارنده است و یک قانون ESLint هر import از moment* را میبندد. جایگزینش نکنید.
ساعت همیشه 24ساعته است
سیستم طراحی هیچجا ق.ظ/ب.ظ یا AM/PM نشان نمیدهد — در fa، ar و en: «13:05» و «00:30»، نه «1:05 ب.ظ». قالبهای
date-fns با HH:mm نوشته میشوند و formatJalaliDate هر نشانهٔ 12ساعته (hh، a، p) را با force24Hour به
24ساعته برمیگرداند؛ Intl.DateTimeFormat با hourCycle: 'h23' صدا زده میشود. فیلد ساعت DateTimePicker هم یک
فیلد HH:mm است، نه <input type="time"> بومی که ساعت و ارقامش را از زبان مرورگر میگیرد. ارقام پاپاورهای تقویم و
ساعت از lang خود پاپاور میآیند (فارسی در fa، لاتین در en).
موارد استفاده رایج
زمان نسبی
import { formatAbsoluteLocaleTime, formatRelativeLocaleTime } from '@partodata/ui'
formatRelativeLocaleTime(post.createdAt, 'fa') // «3 ساعت پیش»
formatAbsoluteLocaleTime(post.createdAt, 'fa') // «27 مرداد 1405، 12:30»
formatAbsoluteLocaleTime(post.createdAt, 'en') // «August 18, 2026 at 12:30»درصد و واحد
در رابط فارسی و عربی درصد را با نشانهٔ ٪ بنویسید، نه %. هیچکدام از این دو را فونت عوض
نمیکند؛ برای جلوگیری از ترکیب دستی و ناهماهنگی، مقدار درصد را به formatPercentage(value, locale)
بسپارید. این تابع برای fa و ar نشانهٔ ٪ و برای en نشانهٔ % برمیگرداند.
چه نکنیم
- تبدیل رقم — نه با
toLocaleString('fa-IR')یاIntl.NumberFormat('fa-IR')(اگرIntlلازم است،numberingSystem: 'latn'بدهید)، نه با نگاشت دستی رقم، نه با رقم فارسیِ تایپشده در متن. هیچ سودی ندارد وCtrl+F، کپی به Excel، صفحهخوان و مرتبسازی را میشکند.convertToLocalNumbersوtoPersianDigitsمنسوخاند و حالا رقم لاتین برمیگردانند؛ صدایشان نزنید. آزمونcheck-digit-doctrineتبدیل رقم و رقم فارسیِ تایپشده را در کد سیستم طراحی رد میکند. - تکیه بر
PERSIAN_WEEKDAYSبا فرض ترتیب هفتهٔ فارسی. این آرایه به ترتیبgetDay()جاوااسکریپت است و با یکشنبه شروع میشود، نه شنبه. اگر با ایندکسِ روزِ فارسی سراغش بروید، روز اشتباه میگیرید. برای نام روز،getPersianWeekdayName(date)را صدا بزنید که خودش از localefaIRمیخواند و به این آرایه کاری ندارد. - انتظار ارقام همعرض. فونت یکان بخ ویژگی
tnumندارد و عرض ارقام فارسیاش از 260 تا 700 یونیت در یک em هزاریونیتی نوسان دارد.tabular-numsامروز بیاثر است؛ اگر پایداری چیدمان لازم دارید، عرض ظرف را تثبیت کنید. (گلیفهای همعرض در خود فونت هست ولی قابلیتی به آنها نمیرسد؛ جزئیات در امکانات فونت.)
صفحات مرتبط
- فارسیمحور بودن — دکترین ارقام و اثبات
ss01 - تایپوگرافی — فونت یکان بخ و ویژگیهای OpenType آن
- انتخابگر بازهٔ تاریخ — همین توابع در یک کامپوننت واقعی