feat: Persian panel/API fixes and structural-model tweaks

- lang/fa: add validation/auth/passwords/pagination translations so admin
  and API validation errors are in Persian
- templates: soft-delete instead of cascade-deleting their generations;
  keep resolving trashed template on generations (labels/downloads)
- templates: add TemplateInfolist with a real thumbnail ImageEntry
- generations: auto-name template-based generations and use that name
  for the download file and as a searchable column
- admin: show all dates as Jalali via ->jalaliDate()/->jalaliDateTime()
  Filament macros (App\Support\Jalali)
- wallets: harden the deposit/withdraw action to surface the exact error
  instead of a 500
- profile: normalize Iranian mobile numbers (App\Support\Mobile),
  add social_links, coerce notification-preference booleans, require the
  current password to delete an account

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013P66ea1dC5CVM9t29496t5
This commit is contained in:
2026-09-07 01:00:09 +03:30
parent 46ae711a20
commit 936f789ac8
38 changed files with 756 additions and 39 deletions

192
lang/fa/validation.php Normal file
View File

@@ -0,0 +1,192 @@
<?php
return [
'accepted' => 'فیلد :attribute باید پذیرفته شود.',
'accepted_if' => 'فیلد :attribute وقتی :other برابر :value است باید پذیرفته شود.',
'active_url' => 'فیلد :attribute باید یک نشانی اینترنتی معتبر باشد.',
'after' => 'فیلد :attribute باید تاریخی بعد از :date باشد.',
'after_or_equal' => 'فیلد :attribute باید تاریخی بعد یا برابر با :date باشد.',
'alpha' => 'فیلد :attribute باید فقط شامل حروف باشد.',
'alpha_dash' => 'فیلد :attribute باید فقط شامل حروف، اعداد، خط تیره و زیرخط باشد.',
'alpha_num' => 'فیلد :attribute باید فقط شامل حروف و اعداد باشد.',
'any_of' => 'فیلد :attribute نامعتبر است.',
'array' => 'فیلد :attribute باید آرایه باشد.',
'ascii' => 'فیلد :attribute باید فقط شامل حروف و نمادهای تک‌بایتی باشد.',
'before' => 'فیلد :attribute باید تاریخی قبل از :date باشد.',
'before_or_equal' => 'فیلد :attribute باید تاریخی قبل یا برابر با :date باشد.',
'between' => [
'array' => 'فیلد :attribute باید بین :min تا :max آیتم داشته باشد.',
'file' => 'حجم فیلد :attribute باید بین :min تا :max کیلوبایت باشد.',
'numeric' => 'فیلد :attribute باید بین :min تا :max باشد.',
'string' => 'فیلد :attribute باید بین :min تا :max کاراکتر باشد.',
],
'boolean' => 'فیلد :attribute باید بله یا خیر باشد.',
'can' => 'فیلد :attribute شامل مقدار غیرمجاز است.',
'confirmed' => 'تکرار فیلد :attribute مطابقت ندارد.',
'contains' => 'فیلد :attribute یک مقدار الزامی را ندارد.',
'current_password' => 'رمز عبور صحیح نیست.',
'date' => 'فیلد :attribute باید یک تاریخ معتبر باشد.',
'date_equals' => 'فیلد :attribute باید تاریخی برابر با :date باشد.',
'date_format' => 'فیلد :attribute باید با قالب :format مطابقت داشته باشد.',
'decimal' => 'فیلد :attribute باید :decimal رقم اعشار داشته باشد.',
'declined' => 'فیلد :attribute باید رد شود.',
'declined_if' => 'فیلد :attribute وقتی :other برابر :value است باید رد شود.',
'different' => 'فیلد :attribute و :other باید متفاوت باشند.',
'digits' => 'فیلد :attribute باید :digits رقم باشد.',
'digits_between' => 'فیلد :attribute باید بین :min تا :max رقم باشد.',
'dimensions' => 'ابعاد تصویر فیلد :attribute نامعتبر است.',
'distinct' => 'فیلد :attribute دارای مقدار تکراری است.',
'doesnt_contain' => 'فیلد :attribute نباید شامل موارد زیر باشد: :values.',
'doesnt_end_with' => 'فیلد :attribute نباید با یکی از موارد زیر تمام شود: :values.',
'doesnt_start_with' => 'فیلد :attribute نباید با یکی از موارد زیر شروع شود: :values.',
'email' => 'فیلد :attribute باید یک نشانی ایمیل معتبر باشد.',
'encoding' => 'فیلد :attribute باید با :encoding کدگذاری شده باشد.',
'ends_with' => 'فیلد :attribute باید با یکی از موارد زیر تمام شود: :values.',
'enum' => 'مقدار انتخاب‌شده برای :attribute نامعتبر است.',
'exists' => 'مقدار انتخاب‌شده برای :attribute نامعتبر است.',
'extensions' => 'فیلد :attribute باید یکی از پسوندهای زیر را داشته باشد: :values.',
'file' => 'فیلد :attribute باید یک فایل باشد.',
'filled' => 'فیلد :attribute باید مقدار داشته باشد.',
'gt' => [
'array' => 'فیلد :attribute باید بیش از :value آیتم داشته باشد.',
'file' => 'حجم فیلد :attribute باید بیشتر از :value کیلوبایت باشد.',
'numeric' => 'فیلد :attribute باید بزرگ‌تر از :value باشد.',
'string' => 'فیلد :attribute باید بیشتر از :value کاراکتر باشد.',
],
'gte' => [
'array' => 'فیلد :attribute باید :value آیتم یا بیشتر داشته باشد.',
'file' => 'حجم فیلد :attribute باید بزرگ‌تر یا مساوی :value کیلوبایت باشد.',
'numeric' => 'فیلد :attribute باید بزرگ‌تر یا مساوی :value باشد.',
'string' => 'فیلد :attribute باید بزرگ‌تر یا مساوی :value کاراکتر باشد.',
],
'hex_color' => 'فیلد :attribute باید یک رنگ هگزادسیمال معتبر باشد.',
'image' => 'فیلد :attribute باید یک تصویر باشد.',
'in' => 'مقدار انتخاب‌شده برای :attribute نامعتبر است.',
'in_array' => 'فیلد :attribute باید در :other وجود داشته باشد.',
'in_array_keys' => 'فیلد :attribute باید حداقل شامل یکی از کلیدهای زیر باشد: :values.',
'integer' => 'فیلد :attribute باید عدد صحیح باشد.',
'ip' => 'فیلد :attribute باید یک نشانی IP معتبر باشد.',
'ipv4' => 'فیلد :attribute باید یک نشانی IPv4 معتبر باشد.',
'ipv6' => 'فیلد :attribute باید یک نشانی IPv6 معتبر باشد.',
'json' => 'فیلد :attribute باید یک رشته JSON معتبر باشد.',
'list' => 'فیلد :attribute باید یک فهرست باشد.',
'lowercase' => 'فیلد :attribute باید با حروف کوچک باشد.',
'lt' => [
'array' => 'فیلد :attribute باید کمتر از :value آیتم داشته باشد.',
'file' => 'حجم فیلد :attribute باید کمتر از :value کیلوبایت باشد.',
'numeric' => 'فیلد :attribute باید کوچک‌تر از :value باشد.',
'string' => 'فیلد :attribute باید کمتر از :value کاراکتر باشد.',
],
'lte' => [
'array' => 'فیلد :attribute نباید بیش از :value آیتم داشته باشد.',
'file' => 'حجم فیلد :attribute باید کوچک‌تر یا مساوی :value کیلوبایت باشد.',
'numeric' => 'فیلد :attribute باید کوچک‌تر یا مساوی :value باشد.',
'string' => 'فیلد :attribute باید کوچک‌تر یا مساوی :value کاراکتر باشد.',
],
'mac_address' => 'فیلد :attribute باید یک نشانی MAC معتبر باشد.',
'max' => [
'array' => 'فیلد :attribute نباید بیش از :max آیتم داشته باشد.',
'file' => 'حجم فیلد :attribute نباید بیشتر از :max کیلوبایت باشد.',
'numeric' => 'فیلد :attribute نباید بزرگ‌تر از :max باشد.',
'string' => 'فیلد :attribute نباید بیشتر از :max کاراکتر باشد.',
],
'max_digits' => 'فیلد :attribute نباید بیش از :max رقم داشته باشد.',
'mimes' => 'فیلد :attribute باید فایلی از نوع: :values باشد.',
'mimetypes' => 'فیلد :attribute باید فایلی از نوع: :values باشد.',
'min' => [
'array' => 'فیلد :attribute باید حداقل :min آیتم داشته باشد.',
'file' => 'حجم فیلد :attribute باید حداقل :min کیلوبایت باشد.',
'numeric' => 'فیلد :attribute باید حداقل :min باشد.',
'string' => 'فیلد :attribute باید حداقل :min کاراکتر باشد.',
],
'min_digits' => 'فیلد :attribute باید حداقل :min رقم داشته باشد.',
'missing' => 'فیلد :attribute نباید وجود داشته باشد.',
'missing_if' => 'فیلد :attribute وقتی :other برابر :value است نباید وجود داشته باشد.',
'missing_unless' => 'فیلد :attribute مگر اینکه :other برابر :value باشد نباید وجود داشته باشد.',
'missing_with' => 'فیلد :attribute وقتی :values وجود دارد نباید وجود داشته باشد.',
'missing_with_all' => 'فیلد :attribute وقتی :values وجود دارند نباید وجود داشته باشد.',
'multiple_of' => 'فیلد :attribute باید مضربی از :value باشد.',
'not_in' => 'مقدار انتخاب‌شده برای :attribute نامعتبر است.',
'not_regex' => 'قالب فیلد :attribute نامعتبر است.',
'numeric' => 'فیلد :attribute باید عدد باشد.',
'password' => [
'letters' => 'فیلد :attribute باید حداقل شامل یک حرف باشد.',
'mixed' => 'فیلد :attribute باید حداقل شامل یک حرف بزرگ و یک حرف کوچک باشد.',
'numbers' => 'فیلد :attribute باید حداقل شامل یک عدد باشد.',
'symbols' => 'فیلد :attribute باید حداقل شامل یک نماد باشد.',
'uncompromised' => 'فیلد :attribute در نشت اطلاعات دیده شده است. لطفاً مقدار دیگری انتخاب کنید.',
],
'present' => 'فیلد :attribute باید موجود باشد.',
'present_if' => 'فیلد :attribute وقتی :other برابر :value است باید موجود باشد.',
'present_unless' => 'فیلد :attribute مگر اینکه :other برابر :value باشد باید موجود باشد.',
'present_with' => 'فیلد :attribute وقتی :values موجود است باید موجود باشد.',
'present_with_all' => 'فیلد :attribute وقتی :values موجود هستند باید موجود باشد.',
'prohibited' => 'فیلد :attribute ممنوع است.',
'prohibited_if' => 'فیلد :attribute وقتی :other برابر :value است ممنوع است.',
'prohibited_if_accepted' => 'فیلد :attribute وقتی :other پذیرفته شده است ممنوع است.',
'prohibited_if_declined' => 'فیلد :attribute وقتی :other رد شده است ممنوع است.',
'prohibited_unless' => 'فیلد :attribute مگر اینکه :other در :values باشد ممنوع است.',
'prohibits' => 'فیلد :attribute از موجود بودن :other جلوگیری می‌کند.',
'regex' => 'قالب فیلد :attribute نامعتبر است.',
'required' => 'فیلد :attribute الزامی است.',
'required_array_keys' => 'فیلد :attribute باید شامل مقادیری برای: :values باشد.',
'required_if' => 'فیلد :attribute وقتی :other برابر :value است الزامی است.',
'required_if_accepted' => 'فیلد :attribute وقتی :other پذیرفته شده است الزامی است.',
'required_if_declined' => 'فیلد :attribute وقتی :other رد شده است الزامی است.',
'required_unless' => 'فیلد :attribute مگر اینکه :other در :values باشد الزامی است.',
'required_with' => 'فیلد :attribute وقتی :values موجود است الزامی است.',
'required_with_all' => 'فیلد :attribute وقتی :values موجود هستند الزامی است.',
'required_without' => 'فیلد :attribute وقتی :values موجود نیست الزامی است.',
'required_without_all' => 'فیلد :attribute وقتی هیچ‌کدام از :values موجود نیستند الزامی است.',
'same' => 'فیلد :attribute باید با :other مطابقت داشته باشد.',
'size' => [
'array' => 'فیلد :attribute باید شامل :size آیتم باشد.',
'file' => 'حجم فیلد :attribute باید :size کیلوبایت باشد.',
'numeric' => 'فیلد :attribute باید برابر :size باشد.',
'string' => 'فیلد :attribute باید :size کاراکتر باشد.',
],
'starts_with' => 'فیلد :attribute باید با یکی از موارد زیر شروع شود: :values.',
'string' => 'فیلد :attribute باید رشته باشد.',
'timezone' => 'فیلد :attribute باید یک منطقه زمانی معتبر باشد.',
'unique' => 'فیلد :attribute قبلاً استفاده شده است.',
'uploaded' => 'بارگذاری فیلد :attribute ناموفق بود.',
'uppercase' => 'فیلد :attribute باید با حروف بزرگ باشد.',
'url' => 'فیلد :attribute باید یک نشانی اینترنتی معتبر باشد.',
'ulid' => 'فیلد :attribute باید یک ULID معتبر باشد.',
'uuid' => 'فیلد :attribute باید یک UUID معتبر باشد.',
'custom' => [
'mobile' => [
'regex' => 'فرمت شماره موبایل صحیح نیست. مثال درست: 09123456789',
],
],
'attributes' => [
'name' => 'نام',
'first_name' => 'نام',
'last_name' => 'نام خانوادگی',
'username' => 'نام کاربری',
'email' => 'ایمیل',
'mobile' => 'شماره موبایل',
'phone' => 'شماره تماس',
'password' => 'رمز عبور',
'password_confirmation' => 'تکرار رمز عبور',
'current_password' => 'رمز عبور فعلی',
'title' => 'عنوان',
'slug' => 'شناسه',
'description' => 'توضیحات',
'category_id' => 'دسته‌بندی',
'amount' => 'مبلغ',
'avatar' => 'تصویر پروفایل',
'is_public' => 'نمایش عمومی پروفایل',
'social_links' => 'شبکه‌های اجتماعی',
'language' => 'زبان',
'slide_count' => 'تعداد اسلایدها',
'text' => 'متن',
'roles' => 'نقش‌ها',
'file_path' => 'فایل پاورپوینت',
'thumbnail_path' => 'تصویر بندانگشتی',
],
];