2026-09-22 19:00:34 +03:00
<? php
namespace Database\Seeders ;
use Illuminate\Database\Seeder ;
use Modules\Core\Localization\Services\TranslationService ;
use Spatie\TranslationLoader\LanguageLine ;
/**
* Default `validation` translation lines — Laravel's own error-message group
* (`validation.required`, `validation.email`, `validation.attributes.*`, …),
* resolved by every `Validator::make()`/`$request->validate()` call in the app
* (see CheckoutController::saveAddress(), CartController, ProductController),
* not just the checkout module.
*
* Spatie's DB loader (spatie/laravel-translation-loader, wired in boboko-core's
* LocalizationServiceProvider) merges this group over Laravel's file-based
* validation.php, which the project doesn't ship a `lang/` copy of — so without
* this, Greek requests fall back to Laravel's untranslated English defaults.
* Only the rule keys and field attributes actually in use are seeded; add more
* as new rules/fields show up.
*
* Additive and idempotent: a key that already exists is left untouched, so
* anything edited in the Filament Language Lines UI wins on a re-run. Runs
* explicitly — `php artisan db:seed --class=ValidationTranslationsSeeder` — it
* is not wired into DatabaseSeeder.
*
* Greek copy uses the project's informal register (εσύ/σου).
*/
class ValidationTranslationsSeeder extends Seeder
{
public function run () : void
{
$translations = app ( TranslationService :: class );
foreach ( $this -> lines () as $key => [ $en , $el ]) {
$exists = LanguageLine :: query ()
-> where ( 'group' , 'validation' )
-> where ( 'key' , $key )
-> exists ();
if ( $exists ) {
$this -> command ?-> warn ( "validation. { $key } already exists — skipped" );
continue ;
}
$translations -> create ( 'validation' , $key , [ 'en' => $en , 'el' => $el ]);
$this -> command ?-> info ( "validation. { $key } added" );
}
}
/**
* key => [English, Greek].
*
* @return array<string, array{0: string, 1: string}>
*/
private function lines () : array
{
return [
// ── Rule messages ─────────────────────────────────────────────
'required' => [ 'The :attribute field is required.' , 'Το πεδίο :attribute είναι υποχρεωτικό.' ],
'email' => [ 'The :attribute field must be a valid email address.' , 'Το πεδίο :attribute πρέπει να είναι έγκυρη διεύθυνση email.' ],
'string' => [ 'The :attribute field must be a string.' , 'Το πεδίο :attribute πρέπει να είναι κείμενο.' ],
'integer' => [ 'The :attribute field must be an integer.' , 'Το πεδίο :attribute πρέπει να είναι ακέραιος αριθμός.' ],
'boolean' => [ 'The :attribute field must be true or false.' , 'Το πεδίο :attribute πρέπει να είναι true ή false.' ],
'min.numeric' => [ 'The :attribute field must be at least :min.' , 'Το πεδίο :attribute πρέπει να είναι τουλάχιστον :min.' ],
'max.string' => [ 'The :attribute field must not be greater than :max characters.' , 'Το πεδίο :attribute δεν πρέπει να ξεπερνά τους :max χαρακτήρες.' ],
'between.numeric' => [ 'The :attribute field must be between :min and :max.' , 'Το πεδίο :attribute πρέπει να είναι μεταξύ :min και :max.' ],
'exists' => [ 'The selected :attribute is invalid.' , 'Η επιλεγμένη τιμή για το πεδίο :attribute δεν είναι έγκυρη.' ],
2026-09-23 17:53:23 +03:00
// Product custom-field photo uploads (CustomFieldUploadController, CartController).
'file' => [ 'The :attribute field must be a file.' , 'Το πεδίο :attribute πρέπει να είναι αρχείο.' ],
'mimes' => [ 'The :attribute field must be a file of type: :values.' , 'Το πεδίο :attribute πρέπει να είναι αρχείο τύπου: :values.' ],
'max.file' => [ 'The :attribute field must not be greater than :max kilobytes.' , 'Το αρχείο στο πεδίο :attribute δεν πρέπει να ξεπερνά τα :max kilobytes.' ],
'uploaded' => [ 'The :attribute failed to upload.' , 'Η μεταφόρτωση στο πεδίο :attribute απέτυχε.' ],
2026-09-22 19:00:34 +03:00
// ── Field names (checkout: billing/shipping address) ──────────
'attributes.contact_email' => [ 'email' , 'email' ],
'attributes.billing_first_name' => [ 'first name' , 'όνομα' ],
'attributes.billing_last_name' => [ 'last name' , 'επώνυμο' ],
'attributes.billing_company_name' => [ 'company name' , 'επωνυμία εταιρείας' ],
'attributes.billing_tax_identifier' => [ 'tax ID' , 'ΑΦΜ' ],
'attributes.billing_line_one' => [ 'address' , 'διεύθυνση' ],
'attributes.billing_line_two' => [ 'address line 2' , 'διεύθυνση (γραμμή 2)' ],
'attributes.billing_city' => [ 'city' , 'πόλη' ],
'attributes.billing_state' => [ 'region' , 'νομό / περιοχή' ],
'attributes.billing_postcode' => [ 'postcode' , 'ταχυδρομικό κώδικα' ],
'attributes.billing_country_id' => [ 'country' , 'χώρα' ],
'attributes.billing_contact_phone' => [ 'phone' , 'τηλέφωνο' ],
'attributes.shipping_first_name' => [ 'first name' , 'όνομα' ],
'attributes.shipping_last_name' => [ 'last name' , 'επώνυμο' ],
'attributes.shipping_company_name' => [ 'company name' , 'επωνυμία εταιρείας' ],
'attributes.shipping_line_one' => [ 'address' , 'διεύθυνση' ],
'attributes.shipping_line_two' => [ 'address line 2' , 'διεύθυνση (γραμμή 2)' ],
'attributes.shipping_city' => [ 'city' , 'πόλη' ],
'attributes.shipping_state' => [ 'region' , 'νομό / περιοχή' ],
'attributes.shipping_postcode' => [ 'postcode' , 'ταχυδρομικό κώδικα' ],
'attributes.shipping_country_id' => [ 'country' , 'χώρα' ],
'attributes.shipping_contact_phone' => [ 'phone' , 'τηλέφωνο' ],
'attributes.shipping_delivery_instructions' => [ 'delivery notes' , 'σχόλια για την παράδοση' ],
// ── Field names (cart) ─────────────────────────────────────────
'attributes.purchasable_id' => [ 'product' , 'προϊόν' ],
'attributes.quantity' => [ 'quantity' , 'ποσότητα' ],
'attributes.code' => [ 'coupon code' , 'κωδικό κουπονιού' ],
// ── Field names (product reviews / stock check) ────────────────
'attributes.variant' => [ 'variant' , 'παραλλαγή' ],
'attributes.rating' => [ 'rating' , 'βαθμολογία' ],
'attributes.content' => [ 'review text' , 'κείμενο κριτικής' ],
'attributes.name' => [ 'name' , 'όνομα' ],
'attributes.email' => [ 'email' , 'email' ],
];
}
}