Files
baya-monorepo/client/messages/fa.json
T
hamid 99ebf5d881 frontend phase 4: catalog browse (Home A5) & nurse service builder (B7)
Light up the two faces of the configurable service catalog over a new cached
services/catalog domain (consumes the b5 contract; unlocks f6 search).

- services/catalog: types/keys/constants/apis(client+mock+seam)/hooks/index +
  names.ts. Categories & option groups are session-cached reference data
  (Infinity staleTime, like geography); variant mutations invalidate
  myVariantsLists() and setQueryData the edited row. Mock-primary
  (USE_CATALOG_MOCK), one-line swap; mock reproduces the 400 missing-required
  and (nurse,category,option-set) 409 duplicate rules.
- Customer Home (A5): greeting+avatar, search bar (navigates toward f6),
  data-driven category grid (loading/empty/error), patient nudge from the
  cached f2 query. Deferred /search placeholder stub.
- Nurse Services & prices (B7) at /nurse/services: offerings list (active vs
  deactivated, edit, soft-deactivate w/ confirm, reactivate, no delete) and a
  3-step variant builder (category -> required/optional options -> price+unit+
  duration). Required-group gate; Toman->IRR digit-string at the field
  boundary (no float); live unit-aware estimated total (never from price
  alone); editable auto display_name; inline 409 duplicate warning; locked
  category edit form.
- Shared, tested components: CategoryTile, PriceDisplay, VariantCard. Money
  util: tomanToRial + multiplyIrr (integer-safe) + tests.
- i18n: catalog/services/search namespaces + home additions + nav.services
  (both locales, in sync). Icons, routes (SEARCH, NURSE_SERVICES), nurse nav.

Gate: npm run check green; npm run test:ci green (147 tests, +18 across 4
suites); npm run build green with NEXT_PUBLIC_API_URL set.

Docs: client/CLAUDE.md (Project Structure, caching note, namespaces), STATUS,
for-backend REQ-010 (pagination param casing), phase report, mocks registry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 17:33:44 +03:30

348 lines
19 KiB
JSON

{
"nav": {
"home": "خانه",
"bookings": "رزروها",
"patients": "بیماران",
"wallet": "کیف‌پول",
"profile": "پروفایل",
"bank": "حساب بانکی",
"coverage": "پوشش",
"services": "خدمات",
"dashboard": "داشبورد",
"verification": "احراز هویت",
"visits": "ویزیت‌ها",
"admin": "مدیریت",
"overview": "نمای کلی",
"users": "کاربران",
"notifications": "اعلان‌ها",
"login": "ورود",
"logout": "خروج"
},
"common": {
"dark_mode": "حالت تاریک",
"light_mode": "حالت روشن",
"direction_ltr": "تغییر به چپ‌به‌راست",
"direction_rtl": "تغییر به راست‌به‌چپ",
"coming_soon": "به‌زودی",
"loading": "در حال بارگذاری…",
"retry": "تلاش مجدد",
"add": "افزودن",
"cancel": "انصراف",
"save": "ذخیره",
"saving": "در حال ذخیره…",
"back": "بازگشت",
"close": "بستن",
"optional": "اختیاری",
"currency_toman": "تومان",
"brand": "بلینیار",
"brand_tagline": "مراقبت مطمئن در خانه"
},
"shell": {
"customer_app": "اپلیکیشن خانواده",
"nurse_app": "نمای پرستار",
"admin_console": "کنسول مدیریت",
"placeholder_body": "این بخش در فازهای بعدی تکمیل می‌شود."
},
"home": {
"greeting_named": "سلام، {name}",
"greeting_plain": "سلام",
"subtitle": "مراقبت از عزیزانتان را مدیریت کنید.",
"search_placeholder": "جستجوی خدمت یا پرستار…",
"search_action": "جستجو",
"categories_title": "خدمات",
"categories_error": "خدمات بارگذاری نشد.",
"categories_empty": "هنوز خدمتی تعریف نشده است.",
"nudge_patient_title": "تکمیل پروندهٔ بیمار",
"nudge_patient_body": "وضعیت‌ها، داروها و روتین را اضافه کنید تا پرستار آماده حاضر شود.",
"nudge_patient_cta": "مشاهدهٔ بیماران",
"nudge_profile_title": "تکمیل پروفایل",
"nudge_profile_body": "برای رزرو سریع‌تر، تماس اضطراری را اضافه کنید.",
"nudge_profile_cta": "رفتن به پروفایل"
},
"onboarding": {
"step_relation": "برای چه کسی",
"step_patient": "بیمار",
"relation_title": "برای چه کسی مراقبت می‌خواهید؟",
"relation_subtitle": "این کمک می‌کند مراقبت مناسب را پیشنهاد دهیم. بعداً می‌توانید افراد دیگری هم اضافه کنید.",
"relation_parent": "پدر/مادر",
"relation_spouse": "همسر",
"relation_child": "فرزند",
"relation_self": "خودم",
"patient_title": "ثبت بیمار",
"patient_subtitle": "فردی که مراقبت می‌شود — لزوماً صاحب حساب نیست.",
"name_label": "نام و نام خانوادگی",
"name_required": "نام بیمار را وارد کنید",
"age_label": "سن",
"age_invalid": "سن معتبر وارد کنید",
"gender_label": "جنسیت",
"gender_male": "مرد",
"gender_female": "زن",
"gender_required": "انتخاب جنسیت بیمار الزامی است",
"conditions_label": "وضعیت‌ها",
"conditions_hint": "اختیاری — موارد مرتبط را انتخاب کنید.",
"condition_elderly": "سالمند",
"condition_post_surgery": "پس از جراحی",
"condition_diabetes": "دیابت",
"condition_mobility": "کم‌تحرک",
"condition_dementia": "آلزایمر/دمانس",
"continue": "ادامه",
"save_continue": "ذخیره و ادامه",
"saved": "بیمار ثبت شد"
},
"patients": {
"title": "بیماران",
"subtitle": "کسانی که برایشان مراقبت می‌گیرید.",
"add": "افزودن بیمار",
"add_title": "افزودن بیمار",
"edit_title": "ویرایش بیمار",
"edit": "ویرایش",
"archive": "آرشیو",
"empty_title": "هنوز بیماری ثبت نشده",
"empty_body": "برای شروع، اولین بیمار را اضافه کنید.",
"archive_title": "آرشیو بیمار؟",
"archive_body": "این بیمار از فهرست شما حذف می‌شود اما سوابق رزروهای گذشته حفظ می‌ماند.",
"archive_confirm": "آرشیو",
"archived": "بیمار آرشیو شد",
"age_years": "{age} سال",
"conditions_none": "وضعیت خاصی ثبت نشده",
"unavailable": "این بیمار در دسترس شما نیست."
},
"profile": {
"title": "پروفایل",
"subtitle": "اطلاعات شما و تماس اضطراری.",
"first_name": "نام",
"last_name": "نام خانوادگی",
"language": "زبان ترجیحی",
"language_fa": "فارسی",
"language_en": "انگلیسی",
"emergency_section": "تماس اضطراری",
"emergency_hint": "شماره‌ای که در مواقع ضروری با آن تماس می‌گیریم.",
"emergency_name": "نام تماس اضطراری",
"emergency_phone": "شماره تماس اضطراری",
"emergency_phone_invalid": "شماره موبایل معتبر وارد کنید",
"save": "ذخیره",
"saved": "پروفایل ذخیره شد",
"completion_done": "پروفایل شما کامل است.",
"completion_todo": "برای رزرو سریع‌تر، پروفایل خود را کامل کنید."
},
"nurseProfile": {
"title": "پروفایل پرستار",
"subtitle": "چیزی که خانواده‌ها هنگام یافتن شما می‌بینند.",
"photo": "عکس پروفایل",
"photo_hint": "یک عکس واضح از چهره‌تان.",
"upload": "بارگذاری عکس",
"uploading": "در حال بارگذاری…",
"bio": "درباره من",
"bio_hint": "یک معرفی کوتاه — تجربه، تخصص، رویکرد.",
"years": "سابقه کار (سال)",
"years_invalid": "عددی بین ۰ تا ۸۰ وارد کنید",
"save": "ذخیره پروفایل",
"saved": "پروفایل ذخیره شد",
"unverified_title": "پروفایل شما هنوز فعال نیست",
"unverified_body": "برای نمایش به خانواده‌ها و دریافت رزرو، احراز هویت را تکمیل کنید.",
"unverified_cta": "تکمیل احراز هویت",
"deferred_services": "خدمات و قیمت‌های خود را در بخش «خدمات و قیمت‌ها» مدیریت کنید؛ روزهای کاری در مرحله بعد اضافه می‌شود."
},
"bank": {
"title": "حساب بانکی",
"subtitle": "مقصد واریز درآمد شما.",
"iban_label": "شماره شبا",
"iban_hint": "با IR شروع می‌شود و ۲۴ رقم دارد.",
"iban_invalid": "شماره شبا معتبر وارد کنید (IR و ۲۴ رقم)",
"holder_label": "نام صاحب حساب",
"holder_hint": "باید دقیقاً به نام خودتان باشد.",
"holder_required": "نام صاحب حساب را وارد کنید",
"submit": "ثبت حساب",
"submitting": "در حال ثبت…",
"added": "حساب ثبت شد — استعلام مالکیت آغاز شد",
"add_error": "ثبت این حساب ممکن نشد. شبا را بررسی کرده و دوباره تلاش کنید.",
"status_pending_chip": "در حال استعلام",
"status_pending_title": "در حال استعلام مالکیت حساب",
"status_pending_body": "استعلام شبا در حال انجام است؛ ممکن است چند لحظه طول بکشد.",
"status_verified_chip": "تاییدشد",
"status_verified_title": "حساب تایید شد",
"status_verified_body": "این حساب برای واریز درآمد شما آماده است.",
"status_mismatch_chip": "مغایرت مالکیت",
"status_mismatch_title": "حساب باید به نام خودتان باشد",
"status_mismatch_body": "نام صاحب این حساب با هویت شما مطابقت ندارد. لطفاً شبای حسابی به نام خودتان وارد کنید.",
"reenter": "ثبت حساب دیگر",
"make_primary": "انتخاب به‌عنوان حساب اصلی",
"primary_set": "حساب اصلی به‌روزرسانی شد",
"iban_masked_label": "شبا",
"primary": "حساب اصلی",
"empty_title": "هنوز حسابی ثبت نشده",
"empty_body": "برای دریافت درآمد، یک حساب بانکی به نام خودتان اضافه کنید."
},
"geo": {
"province": "استان",
"city": "شهر",
"district": "منطقه",
"whole_city": "کل شهر",
"city_needs_province": "ابتدا استان را انتخاب کنید",
"district_needs_city": "ابتدا شهر را انتخاب کنید",
"district_optional": "اختیاری",
"no_districts": "این شهر منطقه‌بندی ندارد — کل شهر"
},
"address": {
"title": "آدرس‌ها",
"subtitle": "جایی که پرستار به آن مراجعه می‌کند.",
"add": "افزودن آدرس",
"add_title": "افزودن آدرس",
"edit_title": "ویرایش آدرس",
"edit": "ویرایش",
"delete": "حذف",
"empty_title": "هنوز آدرسی ثبت نشده",
"empty_body": "اولین آدرس را اضافه کنید تا پرستار بداند کجا بیاید.",
"primary": "آدرس اصلی",
"set_primary": "انتخاب به‌عنوان آدرس اصلی",
"primary_set": "آدرس اصلی به‌روزرسانی شد",
"delete_title": "حذف آدرس؟",
"delete_body": "این آدرس از فهرست شما حذف می‌شود.",
"delete_confirm": "حذف",
"deleted": "آدرس حذف شد",
"saved": "آدرس ذخیره شد",
"save_error": "ذخیرهٔ این آدرس ممکن نشد. دوباره تلاش کنید.",
"unavailable": "این آدرس در دسترس شما نیست.",
"title_label": "عنوان آدرس",
"title_placeholder": "مثلاً خانه، محل کار",
"title_required": "برای این آدرس یک عنوان وارد کنید",
"line_label": "نشانی کامل",
"line_hint": "پلاک، خیابان، واحد — جزئیاتی که پرستار برای یافتن در نیاز دارد.",
"line_required": "نشانی کامل را وارد کنید",
"city_required": "شهر را انتخاب کنید",
"set_primary_toggle": "به‌عنوان آدرس اصلی تنظیم شود",
"map_hint": "برای تعیین محل دقیق بیمار، نشانگر را بکشید یا روی نقشه بزنید.",
"map_required": "روی نقشه یک پین بگذارید",
"map_lat": "عرض",
"map_lng": "طول",
"manage_title": "آدرس‌های شما",
"manage_body": "مکان‌هایی که پرستار به آن‌ها می‌رود را مدیریت کنید.",
"manage_cta": "مدیریت آدرس‌ها"
},
"coverage": {
"title": "مناطق تحت پوشش",
"subtitle": "شهرها و مناطقی که به آن‌ها می‌روید.",
"areas_heading": "مناطق شما",
"add_title": "افزودن منطقهٔ تحت پوشش",
"scope_label": "گستره",
"scope_whole_city": "کل شهر",
"scope_districts": "مناطق خاص",
"add": "افزودن منطقه",
"adding": "در حال افزودن…",
"whole_city_chip": "کل شهر",
"empty_title": "هنوز منطقه‌ای ثبت نشده",
"empty_warning": "تا زمانی که حداقل یک منطقهٔ تحت پوشش اضافه نکنید، در جست‌وجو نمایش داده نمی‌شوید.",
"duplicate": "این منطقه از قبل تحت پوشش شماست.",
"city_required": "شهر را انتخاب کنید",
"district_required": "یک منطقه انتخاب کنید یا به کل شهر تغییر دهید.",
"added": "منطقهٔ تحت پوشش اضافه شد",
"add_error": "افزودن این منطقه ممکن نشد. دوباره تلاش کنید.",
"remove_title": "حذف منطقهٔ تحت پوشش؟",
"remove_body": "دیگر برای ویزیت در این منطقه انتخاب نمی‌شوید.",
"remove_confirm": "حذف",
"removed": "منطقهٔ تحت پوشش حذف شد"
},
"catalog": {
"unit_per_hour": "ساعتی",
"unit_per_session": "هر جلسه",
"unit_per_half_day": "نیم‌روزی",
"unit_per_day": "روزانه",
"unit_per_24h": "شبانه‌روزی",
"count_per_hour": "ساعت",
"count_per_session": "جلسه",
"count_per_half_day": "نیم‌روز",
"count_per_day": "روز",
"count_per_24h": "شبانه‌روز",
"estimate_label": "برآورد کل",
"estimate_for": "برای {count} {unit}"
},
"services": {
"title": "خدمات و قیمت‌ها",
"subtitle": "خدماتی که ارائه می‌دهید و قیمت هرکدام.",
"add": "افزودن خدمت",
"empty_title": "هنوز خدمتی اضافه نکرده‌اید",
"empty_body": "برای دیده‌شدن و دریافت رزرو، حداقل یک خدمت فعال و دارای قیمت اضافه کنید.",
"active_chip": "فعال",
"inactive_chip": "غیرفعال",
"inactive_hint": "این خدمت غیرفعال است و قابل رزرو نیست.",
"edit": "ویرایش",
"deactivate": "غیرفعال‌سازی",
"activate": "فعال‌سازی دوباره",
"deactivate_title": "این خدمت غیرفعال شود؟",
"deactivate_body": "این خدمت قابل رزرو نخواهد بود و از نتایج جستجو حذف می‌شود. هر زمان می‌توانید دوباره فعالش کنید — هرگز حذف نمی‌شود.",
"deactivate_confirm": "غیرفعال کن",
"deactivated_toast": "خدمت غیرفعال شد",
"activated_toast": "خدمت دوباره فعال شد",
"toggle_error": "این عملیات انجام نشد. دوباره تلاش کنید.",
"builder_add_title": "افزودن خدمت جدید",
"builder_edit_title": "ویرایش خدمت",
"step_category": "دسته",
"step_options": "گزینه‌ها",
"step_price": "قیمت",
"category_title": "دستهٔ خدمت را انتخاب کنید",
"category_subtitle": "هر خدمت به یک دسته تعلق دارد.",
"categories_error": "دسته‌ها بارگذاری نشد. دوباره تلاش کنید.",
"category_locked": "دسته پس از ایجاد خدمت قابل تغییر نیست.",
"options_title": "گزینه‌های خدمت را مشخص کنید",
"options_subtitle": "برای هر مورد الزامی یک گزینه انتخاب کنید.",
"options_none": "این دسته گزینه‌ای برای تنظیم ندارد.",
"required_badge": "الزامی",
"optional_badge": "اختیاری",
"options_incomplete": "برای ادامه، همهٔ موارد الزامی را انتخاب کنید.",
"price_title": "قیمت و واحد را تعیین کنید",
"price_label": "قیمت (تومان)",
"price_hint": "قیمت را به تومان وارد کنید.",
"price_required": "قیمتی معتبر و بزرگ‌تر از صفر وارد کنید.",
"unit_label": "واحد قیمت",
"duration_label": "مدت / تعداد",
"duration_hint": "اختیاری — برای نمایش برآورد هزینهٔ کل، مدت را وارد کنید.",
"rate_note": "این نرخ پایه به ازای هر واحد است، نه هزینهٔ کل.",
"display_name_label": "نام نمایشی",
"display_name_hint": "به‌صورت خودکار از گزینه‌ها ساخته می‌شود؛ می‌توانید تغییرش دهید.",
"duplicate_warning": "شما قبلاً خدمتی با همین مشخصات دارید. یک گزینه یا دسته را تغییر دهید.",
"summary_options": "گزینه‌ها",
"summary_none": "بدون گزینه",
"next": "بعدی",
"submit_create": "ثبت خدمت",
"submit_save": "ذخیره تغییرات",
"create_error": "ثبت خدمت انجام نشد. ورودی‌ها را بررسی کرده و دوباره تلاش کنید.",
"created_toast": "خدمت اضافه شد",
"saved_toast": "تغییرات ذخیره شد"
},
"search": {
"title": "جستجو",
"deferred": "جستجو و نتایج در فاز بعدی اضافه می‌شود.",
"query_echo": "جستجوی شما: «{query}».",
"category_echo": "محدود به دستهٔ خدمت انتخاب‌شده."
},
"auth": {
"customer_title": "ورود به بلینیار",
"customer_subtitle": "با شماره موبایل خود وارد شوید",
"nurse_title": "ورود پرستاران",
"nurse_subtitle": "ویژه پرستاران دارای پروانه نظام پرستاری",
"phone_label": "شماره موبایل",
"phone_invalid": "شماره موبایل معتبر وارد کنید",
"request_code": "دریافت کد تایید",
"nurse_switch": "پرستار هستید؟ ورود پرستاران ←",
"customer_switch": "خانواده هستید؟ ورود خانواده‌ها ←",
"rate_limited": "به‌دلیل تلاش زیاد، کمی بعد دوباره تلاش کنید",
"otp_title": "کد تایید را وارد کنید",
"otp_sent_to": "کد به شماره {phone} ارسال شد",
"otp_verify_customer": "تایید و ادامه",
"otp_verify_nurse": "تایید و ورود",
"otp_invalid": "کد وارد شده نادرست یا منقضی شده است",
"otp_locked": "به‌دلیل تلاش‌های زیاد، ورود موقتاً قفل شد. کد جدید دریافت کنید.",
"resend_in": "ارسال مجدد کد تا {time}",
"resend": "ارسال مجدد کد",
"change_number": "تغییر شماره",
"routing_title": "در حال ورود…",
"select_role_title": "به بلینیار خوش آمدید",
"select_role_subtitle": "برای شروع، نقش خود را انتخاب کنید",
"role_customer": "خانواده",
"role_customer_desc": "برای رزرو پرستار و مراقبت در منزل",
"role_nurse": "پرستار",
"role_nurse_desc": "برای ارائه خدمات پرستاری",
"continue": "ادامه"
}
}