هذه الصفحة مترجمة من الإنجليزية. اقرأ الصفحة الإنجليزية
التواريخ والأوقات مصدر شائع للأخطاء في تطبيقات الأعمال: عيد ميلاد ينتقل يوماً عندما يسافر المستخدم، ومناوبة تبدأ متأخرة ساعة بعد تغيير الساعة. يمنح Zeyn كل نوع من القيم نوعه الخاص، فيبقي المترجم الأنواع منفصلة.
أربعة أنواع
| النوع | هو | مثال |
|---|---|---|
Date | يوم في التقويم، بلا منطقة | عيد ميلاد، تاريخ فاتورة |
Time | وقت على ساعة الحائط، بلا منطقة | ساعات العمل |
DateTime | لحظة محددة، مخزنة بتوقيت UTC | وقت إنشاء سجل |
LocalDateTime | تاريخ ووقت على ساعة الحائط في مكان ما | موعد في الساعة 14:00 في إسطنبول |
لا تخزّن يوماً من التقويم كلحظة أبداً. Date هو اليوم نفسه في كل منطقة؛ أما DateTime فهو اللحظة نفسها في كل مكان ويظهر بوقت ساعة حائط مختلف في كل منطقة.
let day = Date::new(2026, 3, 29).unwrap_or_default();
let at = Time::new(9, 30, 0).unwrap_or_default();
let slot = LocalDateTime::new(day, at);
let zone = TimeZone::named("Europe/Istanbul").unwrap_or(TimeZone::UTC);
let moment = DateTime::from_local(slot, zone)?;
let back = moment.local(zone);يفشل DateTime::from_local مع وقت ساعة حائط غير موجود في المنطقة، مثل أثناء تقديم الساعة في الربيع، بدلاً من التخمين.
الساعة
استخدم ctx.now() وctx.today()، لا ساعة النظام أبداً. ctx.today() هو اليوم في منطقة المستخدم. تثبّت الاختبارات الساعة لكل طلب بـ App::fixed_now(moment).
المناطق الزمنية
App::new(t!("app.name"))
.time_policy(TimePolicy::User { default: TimeZone::named("Europe/Istanbul").unwrap_or(TimeZone::UTC) })
.time_zone_picker()| السياسة | تُعرض اللحظات في |
|---|---|
TimePolicy::User { default } | المنطقة التي يبلّغ عنها متصفح المستخدم، أو default إلى أن يفعل |
TimePolicy::Organization(zone) | منطقة واحدة للجميع |
يضيف .time_zone_picker() محدداً إلى القائمة ليتمكن المستخدمون من اختيار منطقة يدوياً. ويمكن لوكيل تسجيل دخول موحد أن يرسل المنطقة في ترويسة أيضاً (ForwardAuth::time_zone). تُقرأ مرشحات الجداول على أعمدة DateTime بمنطقة المستخدم.
المحددات
تحصل حقول التاريخ والوقت والتاريخ مع الوقت على محددات ملائمة للوحة المفاتيح. يحد DateOptions ما يمكن اختياره:
Form::of(visit)
.row(|r| r.field(Visit::day).field(Visit::arrives))
.range(Visit::stay_from, Visit::stay_to)
.date_options(Visit::day, DateOptions::new().no_weekends().week_numbers())
.date_options(Visit::arrives, DateOptions::new().step_minutes(15))اختيار اللغة
يختار الخادم اللغة من ملف تعريف الارتباط zeyn_locale، ثم من Accept-Language في المتصفح، ثم من الافتراضي للتطبيق. ويطابق <html lang> دائماً. يضبط محدد اللغة في القائمة ملف تعريف الارتباط ويبدّل الصفحة في مكانها، دون إعادة تحميل.
مع App::locale_paths() تصبح اللغة جزءًا من عنوان URL: تبقى اللغة الافتراضية على /orders، وتحصل اللغات الأخرى على /tr/orders أو /ar/orders. المسار وحده يحدد اللغة، فيُفتح الرابط المشارَك باللغة نفسها، ويبقى لكل شاشة مسار واحد، وتقرأ اللغة عبر ctx.locale(). تحافظ روابط القائمة على اللغة، ويفتح محدد اللغة الصفحة نفسها باللغة الأخرى دون إعادة تحميل. تحصل العربية واللغات الأخرى التي تُكتب من اليمين إلى اليسار على <html dir="rtl">. اذكر لغات الصفحة العامة لمحركات البحث باستخدام Screen::alternate("tr", "/tr/orders").
الأرقام والمبالغ والتواريخ
تُنسَّق القيم على الخادم بحسب لغة المستخدم: 1.234,56 بالتركية و1,234.56 بالإنجليزية، والتواريخ على صورة 29.03.2026 أو 3/29/2026، والمبالغ برمز عملتها. وتقرأ حقول الإدخال الصيغ نفسها عائدةً.
يحتفظ Money بوحدات صغرى صحيحة وعملة، فلا تفقد المجاميع قرشاً أبداً:
let price = Money::tl(2_500_000);
let text = price.format("tr");