Skip to content

Locale و ارقام

دو چیز بسته به مخاطب تغییر می‌کند: locale (نام ماه/روز هفته، عبارت‌های زمان نسبی و برچسب کنترل‌های تقویم) و سبک ارقام (فارسی ۱۴۰۵ در برابر لاتین 1405). دوران این دو را جدا نگه می‌دارد تا یک UI انگلیسیِ LTR بتواند نام ماه فارسی را با ارقام لاتین — یا هر ترکیب دیگری — نشان دهد، بدون جنگیدن با سیستم locale.

ترتیب اولویت locale

وقتی مقداری به locale نیاز دارد، دوران به این ترتیب آن را resolve می‌کند — اولین تطبیق برنده است:

locale در محل فراخوانی  →  پیش‌فرض سراسری  →  fa-IR داخلی
      (هر فراخوانی)         (setDefaultLocale)     (fallback)
ts
import { DoranDate, enUS, setDefaultLocale } from '@doranjs/core';

// ۳. fallback داخلی: اگر چیزی تنظیم نکنید، fa-IR (فارسی).
DoranDate.fromJalali(1405, 3, 11).format('dddd'); // "دوشنبه"

// ۲. پیش‌فرض سراسری: یک‌بار در ابتدای اپ تنظیم کنید.
setDefaultLocale(enUS);
DoranDate.fromJalali(1405, 3, 11).format('dddd'); // "Doshanbe"

// ۱. محل فراخوانی بر پیش‌فرض سراسری اولویت دارد.
DoranDate.fromJalali(1405, 3, 11, { locale: 'fa-IR' }).format('dddd'); // "دوشنبه"

withLocale یک نمونهٔ تازه می‌سازد که به یک locale سنجاق شده است، معادل پاس‌دادن { locale } در محل فراخوانی:

ts
date.withLocale(enUS).format('dddd D MMMM YYYY'); // "Doshanbe 11 Khordad 1405"

تحمیل یک locale در کل اپ

برای یک UI انگلیسیِ LTR، یک‌بار در ابتدا setDefaultLocale(enUS) را صدا بزنید. آنگاه هر DoranDate به‌صورت پیش‌فرض نام انگلیسی + ارقام لاتین خواهد داشت، بدون نیاز به گزینه در هر فراخوانی.

کنترل‌های تقویم نیز برچسب‌های خود را از همین locale می‌گیرند:

ts
import { enUS, resolveCalendarLabels } from '@doranjs/core';

resolveCalendarLabels(enUS); // { today: "Today", clear: "Clear" }

در localeهای سفارشی می‌توانید calendarLabels را تعریف کنید. localeهای سفارشی قدیمی که آن را ندارند همچنان سازگارند و از برچسب‌های فارسی استفاده می‌کنند.

در React، DoranProvider می‌تواند locale را به یک زیردرخت محدود کند. بایندینگ‌های مبتنی‌بر وب‌کامپوننت (Vue، Svelte و Angular) روی هر کامپوننت locale="fa" یا locale="en" می‌پذیرند.

جهت و برچسب‌های کامپوننت

هر locale یک direction دارد و کامپوننت‌ها به‌جای مقدار ثابت، همان را می‌خوانند — پس سوئیچ به یک locale لاتین واقعاً یک ویجت چپ‌به‌راست می‌دهد، نه یک ویجت راست‌به‌چپ با متن لاتین داخلش.

tsx
setDefaultLocale(enUS); // dir="ltr"، برچسب انگلیسی، کلیدهای جهت LTR

<DoranDatePicker dir="rtl" />; // پراپ صریح همچنان برنده است

پیمایش با کلیدهای جهت هم از جهت پیروی می‌کند: ArrowLeft در RTL جلو می‌رود و در LTR عقب، و فلش‌های پیش‌فرضِ ناوبری هم برعکس می‌شوند.

هر رشتهٔ قابل‌مشاهده و هر رشته‌ای که صفحه‌خوان می‌خواند در calendarLabels است:

فیلدکاربرد
today، clearاکشن‌های فوتر
datePlaceholderplaceholder ورودی تاریخ
calendar، openCalendarنام پاپ‌اور و دکمهٔ بازکننده
previousMonth، nextMonthفلش‌های ناوبری
month، yearانتخابگر ماه و سال
hour، minute، increase، decreaseانتخاب زمان
presets، lastDays، thisMonth، thisYearمیان‌برهای بازه
rangeSeparator، rangeEmptyخلاصهٔ بازه
nlpPlaceholder، unresolvedورودی زبان طبیعی
listSeparatorاتصال تاریخ روز به توضیح آن

همهٔ فیلدها اختیاری‌اند. locale‌ای که فقط بخشی را بدهد، بقیه را از پیش‌فرض فارسی می‌گیرد، پس locale‌هایی که پیش از وجود این فیلدها نوشته شده‌اند کار می‌کنند:

ts
const custom: Locale = {
  ...faIR,
  name: 'fa-custom',
  calendarLabels: { today: 'همین امروز' }, // بقیه fallback می‌شوند
};

lastDays یک قالب است: {count} با عددی که از locale.formatNumber گذشته جایگزین می‌شود، پس defaultRangePresets(faIR) می‌دهد '۷ روز اخیر' و defaultRangePresets(enUS) می‌دهد 'Last 7 days'.

مجموعهٔ نهایی را با resolveCalendarLabels(locale) بخوانید که جاهای خالی را پر می‌کند، و جهت را با resolveDirection(locale) که پیش‌فرضش 'rtl' است.

در وب‌کامپوننت‌ها همین‌ها را ویژگی locale هدایت می‌کند و نبودِ آن حالا به مقدارِ setDefaultLocale() برمی‌گردد:

html
<doran-datepicker locale="en"></doran-datepicker>

کنترل ارقام در هر فراخوانی

سبک ارقام مستقل از locale است. با { digits } به format فقط ارقام همان فراخوانی را override کنید — نام‌ها همچنان از locale می‌آیند:

ts
const d = DoranDate.fromJalali(1405, 3, 11); // fa-IR → پیش‌فرض ارقام فارسی

d.format('YYYY/MM/DD'); // "۱۴۰۵/۰۳/۱۱"  (پیش‌فرض locale)
d.format('YYYY/MM/DD', { digits: 'latin' }); // "1405/03/11"
d.format('D MMMM', { digits: 'latin' }); // "11 خرداد"  ← رقم لاتین، نام فارسی

// و برعکس، زیر یک locale لاتین:
d.withLocale(enUS).format('YYYY/MM/DD', { digits: 'persian' }); // "۱۴۰۵/۰۳/۱۱"

digits مقدار 'latin' | 'persian' می‌پذیرد. آن را حذف کنید تا از هر چه locale فعال تعریف می‌کند استفاده شود (fa-IR → فارسی، en-US → لاتین).

چرا فقط locale را عوض نکنیم؟

عوض‌کردن به enUS برای گرفتن ارقام لاتین، نام ماه/روز و برچسب کنترل‌های تقویم را هم به انگلیسی عوض می‌کند. وقتی نام فارسی با ارقام لاتین می‌خواهید (رایج در UIهای دوزبانه)، کلید digits در هر فراخوانی مسیر ارگونومیک است — بدون نیاز به locale سفارشی.

ابزارهای رقم

برای رشته‌های خام (نه تاریخ‌های قالب‌بندی‌شده)، مبدل‌های رقم مستقیماً export شده‌اند:

ts
import { toPersianDigits, toLatinDigits, normalizeDigits } from '@doranjs/core';

toPersianDigits('1405'); // "۱۴۰۵"
normalizeDigits('۱۴۰۵'); // "1405"  (فارسی/عربی → ASCII، برای parse ورودی)
toLatinDigits('١٤٠٥'); // "1405"  (نام مستعار normalizeDigits)

برای هر مقداری که کاربر تایپ می‌کند — شمارهٔ تلفن، شمارهٔ کارت، تاریخ — پیش از اعتبارسنجی یا ذخیره از normalizeDigits استفاده کنید. کیبورد فارسی ۰۹۱۲… تولید می‌کند که بی‌سروصدا در بررسی /[0-9]/ رد می‌شود. ورودی ASCII بدون تغییر عبور می‌کند، پس اعمال بی‌قیدوشرط آن امن است.

Released under the MIT License.