diff --git a/lang/es/validation.php b/lang/es/validation.php new file mode 100644 index 0000000..03a0da3 --- /dev/null +++ b/lang/es/validation.php @@ -0,0 +1,173 @@ + 'El campo :attribute debe ser aceptado.', + 'accepted_if' => 'El campo :attribute debe ser aceptado cuando :other es :value.', + 'active_url' => 'El campo :attribute no es una URL válida.', + 'after' => 'El campo :attribute debe ser una fecha posterior a :date.', + 'after_or_equal' => 'El campo :attribute debe ser una fecha posterior o igual a :date.', + 'alpha' => 'El campo :attribute solo puede contener letras.', + 'alpha_dash' => 'El campo :attribute solo puede contener letras, números, guiones y guiones bajos.', + 'alpha_num' => 'El campo :attribute solo puede contener letras y números.', + 'array' => 'El campo :attribute debe ser un array.', + 'ascii' => 'El campo :attribute solo puede contener caracteres alfanuméricos de un byte y símbolos.', + 'before' => 'El campo :attribute debe ser una fecha anterior a :date.', + 'before_or_equal' => 'El campo :attribute debe ser una fecha anterior o igual a :date.', + 'between' => [ + 'array' => 'El campo :attribute debe tener entre :min y :max elementos.', + 'file' => 'El archivo :attribute debe pesar entre :min y :max kilobytes.', + 'numeric' => 'El campo :attribute debe estar entre :min y :max.', + 'string' => 'El campo :attribute debe tener entre :min y :max caracteres.', + ], + 'boolean' => 'El campo :attribute debe ser verdadero o falso.', + 'can' => 'El campo :attribute contiene un valor no autorizado.', + 'confirmed' => 'La confirmación de :attribute no coincide.', + 'current_password' => 'La contraseña es incorrecta.', + 'date' => 'El campo :attribute no es una fecha válida.', + 'date_equals' => 'El campo :attribute debe ser una fecha igual a :date.', + 'date_format' => 'El campo :attribute no corresponde con el formato :format.', + 'decimal' => 'El campo :attribute debe tener :decimal decimales.', + 'declined' => 'El campo :attribute debe ser rechazado.', + 'declined_if' => 'El campo :attribute debe ser rechazado cuando :other es :value.', + 'different' => 'El campo :attribute y :other deben ser diferentes.', + 'digits' => 'El campo :attribute debe tener :digits dígitos.', + 'digits_between' => 'El campo :attribute debe tener entre :min y :max dígitos.', + 'dimensions' => 'Las dimensiones de la imagen :attribute no son válidas.', + 'distinct' => 'El campo :attribute tiene un valor duplicado.', + 'doesnt_end_with' => 'El campo :attribute no debe terminar con uno de los siguientes valores: :values.', + 'doesnt_start_with' => 'El campo :attribute no debe comenzar con uno de los siguientes valores: :values.', + 'email' => 'El campo :attribute debe ser una dirección de correo válida.', + 'ends_with' => 'El campo :attribute debe terminar con uno de los siguientes valores: :values.', + 'enum' => 'El valor seleccionado para :attribute no es válido.', + 'exists' => 'El campo :attribute seleccionado no existe.', + 'extensions' => 'El campo :attribute debe tener una de las extensiones: :values.', + 'file' => 'El campo :attribute debe ser un archivo.', + 'filled' => 'El campo :attribute no puede estar vacío.', + 'gt' => [ + 'array' => 'El campo :attribute debe tener más de :value elementos.', + 'file' => 'El archivo :attribute debe ser mayor a :value kilobytes.', + 'numeric' => 'El campo :attribute debe ser mayor que :value.', + 'string' => 'El campo :attribute debe tener más de :value caracteres.', + ], + 'gte' => [ + 'array' => 'El campo :attribute debe tener :value elementos o más.', + 'file' => 'El archivo :attribute debe ser mayor o igual a :value kilobytes.', + 'numeric' => 'El campo :attribute debe ser mayor o igual que :value.', + 'string' => 'El campo :attribute debe tener :value caracteres o más.', + ], + 'hex_color' => 'El campo :attribute debe ser un color hexadecimal válido.', + 'image' => 'El campo :attribute debe ser una imagen.', + 'in' => 'El valor seleccionado para :attribute no es válido.', + 'in_array' => 'El campo :attribute no existe en :other.', + 'integer' => 'El campo :attribute debe ser un número entero.', + 'ip' => 'El campo :attribute debe ser una dirección IP válida.', + 'ipv4' => 'El campo :attribute debe ser una dirección IPv4 válida.', + 'ipv6' => 'El campo :attribute debe ser una dirección IPv6 válida.', + 'json' => 'El campo :attribute debe ser una cadena JSON válida.', + 'list' => 'El campo :attribute debe ser una lista.', + 'lowercase' => 'El campo :attribute debe estar en minúsculas.', + 'lt' => [ + 'array' => 'El campo :attribute debe tener menos de :value elementos.', + 'file' => 'El archivo :attribute debe ser menor a :value kilobytes.', + 'numeric' => 'El campo :attribute debe ser menor que :value.', + 'string' => 'El campo :attribute debe tener menos de :value caracteres.', + ], + 'lte' => [ + 'array' => 'El campo :attribute no debe tener más de :value elementos.', + 'file' => 'El archivo :attribute debe ser menor o igual a :value kilobytes.', + 'numeric' => 'El campo :attribute debe ser menor o igual que :value.', + 'string' => 'El campo :attribute debe tener :value caracteres o menos.', + ], + 'mac_address' => 'El campo :attribute debe ser una dirección MAC válida.', + 'max' => [ + 'array' => 'El campo :attribute no puede tener más de :max elementos.', + 'file' => 'El archivo :attribute no puede ser mayor a :max kilobytes.', + 'numeric' => 'El campo :attribute no puede ser mayor a :max.', + 'string' => 'El campo :attribute no puede tener más de :max caracteres.', + ], + 'max_digits' => 'El campo :attribute no puede tener más de :max dígitos.', + 'mimes' => 'El campo :attribute debe ser un archivo de tipo: :values.', + 'mimetypes' => 'El campo :attribute debe ser un archivo de tipo: :values.', + 'min' => [ + 'array' => 'El campo :attribute debe tener al menos :min elementos.', + 'file' => 'El archivo :attribute debe pesar al menos :min kilobytes.', + 'numeric' => 'El campo :attribute debe ser al menos :min.', + 'string' => 'El campo :attribute debe tener al menos :min caracteres.', + ], + 'min_digits' => 'El campo :attribute debe tener al menos :min dígitos.', + 'missing' => 'El campo :attribute debe estar ausente.', + 'missing_if' => 'El campo :attribute debe estar ausente cuando :other es :value.', + 'missing_unless' => 'El campo :attribute debe estar ausente a menos que :other sea :value.', + 'missing_with' => 'El campo :attribute debe estar ausente cuando :values está presente.', + 'missing_with_all' => 'El campo :attribute debe estar ausente cuando :values están presentes.', + 'multiple_of' => 'El campo :attribute debe ser un múltiplo de :value.', + 'not_in' => 'El valor seleccionado para :attribute no es válido.', + 'not_regex' => 'El formato del campo :attribute no es válido.', + 'numeric' => 'El campo :attribute debe ser un número.', + 'password' => [ + 'letters' => 'El campo :attribute debe contener al menos una letra.', + 'mixed' => 'El campo :attribute debe contener al menos una letra mayúscula y una minúscula.', + 'numbers' => 'El campo :attribute debe contener al menos un número.', + 'symbols' => 'El campo :attribute debe contener al menos un símbolo.', + 'uncompromised' => 'El :attribute dado ha aparecido en una filtración de datos. Por favor, elija un :attribute diferente.', + ], + 'present' => 'El campo :attribute debe estar presente.', + 'present_if' => 'El campo :attribute debe estar presente cuando :other es :value.', + 'present_unless' => 'El campo :attribute debe estar presente a menos que :other sea :value.', + 'present_with' => 'El campo :attribute debe estar presente cuando :values esté presente.', + 'present_with_all' => 'El campo :attribute debe estar presente cuando :values estén presentes.', + 'prohibited' => 'El campo :attribute está prohibido.', + 'prohibited_if' => 'El campo :attribute está prohibido cuando :other es :value.', + 'prohibited_unless' => 'El campo :attribute está prohibido a menos que :other esté en :values.', + 'prohibits' => 'El campo :attribute prohíbe que :other esté presente.', + 'regex' => 'El formato del campo :attribute no es válido.', + 'required' => 'El campo :attribute es obligatorio.', + 'required_array_keys' => 'El campo :attribute debe contener entradas para: :values.', + 'required_if' => 'El campo :attribute es obligatorio cuando :other es :value.', + 'required_if_accepted' => 'El campo :attribute es obligatorio cuando :other es aceptado.', + 'required_unless' => 'El campo :attribute es obligatorio a menos que :other esté en :values.', + 'required_with' => 'El campo :attribute es obligatorio cuando :values está presente.', + 'required_with_all' => 'El campo :attribute es obligatorio cuando :values están presentes.', + 'required_without' => 'El campo :attribute es obligatorio cuando :values no está presente.', + 'required_without_all' => 'El campo :attribute es obligatorio cuando ninguno de los valores :values está presente.', + 'same' => 'El campo :attribute y :other deben coincidir.', + 'size' => [ + 'array' => 'El campo :attribute debe contener :size elementos.', + 'file' => 'El archivo :attribute debe pesar :size kilobytes.', + 'numeric' => 'El campo :attribute debe ser :size.', + 'string' => 'El campo :attribute debe tener :size caracteres.', + ], + 'starts_with' => 'El campo :attribute debe comenzar con uno de los siguientes valores: :values.', + 'string' => 'El campo :attribute debe ser una cadena de texto.', + 'timezone' => 'El campo :attribute debe ser una zona horaria válida.', + 'unique' => 'El valor del campo :attribute ya está en uso.', + 'uploaded' => 'El archivo :attribute no pudo ser subido.', + 'uppercase' => 'El campo :attribute debe estar en mayúsculas.', + 'url' => 'El campo :attribute debe ser una URL válida.', + 'ulid' => 'El campo :attribute debe ser un ULID válido.', + 'uuid' => 'El campo :attribute debe ser un UUID válido.', + + 'attributes' => [ + 'nombre' => 'nombre', + 'imagen' => 'imagen', + 'url' => 'URL', + 'activo' => 'estado activo', + 'orden' => 'orden', + 'titulo' => 'título', + 'subtitulo' => 'subtítulo', + 'boton_texto' => 'texto del botón', + 'boton_enlace' => 'enlace del botón', + 'email' => 'correo electrónico', + 'password' => 'contraseña', + 'nombre_evento' => 'nombre del evento', + 'fecha_evento' => 'fecha del evento', + 'hora_inicio' => 'hora de inicio', + 'hora_fin' => 'hora de fin', + 'sede' => 'sede', + 'documento' => 'documento', + 'apellido' => 'apellido', + 'fecha_nacimiento' => 'fecha de nacimiento', + ], + +]; diff --git a/lang/vendor/backup/ar/notifications.php b/lang/vendor/backup/ar/notifications.php new file mode 100644 index 0000000..48bc709 --- /dev/null +++ b/lang/vendor/backup/ar/notifications.php @@ -0,0 +1,45 @@ + 'رسالة استثناء: :message', + 'exception_trace' => 'تتبع الإستثناء: :trace', + 'exception_message_title' => 'رسالة استثناء', + 'exception_trace_title' => 'تتبع الإستثناء', + + 'backup_failed_subject' => 'أخفق النسخ الاحتياطي لل :application_name', + 'backup_failed_body' => 'مهم: حدث خطأ أثناء النسخ الاحتياطي :application_name', + + 'backup_successful_subject' => 'نسخ احتياطي جديد ناجح ل :application_name', + 'backup_successful_subject_title' => 'نجاح النسخ الاحتياطي الجديد!', + 'backup_successful_body' => 'أخبار عظيمة، نسخة احتياطية جديدة ل :application_name تم إنشاؤها بنجاح على القرص المسمى :disk_name.', + + 'cleanup_failed_subject' => 'فشل تنظيف النسخ الاحتياطي للتطبيق :application_name .', + 'cleanup_failed_body' => 'حدث خطأ أثناء تنظيف النسخ الاحتياطية ل :application_name', + + 'cleanup_successful_subject' => 'تنظيف النسخ الاحتياطية ل :application_name تمت بنجاح', + 'cleanup_successful_subject_title' => 'تنظيف النسخ الاحتياطية تم بنجاح!', + 'cleanup_successful_body' => 'تنظيف النسخ الاحتياطية ل :application_name على القرص المسمى :disk_name تم بنجاح.', + + 'healthy_backup_found_subject' => 'النسخ الاحتياطية ل :application_name على القرص :disk_name صحية', + 'healthy_backup_found_subject_title' => 'النسخ الاحتياطية ل :application_name صحية', + 'healthy_backup_found_body' => 'تعتبر النسخ الاحتياطية ل :application_name صحية. عمل جيد!', + + 'unhealthy_backup_found_subject' => 'مهم: النسخ الاحتياطية ل :application_name غير صحية', + 'unhealthy_backup_found_subject_title' => 'مهم: النسخ الاحتياطية ل :application_name غير صحية. :problem', + 'unhealthy_backup_found_body' => 'النسخ الاحتياطية ل :application_name على القرص :disk_name غير صحية.', + 'unhealthy_backup_found_not_reachable' => 'لا يمكن الوصول إلى وجهة النسخ الاحتياطي. :error', + 'unhealthy_backup_found_empty' => 'لا توجد نسخ احتياطية لهذا التطبيق على الإطلاق.', + 'unhealthy_backup_found_old' => 'تم إنشاء أحدث النسخ الاحتياطية في :date وتعتبر قديمة جدا.', + 'unhealthy_backup_found_unknown' => 'عذرا، لا يمكن تحديد سبب دقيق.', + 'unhealthy_backup_found_full' => 'النسخ الاحتياطية تستخدم الكثير من التخزين. الاستخدام الحالي هو :disk_usage وهو أعلى من الحد المسموح به من :disk_limit.', + + 'no_backups_info' => 'لم يتم عمل نسخ احتياطية حتى الآن', + 'application_name' => 'اسم التطبيق', + 'backup_name' => 'اسم النسخ الاحتياطي', + 'disk' => 'القرص', + 'newest_backup_size' => 'أحدث حجم للنسخ الاحتياطي', + 'number_of_backups' => 'عدد النسخ الاحتياطية', + 'total_storage_used' => 'إجمالي مساحة التخزين المستخدمة', + 'newest_backup_date' => 'أحدث تاريخ النسخ الاحتياطي', + 'oldest_backup_date' => 'أقدم تاريخ نسخ احتياطي', +]; diff --git a/lang/vendor/backup/bg/notifications.php b/lang/vendor/backup/bg/notifications.php new file mode 100644 index 0000000..7c87d5b --- /dev/null +++ b/lang/vendor/backup/bg/notifications.php @@ -0,0 +1,45 @@ + 'Съобщение за изключение: :message', + 'exception_trace' => 'Проследяване на изключение: :trace', + 'exception_message_title' => 'Съобщение за изключение', + 'exception_trace_title' => 'Проследяване на изключение', + + 'backup_failed_subject' => 'Неуспешно резервно копие на :application_name', + 'backup_failed_body' => 'Важно: Възникна грешка при архивиране на :application_name', + + 'backup_successful_subject' => 'Успешно ново резервно копие на :application_name', + 'backup_successful_subject_title' => 'Успешно ново резервно копие!', + 'backup_successful_body' => 'Чудесни новини, ново резервно копие на :application_name беше успешно създадено на диска с име :disk_name.', + + 'cleanup_failed_subject' => 'Почистването на резервните копия на :application_name не бе успешно.', + 'cleanup_failed_body' => 'Възникна грешка при почистването на резервните копия на :application_name', + + 'cleanup_successful_subject' => 'Почистването на архивите на :application_name е успешно', + 'cleanup_successful_subject_title' => 'Почистването на резервните копия е успешно!', + 'cleanup_successful_body' => 'Почистването на резервни копия на :application_name на диска с име :disk_name беше успешно.', + + 'healthy_backup_found_subject' => 'Резервните копия за :application_name на диск :disk_name са здрави', + 'healthy_backup_found_subject_title' => 'Резервните копия за :application_name са здрави', + 'healthy_backup_found_body' => 'Резервните копия за :application_name се считат за здрави. Добра работа!', + + 'unhealthy_backup_found_subject' => 'Важно: Резервните копия за :application_name не са здрави', + 'unhealthy_backup_found_subject_title' => 'Важно: Резервните копия за :application_name не са здрави. :проблем', + 'unhealthy_backup_found_body' => 'Резервните копия за :application_name на диск :disk_name не са здрави.', + 'unhealthy_backup_found_not_reachable' => 'Дестинацията за резервни копия не може да бъде достигната. :грешка', + 'unhealthy_backup_found_empty' => 'Изобщо няма резервни копия на това приложение.', + 'unhealthy_backup_found_old' => 'Последното резервно копие, направено на :date, се счита за твърде старо.', + 'unhealthy_backup_found_unknown' => 'За съжаление не може да се определи точна причина.', + 'unhealthy_backup_found_full' => 'Резервните копия използват твърде много място за съхранение. Текущото използване е :disk_usage, което е по-високо от разрешеното ограничение на :disk_limit.', + + 'no_backups_info' => 'Все още не са правени резервни копия', + 'application_name' => 'Име на приложението', + 'backup_name' => 'Име на резервно копие', + 'disk' => 'Диск', + 'newest_backup_size' => 'Най-новият размер на резервно копие', + 'number_of_backups' => 'Брой резервни копия', + 'total_storage_used' => 'Общо използвано дисково пространство', + 'newest_backup_date' => 'Най-нова дата на резервно копие', + 'oldest_backup_date' => 'Най-старата дата на резервно копие', +]; diff --git a/lang/vendor/backup/bn/notifications.php b/lang/vendor/backup/bn/notifications.php new file mode 100644 index 0000000..bd0bf81 --- /dev/null +++ b/lang/vendor/backup/bn/notifications.php @@ -0,0 +1,45 @@ + 'এক্সসেপশন বার্তা: :message', + 'exception_trace' => 'এক্সসেপশন ট্রেস: :trace', + 'exception_message_title' => 'এক্সসেপশন message', + 'exception_trace_title' => 'এক্সসেপশন ট্রেস', + + 'backup_failed_subject' => ':application_name এর ব্যাকআপ ব্যর্থ হয়েছে।', + 'backup_failed_body' => 'গুরুত্বপূর্ণঃ :application_name ব্যাক আপ করার সময় একটি ত্রুটি ঘটেছে।', + + 'backup_successful_subject' => ':application_name এর নতুন ব্যাকআপ সফল হয়েছে।', + 'backup_successful_subject_title' => 'নতুন ব্যাকআপ সফল হয়েছে!', + 'backup_successful_body' => 'খুশির খবর, :application_name এর নতুন ব্যাকআপ :disk_name ডিস্কে সফলভাবে তৈরি হয়েছে।', + + 'cleanup_failed_subject' => ':application_name ব্যাকআপগুলি সাফ করতে ব্যর্থ হয়েছে।', + 'cleanup_failed_body' => ':application_name ব্যাকআপগুলি সাফ করার সময় একটি ত্রুটি ঘটেছে।', + + 'cleanup_successful_subject' => ':application_name এর ব্যাকআপগুলি সফলভাবে সাফ করা হয়েছে।', + 'cleanup_successful_subject_title' => 'ব্যাকআপগুলি সফলভাবে সাফ করা হয়েছে!', + 'cleanup_successful_body' => ':application_name এর ব্যাকআপগুলি :disk_name ডিস্ক থেকে সফলভাবে সাফ করা হয়েছে।', + + 'healthy_backup_found_subject' => ':application_name এর ব্যাকআপগুলি :disk_name ডিস্কে স্বাস্থ্যকর অবস্থায় আছে।', + 'healthy_backup_found_subject_title' => ':application_name এর ব্যাকআপগুলি স্বাস্থ্যকর অবস্থায় আছে।', + 'healthy_backup_found_body' => ':application_name এর ব্যাকআপগুলি স্বাস্থ্যকর বিবেচনা করা হচ্ছে। Good job!', + + 'unhealthy_backup_found_subject' => 'গুরুত্বপূর্ণঃ :application_name এর ব্যাকআপগুলি অস্বাস্থ্যকর অবস্থায় আছে।', + 'unhealthy_backup_found_subject_title' => 'গুরুত্বপূর্ণঃ :application_name এর ব্যাকআপগুলি অস্বাস্থ্যকর অবস্থায় আছে। :problem', + 'unhealthy_backup_found_body' => ':disk_name ডিস্কের :application_name এর ব্যাকআপগুলি অস্বাস্থ্যকর অবস্থায় আছে।', + 'unhealthy_backup_found_not_reachable' => 'ব্যাকআপ গন্তব্যে পৌঁছানো যায় নি। :error', + 'unhealthy_backup_found_empty' => 'এই অ্যাপ্লিকেশনটির কোনও ব্যাকআপ নেই।', + 'unhealthy_backup_found_old' => 'সর্বশেষ ব্যাকআপ যেটি :date এই তারিখে করা হয়েছে, সেটি খুব পুরানো।', + 'unhealthy_backup_found_unknown' => 'দুঃখিত, সঠিক কারণ নির্ধারণ করা সম্ভব হয়নি।', + 'unhealthy_backup_found_full' => 'ব্যাকআপগুলি অতিরিক্ত স্টোরেজ ব্যবহার করছে। বর্তমান ব্যবহারের পরিমান :disk_usage যা অনুমোদিত সীমা :disk_limit এর বেশি।', + + 'no_backups_info' => 'কোনো ব্যাকআপ এখনও তৈরি হয়নি', + 'application_name' => 'আবেদনের নাম', + 'backup_name' => 'ব্যাকআপের নাম', + 'disk' => 'ডিস্ক', + 'newest_backup_size' => 'নতুন ব্যাকআপ আকার', + 'number_of_backups' => 'ব্যাকআপের সংখ্যা', + 'total_storage_used' => 'ব্যবহৃত মোট সঞ্চয়স্থান', + 'newest_backup_date' => 'নতুন ব্যাকআপের তারিখ', + 'oldest_backup_date' => 'পুরানো ব্যাকআপের তারিখ', +]; diff --git a/lang/vendor/backup/cs/notifications.php b/lang/vendor/backup/cs/notifications.php new file mode 100644 index 0000000..9a145d9 --- /dev/null +++ b/lang/vendor/backup/cs/notifications.php @@ -0,0 +1,45 @@ + 'Zpráva výjimky: :message', + 'exception_trace' => 'Stopa výjimky: :trace', + 'exception_message_title' => 'Zpráva výjimky', + 'exception_trace_title' => 'Stopa výjimky', + + 'backup_failed_subject' => 'Záloha :application_name neuspěla', + 'backup_failed_body' => 'Důležité: Při záloze :application_name se vyskytla chyba', + + 'backup_successful_subject' => 'Úspěšná nová záloha :application_name', + 'backup_successful_subject_title' => 'Úspěšná nová záloha!', + 'backup_successful_body' => 'Dobrá zpráva, na disku jménem :disk_name byla úspěšně vytvořena nová záloha :application_name.', + + 'cleanup_failed_subject' => 'Vyčištění záloh :application_name neuspělo.', + 'cleanup_failed_body' => 'Při čištění záloh :application_name se vyskytla chyba', + + 'cleanup_successful_subject' => 'Vyčištění záloh :application_name úspěšné', + 'cleanup_successful_subject_title' => 'Vyčištění záloh bylo úspěšné!', + 'cleanup_successful_body' => 'Vyčištění záloh :application_name na disku jménem :disk_name bylo úspěšné.', + + 'healthy_backup_found_subject' => 'Zálohy pro :application_name na disku :disk_name jsou zdravé', + 'healthy_backup_found_subject_title' => 'Zálohy pro :application_name jsou zdravé', + 'healthy_backup_found_body' => 'Zálohy pro :application_name jsou považovány za zdravé. Dobrá práce!', + + 'unhealthy_backup_found_subject' => 'Důležité: Zálohy pro :application_name jsou nezdravé', + 'unhealthy_backup_found_subject_title' => 'Důležité: Zálohy pro :application_name jsou nezdravé. :problem', + 'unhealthy_backup_found_body' => 'Zálohy pro :application_name na disku :disk_name jsou nezdravé.', + 'unhealthy_backup_found_not_reachable' => 'Nelze se dostat k cíli zálohy. :error', + 'unhealthy_backup_found_empty' => 'Tato aplikace nemá vůbec žádné zálohy.', + 'unhealthy_backup_found_old' => 'Poslední záloha vytvořená dne :date je považována za příliš starou.', + 'unhealthy_backup_found_unknown' => 'Omlouváme se, nemůžeme určit přesný důvod.', + 'unhealthy_backup_found_full' => 'Zálohy zabírají příliš mnoho místa na disku. Aktuální využití disku je :disk_usage, což je vyšší než povolený limit :disk_limit.', + + 'no_backups_info' => 'Zatím nebyly vytvořeny žádné zálohy', + 'application_name' => 'Název aplikace', + 'backup_name' => 'Název zálohy', + 'disk' => 'Disk', + 'newest_backup_size' => 'Velikost nejnovější zálohy', + 'number_of_backups' => 'Počet záloh', + 'total_storage_used' => 'Celková využitá kapacita úložiště', + 'newest_backup_date' => 'Datum nejnovější zálohy', + 'oldest_backup_date' => 'Datum nejstarší zálohy', +]; diff --git a/lang/vendor/backup/da/notifications.php b/lang/vendor/backup/da/notifications.php new file mode 100644 index 0000000..80b4697 --- /dev/null +++ b/lang/vendor/backup/da/notifications.php @@ -0,0 +1,45 @@ + 'Fejlbesked: :message', + 'exception_trace' => 'Fejl trace: :trace', + 'exception_message_title' => 'Fejlbesked', + 'exception_trace_title' => 'Fejl trace', + + 'backup_failed_subject' => 'Backup af :application_name fejlede', + 'backup_failed_body' => 'Vigtigt: Der skete en fejl under backup af :application_name', + + 'backup_successful_subject' => 'Ny backup af :application_name oprettet', + 'backup_successful_subject_title' => 'Ny backup!', + 'backup_successful_body' => 'Gode nyheder - der blev oprettet en ny backup af :application_name på disken :disk_name.', + + 'cleanup_failed_subject' => 'Oprydning af backups for :application_name fejlede.', + 'cleanup_failed_body' => 'Der skete en fejl under oprydning af backups for :application_name', + + 'cleanup_successful_subject' => 'Oprydning af backups for :application_name gennemført', + 'cleanup_successful_subject_title' => 'Backup oprydning gennemført!', + 'cleanup_successful_body' => 'Oprydningen af backups for :application_name på disken :disk_name er gennemført.', + + 'healthy_backup_found_subject' => 'Alle backups for :application_name på disken :disk_name er OK', + 'healthy_backup_found_subject_title' => 'Alle backups for :application_name er OK', + 'healthy_backup_found_body' => 'Alle backups for :application_name er ok. Godt gået!', + + 'unhealthy_backup_found_subject' => 'Vigtigt: Backups for :application_name fejlbehæftede', + 'unhealthy_backup_found_subject_title' => 'Vigtigt: Backups for :application_name er fejlbehæftede. :problem', + 'unhealthy_backup_found_body' => 'Backups for :application_name på disken :disk_name er fejlbehæftede.', + 'unhealthy_backup_found_not_reachable' => 'Backup destinationen kunne ikke findes. :error', + 'unhealthy_backup_found_empty' => 'Denne applikation har ingen backups overhovedet.', + 'unhealthy_backup_found_old' => 'Den seneste backup fra :date er for gammel.', + 'unhealthy_backup_found_unknown' => 'Beklager, en præcis årsag kunne ikke findes.', + 'unhealthy_backup_found_full' => 'Backups bruger for meget plads. Nuværende disk forbrug er :disk_usage, hvilket er mere end den tilladte grænse på :disk_limit.', + + 'no_backups_info' => 'Der blev ikke foretaget nogen sikkerhedskopier endnu', + 'application_name' => 'Applikationens navn', + 'backup_name' => 'Backup navn', + 'disk' => 'Disk', + 'newest_backup_size' => 'Nyeste backup-størrelse', + 'number_of_backups' => 'Antal sikkerhedskopier', + 'total_storage_used' => 'Samlet lagerplads brugt', + 'newest_backup_date' => 'Nyeste backup-størrelse', + 'oldest_backup_date' => 'Ældste backup-størrelse', +]; diff --git a/lang/vendor/backup/de/notifications.php b/lang/vendor/backup/de/notifications.php new file mode 100644 index 0000000..acce789 --- /dev/null +++ b/lang/vendor/backup/de/notifications.php @@ -0,0 +1,45 @@ + 'Fehlermeldung: :message', + 'exception_trace' => 'Fehlerverfolgung: :trace', + 'exception_message_title' => 'Fehlermeldung', + 'exception_trace_title' => 'Fehlerverfolgung', + + 'backup_failed_subject' => 'Backup von :application_name konnte nicht erstellt werden', + 'backup_failed_body' => 'Wichtig: Beim Backup von :application_name ist ein Fehler aufgetreten', + + 'backup_successful_subject' => 'Erfolgreiches neues Backup von :application_name', + 'backup_successful_subject_title' => 'Erfolgreiches neues Backup!', + 'backup_successful_body' => 'Gute Nachrichten, ein neues Backup von :application_name wurde erfolgreich erstellt und in :disk_name gepeichert.', + + 'cleanup_failed_subject' => 'Aufräumen der Backups von :application_name schlug fehl.', + 'cleanup_failed_body' => 'Beim aufräumen der Backups von :application_name ist ein Fehler aufgetreten', + + 'cleanup_successful_subject' => 'Aufräumen der Backups von :application_name backups erfolgreich', + 'cleanup_successful_subject_title' => 'Aufräumen der Backups erfolgreich!', + 'cleanup_successful_body' => 'Aufräumen der Backups von :application_name in :disk_name war erfolgreich.', + + 'healthy_backup_found_subject' => 'Die Backups von :application_name in :disk_name sind gesund', + 'healthy_backup_found_subject_title' => 'Die Backups von :application_name sind Gesund', + 'healthy_backup_found_body' => 'Die Backups von :application_name wurden als gesund eingestuft. Gute Arbeit!', + + 'unhealthy_backup_found_subject' => 'Wichtig: Die Backups für :application_name sind nicht gesund', + 'unhealthy_backup_found_subject_title' => 'Wichtig: Die Backups für :application_name sind ungesund. :problem', + 'unhealthy_backup_found_body' => 'Die Backups für :application_name in :disk_name sind ungesund.', + 'unhealthy_backup_found_not_reachable' => 'Das Backup Ziel konnte nicht erreicht werden. :error', + 'unhealthy_backup_found_empty' => 'Es gibt für die Anwendung noch gar keine Backups.', + 'unhealthy_backup_found_old' => 'Das letzte Backup am :date ist zu lange her.', + 'unhealthy_backup_found_unknown' => 'Sorry, ein genauer Grund konnte nicht gefunden werden.', + 'unhealthy_backup_found_full' => 'Die Backups verbrauchen zu viel Platz. Aktuell wird :disk_usage belegt, dass ist höher als das erlaubte Limit von :disk_limit.', + + 'no_backups_info' => 'Bisher keine Backups vorhanden', + 'application_name' => 'Applikationsname', + 'backup_name' => 'Backup Name', + 'disk' => 'Speicherort', + 'newest_backup_size' => 'Neuste Backup-Größe', + 'number_of_backups' => 'Anzahl Backups', + 'total_storage_used' => 'Gesamter genutzter Speicherplatz', + 'newest_backup_date' => 'Neustes Backup', + 'oldest_backup_date' => 'Ältestes Backup', +]; diff --git a/lang/vendor/backup/en/notifications.php b/lang/vendor/backup/en/notifications.php new file mode 100644 index 0000000..73811bd --- /dev/null +++ b/lang/vendor/backup/en/notifications.php @@ -0,0 +1,45 @@ + 'Exception message: :message', + 'exception_trace' => 'Exception trace: :trace', + 'exception_message_title' => 'Exception message', + 'exception_trace_title' => 'Exception trace', + + 'backup_failed_subject' => 'Failed backup of :application_name', + 'backup_failed_body' => 'Important: An error occurred while backing up :application_name', + + 'backup_successful_subject' => 'Successful new backup of :application_name', + 'backup_successful_subject_title' => 'Successful new backup!', + 'backup_successful_body' => 'Great news, a new backup of :application_name was successfully created on the disk named :disk_name.', + + 'cleanup_failed_subject' => 'Cleaning up the backups of :application_name failed.', + 'cleanup_failed_body' => 'An error occurred while cleaning up the backups of :application_name', + + 'cleanup_successful_subject' => 'Clean up of :application_name backups successful', + 'cleanup_successful_subject_title' => 'Clean up of backups successful!', + 'cleanup_successful_body' => 'The clean up of the :application_name backups on the disk named :disk_name was successful.', + + 'healthy_backup_found_subject' => 'The backups for :application_name on disk :disk_name are healthy', + 'healthy_backup_found_subject_title' => 'The backups for :application_name are healthy', + 'healthy_backup_found_body' => 'The backups for :application_name are considered healthy. Good job!', + + 'unhealthy_backup_found_subject' => 'Important: The backups for :application_name are unhealthy', + 'unhealthy_backup_found_subject_title' => 'Important: The backups for :application_name are unhealthy. :problem', + 'unhealthy_backup_found_body' => 'The backups for :application_name on disk :disk_name are unhealthy.', + 'unhealthy_backup_found_not_reachable' => 'The backup destination cannot be reached. :error', + 'unhealthy_backup_found_empty' => 'There are no backups of this application at all.', + 'unhealthy_backup_found_old' => 'The latest backup made on :date is considered too old.', + 'unhealthy_backup_found_unknown' => 'Sorry, an exact reason cannot be determined.', + 'unhealthy_backup_found_full' => 'The backups are using too much storage. Current usage is :disk_usage which is higher than the allowed limit of :disk_limit.', + + 'no_backups_info' => 'No backups were made yet', + 'application_name' => 'Application name', + 'backup_name' => 'Backup name', + 'disk' => 'Disk', + 'newest_backup_size' => 'Newest backup size', + 'number_of_backups' => 'Number of backups', + 'total_storage_used' => 'Total storage used', + 'newest_backup_date' => 'Newest backup date', + 'oldest_backup_date' => 'Oldest backup date', +]; diff --git a/lang/vendor/backup/es/notifications.php b/lang/vendor/backup/es/notifications.php new file mode 100644 index 0000000..d2071b8 --- /dev/null +++ b/lang/vendor/backup/es/notifications.php @@ -0,0 +1,45 @@ + 'Mensaje de la excepción: :message', + 'exception_trace' => 'Traza de la excepción: :trace', + 'exception_message_title' => 'Mensaje de la excepción', + 'exception_trace_title' => 'Traza de la excepción', + + 'backup_failed_subject' => 'Copia de seguridad de :application_name fallida', + 'backup_failed_body' => 'Importante: Ocurrió un error al realizar la copia de seguridad de :application_name', + + 'backup_successful_subject' => 'Se completó con éxito la copia de seguridad de :application_name', + 'backup_successful_subject_title' => '¡Nueva copia de seguridad creada con éxito!', + 'backup_successful_body' => 'Buenas noticias, una nueva copia de seguridad de :application_name fue creada con éxito en el disco llamado :disk_name.', + + 'cleanup_failed_subject' => 'La limpieza de copias de seguridad de :application_name falló.', + 'cleanup_failed_body' => 'Ocurrió un error mientras se realizaba la limpieza de copias de seguridad de :application_name', + + 'cleanup_successful_subject' => 'La limpieza de copias de seguridad de :application_name se completó con éxito', + 'cleanup_successful_subject_title' => '!Limpieza de copias de seguridad completada con éxito!', + 'cleanup_successful_body' => 'La limpieza de copias de seguridad de :application_name en el disco llamado :disk_name se completo con éxito.', + + 'healthy_backup_found_subject' => 'Las copias de seguridad de :application_name en el disco :disk_name están en buen estado', + 'healthy_backup_found_subject_title' => 'Las copias de seguridad de :application_name están en buen estado', + 'healthy_backup_found_body' => 'Las copias de seguridad de :application_name se consideran en buen estado. ¡Buen trabajo!', + + 'unhealthy_backup_found_subject' => 'Importante: Las copias de seguridad de :application_name están en mal estado', + 'unhealthy_backup_found_subject_title' => 'Importante: Las copias de seguridad de :application_name están en mal estado. :problem', + 'unhealthy_backup_found_body' => 'Las copias de seguridad de :application_name en el disco :disk_name están en mal estado.', + 'unhealthy_backup_found_not_reachable' => 'No se puede acceder al destino de la copia de seguridad. :error', + 'unhealthy_backup_found_empty' => 'No existe ninguna copia de seguridad de esta aplicación.', + 'unhealthy_backup_found_old' => 'La última copia de seguriad hecha en :date es demasiado antigua.', + 'unhealthy_backup_found_unknown' => 'Lo siento, no es posible determinar la razón exacta.', + 'unhealthy_backup_found_full' => 'Las copias de seguridad están ocupando demasiado espacio. El espacio utilizado actualmente es :disk_usage el cual es mayor que el límite permitido de :disk_limit.', + + 'no_backups_info' => 'Aún no se hicieron copias de seguridad', + 'application_name' => 'Nombre de la aplicación', + 'backup_name' => 'Nombre de la copia de seguridad', + 'disk' => 'Disco', + 'newest_backup_size' => 'Tamaño de copia de seguridad más reciente', + 'number_of_backups' => 'Número de copias de seguridad', + 'total_storage_used' => 'Almacenamiento total utilizado', + 'newest_backup_date' => 'Fecha de la copia de seguridad más reciente', + 'oldest_backup_date' => 'Fecha de la copia de seguridad más antigua', +]; diff --git a/lang/vendor/backup/fa/notifications.php b/lang/vendor/backup/fa/notifications.php new file mode 100644 index 0000000..580a1f1 --- /dev/null +++ b/lang/vendor/backup/fa/notifications.php @@ -0,0 +1,45 @@ + 'پیغام خطا: :message', + 'exception_trace' => 'جزییات خطا: :trace', + 'exception_message_title' => 'پیغام خطا', + 'exception_trace_title' => 'جزییات خطا', + + 'backup_failed_subject' => 'پشتیبان‌گیری :application_name با خطا مواجه شد.', + 'backup_failed_body' => 'پیغام مهم: هنگام پشتیبان‌گیری از :application_name خطایی رخ داده است. ', + + 'backup_successful_subject' => 'نسخه پشتیبان جدید :application_name با موفقیت ساخته شد.', + 'backup_successful_subject_title' => 'پشتیبان‌گیری موفق!', + 'backup_successful_body' => 'خبر خوب، به تازگی نسخه پشتیبان :application_name روی دیسک :disk_name با موفقیت ساخته شد. ', + + 'cleanup_failed_subject' => 'پاک‌‌سازی نسخه پشتیبان :application_name انجام نشد.', + 'cleanup_failed_body' => 'هنگام پاک‌سازی نسخه پشتیبان :application_name خطایی رخ داده است.', + + 'cleanup_successful_subject' => 'پاک‌سازی نسخه پشتیبان :application_name با موفقیت انجام شد.', + 'cleanup_successful_subject_title' => 'پاک‌سازی نسخه پشتیبان!', + 'cleanup_successful_body' => 'پاک‌سازی نسخه پشتیبان :application_name روی دیسک :disk_name با موفقیت انجام شد.', + + 'healthy_backup_found_subject' => 'نسخه پشتیبان :application_name روی دیسک :disk_name سالم بود.', + 'healthy_backup_found_subject_title' => 'نسخه پشتیبان :application_name سالم بود.', + 'healthy_backup_found_body' => 'نسخه پشتیبان :application_name به نظر سالم میاد. دمت گرم!', + + 'unhealthy_backup_found_subject' => 'خبر مهم: نسخه پشتیبان :application_name سالم نبود.', + 'unhealthy_backup_found_subject_title' => 'خبر مهم: نسخه پشتیبان :application_name سالم نبود. :problem', + 'unhealthy_backup_found_body' => 'نسخه پشتیبان :application_name روی دیسک :disk_name سالم نبود.', + 'unhealthy_backup_found_not_reachable' => 'مقصد پشتیبان‌گیری در دسترس نبود. :error', + 'unhealthy_backup_found_empty' => 'برای این برنامه هیچ نسخه پشتیبانی وجود ندارد.', + 'unhealthy_backup_found_old' => 'آخرین نسخه پشتیبان برای تاریخ :date است، که به نظر خیلی قدیمی میاد. ', + 'unhealthy_backup_found_unknown' => 'متاسفانه دلیل دقیقی قابل تعیین نیست.', + 'unhealthy_backup_found_full' => 'نسخه‌های پشتیبان حجم زیادی اشغال کرده‌اند. میزان دیسک استفاده‌شده :disk_usage است که از میزان مجاز :disk_limit فراتر رفته است. ', + + 'no_backups_info' => 'هنوز نسخه پشتیبان تهیه نشده است', + 'application_name' => 'نام نرم‌افزار', + 'backup_name' => 'نام نسخه پشتیبان', + 'disk' => 'دیسک', + 'newest_backup_size' => 'اندازه جدیدترین نسخه پشتیبان', + 'number_of_backups' => 'تعداد نسخه‌های پشتیبان', + 'total_storage_used' => 'کل فضای ذخیره‌سازی استفاده‌شده', + 'newest_backup_date' => 'تاریخ جدیدترین نسخه پشتیبان', + 'oldest_backup_date' => 'تاریخ قدیمی‌ترین نسخه پشتیبان', +]; diff --git a/lang/vendor/backup/fi/notifications.php b/lang/vendor/backup/fi/notifications.php new file mode 100644 index 0000000..98bec62 --- /dev/null +++ b/lang/vendor/backup/fi/notifications.php @@ -0,0 +1,45 @@ + 'Virheilmoitus: :message', + 'exception_trace' => 'Virhe, jäljitys: :trace', + 'exception_message_title' => 'Virheilmoitus', + 'exception_trace_title' => 'Virheen jäljitys', + + 'backup_failed_subject' => ':application_name varmuuskopiointi epäonnistui', + 'backup_failed_body' => 'HUOM!: :application_name varmuuskoipionnissa tapahtui virhe', + + 'backup_successful_subject' => ':application_name varmuuskopioitu onnistuneesti', + 'backup_successful_subject_title' => 'Uusi varmuuskopio!', + 'backup_successful_body' => 'Hyviä uutisia! :application_name on varmuuskopioitu levylle :disk_name.', + + 'cleanup_failed_subject' => ':application_name varmuuskopioiden poistaminen epäonnistui.', + 'cleanup_failed_body' => ':application_name varmuuskopioiden poistamisessa tapahtui virhe.', + + 'cleanup_successful_subject' => ':application_name varmuuskopiot poistettu onnistuneesti', + 'cleanup_successful_subject_title' => 'Varmuuskopiot poistettu onnistuneesti!', + 'cleanup_successful_body' => ':application_name varmuuskopiot poistettu onnistuneesti levyltä :disk_name.', + + 'healthy_backup_found_subject' => ':application_name varmuuskopiot levyllä :disk_name ovat kunnossa', + 'healthy_backup_found_subject_title' => ':application_name varmuuskopiot ovat kunnossa', + 'healthy_backup_found_body' => ':application_name varmuuskopiot ovat kunnossa. Hieno homma!', + + 'unhealthy_backup_found_subject' => 'HUOM!: :application_name varmuuskopiot ovat vialliset', + 'unhealthy_backup_found_subject_title' => 'HUOM!: :application_name varmuuskopiot ovat vialliset. :problem', + 'unhealthy_backup_found_body' => ':application_name varmuuskopiot levyllä :disk_name ovat vialliset.', + 'unhealthy_backup_found_not_reachable' => 'Varmuuskopioiden kohdekansio ei ole saatavilla. :error', + 'unhealthy_backup_found_empty' => 'Tästä sovelluksesta ei ole varmuuskopioita.', + 'unhealthy_backup_found_old' => 'Viimeisin varmuuskopio, luotu :date, on liian vanha.', + 'unhealthy_backup_found_unknown' => 'Virhe, tarkempaa tietoa syystä ei valitettavasti ole saatavilla.', + 'unhealthy_backup_found_full' => 'Varmuuskopiot vievät liikaa levytilaa. Tällä hetkellä käytössä :disk_usage, mikä on suurempi kuin sallittu tilavuus (:disk_limit).', + + 'no_backups_info' => 'Varmuuskopioita ei vielä tehty', + 'application_name' => 'Sovelluksen nimi', + 'backup_name' => 'Varmuuskopion nimi', + 'disk' => 'Levy', + 'newest_backup_size' => 'Uusin varmuuskopion koko', + 'number_of_backups' => 'Varmuuskopioiden määrä', + 'total_storage_used' => 'Käytetty tallennustila yhteensä', + 'newest_backup_date' => 'Uusin varmuuskopion koko', + 'oldest_backup_date' => 'Vanhin varmuuskopion koko', +]; diff --git a/lang/vendor/backup/fr/notifications.php b/lang/vendor/backup/fr/notifications.php new file mode 100644 index 0000000..ad60a5c --- /dev/null +++ b/lang/vendor/backup/fr/notifications.php @@ -0,0 +1,45 @@ + "Message de l'exception : :message", + 'exception_trace' => "Trace de l'exception : :trace", + 'exception_message_title' => "Message de l'exception", + 'exception_trace_title' => "Trace de l'exception", + + 'backup_failed_subject' => 'Échec de la sauvegarde de :application_name', + 'backup_failed_body' => 'Important : Une erreur est survenue lors de la sauvegarde de :application_name', + + 'backup_successful_subject' => 'Succès de la sauvegarde de :application_name', + 'backup_successful_subject_title' => 'Sauvegarde créée avec succès !', + 'backup_successful_body' => 'Bonne nouvelle, une nouvelle sauvegarde de :application_name a été créée avec succès sur le disque nommé :disk_name.', + + 'cleanup_failed_subject' => 'Le nettoyage des sauvegardes de :application_name a echoué.', + 'cleanup_failed_body' => 'Une erreur est survenue lors du nettoyage des sauvegardes de :application_name', + + 'cleanup_successful_subject' => 'Succès du nettoyage des sauvegardes de :application_name', + 'cleanup_successful_subject_title' => 'Sauvegardes nettoyées avec succès !', + 'cleanup_successful_body' => 'Le nettoyage des sauvegardes de :application_name sur le disque nommé :disk_name a été effectué avec succès.', + + 'healthy_backup_found_subject' => 'Les sauvegardes pour :application_name sur le disque :disk_name sont saines', + 'healthy_backup_found_subject_title' => 'Les sauvegardes pour :application_name sont saines', + 'healthy_backup_found_body' => 'Les sauvegardes pour :application_name sont considérées saines. Bon travail !', + + 'unhealthy_backup_found_subject' => 'Important : Les sauvegardes pour :application_name sont corrompues', + 'unhealthy_backup_found_subject_title' => 'Important : Les sauvegardes pour :application_name sont corrompues. :problem', + 'unhealthy_backup_found_body' => 'Les sauvegardes pour :application_name sur le disque :disk_name sont corrompues.', + 'unhealthy_backup_found_not_reachable' => "La destination de la sauvegarde n'est pas accessible. :error", + 'unhealthy_backup_found_empty' => "Il n'y a aucune sauvegarde pour cette application.", + 'unhealthy_backup_found_old' => 'La dernière sauvegarde du :date est considérée trop vieille.', + 'unhealthy_backup_found_unknown' => 'Désolé, une raison exacte ne peut être déterminée.', + 'unhealthy_backup_found_full' => 'Les sauvegardes utilisent trop d\'espace disque. L\'utilisation actuelle est de :disk_usage alors que la limite autorisée est de :disk_limit.', + + 'no_backups_info' => 'Aucune sauvegarde n\'a encore été effectuée', + 'application_name' => "Nom de l'application", + 'backup_name' => 'Nom de la sauvegarde', + 'disk' => 'Disque', + 'newest_backup_size' => 'Taille de la sauvegarde la plus récente', + 'number_of_backups' => 'Nombre de sauvegardes', + 'total_storage_used' => 'Stockage total utilisé', + 'newest_backup_date' => 'Date de la sauvegarde la plus récente', + 'oldest_backup_date' => 'Date de la sauvegarde la plus ancienne', +]; diff --git a/lang/vendor/backup/he/notifications.php b/lang/vendor/backup/he/notifications.php new file mode 100644 index 0000000..db3b35f --- /dev/null +++ b/lang/vendor/backup/he/notifications.php @@ -0,0 +1,45 @@ + 'הודעת חריגה: :message', + 'exception_trace' => 'מעקב חריגה: :trace', + 'exception_message_title' => 'הודעת חריגה', + 'exception_trace_title' => 'מעקב חריגה', + + 'backup_failed_subject' => 'כשל בגיבוי של :application_name', + 'backup_failed_body' => 'חשוב: אירעה שגיאה במהלך גיבוי היישום :application_name', + + 'backup_successful_subject' => 'גיבוי חדש מוצלח של :application_name', + 'backup_successful_subject_title' => 'גיבוי חדש מוצלח!', + 'backup_successful_body' => 'חדשות טובות, גיבוי חדש של :application_name נוצר בהצלחה על הדיסק בשם :disk_name.', + + 'cleanup_failed_subject' => 'נכשל בניקוי הגיבויים של :application_name', + 'cleanup_failed_body' => 'אירעה שגיאה במהלך ניקוי הגיבויים של :application_name', + + 'cleanup_successful_subject' => 'ניקוי הגיבויים של :application_name בוצע בהצלחה', + 'cleanup_successful_subject_title' => 'ניקוי הגיבויים בוצע בהצלחה!', + 'cleanup_successful_body' => 'ניקוי הגיבויים של :application_name על הדיסק בשם :disk_name בוצע בהצלחה.', + + 'healthy_backup_found_subject' => 'הגיבויים של :application_name על הדיסק :disk_name תקינים', + 'healthy_backup_found_subject_title' => 'הגיבויים של :application_name תקינים', + 'healthy_backup_found_body' => 'הגיבויים של :application_name נחשבים לתקינים. עבודה טובה!', + + 'unhealthy_backup_found_subject' => 'חשוב: הגיבויים של :application_name אינם תקינים', + 'unhealthy_backup_found_subject_title' => 'חשוב: הגיבויים של :application_name אינם תקינים. :problem', + 'unhealthy_backup_found_body' => 'הגיבויים של :application_name על הדיסק :disk_name אינם תקינים.', + 'unhealthy_backup_found_not_reachable' => 'לא ניתן להגיע ליעד הגיבוי. :error', + 'unhealthy_backup_found_empty' => 'אין גיבויים של היישום הזה בכלל.', + 'unhealthy_backup_found_old' => 'הגיבוי האחרון שנעשה בתאריך :date נחשב כישן מדי.', + 'unhealthy_backup_found_unknown' => 'מצטערים, לא ניתן לקבוע סיבה מדויקת.', + 'unhealthy_backup_found_full' => 'הגיבויים משתמשים בשטח אחסון רב מידי. שימוש הנוכחי הוא :disk_usage, שגבול המותר הוא :disk_limit.', + + 'no_backups_info' => 'לא נעשו עדיין גיבויים', + 'application_name' => 'שם היישום', + 'backup_name' => 'שם הגיבוי', + 'disk' => 'דיסק', + 'newest_backup_size' => 'גודל הגיבוי החדש ביותר', + 'number_of_backups' => 'מספר הגיבויים', + 'total_storage_used' => 'סך האחסון המופעל', + 'newest_backup_date' => 'תאריך הגיבוי החדש ביותר', + 'oldest_backup_date' => 'תאריך הגיבוי הישן ביותר', +]; diff --git a/lang/vendor/backup/hi/notifications.php b/lang/vendor/backup/hi/notifications.php new file mode 100644 index 0000000..f812867 --- /dev/null +++ b/lang/vendor/backup/hi/notifications.php @@ -0,0 +1,45 @@ + 'अपवाद संदेश: :message', + 'exception_trace' => 'अपवाद निशान: :trace', + 'exception_message_title' => 'अपवादी संदेश', + 'exception_trace_title' => 'अपवाद निशान', + + 'backup_failed_subject' => ':application_name का बैकअप असफल रहा', + 'backup_failed_body' => 'जरूरी सुचना: :application_name का बैकअप लेते समय असफल रहे', + + 'backup_successful_subject' => ':application_name का बैकअप सफल रहा', + 'backup_successful_subject_title' => 'बैकअप सफल रहा!', + 'backup_successful_body' => 'खुशखबर, :application_name का बैकअप :disk_name पर संग्रहित करने मे सफल रहे.', + + 'cleanup_failed_subject' => ':application_name के बैकअप की सफाई असफल रही.', + 'cleanup_failed_body' => ':application_name के बैकअप की सफाई करते समय कुछ बाधा आयी है.', + + 'cleanup_successful_subject' => ':application_name के बैकअप की सफाई सफल रही', + 'cleanup_successful_subject_title' => 'बैकअप की सफाई सफल रही!', + 'cleanup_successful_body' => ':application_name का बैकअप जो :disk_name नाम की डिस्क पर संग्रहित है, उसकी सफाई सफल रही.', + + 'healthy_backup_found_subject' => ':disk_name नाम की डिस्क पर संग्रहित :application_name के बैकअप स्वस्थ है', + 'healthy_backup_found_subject_title' => ':application_name के सभी बैकअप स्वस्थ है', + 'healthy_backup_found_body' => 'बहुत बढ़िया! :application_name के सभी बैकअप स्वस्थ है.', + + 'unhealthy_backup_found_subject' => 'जरूरी सुचना : :application_name के बैकअप अस्वस्थ है', + 'unhealthy_backup_found_subject_title' => 'जरूरी सुचना : :application_name के बैकअप :problem के बजेसे अस्वस्थ है', + 'unhealthy_backup_found_body' => ':disk_name नाम की डिस्क पर संग्रहित :application_name के बैकअप अस्वस्थ है', + 'unhealthy_backup_found_not_reachable' => ':error के बजेसे बैकअप की मंजिल तक पोहोच नहीं सकते.', + 'unhealthy_backup_found_empty' => 'इस एप्लीकेशन का कोई भी बैकअप नहीं है.', + 'unhealthy_backup_found_old' => 'हालहीमें :date को लिया हुआ बैकअप बहुत पुराना है.', + 'unhealthy_backup_found_unknown' => 'माफ़ कीजिये, सही कारण निर्धारित नहीं कर सकते.', + 'unhealthy_backup_found_full' => 'सभी बैकअप बहुत ज्यादा जगह का उपयोग कर रहे है. फ़िलहाल सभी बैकअप :disk_usage जगह का उपयोग कर रहे है, जो की :disk_limit अनुमति सीमा से अधिक का है.', + + 'no_backups_info' => 'अभी तक कोई बैकअप नहीं बनाया गया था', + 'application_name' => 'आवेदन का नाम', + 'backup_name' => 'बैकअप नाम', + 'disk' => 'डिस्क', + 'newest_backup_size' => 'नवीनतम बैकअप आकार', + 'number_of_backups' => 'बैकअप की संख्या', + 'total_storage_used' => 'उपयोग किया गया कुल संग्रहण', + 'newest_backup_date' => 'नवीनतम बैकअप आकार', + 'oldest_backup_date' => 'सबसे पुराना बैकअप आकार', +]; diff --git a/lang/vendor/backup/hr/notifications.php b/lang/vendor/backup/hr/notifications.php new file mode 100644 index 0000000..0b12bfd --- /dev/null +++ b/lang/vendor/backup/hr/notifications.php @@ -0,0 +1,45 @@ + 'Greška: :message', + 'exception_trace' => 'Praćenje greške: :trace', + 'exception_message_title' => 'Greška', + 'exception_trace_title' => 'Praćenje greške', + + 'backup_failed_subject' => 'Neuspješno sigurnosno kopiranje za :application_name', + 'backup_failed_body' => 'Važno: Došlo je do greške prilikom sigurnosnog kopiranja za :application_name', + + 'backup_successful_subject' => 'Uspješno sigurnosno kopiranje za :application_name', + 'backup_successful_subject_title' => 'Uspješno sigurnosno kopiranje!', + 'backup_successful_body' => 'Nova sigurnosna kopija za :application_name je uspješno spremljena na disk :disk_name.', + + 'cleanup_failed_subject' => 'Neuspješno čišćenje sigurnosnih kopija za :application_name', + 'cleanup_failed_body' => 'Došlo je do greške prilikom čišćenja sigurnosnih kopija za :application_name', + + 'cleanup_successful_subject' => 'Uspješno čišćenje sigurnosnih kopija za :application_name', + 'cleanup_successful_subject_title' => 'Uspješno čišćenje sigurnosnih kopija!', + 'cleanup_successful_body' => 'Sigurnosne kopije za :application_name su uspješno očišćene s diska :disk_name.', + + 'healthy_backup_found_subject' => 'Sigurnosne kopije za :application_name na disku :disk_name su zdrave', + 'healthy_backup_found_subject_title' => 'Sigurnosne kopije za :application_name su zdrave', + 'healthy_backup_found_body' => 'Sigurnosne kopije za :application_name se smatraju zdravima. Svaka čast!', + + 'unhealthy_backup_found_subject' => 'Važno: Sigurnosne kopije za :application_name su nezdrave', + 'unhealthy_backup_found_subject_title' => 'Važno: Sigurnosne kopije za :application_name su nezdrave. :problem', + 'unhealthy_backup_found_body' => 'Sigurnosne kopije za :application_name na disku :disk_name su nezdrave.', + 'unhealthy_backup_found_not_reachable' => 'Destinacija sigurnosne kopije nije dohvatljiva. :error', + 'unhealthy_backup_found_empty' => 'Nijedna sigurnosna kopija ove aplikacije ne postoji.', + 'unhealthy_backup_found_old' => 'Zadnja sigurnosna kopija generirana na datum :date smatra se prestarom.', + 'unhealthy_backup_found_unknown' => 'Isprike, ali nije moguće odrediti razlog.', + 'unhealthy_backup_found_full' => 'Sigurnosne kopije zauzimaju previše prostora. Trenutno zauzeće je :disk_usage što je više od dozvoljenog ograničenja od :disk_limit.', + + 'no_backups_info' => 'Nema sigurnosnih kopija', + 'application_name' => 'Naziv aplikacije', + 'backup_name' => 'Naziv sigurnosne kopije', + 'disk' => 'Disk', + 'newest_backup_size' => 'Veličina najnovije sigurnosne kopije', + 'number_of_backups' => 'Broj sigurnosnih kopija', + 'total_storage_used' => 'Ukupno zauzeće', + 'newest_backup_date' => 'Najnovija kopija na datum', + 'oldest_backup_date' => 'Najstarija kopija na datum', +]; diff --git a/lang/vendor/backup/id/notifications.php b/lang/vendor/backup/id/notifications.php new file mode 100644 index 0000000..12364b5 --- /dev/null +++ b/lang/vendor/backup/id/notifications.php @@ -0,0 +1,45 @@ + 'Pesan pengecualian: :message', + 'exception_trace' => 'Jejak pengecualian: :trace', + 'exception_message_title' => 'Pesan pengecualian', + 'exception_trace_title' => 'Jejak pengecualian', + + 'backup_failed_subject' => 'Gagal backup :application_name', + 'backup_failed_body' => 'Penting: Sebuah error terjadi ketika membackup :application_name', + + 'backup_successful_subject' => 'Backup baru sukses dari :application_name', + 'backup_successful_subject_title' => 'Backup baru sukses!', + 'backup_successful_body' => 'Kabar baik, sebuah backup baru dari :application_name sukses dibuat pada disk bernama :disk_name.', + + 'cleanup_failed_subject' => 'Membersihkan backup dari :application_name yang gagal.', + 'cleanup_failed_body' => 'Sebuah error teradi ketika membersihkan backup dari :application_name', + + 'cleanup_successful_subject' => 'Sukses membersihkan backup :application_name', + 'cleanup_successful_subject_title' => 'Sukses membersihkan backup!', + 'cleanup_successful_body' => 'Pembersihan backup :application_name pada disk bernama :disk_name telah sukses.', + + 'healthy_backup_found_subject' => 'Backup untuk :application_name pada disk :disk_name sehat', + 'healthy_backup_found_subject_title' => 'Backup untuk :application_name sehat', + 'healthy_backup_found_body' => 'Backup untuk :application_name dipertimbangkan sehat. Kerja bagus!', + + 'unhealthy_backup_found_subject' => 'Penting: Backup untuk :application_name tidak sehat', + 'unhealthy_backup_found_subject_title' => 'Penting: Backup untuk :application_name tidak sehat. :problem', + 'unhealthy_backup_found_body' => 'Backup untuk :application_name pada disk :disk_name tidak sehat.', + 'unhealthy_backup_found_not_reachable' => 'Tujuan backup tidak dapat terjangkau. :error', + 'unhealthy_backup_found_empty' => 'Tidak ada backup pada aplikasi ini sama sekali.', + 'unhealthy_backup_found_old' => 'Backup terakhir dibuat pada :date dimana dipertimbahkan sudah sangat lama.', + 'unhealthy_backup_found_unknown' => 'Maaf, sebuah alasan persisnya tidak dapat ditentukan.', + 'unhealthy_backup_found_full' => 'Backup menggunakan terlalu banyak kapasitas penyimpanan. Penggunaan terkini adalah :disk_usage dimana lebih besar dari batas yang diperbolehkan yaitu :disk_limit.', + + 'no_backups_info' => 'Belum ada backup yang dibuat', + 'application_name' => 'Nama aplikasi', + 'backup_name' => 'Nama cadangan', + 'disk' => 'Disk', + 'newest_backup_size' => 'Ukuran cadangan terbaru', + 'number_of_backups' => 'Jumlah cadangan', + 'total_storage_used' => 'Total penyimpanan yang digunakan', + 'newest_backup_date' => 'Ukuran cadangan terbaru', + 'oldest_backup_date' => 'Ukuran cadangan tertua', +]; diff --git a/lang/vendor/backup/it/notifications.php b/lang/vendor/backup/it/notifications.php new file mode 100644 index 0000000..e96618d --- /dev/null +++ b/lang/vendor/backup/it/notifications.php @@ -0,0 +1,45 @@ + "Messaggio dell'eccezione: :message", + 'exception_trace' => "Traccia dell'eccezione: :trace", + 'exception_message_title' => "Messaggio dell'eccezione", + 'exception_trace_title' => "Traccia dell'eccezione", + + 'backup_failed_subject' => 'Fallito il backup di :application_name', + 'backup_failed_body' => 'Importante: Si è verificato un errore durante il backup di :application_name', + + 'backup_successful_subject' => 'Creato nuovo backup di :application_name', + 'backup_successful_subject_title' => 'Nuovo backup creato!', + 'backup_successful_body' => 'Grande notizia, un nuovo backup di :application_name è stato creato con successo sul disco :disk_name.', + + 'cleanup_failed_subject' => 'Pulizia dei backup di :application_name fallita.', + 'cleanup_failed_body' => 'Si è verificato un errore durante la pulizia dei backup di :application_name', + + 'cleanup_successful_subject' => 'Pulizia dei backup di :application_name avvenuta con successo', + 'cleanup_successful_subject_title' => 'Pulizia dei backup avvenuta con successo!', + 'cleanup_successful_body' => 'La pulizia dei backup di :application_name sul disco :disk_name è avvenuta con successo.', + + 'healthy_backup_found_subject' => 'I backup per :application_name sul disco :disk_name sono sani', + 'healthy_backup_found_subject_title' => 'I backup per :application_name sono sani', + 'healthy_backup_found_body' => 'I backup per :application_name sono considerati sani. Bel Lavoro!', + + 'unhealthy_backup_found_subject' => 'Importante: i backup per :application_name sono corrotti', + 'unhealthy_backup_found_subject_title' => 'Importante: i backup per :application_name sono corrotti. :problem', + 'unhealthy_backup_found_body' => 'I backup per :application_name sul disco :disk_name sono corrotti.', + 'unhealthy_backup_found_not_reachable' => 'Impossibile raggiungere la destinazione di backup. :error', + 'unhealthy_backup_found_empty' => 'Non esiste alcun backup di questa applicazione.', + 'unhealthy_backup_found_old' => 'L\'ultimo backup fatto il :date è considerato troppo vecchio.', + 'unhealthy_backup_found_unknown' => 'Spiacenti, non è possibile determinare una ragione esatta.', + 'unhealthy_backup_found_full' => 'I backup utilizzano troppa memoria. L\'utilizzo corrente è :disk_usage che è superiore al limite consentito di :disk_limit.', + + 'no_backups_info' => 'Non sono stati ancora effettuati backup', + 'application_name' => "Nome dell'applicazione", + 'backup_name' => 'Nome di backup', + 'disk' => 'Disco', + 'newest_backup_size' => 'Dimensione backup più recente', + 'number_of_backups' => 'Numero di backup', + 'total_storage_used' => 'Spazio di archiviazione totale utilizzato', + 'newest_backup_date' => 'Data del backup più recente', + 'oldest_backup_date' => 'Data del backup più vecchio', +]; diff --git a/lang/vendor/backup/ja/notifications.php b/lang/vendor/backup/ja/notifications.php new file mode 100644 index 0000000..1b57ca3 --- /dev/null +++ b/lang/vendor/backup/ja/notifications.php @@ -0,0 +1,45 @@ + '例外のメッセージ: :message', + 'exception_trace' => '例外の追跡: :trace', + 'exception_message_title' => '例外のメッセージ', + 'exception_trace_title' => '例外の追跡', + + 'backup_failed_subject' => ':application_name のバックアップに失敗しました。', + 'backup_failed_body' => '重要: :application_name のバックアップ中にエラーが発生しました。', + + 'backup_successful_subject' => ':application_name のバックアップに成功しました。', + 'backup_successful_subject_title' => 'バックアップに成功しました!', + 'backup_successful_body' => '朗報です。ディスク :disk_name へ :application_name のバックアップが成功しました。', + + 'cleanup_failed_subject' => ':application_name のバックアップ削除に失敗しました。', + 'cleanup_failed_body' => ':application_name のバックアップ削除中にエラーが発生しました。', + + 'cleanup_successful_subject' => ':application_name のバックアップ削除に成功しました。', + 'cleanup_successful_subject_title' => 'バックアップ削除に成功しました!', + 'cleanup_successful_body' => 'ディスク :disk_name に保存された :application_name のバックアップ削除に成功しました。', + + 'healthy_backup_found_subject' => 'ディスク :disk_name への :application_name のバックアップは正常です。', + 'healthy_backup_found_subject_title' => ':application_name のバックアップは正常です。', + 'healthy_backup_found_body' => ':application_name へのバックアップは正常です。いい仕事してますね!', + + 'unhealthy_backup_found_subject' => '重要: :application_name のバックアップに異常があります。', + 'unhealthy_backup_found_subject_title' => '重要: :application_name のバックアップに異常があります。 :problem', + 'unhealthy_backup_found_body' => ':disk_name への :application_name のバックアップに異常があります。', + 'unhealthy_backup_found_not_reachable' => 'バックアップ先にアクセスできませんでした。 :error', + 'unhealthy_backup_found_empty' => 'このアプリケーションのバックアップは見つかりませんでした。', + 'unhealthy_backup_found_old' => ':date に保存された直近のバックアップが古すぎます。', + 'unhealthy_backup_found_unknown' => '申し訳ございません。予期せぬエラーです。', + 'unhealthy_backup_found_full' => 'バックアップがディスク容量を圧迫しています。現在の使用量 :disk_usage は、許可された限界値 :disk_limit を超えています。', + + 'no_backups_info' => 'バックアップはまだ作成されていません', + 'application_name' => 'アプリケーション名', + 'backup_name' => 'バックアップ名', + 'disk' => 'ディスク', + 'newest_backup_size' => '最新のバックアップサイズ', + 'number_of_backups' => 'バックアップ数', + 'total_storage_used' => '使用された合計ストレージ', + 'newest_backup_date' => '最新のバックアップ日時', + 'oldest_backup_date' => '最も古いバックアップ日時', +]; diff --git a/lang/vendor/backup/kk/notifications.php b/lang/vendor/backup/kk/notifications.php new file mode 100644 index 0000000..2382e48 --- /dev/null +++ b/lang/vendor/backup/kk/notifications.php @@ -0,0 +1,45 @@ + 'Қате туралы хабарлама: :message', + 'exception_trace' => 'Қате туралы мәліметтер: :trace', + 'exception_message_title' => 'Қате туралы хабарлама', + 'exception_trace_title' => 'Қате туралы мәліметтер', + + 'backup_failed_subject' => ':application_name бағдарламасының резервтік көшірмесін жасау сәтсіз аяқталды', + 'backup_failed_body' => 'Маңызды: :application_name бағдарламасының резервтік көшірмесін жасау барысында қате орын алды', + + 'backup_successful_subject' => ':application_name бағдарламасының жаңа резервтік көшірмесі сәтті құрылды', + 'backup_successful_subject_title' => 'Жаңа резервтік көшірме сәтті құрылды!', + 'backup_successful_body' => 'Жақсы жаңалық: :application_name бағдарламасының жаңа резервтік көшірмесі :disk_name дискінде сәтті құрылды.', + + 'cleanup_failed_subject' => ':application_name бағдарламасының резервтік көшірмелерін тазалау сәтсіз аяқталды', + 'cleanup_failed_body' => ':application_name бағдарламасының резервтік көшірмелерін тазалау барысында қате орын алды', + + 'cleanup_successful_subject' => ':application_name бағдарламасының резервтік көшірмелерін тазалау сәтті өтті', + 'cleanup_successful_subject_title' => 'Резервтік көшірмелерді тазалау сәтті аяқталды!', + 'cleanup_successful_body' => ':disk_name дискіндегі :application_name бағдарламасының резервтік көшірмелерін тазалау сәтті аяқталды.', + + 'healthy_backup_found_subject' => ':disk_name дискіндегі :application_name бағдарламасының резервтік көшірмелері қалыпты күйде', + 'healthy_backup_found_subject_title' => ':application_name бағдарламасының резервтік көшірмелері қалыпты күйде', + 'healthy_backup_found_body' => ':application_name бағдарламасының резервтік көшірмелері толық тексеруден өтті. Өте жақсы!', + + 'unhealthy_backup_found_subject' => 'Маңызды: :application_name бағдарламасының резервтік көшірмелері жарамсыз күйде', + 'unhealthy_backup_found_subject_title' => 'Маңызды: :application_name бағдарламасының резервтік көшірмелері жарамсыз күйде. :problem', + 'unhealthy_backup_found_body' => ':disk_name дискіндегі :application_name бағдарламасының резервтік көшірмелері жарамсыз күйде.', + 'unhealthy_backup_found_not_reachable' => 'Резервтік көшірме сақтау орнына қол жеткізу мүмкін емес. :error', + 'unhealthy_backup_found_empty' => 'Осы бағдарлама бойынша резервтік көшірмелер әлі жасалмаған.', + 'unhealthy_backup_found_old' => 'Соңғы резервтік көшірме (:date) тым ескі болып саналады.', + 'unhealthy_backup_found_unknown' => 'Кешіріңіз, нақты себебін анықтау мүмкін емес.', + 'unhealthy_backup_found_full' => 'Резервтік көшірмелер тым көп орын алып отыр. Ағымдағы пайдалану көлемі :disk_usage, бұл рұқсат етілген шектен :disk_limit аса жоғары.', + + 'no_backups_info' => 'Әлі резервтік көшірме жасалмаған', + 'application_name' => 'Бағдарлама атауы', + 'backup_name' => 'Резервтік көшірме атауы', + 'disk' => 'Диск', + 'newest_backup_size' => 'Соңғы резервтік көшірменің көлемі', + 'number_of_backups' => 'Резервтік көшірмелер саны', + 'total_storage_used' => 'Жалпы қолданылған сақтау көлемі', + 'newest_backup_date' => 'Соңғы резервтік көшірме күні', + 'oldest_backup_date' => 'Ең ескі резервтік көшірме күні', +]; diff --git a/lang/vendor/backup/ko/notifications.php b/lang/vendor/backup/ko/notifications.php new file mode 100644 index 0000000..d13c0f9 --- /dev/null +++ b/lang/vendor/backup/ko/notifications.php @@ -0,0 +1,45 @@ + '예외 메시지: :message', + 'exception_trace' => '예외 추적: :trace', + 'exception_message_title' => '예외 메시지', + 'exception_trace_title' => '예외 추적', + + 'backup_failed_subject' => ':application_name 백업 실패', + 'backup_failed_body' => '중요: :application_name 백업 중 오류 발생', + + 'backup_successful_subject' => ':application_name 백업 성공', + 'backup_successful_subject_title' => '백업이 성공적으로 완료되었습니다!', + 'backup_successful_body' => '좋은 소식입니다. :disk_name 디스크에 :application_name 백업이 성공적으로 완료되었습니다.', + + 'cleanup_failed_subject' => ':application_name 백업 정리 실패', + 'cleanup_failed_body' => ':application_name 백업 정리 중 오류 발생', + + 'cleanup_successful_subject' => ':application_name 백업 정리 성공', + 'cleanup_successful_subject_title' => '백업 정리가 성공적으로 완료되었습니다!', + 'cleanup_successful_body' => ':disk_name 디스크에 저장된 :application_name 백업 정리가 성공적으로 완료되었습니다.', + + 'healthy_backup_found_subject' => ':application_name 백업은 정상입니다.', + 'healthy_backup_found_subject_title' => ':application_name 백업은 정상입니다.', + 'healthy_backup_found_body' => ':application_name 백업은 정상입니다. 수고하셨습니다!', + + 'unhealthy_backup_found_subject' => '중요: :application_name 백업에 문제가 있습니다.', + 'unhealthy_backup_found_subject_title' => '중요: :application_name 백업에 문제가 있습니다. :problem', + 'unhealthy_backup_found_body' => ':disk_name 디스크에 :application_name 백업에 문제가 있습니다.', + 'unhealthy_backup_found_not_reachable' => '백업 위치에 액세스할 수 없습니다. :error', + 'unhealthy_backup_found_empty' => '이 애플리케이션에는 백업이 없습니다.', + 'unhealthy_backup_found_old' => ':date에 저장된 최신 백업이 너무 오래되었습니다.', + 'unhealthy_backup_found_unknown' => '죄송합니다. 예기치 않은 오류가 발생했습니다.', + 'unhealthy_backup_found_full' => '백업이 디스크 공간을 다 차지하고 있습니다. 현재 사용량 :disk_usage는 허용 한도 :disk_limit을 초과합니다.', + + 'no_backups_info' => '아직 백업이 생성되지 않았습니다.', + 'application_name' => '애플리케이션 이름', + 'backup_name' => '백업 이름', + 'disk' => '디스크', + 'newest_backup_size' => '최신 백업 크기', + 'number_of_backups' => '백업 수', + 'total_storage_used' => '총 사용 스토리지', + 'newest_backup_date' => '최신 백업 날짜', + 'oldest_backup_date' => '가장 오래된 백업 날짜', +]; diff --git a/lang/vendor/backup/nl/notifications.php b/lang/vendor/backup/nl/notifications.php new file mode 100644 index 0000000..4887cbf --- /dev/null +++ b/lang/vendor/backup/nl/notifications.php @@ -0,0 +1,45 @@ + 'Fout bericht: :message', + 'exception_trace' => 'Fout trace: :trace', + 'exception_message_title' => 'Fout bericht', + 'exception_trace_title' => 'Fout trace', + + 'backup_failed_subject' => 'Back-up van :application_name mislukt', + 'backup_failed_body' => 'Belangrijk: Er ging iets fout tijdens het maken van een back-up van :application_name', + + 'backup_successful_subject' => 'Succesvolle nieuwe back-up van :application_name', + 'backup_successful_subject_title' => 'Succesvolle nieuwe back-up!', + 'backup_successful_body' => 'Goed nieuws, een nieuwe back-up van :application_name was succesvol aangemaakt op de schijf genaamd :disk_name.', + + 'cleanup_failed_subject' => 'Het opschonen van de back-ups van :application_name is mislukt.', + 'cleanup_failed_body' => 'Er ging iets fout tijdens het opschonen van de back-ups van :application_name', + + 'cleanup_successful_subject' => 'Opschonen van :application_name back-ups was succesvol.', + 'cleanup_successful_subject_title' => 'Opschonen van back-ups was succesvol!', + 'cleanup_successful_body' => 'Het opschonen van de :application_name back-ups op de schijf genaamd :disk_name was succesvol.', + + 'healthy_backup_found_subject' => 'De back-ups voor :application_name op schijf :disk_name zijn gezond', + 'healthy_backup_found_subject_title' => 'De back-ups voor :application_name zijn gezond', + 'healthy_backup_found_body' => 'De back-ups voor :application_name worden als gezond beschouwd. Goed gedaan!', + + 'unhealthy_backup_found_subject' => 'Belangrijk: De back-ups voor :application_name zijn niet meer gezond', + 'unhealthy_backup_found_subject_title' => 'Belangrijk: De back-ups voor :application_name zijn niet gezond. :problem', + 'unhealthy_backup_found_body' => 'De back-ups voor :application_name op schijf :disk_name zijn niet gezond.', + 'unhealthy_backup_found_not_reachable' => 'De back-upbestemming kon niet worden bereikt. :error', + 'unhealthy_backup_found_empty' => 'Er zijn geen back-ups van deze applicatie beschikbaar.', + 'unhealthy_backup_found_old' => 'De laatste back-up gemaakt op :date is te oud.', + 'unhealthy_backup_found_unknown' => 'Sorry, een exacte reden kon niet worden bepaald.', + 'unhealthy_backup_found_full' => 'De back-ups gebruiken te veel opslagruimte. Momenteel wordt er :disk_usage gebruikt wat hoger is dan de toegestane limiet van :disk_limit.', + + 'no_backups_info' => 'Er zijn nog geen back-ups gemaakt', + 'application_name' => 'Naam van de toepassing', + 'backup_name' => 'Back-upnaam', + 'disk' => 'Schijf', + 'newest_backup_size' => 'Nieuwste back-upgrootte', + 'number_of_backups' => 'Aantal back-ups', + 'total_storage_used' => 'Totale gebruikte opslagruimte', + 'newest_backup_date' => 'Datum nieuwste back-up', + 'oldest_backup_date' => 'Datum oudste back-up', +]; diff --git a/lang/vendor/backup/no/notifications.php b/lang/vendor/backup/no/notifications.php new file mode 100644 index 0000000..e1d7019 --- /dev/null +++ b/lang/vendor/backup/no/notifications.php @@ -0,0 +1,45 @@ + 'Exception: :message', + 'exception_trace' => 'Exception trace: :trace', + 'exception_message_title' => 'Exception', + 'exception_trace_title' => 'Exception trace', + + 'backup_failed_subject' => 'Backup feilet for :application_name', + 'backup_failed_body' => 'Viktg: En feil oppstod under backing av :application_name', + + 'backup_successful_subject' => 'Gjennomført backup av :application_name', + 'backup_successful_subject_title' => 'Gjennomført backup!', + 'backup_successful_body' => 'Gode nyheter, en ny backup av :application_name ble opprettet på disken :disk_name.', + + 'cleanup_failed_subject' => 'Opprydding av backup for :application_name feilet.', + 'cleanup_failed_body' => 'En feil oppstod under opprydding av backups for :application_name', + + 'cleanup_successful_subject' => 'Opprydding av backup for :application_name gjennomført', + 'cleanup_successful_subject_title' => 'Opprydding av backup gjennomført!', + 'cleanup_successful_body' => 'Oppryddingen av backup for :application_name på disken :disk_name har blitt gjennomført.', + + 'healthy_backup_found_subject' => 'Alle backups for :application_name på disken :disk_name er OK', + 'healthy_backup_found_subject_title' => 'Alle backups for :application_name er OK', + 'healthy_backup_found_body' => 'Alle backups for :application_name er ok. Godt jobba!', + + 'unhealthy_backup_found_subject' => 'Viktig: Backups for :application_name ikke OK', + 'unhealthy_backup_found_subject_title' => 'Viktig: Backups for :application_name er ikke OK. :problem', + 'unhealthy_backup_found_body' => 'Backups for :application_name på disken :disk_name er ikke OK.', + 'unhealthy_backup_found_not_reachable' => 'Kunne ikke finne backup-destinasjonen. :error', + 'unhealthy_backup_found_empty' => 'Denne applikasjonen mangler backups.', + 'unhealthy_backup_found_old' => 'Den siste backupem fra :date er for gammel.', + 'unhealthy_backup_found_unknown' => 'Beklager, kunne ikke finne nøyaktig årsak.', + 'unhealthy_backup_found_full' => 'Backups bruker for mye lagringsplass. Nåværende diskbruk er :disk_usage, som er mer enn den tillatte grensen på :disk_limit.', + + 'no_backups_info' => 'Ingen sikkerhetskopier ble gjort ennå', + 'application_name' => 'Programnavn', + 'backup_name' => 'Navn på sikkerhetskopi', + 'disk' => 'Disk', + 'newest_backup_size' => 'Nyeste backup-størrelse', + 'number_of_backups' => 'Antall sikkerhetskopier', + 'total_storage_used' => 'Total lagring brukt', + 'newest_backup_date' => 'Nyeste backup-størrelse', + 'oldest_backup_date' => 'Eldste sikkerhetskopistørrelse', +]; diff --git a/lang/vendor/backup/pl/notifications.php b/lang/vendor/backup/pl/notifications.php new file mode 100644 index 0000000..5e79902 --- /dev/null +++ b/lang/vendor/backup/pl/notifications.php @@ -0,0 +1,45 @@ + 'Błąd: :message', + 'exception_trace' => 'Zrzut błędu: :trace', + 'exception_message_title' => 'Błąd', + 'exception_trace_title' => 'Zrzut błędu', + + 'backup_failed_subject' => 'Tworzenie kopii zapasowej aplikacji :application_name nie powiodło się', + 'backup_failed_body' => 'Ważne: Wystąpił błąd podczas tworzenia kopii zapasowej aplikacji :application_name', + + 'backup_successful_subject' => 'Pomyślnie utworzono kopię zapasową aplikacji :application_name', + 'backup_successful_subject_title' => 'Nowa kopia zapasowa!', + 'backup_successful_body' => 'Wspaniała wiadomość, nowa kopia zapasowa aplikacji :application_name została pomyślnie utworzona na dysku o nazwie :disk_name.', + + 'cleanup_failed_subject' => 'Czyszczenie kopii zapasowych aplikacji :application_name nie powiodło się.', + 'cleanup_failed_body' => 'Wystąpił błąd podczas czyszczenia kopii zapasowej aplikacji :application_name', + + 'cleanup_successful_subject' => 'Kopie zapasowe aplikacji :application_name zostały pomyślnie wyczyszczone', + 'cleanup_successful_subject_title' => 'Kopie zapasowe zostały pomyślnie wyczyszczone!', + 'cleanup_successful_body' => 'Czyszczenie kopii zapasowych aplikacji :application_name na dysku :disk_name zakończone sukcesem.', + + 'healthy_backup_found_subject' => 'Kopie zapasowe aplikacji :application_name na dysku :disk_name są poprawne', + 'healthy_backup_found_subject_title' => 'Kopie zapasowe aplikacji :application_name są poprawne', + 'healthy_backup_found_body' => 'Kopie zapasowe aplikacji :application_name są poprawne. Dobra robota!', + + 'unhealthy_backup_found_subject' => 'Ważne: Kopie zapasowe aplikacji :application_name są niepoprawne', + 'unhealthy_backup_found_subject_title' => 'Ważne: Kopie zapasowe aplikacji :application_name są niepoprawne. :problem', + 'unhealthy_backup_found_body' => 'Kopie zapasowe aplikacji :application_name na dysku :disk_name są niepoprawne.', + 'unhealthy_backup_found_not_reachable' => 'Miejsce docelowe kopii zapasowej nie jest osiągalne. :error', + 'unhealthy_backup_found_empty' => 'W aplikacji nie ma żadnej kopii zapasowych tej aplikacji.', + 'unhealthy_backup_found_old' => 'Ostatnia kopia zapasowa wykonania dnia :date jest zbyt stara.', + 'unhealthy_backup_found_unknown' => 'Niestety, nie można ustalić dokładnego błędu.', + 'unhealthy_backup_found_full' => 'Kopie zapasowe zajmują zbyt dużo miejsca. Obecne użycie dysku :disk_usage jest większe od ustalonego limitu :disk_limit.', + + 'no_backups_info' => 'Nie utworzono jeszcze kopii zapasowych', + 'application_name' => 'Nazwa aplikacji', + 'backup_name' => 'Nazwa kopii zapasowej', + 'disk' => 'Dysk', + 'newest_backup_size' => 'Najnowszy rozmiar kopii zapasowej', + 'number_of_backups' => 'Liczba kopii zapasowych', + 'total_storage_used' => 'Całkowite wykorzystane miejsce', + 'newest_backup_date' => 'Najnowszy rozmiar kopii zapasowej', + 'oldest_backup_date' => 'Najstarszy rozmiar kopii zapasowej', +]; diff --git a/lang/vendor/backup/pt/notifications.php b/lang/vendor/backup/pt/notifications.php new file mode 100644 index 0000000..835cfeb --- /dev/null +++ b/lang/vendor/backup/pt/notifications.php @@ -0,0 +1,45 @@ + 'Mensagem de exceção: :message', + 'exception_trace' => 'Rasto da exceção: :trace', + 'exception_message_title' => 'Mensagem de exceção', + 'exception_trace_title' => 'Rasto da exceção', + + 'backup_failed_subject' => 'Falha no backup da aplicação :application_name', + 'backup_failed_body' => 'Importante: Ocorreu um erro ao executar o backup da aplicação :application_name', + + 'backup_successful_subject' => 'Backup realizado com sucesso: :application_name', + 'backup_successful_subject_title' => 'Backup Realizado com Sucesso!', + 'backup_successful_body' => 'Boas notícias, foi criado um novo backup no disco :disk_name referente à aplicação :application_name.', + + 'cleanup_failed_subject' => 'Falha na limpeza dos backups da aplicação :application_name.', + 'cleanup_failed_body' => 'Ocorreu um erro ao executar a limpeza dos backups da aplicação :application_name', + + 'cleanup_successful_subject' => 'Limpeza dos backups da aplicação :application_name concluída!', + 'cleanup_successful_subject_title' => 'Limpeza dos backups concluída!', + 'cleanup_successful_body' => 'Concluída a limpeza dos backups da aplicação :application_name no disco :disk_name.', + + 'healthy_backup_found_subject' => 'Os backups da aplicação :application_name no disco :disk_name estão em dia', + 'healthy_backup_found_subject_title' => 'Os backups da aplicação :application_name estão em dia', + 'healthy_backup_found_body' => 'Os backups da aplicação :application_name estão em dia. Bom trabalho!', + + 'unhealthy_backup_found_subject' => 'Importante: Os backups da aplicação :application_name não estão em dia', + 'unhealthy_backup_found_subject_title' => 'Importante: Os backups da aplicação :application_name não estão em dia. :problem', + 'unhealthy_backup_found_body' => 'Os backups da aplicação :application_name no disco :disk_name não estão em dia.', + 'unhealthy_backup_found_not_reachable' => 'O destino dos backups não pode ser alcançado. :error', + 'unhealthy_backup_found_empty' => 'Não existem backups para essa aplicação.', + 'unhealthy_backup_found_old' => 'O último backup realizado em :date é demasiado antigo.', + 'unhealthy_backup_found_unknown' => 'Desculpe, impossível determinar a razão exata.', + 'unhealthy_backup_found_full' => 'Os backups estão a utilizar demasiado espaço de armazenamento. A utilização atual é de :disk_usage, o que é maior que o limite permitido de :disk_limit.', + + 'no_backups_info' => 'Nenhum backup foi feito ainda', + 'application_name' => 'Nome da Aplicação', + 'backup_name' => 'Nome de backup', + 'disk' => 'Disco', + 'newest_backup_size' => 'Tamanho de backup mais recente', + 'number_of_backups' => 'Número de backups', + 'total_storage_used' => 'Armazenamento total usado', + 'newest_backup_date' => 'Data de backup mais recente', + 'oldest_backup_date' => 'Data de backup mais antiga', +]; diff --git a/lang/vendor/backup/pt_BR/notifications.php b/lang/vendor/backup/pt_BR/notifications.php new file mode 100644 index 0000000..406d4da --- /dev/null +++ b/lang/vendor/backup/pt_BR/notifications.php @@ -0,0 +1,45 @@ + 'Mensagem de exceção: :message', + 'exception_trace' => 'Rastreamento de exceção: :trace', + 'exception_message_title' => 'Mensagem de exceção', + 'exception_trace_title' => 'Rastreamento de exceção', + + 'backup_failed_subject' => 'Falha no backup da aplicação :application_name', + 'backup_failed_body' => 'Importante: Ocorreu um erro ao fazer o backup da aplicação :application_name', + + 'backup_successful_subject' => 'Backup realizado com sucesso: :application_name', + 'backup_successful_subject_title' => 'Backup Realizado com sucesso!', + 'backup_successful_body' => 'Boas notícias, um novo backup da aplicação :application_name foi criado no disco :disk_name.', + + 'cleanup_failed_subject' => 'Falha na limpeza dos backups da aplicação :application_name.', + 'cleanup_failed_body' => 'Um erro ocorreu ao fazer a limpeza dos backups da aplicação :application_name', + + 'cleanup_successful_subject' => 'Limpeza dos backups da aplicação :application_name concluída!', + 'cleanup_successful_subject_title' => 'Limpeza dos backups concluída!', + 'cleanup_successful_body' => 'A limpeza dos backups da aplicação :application_name no disco :disk_name foi concluída.', + + 'healthy_backup_found_subject' => 'Os backups da aplicação :application_name no disco :disk_name estão em dia', + 'healthy_backup_found_subject_title' => 'Os backups da aplicação :application_name estão em dia', + 'healthy_backup_found_body' => 'Os backups da aplicação :application_name estão em dia. Bom trabalho!', + + 'unhealthy_backup_found_subject' => 'Importante: Os backups da aplicação :application_name não estão em dia', + 'unhealthy_backup_found_subject_title' => 'Importante: Os backups da aplicação :application_name não estão em dia. :problem', + 'unhealthy_backup_found_body' => 'Os backups da aplicação :application_name no disco :disk_name não estão em dia.', + 'unhealthy_backup_found_not_reachable' => 'O destino dos backups não pode ser alcançado. :error', + 'unhealthy_backup_found_empty' => 'Não existem backups para essa aplicação.', + 'unhealthy_backup_found_old' => 'O último backup realizado em :date é considerado muito antigo.', + 'unhealthy_backup_found_unknown' => 'Desculpe, a exata razão não pode ser encontrada.', + 'unhealthy_backup_found_full' => 'Os backups estão usando muito espaço de armazenamento. A utilização atual é de :disk_usage, o que é maior que o limite permitido de :disk_limit.', + + 'no_backups_info' => 'Nenhum backup foi feito ainda', + 'application_name' => 'Nome da Aplicação', + 'backup_name' => 'Nome de backup', + 'disk' => 'Disco', + 'newest_backup_size' => 'Tamanho do backup mais recente', + 'number_of_backups' => 'Número de backups', + 'total_storage_used' => 'Armazenamento total usado', + 'newest_backup_date' => 'Data do backup mais recente', + 'oldest_backup_date' => 'Data do backup mais antigo', +]; diff --git a/lang/vendor/backup/ro/notifications.php b/lang/vendor/backup/ro/notifications.php new file mode 100644 index 0000000..0e8bc91 --- /dev/null +++ b/lang/vendor/backup/ro/notifications.php @@ -0,0 +1,45 @@ + 'Cu excepția mesajului: :message', + 'exception_trace' => 'Urmă excepţie: :trace', + 'exception_message_title' => 'Mesaj de excepție', + 'exception_trace_title' => 'Urmă excepţie', + + 'backup_failed_subject' => 'Nu s-a putut face copie de rezervă pentru :application_name', + 'backup_failed_body' => 'Important: A apărut o eroare în timpul generării copiei de rezervă pentru :application_name', + + 'backup_successful_subject' => 'Copie de rezervă efectuată cu succes pentru :application_name', + 'backup_successful_subject_title' => 'O nouă copie de rezervă a fost efectuată cu succes!', + 'backup_successful_body' => 'Vești bune, o nouă copie de rezervă pentru :application_name a fost creată cu succes pe discul cu numele :disk_name.', + + 'cleanup_failed_subject' => 'Curățarea copiilor de rezervă pentru :application_name nu a reușit.', + 'cleanup_failed_body' => 'A apărut o eroare în timpul curățirii copiilor de rezervă pentru :application_name', + + 'cleanup_successful_subject' => 'Curățarea copiilor de rezervă pentru :application_name a fost făcută cu succes', + 'cleanup_successful_subject_title' => 'Curățarea copiilor de rezervă a fost făcută cu succes!', + 'cleanup_successful_body' => 'Curățarea copiilor de rezervă pentru :application_name de pe discul cu numele :disk_name a fost făcută cu succes.', + + 'healthy_backup_found_subject' => 'Copiile de rezervă pentru :application_name de pe discul :disk_name sunt în regulă', + 'healthy_backup_found_subject_title' => 'Copiile de rezervă pentru :application_name sunt în regulă', + 'healthy_backup_found_body' => 'Copiile de rezervă pentru :application_name sunt considerate în regulă. Bună treabă!', + + 'unhealthy_backup_found_subject' => 'Important: Copiile de rezervă pentru :application_name nu sunt în regulă', + 'unhealthy_backup_found_subject_title' => 'Important: Copiile de rezervă pentru :application_name nu sunt în regulă. :problem', + 'unhealthy_backup_found_body' => 'Copiile de rezervă pentru :application_name de pe discul :disk_name nu sunt în regulă.', + 'unhealthy_backup_found_not_reachable' => 'Nu se poate ajunge la destinația copiilor de rezervă. :error', + 'unhealthy_backup_found_empty' => 'Nu există copii de rezervă ale acestei aplicații.', + 'unhealthy_backup_found_old' => 'Cea mai recentă copie de rezervă făcută la :date este considerată prea veche.', + 'unhealthy_backup_found_unknown' => 'Ne pare rău, un motiv exact nu poate fi determinat.', + 'unhealthy_backup_found_full' => 'Copiile de rezervă folosesc prea mult spațiu de stocare. Utilizarea curentă este de :disk_usage care este mai mare decât limita permisă de :disk_limit.', + + 'no_backups_info' => 'Nu s-au făcut încă copii de rezervă', + 'application_name' => 'Numele aplicatiei', + 'backup_name' => 'Numele de rezervă', + 'disk' => 'Disc', + 'newest_backup_size' => 'Cea mai nouă dimensiune de rezervă', + 'number_of_backups' => 'Număr de copii de rezervă', + 'total_storage_used' => 'Spațiu total de stocare utilizat', + 'newest_backup_date' => 'Cea mai nouă dimensiune de rezervă', + 'oldest_backup_date' => 'Cea mai veche dimensiune de rezervă', +]; diff --git a/lang/vendor/backup/ru/notifications.php b/lang/vendor/backup/ru/notifications.php new file mode 100644 index 0000000..d58beb7 --- /dev/null +++ b/lang/vendor/backup/ru/notifications.php @@ -0,0 +1,45 @@ + 'Сообщение об ошибке: :message', + 'exception_trace' => 'Сведения об ошибке: :trace', + 'exception_message_title' => 'Сообщение об ошибке', + 'exception_trace_title' => 'Сведения об ошибке', + + 'backup_failed_subject' => 'Не удалось сделать резервную копию :application_name', + 'backup_failed_body' => 'Внимание: Произошла ошибка во время резервного копирования :application_name', + + 'backup_successful_subject' => 'Успешно создана новая резервная копия :application_name', + 'backup_successful_subject_title' => 'Успешно создана новая резервная копия!', + 'backup_successful_body' => 'Отличная новость, новая резервная копия :application_name успешно создана и сохранена на диск :disk_name.', + + 'cleanup_failed_subject' => 'Не удалось очистить резервные копии :application_name', + 'cleanup_failed_body' => 'Произошла ошибка при очистке резервных копий :application_name', + + 'cleanup_successful_subject' => 'Очистка от резервных копий :application_name прошла успешно', + 'cleanup_successful_subject_title' => 'Очистка резервных копий прошла успешно!', + 'cleanup_successful_body' => 'Очистка от старых резервных копий :application_name на диске :disk_name прошла успешно.', + + 'healthy_backup_found_subject' => 'Резервные копии :application_name с диска :disk_name исправны', + 'healthy_backup_found_subject_title' => 'Резервные копии :application_name исправны', + 'healthy_backup_found_body' => 'Резервные копии :application_name считаются исправными. Хорошая работа!', + + 'unhealthy_backup_found_subject' => 'Внимание: резервные копии :application_name неисправны', + 'unhealthy_backup_found_subject_title' => 'Внимание: резервные копии для :application_name неисправны. :problem', + 'unhealthy_backup_found_body' => 'Резервные копии для :application_name на диске :disk_name неисправны.', + 'unhealthy_backup_found_not_reachable' => 'Не удается достичь места назначения резервной копии. :error', + 'unhealthy_backup_found_empty' => 'Резервные копии для этого приложения отсутствуют.', + 'unhealthy_backup_found_old' => 'Последнее резервное копирование созданное :date является устаревшим.', + 'unhealthy_backup_found_unknown' => 'Извините, точная причина не может быть определена.', + 'unhealthy_backup_found_full' => 'Резервные копии используют слишком много памяти. Используется :disk_usage что выше допустимого предела: :disk_limit.', + + 'no_backups_info' => 'Резервных копий еще не было', + 'application_name' => 'Имя приложения', + 'backup_name' => 'Имя резервной копии', + 'disk' => 'Диск', + 'newest_backup_size' => 'Размер последней резервной копии', + 'number_of_backups' => 'Количество резервных копий', + 'total_storage_used' => 'Общий объем используемого хранилища', + 'newest_backup_date' => 'Дата последней резервной копии', + 'oldest_backup_date' => 'Дата самой старой резервной копии', +]; diff --git a/lang/vendor/backup/sk/notifications.php b/lang/vendor/backup/sk/notifications.php new file mode 100644 index 0000000..1d95e44 --- /dev/null +++ b/lang/vendor/backup/sk/notifications.php @@ -0,0 +1,45 @@ + 'Správa výnimky: :message', + 'exception_trace' => 'Stopa výnimky: :trace', + 'exception_message_title' => 'Správa výnimky', + 'exception_trace_title' => 'Stopa výnimky', + + 'backup_failed_subject' => 'Záloha :application_name zlyhala', + 'backup_failed_body' => 'Dôležité: Pri zálohovaní :application_name sa vyskytla chyba', + + 'backup_successful_subject' => 'Úspešná nová záloha :application_name', + 'backup_successful_subject_title' => 'Úspešná nová záloha!', + 'backup_successful_body' => 'Dobrá správa, na disku s názvom :disk_name bola úspešne vytvorená nová záloha :application_name.', + + 'cleanup_failed_subject' => 'Vyčistenie záloh :application_name zlyhalo.', + 'cleanup_failed_body' => 'Pri čistení záloh :application_name sa vyskytla chyba', + + 'cleanup_successful_subject' => 'Vyčistenie záloh :application_name bolo úspešné', + 'cleanup_successful_subject_title' => 'Vyčistenie záloh bolo úspešné!', + 'cleanup_successful_body' => 'Vyčistenie záloh :application_name na disku s názvom :disk_name bolo úspešné.', + + 'healthy_backup_found_subject' => 'Zálohy pre :application_name na disku :disk_name sú zdravé', + 'healthy_backup_found_subject_title' => 'Zálohy pre :application_name sú zdravé', + 'healthy_backup_found_body' => 'Zálohy pre :application_name sa považujú za zdravé. Dobrá práca!', + + 'unhealthy_backup_found_subject' => 'Dôležité: Zálohy pre :application_name sú nezdravé', + 'unhealthy_backup_found_subject_title' => 'Dôležité: Zálohy pre :application_name sú nezdravé. :problem', + 'unhealthy_backup_found_body' => 'Zálohy pre :application_name na disku :disk_name sú nezdravé.', + 'unhealthy_backup_found_not_reachable' => 'Nemožno sa dostať k cieľu zálohy. :error', + 'unhealthy_backup_found_empty' => 'Táto aplikácia nemá žiadne zálohy.', + 'unhealthy_backup_found_old' => 'Posledná záloha vytvorená dňa :date sa považuje za príliš starú.', + 'unhealthy_backup_found_unknown' => 'Ospravedlňujeme sa, nemôžeme určiť presný dôvod.', + 'unhealthy_backup_found_full' => 'Zálohy zaberajú príliš veľa miesta na disku. Aktuálne využitie disku je :disk_usage, čo je viac ako povolený limit :disk_limit.', + + 'no_backups_info' => 'Zatiaľ neboli vytvorené žiadne zálohy', + 'application_name' => 'Názov aplikácie', + 'backup_name' => 'Názov zálohy', + 'disk' => 'Disk', + 'newest_backup_size' => 'Veľkosť najnovšej zálohy', + 'number_of_backups' => 'Počet záloh', + 'total_storage_used' => 'Celková využitá kapacita úložiska', + 'newest_backup_date' => 'Dátum najnovšej zálohy', + 'oldest_backup_date' => 'Dátum najstaršej zálohy', +]; diff --git a/lang/vendor/backup/tr/notifications.php b/lang/vendor/backup/tr/notifications.php new file mode 100644 index 0000000..64cfa5a --- /dev/null +++ b/lang/vendor/backup/tr/notifications.php @@ -0,0 +1,45 @@ + 'Hata mesajı: :message', + 'exception_trace' => 'Hata izleri: :trace', + 'exception_message_title' => 'Hata mesajı', + 'exception_trace_title' => 'Hata izleri', + + 'backup_failed_subject' => 'Yedeklenemedi :application_name', + 'backup_failed_body' => 'Önemli: Yedeklenirken bir hata oluştu :application_name', + + 'backup_successful_subject' => 'Başarılı :application_name yeni yedeklemesi', + 'backup_successful_subject_title' => 'Başarılı bir yeni yedekleme!', + 'backup_successful_body' => 'Harika bir haber, :application_name ait yeni bir yedekleme :disk_name adlı diskte başarıyla oluşturuldu.', + + 'cleanup_failed_subject' => ':application_name yedeklemeleri temizlenmesi başarısız.', + 'cleanup_failed_body' => ':application_name yedeklerini temizlerken bir hata oluştu ', + + 'cleanup_successful_subject' => ':application_name yedeklemeleri temizlenmesi başarılı.', + 'cleanup_successful_subject_title' => 'Yedeklerin temizlenmesi başarılı!', + 'cleanup_successful_body' => ':application_name yedeklemeleri temizlenmesi, :disk_name diskinden silindi', + + 'healthy_backup_found_subject' => ':application_name yedeklenmesi, :disk_name adlı diskte sağlıklı', + 'healthy_backup_found_subject_title' => ':application_name yedeklenmesi sağlıklı', + 'healthy_backup_found_body' => ':application_name için yapılan yedeklemeler sağlıklı sayılır. Aferin!', + + 'unhealthy_backup_found_subject' => 'Önemli: :application_name için yedeklemeler sağlıksız', + 'unhealthy_backup_found_subject_title' => 'Önemli: :application_name için yedeklemeler sağlıksız. :problem', + 'unhealthy_backup_found_body' => 'Yedeklemeler: :application_name disk: :disk_name sağlıksız.', + 'unhealthy_backup_found_not_reachable' => 'Yedekleme hedefine ulaşılamıyor. :error', + 'unhealthy_backup_found_empty' => 'Bu uygulamanın yedekleri yok.', + 'unhealthy_backup_found_old' => ':date tarihinde yapılan en son yedekleme çok eski kabul ediliyor.', + 'unhealthy_backup_found_unknown' => 'Üzgünüm, kesin bir sebep belirlenemiyor.', + 'unhealthy_backup_found_full' => 'Yedeklemeler çok fazla depolama alanı kullanıyor. Şu anki kullanım: :disk_usage, izin verilen sınırdan yüksek: :disk_limit.', + + 'no_backups_info' => 'Henüz yedekleme yapılmadı', + 'application_name' => 'Uygulama Adı', + 'backup_name' => 'Yedek adı', + 'disk' => 'Disk', + 'newest_backup_size' => 'En yeni yedekleme boyutu', + 'number_of_backups' => 'Yedekleme sayısı', + 'total_storage_used' => 'Kullanılan toplam depolama alanı', + 'newest_backup_date' => 'En yeni yedekleme tarihi', + 'oldest_backup_date' => 'En eski yedekleme tarihi', +]; diff --git a/lang/vendor/backup/uk/notifications.php b/lang/vendor/backup/uk/notifications.php new file mode 100644 index 0000000..6f6f83b --- /dev/null +++ b/lang/vendor/backup/uk/notifications.php @@ -0,0 +1,45 @@ + 'Повідомлення про помилку: :message', + 'exception_trace' => 'Деталі помилки: :trace', + 'exception_message_title' => 'Повідомлення помилки', + 'exception_trace_title' => 'Деталі помилки', + + 'backup_failed_subject' => 'Не вдалось зробити резервну копію :application_name', + 'backup_failed_body' => 'Увага: Трапилась помилка під час резервного копіювання :application_name', + + 'backup_successful_subject' => 'Успішне резервне копіювання :application_name', + 'backup_successful_subject_title' => 'Успішно створена резервна копія!', + 'backup_successful_body' => 'Чудова новина, нова резервна копія :application_name успішно створена і збережена на диск :disk_name.', + + 'cleanup_failed_subject' => 'Не вдалось очистити резервні копії :application_name', + 'cleanup_failed_body' => 'Сталася помилка під час очищення резервних копій :application_name', + + 'cleanup_successful_subject' => 'Успішне очищення від резервних копій :application_name', + 'cleanup_successful_subject_title' => 'Очищення резервних копій пройшло вдало!', + 'cleanup_successful_body' => 'Очищенно від старих резервних копій :application_name на диску :disk_name пойшло успішно.', + + 'healthy_backup_found_subject' => 'Резервна копія :application_name з диску :disk_name установлена', + 'healthy_backup_found_subject_title' => 'Резервна копія :application_name установлена', + 'healthy_backup_found_body' => 'Резервна копія :application_name успішно установлена. Хороша робота!', + + 'unhealthy_backup_found_subject' => 'Увага: резервна копія :application_name не установилась', + 'unhealthy_backup_found_subject_title' => 'Увага: резервна копія для :application_name не установилась. :problem', + 'unhealthy_backup_found_body' => 'Резервна копія для :application_name на диску :disk_name не установилась.', + 'unhealthy_backup_found_not_reachable' => 'Резервна копія не змогла установитись. :error', + 'unhealthy_backup_found_empty' => 'Резервні копії для цього додатку відсутні.', + 'unhealthy_backup_found_old' => 'Останнє резервне копіювання створено :date є застарілим.', + 'unhealthy_backup_found_unknown' => 'Вибачте, але ми не змогли визначити точну причину.', + 'unhealthy_backup_found_full' => 'Резервні копії використовують занадто багато пам`яті. Використовується :disk_usage що вище за допустиму межу :disk_limit.', + + 'no_backups_info' => 'Резервних копій ще не було зроблено', + 'application_name' => 'Назва програми', + 'backup_name' => 'Резервне ім’я', + 'disk' => 'Диск', + 'newest_backup_size' => 'Найновіший розмір резервної копії', + 'number_of_backups' => 'Кількість резервних копій', + 'total_storage_used' => 'Загальний обсяг використаного сховища', + 'newest_backup_date' => 'Найновіший розмір резервної копії', + 'oldest_backup_date' => 'Найстаріший розмір резервної копії', +]; diff --git a/lang/vendor/backup/zh_CN/notifications.php b/lang/vendor/backup/zh_CN/notifications.php new file mode 100644 index 0000000..7927084 --- /dev/null +++ b/lang/vendor/backup/zh_CN/notifications.php @@ -0,0 +1,45 @@ + '异常信息: :message', + 'exception_trace' => '异常跟踪: :trace', + 'exception_message_title' => '异常信息', + 'exception_trace_title' => '异常跟踪', + + 'backup_failed_subject' => ':application_name 备份失败', + 'backup_failed_body' => '重要说明:备份 :application_name 时发生错误', + + 'backup_successful_subject' => ':application_name 备份成功', + 'backup_successful_subject_title' => '备份成功!', + 'backup_successful_body' => '好消息, :application_name 备份成功,位于磁盘 :disk_name 中。', + + 'cleanup_failed_subject' => '清除 :application_name 的备份失败。', + 'cleanup_failed_body' => '清除备份 :application_name 时发生错误', + + 'cleanup_successful_subject' => '成功清除 :application_name 的备份', + 'cleanup_successful_subject_title' => '成功清除备份!', + 'cleanup_successful_body' => '成功清除 :disk_name 磁盘上 :application_name 的备份。', + + 'healthy_backup_found_subject' => ':disk_name 磁盘上 :application_name 的备份是健康的', + 'healthy_backup_found_subject_title' => ':application_name 的备份是健康的', + 'healthy_backup_found_body' => ':application_name 的备份是健康的。干的好!', + + 'unhealthy_backup_found_subject' => '重要说明::application_name 的备份不健康', + 'unhealthy_backup_found_subject_title' => '重要说明::application_name 备份不健康。 :problem', + 'unhealthy_backup_found_body' => ':disk_name 磁盘上 :application_name 的备份不健康。', + 'unhealthy_backup_found_not_reachable' => '无法访问备份目标。 :error', + 'unhealthy_backup_found_empty' => '根本没有此应用程序的备份。', + 'unhealthy_backup_found_old' => '最近的备份创建于 :date ,太旧了。', + 'unhealthy_backup_found_unknown' => '对不起,确切原因无法确定。', + 'unhealthy_backup_found_full' => '备份占用了太多存储空间。当前占用了 :disk_usage ,高于允许的限制 :disk_limit。', + + 'no_backups_info' => '尚未进行任何备份', + 'application_name' => '应用名称', + 'backup_name' => '备份名称', + 'disk' => '磁盘', + 'newest_backup_size' => '最新备份大小', + 'number_of_backups' => '备份数量', + 'total_storage_used' => '使用的总存储量', + 'newest_backup_date' => '最新备份大小', + 'oldest_backup_date' => '最旧的备份大小', +]; diff --git a/lang/vendor/backup/zh_TW/notifications.php b/lang/vendor/backup/zh_TW/notifications.php new file mode 100644 index 0000000..7bc7dcb --- /dev/null +++ b/lang/vendor/backup/zh_TW/notifications.php @@ -0,0 +1,45 @@ + '異常訊息: :message', + 'exception_trace' => '異常追蹤: :trace', + 'exception_message_title' => '異常訊息', + 'exception_trace_title' => '異常追蹤', + + 'backup_failed_subject' => ':application_name 備份失敗', + 'backup_failed_body' => '重要說明:備份 :application_name 時發生錯誤', + + 'backup_successful_subject' => ':application_name 備份成功', + 'backup_successful_subject_title' => '備份成功!', + 'backup_successful_body' => '好消息, :application_name 備份成功,位於磁碟 :disk_name 中。', + + 'cleanup_failed_subject' => '清除 :application_name 的備份失敗。', + 'cleanup_failed_body' => '清除備份 :application_name 時發生錯誤', + + 'cleanup_successful_subject' => '成功清除 :application_name 的備份', + 'cleanup_successful_subject_title' => '成功清除備份!', + 'cleanup_successful_body' => '成功清除 :disk_name 磁碟上 :application_name 的備份。', + + 'healthy_backup_found_subject' => ':disk_name 磁碟上 :application_name 的備份是健康的', + 'healthy_backup_found_subject_title' => ':application_name 的備份是健康的', + 'healthy_backup_found_body' => ':application_name 的備份是健康的。幹的好!', + + 'unhealthy_backup_found_subject' => '重要說明::application_name 的備份不健康', + 'unhealthy_backup_found_subject_title' => '重要說明::application_name 備份不健康。 :problem', + 'unhealthy_backup_found_body' => ':disk_name 磁碟上 :application_name 的備份不健康。', + 'unhealthy_backup_found_not_reachable' => '無法訪問備份目標。 :error', + 'unhealthy_backup_found_empty' => '根本沒有此應用程序的備份。', + 'unhealthy_backup_found_old' => '最近的備份創建於 :date ,太舊了。', + 'unhealthy_backup_found_unknown' => '對不起,確切原因無法確定。', + 'unhealthy_backup_found_full' => '備份佔用了太多存儲空間。當前佔用了 :disk_usage ,高於允許的限制 :disk_limit。', + + 'no_backups_info' => '尚未進行任何備份', + 'application_name' => '應用名稱', + 'backup_name' => '備份名稱', + 'disk' => '磁碟', + 'newest_backup_size' => '最新備份大小', + 'number_of_backups' => '備份數量', + 'total_storage_used' => '使用的總存儲量', + 'newest_backup_date' => '最新備份大小', + 'oldest_backup_date' => '最早的備份大小', +]; diff --git a/misc/ENSAYO_PRESENTACION.md b/misc/ENSAYO_PRESENTACION.md new file mode 100644 index 0000000..4328868 --- /dev/null +++ b/misc/ENSAYO_PRESENTACION.md @@ -0,0 +1,191 @@ +# 🎤 Guión de Ensayo — Presentación OnAPB +### Taller de Integración — FCYT UADER | 7 de Abril 2026, 18:30 hs +**Presentadores:** Lautaro · Fabricio + +--- + +> **Objetivo de la demo:** ~20 minutos en total. +> Mostrar el sistema funcionando en producción (onapb.com) de principio a fin. +> El hilo conductor es una historia: *un jugador real pide un QR para un partido, y el admin lo escanea en la puerta.* + +--- + +## 🎬 Estructura general + +| Bloque | Quién | Tiempo estimado | +|---|---|---| +| **Introducción** (qué es OnAPB y qué problema resuelve) | Lautaro | 2 min | +| **Demo pública** (home, eventos, noticias, promos) | Fabricio | 3 min | +| **Demo jugador** (login, solicitar QR, ver QRs) | Lautaro | 5 min | +| **Demo admin** (panel, gestión, escanear QR) | Fabricio | 6 min | +| **Demo técnica** (tests, backup) | Lautaro | 2 min | +| **Cierre** (conclusiones, pendientes, mejoras) | Ambos | 2 min | + +--- + +## 🟠 Bloque 1 — Introducción (Lautaro) + +**Lautaro dice:** + +> *"Buenas tardes. Somos Lautaro y Fabricio, y vamos a presentar OnAPB: un sistema web de gestión para asociaciones de básquetbol.* +> +> *El problema que resuelve es simple: hasta ahora, la administración de clubes, jugadores y el acceso a los partidos se hacía completamente en papel o con planillas de Excel desconectadas. Nosotros digitalizamos eso.* +> +> *El sistema está en producción en onapb.com y tiene cargados actualmente 35 equipos y alrededor de 3500 jugadores reales. Fue construido con Laravel 12, MySQL y Bootstrap 5."* + +👉 **Abrí el navegador en onapb.com mientras hablás.** + +--- + +## 🟢 Bloque 2 — Demo Pública (Fabricio) + +**Fabricio toma el control del teclado/mouse.** + +### 2.1 Home +- Mostrá el carrusel/hero de la portada. Decí brevemente: + > *"Esta es la página pública. Cualquier persona, sin registrarse, puede ver la cartelera de partidos, las noticias y los sponsors de la liga."* + +### 2.2 Eventos +- Navegá a `/eventos`. +- Hacé clic en un partido concreto (elegí uno que tenga equipos asignados y estado *Próximo*). + > *"Acá se ve el detalle del partido: los equipos, la categoría, la fecha y la sede."* + +### 2.3 Torneos (posiciones + goleadores) +- Navegá a la sección de torneos. +- Mostrá la tabla de posiciones y la tabla de goleadores. + > *"El sistema también gestiona torneos con grupos, posiciones acumuladas y ranking de goleadores. Cuando hay playoffs, se genera el bracket automáticamente."* + +### 2.4 Promos y Noticias (rápido) +- 15 segundos nomás: mostrá que existen. + > *"También tenemos noticias publicables y locales con beneficios para los miembros."* + +--- + +## 🔵 Bloque 3 — Demo Jugador (Lautaro) + +**Lautaro toma el control. Este es el bloque más importante de cara a la historia principal.** + +### 3.1 Login como Jugador +- Ir a la pantalla de login (botón en el menú). +- Pestaña *"Jugadores / Aficionados"*. +- Ingresar un DNI y contraseña reales de un jugador de prueba. + > *"Los jugadores se loguean con su DNI y contraseña. El captcha de Cloudflare Turnstile protege contra bots."* +- Clic en **Ingresar**. El sistema redirige a la home ya logueado. + +### 3.2 Panel de Usuario +- Ir a `/panel-usuario`. + > *"Este es el panel personal del jugador. Ve sus datos, a qué club pertenece, a qué equipo está asignado, y su categoría, que se calcula automáticamente en base a la fecha de nacimiento."* + +### 3.3 ⭐ Solicitar QR para un Partido *(paso a paso detallado)* + +Este es el **momento central de la demo**. Hacelo con calma. + +1. Desde el panel o desde el menú, navegá a `/eventos`. +2. Hacé clic en el partido preparado con anticipación (uno con estado *Próximo* y que tenga al jugador logueado en uno de los equipos). +3. Mostrá el detalle del partido. + > *"En el detalle del evento, el jugador puede solicitar su QR. El sistema verifica automáticamente si pertenece a alguno de los equipos del partido."* +4. Hacé clic en **"Solicitar QR"**. +5. El sistema procesa y redirige a "Mis QRs". + > *"Como el jugador pertenece al equipo local, el sistema le genera 3 QRs: uno para él y dos para que les dé a familiares o acompañantes. Si fuera de categoría Libre, obtendría 1 QR con 50% de descuento."* + +### 3.4 Mis QRs +- Mostrá la pantalla de Mis QRs. +- Ampliá uno de los QR para que se vea bien grande. + > *"Cada QR es único, tiene un solo uso. Su estado es 'Válido' hasta que es escaneado, momento en que pasa a 'Usado'.* + > + > *Además, el jugador recibe estos QRs por correo electrónico automáticamente."* + +- **Consejo:** si podés, mostrá que el correo llegó a la bandeja (tené el mail abierto en otra pestaña). + +### 3.5 Cerrar sesión del jugador +- Clic en **Cerrar sesión**. + +--- + +## 🔴 Bloque 4 — Demo Administrador (Fabricio) + +**Fabricio toma el control.** + +### 4.1 Login como SuperAdmin +- Login con usuario y contraseña del superadmin. + > *"Ahora ingresamos como Súper Administrador."* +- Clic en **Ingresar**. + +### 4.2 Dashboard Admin +- Mostrá el dashboard con las estadísticas globales (clubes, equipos, jugadores totales). + > *"El panel de administración tiene visión global de todo el sistema."* + +### 4.3 Gestión de Jugadores (rápido) +- Ir a `/admin/jugadores`. +- Mostrá el listado con búsqueda. + > *"Podemos buscar cualquier jugador. Hay 3500 cargados actualmente."* +- Hacé clic en un jugador para mostrar el formulario de edición. No guardes nada. + > *"El admin puede editar datos, cambiar el club o eliminar un jugador. Si se elimina, usamos SoftDelete: no se borra físicamente, es recuperable."* + +### 4.4 Importación CSV (30 segundos) +- Mostrá el botón de importar en `/admin/jugadores`. + > *"Una funcionalidad clave fue la importación masiva desde CSV. El sistema soporta el formato oficial de CAB — la Confederación Argentina de Básquet — y también formatos internos. Importamos los 3500 jugadores desde esas planillas."* + +### 4.5 Gestión de Eventos (rápido) +- Ir a `/admin/eventos`. + > *"El admin calendariza los partidos, asigna equipos y controla el estado. Cuando se cargan los resultados, el evento pasa automáticamente a Finalizado y los puntos impactan en la tabla de posiciones."* + +### 4.6 ⭐ Escanear el QR *(paso a paso detallado)* + +Este es el **cierre de la historia**. Hacelo en vivo. + +1. Ir a `/admin/escanear-qr`. + > *"Esta es la herramienta para usar en la puerta del gimnasio el día del partido. El admin de turno selecciona el evento."* +2. Seleccioná el mismo partido del que Lautaro sacó el QR antes. +3. Activá la cámara o usá el campo de texto para ingresar el ID del QR. + > *"El árbitro o responsable escanea el código. El sistema valida en tiempo real."* +4. Escaneá (o pegá el ID del QR generado antes). + > *"¿Ven? El sistema muestra el nombre del titular, el tipo de QR —en este caso 'invitado'— y lo pasa a estado Usado. Si alguien intentara entrar con ese mismo QR de nuevo, el sistema lo rechazaría."* +5. Mostrá el resultado: QR validado, nombre del jugador, estado actualizado. + +--- + +## 🟣 Bloque 5 — Demo Técnica (Lautaro) + +**Lautaro toma el control. Abrí una terminal.** + +### 5.1 Correr los tests +```bash +php artisan test +``` + > *"El proyecto tiene una suite de pruebas automatizadas con PHPUnit. Tenemos 5 archivos de Feature Tests que cubren el login de los 3 tipos de usuario, el acceso denegado, la solicitud de QR y la prevención de duplicados."* + +- Mostrá que todos pasan en verde. + +### 5.2 Sistema de Backup +```bash +php artisan backup:run --only-db --disable-notifications +``` + > *"También integramos spatie/laravel-backup para las copias de seguridad automáticas de la base de datos. Esto cubre el requisito de recuperación ante fallos."* + +### 5.3 SoftDeletes (explicación verbal, sin demo) + > *"Además, los modelos críticos —Club, Equipo, Jugador, Evento— implementan SoftDeletes. Esto significa que ningún dato crítico se borra permanentemente: si un admin elimina algo por error, los registros siguen en la base de datos con un timestamp de eliminación y son recuperables."* + +--- + +## ⚪ Bloque 6 — Cierre (Ambos) + +**Turno de Fabricio primero:** + +> *"En cuanto a lo que quedó pendiente: la integración de pagos con Banco Macro —que llamamos Fase 6— no se implementó porque requiere credenciales y aprobación formal del banco, algo que está fuera del alcance académico. Sin embargo, la arquitectura está preparada para recibirla: tenemos el modelo `PagoMp` y la estructura de datos lista."* + +**Cierre de Lautaro:** + +> *"Como reflexión del equipo: el mayor desafío fue modelar correctamente la lógica de negocio real de una asociación de básquet —categorías por edad, pases entre clubes, permisos por rol— sin que el sistema se volviera rígido. El uso de SoftDeletes, servicios desacoplados y el scheduler nos permitió tener algo robusto y mantenible.* +> +> *Quedamos a disposición para preguntas."* + +--- + +## ⚠️ Tips para el día de la presentación + +- **Elegí con anticipación** el jugador de prueba y el evento para el demo del QR. Verificá que el jugador esté en uno de los equipos del partido. +- **Tené el correo abierto** en una pestaña aparte para mostrar que llegó el mail con el QR. +- Si el profesor pregunta algo que no saben, **no inventen**: digan *"ese detalle lo tenemos en el código, si quiere lo revisamos juntos"*. +- **Turno de hablar**: si uno habla, el otro maneja el mouse, y viceversa. No hablen los dos a la vez. +- **Cronometren** el ensayo. Si lleva más de 25 minutos, recorten las partes "rápido". diff --git a/misc/GESTION-JUGADORES.md b/misc/GESTION-JUGADORES.md new file mode 100644 index 0000000..6bddf71 --- /dev/null +++ b/misc/GESTION-JUGADORES.md @@ -0,0 +1,43 @@ +# Gestión de Jugadores: Roles y Funcionalidades + +Este documento detalla las capacidades y restricciones para los distintos tipos de administradores al crear o importar jugadores en el sistema OnAPB. + +## 1. Creación Manual (Formulario Individual) + +| Característica | Súper Administrador (Rol 1) | Administrador de Club (Rol 2) | +| :--- | :--- | :--- | +| **Club de Origen** | **Editable:** Puede seleccionar cualquier club registrado. | **Editable:** Puede seleccionar cualquier club registrado (ej: para pases entre clubes). | +| **Club Actual** | **Editable:** Puede asignar al jugador a cualquier club. | **Bloqueado:** El jugador se asigna automáticamente a su propio club. | +| **Validación de DNI** | Bloqueado si el DNI ya existe. Muestra el club actual del jugador. | Bloqueado si el DNI ya existe. Muestra el club actual del jugador. | +| **Generación de ID** | Automática: Basada en Club Origen + Año Nacimiento + Secuencia. | Automática: Basada en Club Origen + Año Nacimiento + Secuencia. | +| **Estado Inicial** | Siempre `Inactivo`. Debe completarse en `/asociate`. | Siempre `Inactivo`. Debe completarse en `/asociate`. | + +## 2. Importación Masiva (Archivo .CSV) + +**Formato del archivo:** `DNI; Apellido; Nombre; ddmmaaaa; id_club_origen` + +| Característica | Súper Administrador (Rol 1) | Administrador de Club (Rol 2) | +| :--- | :--- | :--- | +| **Clubes de Origen Permitidos** | Cualquier ID de club. | **Solo su propio Club** o ID 99 (Default). | +| **Asignación de Club Actual** | Se asigna el mismo ID del Club de Origen. | **Forzado** al ID del club del administrador. | +| **Gestión de Errores** | Omite duplicados si el DNI ya existe. | Omite duplicados; bloquea filas con IDs de otros clubes. | + +--- + +## Reglas Generales de Validación + +### Control de Duplicados (DNI) +Independientemente del rol, el sistema no permite registros duplicados por DNI. +- **Mensaje de Error:** *"No se puede registrar al jugador dado que ya pertenece al club [Nombre del Club]."* +- Esta validación asegura que no se creen registros paralelos para el mismo jugador. + +### Generación del `id_jugador` +El ID del jugador es un código único compuesto: `CCYYSSS`. +- `CC`: ID del Club de Origen. +- `YY`: Últimos dos dígitos del año de nacimiento. +- `SSS`: Secuencia incremental (ej: 01, 02) para ese club y ese año. + +### Datos Automáticos +- **Edad:** Se calcula automáticamente a partir de la fecha de nacimiento. +- **Categoría:** Es dinámica. Se calcula cada año basándose en el año de nacimiento (ej: U15 para jugadores que cumplen 14 o 15 años en el año corriente). +- **Contraseña:** Si no se especifica, queda pendiente hasta la activación por el usuario. diff --git a/misc/HOJA-DE-RUTA.md b/misc/HOJA-DE-RUTA.md new file mode 100644 index 0000000..7f53696 --- /dev/null +++ b/misc/HOJA-DE-RUTA.md @@ -0,0 +1,92 @@ +# Hoja de Ruta - Migración a Laravel + +## Fase 1: Fundamentos (✅ Completado) +- Modelos Eloquent +- Controladores RESTful +- Rutas API +- Layout base + Welcome + +## Fase 2: Autenticación (✅ Completado) +- AuthController (login/logout player + admin) +- Recuperar contraseña (token + email + vista reset ✅) +- Registro de jugadores/aficionados +- Middlewares de autenticación + +## Fase 3: Vistas Públicas (✅ Completado) +- Vista eventos (lista) +- Vista evento_detalle +- Vista promos (mapa/lista) +- Vista asociate (registro) +- Vista noticias + +## Fase 4: Panel de Usuario (✅ Completado) +- Dashboard usuario +- Mis QRs +- Solicitar QR para eventos ✅ +- Generar QR para promociones ✅ + +## Fase 5: Admin - Gestión (✅ Completado) +- [x] ABM Clubes (API ✅, vistas ✅) +- [x] ABM Equipos (API ✅, vistas ✅) +- [x] ABM Jugadores (API ✅, vistas ✅) +- [x] ABM Eventos (API ✅, CRUD completo ✅) +- [x] ABM Promociones/Lugares (✅) +- [x] ABM Noticias (API ✅, vistas ✅) +- [x] Escanear/validar QR (✅) + +## Fase 6: Pagos - Banco Macro (⏳ Pendiente - esperando credenciales) + +### 6.1 Configuración Inicial +- [ ] Obtener credenciales de Banco Macro (CLIENT_ID, CLIENT_SECRET) +- [ ] Configurar ambiente sandbox +- [ ] Configurar webhook + +### 6.2 Modelado de Datos +- [ ] Crear modelo ConceptoPago +- [ ] Crear modelo Deuda +- [ ] Extender modelo PagoMp existente + +### 6.3 Backend - API +- [ ] CRUD conceptos de pago +- [ ] CRUD deudas +- [ ] Generación masiva de deudas (ej: cuota a todos) +- [ ] Integración Botón Integrado Macro Click +- [ ] Endpoint webhook para notificaciones +- [ ] Endpoint validación de pagos + +### 6.4 Frontend - Panel Usuario +- [ ] Sección "Mis Pagos" en panel usuario +- [ ] Listado de deudas pendientes +- [ ] Historial de pagos +- [ ] Componente Botón Integrado (formulario embebido) +- [ ] Estados de éxito/error del pago + +### 6.5 Panel Admin - Gestión de Pagos +- [ ] Dashboard de deudas y cobros +- [ ] Crear sanción individual a jugador +- [ ] Generar cuotas masivas por club/equipo +- [ ] Validación manual de pagos +- [ ] Reportes (Excel/PDF) + +## Fase 7: Panel Usuario - QRs y Pagos (✅ Completado parcial) +- [x] Solicitar QR para evento (desde detalle de evento) +- [x] Generar QR tras solicitud (sin pago por ahora, Fase 6 pendiente) +- [x] Visualizar mis QRs activos (con estado válido/usado) +- [x] Generar QR para promociones (desde vista de promos) +- [ ] Integrar generación de QR tras pago exitoso (depende de Fase 6) + +## Fase 8: Varias (✅ Completado parcial) +- [x] Completar recuperar contraseña (vista reset + proceso completo) +- [x] Fix formulario recuperar contraseña (HTML roto) +- [ ] Envío de emails (deuda generada, pago confirmado) — depende de config SMTP +- [x] Limpieza links admin (editar/eliminar desde detalle evento, promos admin) +- [ ] Testing webhooks — depende de Fase 6 + +--- + +## Notas + +- **Fase 6 reemplaza MercadoPago** por Macro Click de Banco Macro +- La integración será mediante **Botón Integrado** (pago dentro de la app) +- El sistema permitirá autogestión de pagos por parte de los jugadores +- **Reset password** incluye enlace de desarrollo directo (en producción, se enviaría por email) diff --git a/misc/MANUAL_USUARIO.md b/misc/MANUAL_USUARIO.md new file mode 100644 index 0000000..3d43190 --- /dev/null +++ b/misc/MANUAL_USUARIO.md @@ -0,0 +1,648 @@ +# 📖 Manual de Usuario — OnAPB +### Sistema de Gestión de Asociación de Básquet +> **Sitio:** [onapb.com](https://onapb.com) + +--- + +## ¿A quién está dirigido este manual? + +OnAPB es utilizado por cuatro tipos de personas. Este manual explica paso a paso qué puede hacer cada una: + +| Capítulo | Perfil | +|---|---| +| [Capítulo 1](#cap1) | Visitantes (sin cuenta) | +| [Capítulo 2](#cap2) | Jugadores federados | +| [Capítulo 3](#cap3) | Aficionados / Hinchas | +| [Capítulo 4](#cap4) | Administradores de Club | +| [Capítulo 5](#cap5) | Súper Administradores (OnAPB) | + +--- + + +## 📌 Capítulo 1 — Visitante (Sin cuenta) + +Cualquier persona puede ingresar a **onapb.com** sin necesidad de registrarse y acceder a información pública de la liga. + +### 1.1 Página de Inicio (`/`) + +Al entrar al sitio el visitante encuentra: + +- **Carrusel / Hero**: Diapositivas destacadas configuradas por la asociación (noticias importantes, convocatorias, avisos). +- **Próximos Partidos**: Listado de los eventos más cercanos con día, hora y equipos. +- **Noticias recientes**: Artículos publicados por OnAPB. +- **Sponsors**: Franja rotativa con los patrocinadores de la liga visible en el pie de página. + +### 1.2 Cartelera de Eventos (`/eventos`) + +- Ver todos los partidos programados: próximos, en curso y finalizados. +- Cada tarjeta de evento muestra: equipos, categoría, fecha, hora y sede. +- Hacer clic en un evento abre el **detalle del partido** con información completa. +- Si el partido ya fue jugado, se muestran los marcadores finales. + +### 1.3 Tabla de Posiciones y Goleadores de Torneo + +- Desde la sección de torneos se puede ver: + - **Posiciones** por grupo o categoría. + - **Tabla de goleadores** del torneo con puntos acumulados. + - **Bracket de Playoffs**: diagrama del cuadro eliminatorio cuando corresponde. + +### 1.4 Noticias (`/noticias`) + +- Listado de artículos publicados por la asociación con imagen, título y texto completo. + +### 1.5 Promociones y Lugares con Beneficios (`/promos`) + +- Mapa y/o listado de locales comerciales asociados que ofrecen descuentos a miembros de OnAPB. +- Ver información de cada comercio (nombre, dirección, beneficio). +- Para **obtener el QR de descuento** es necesario tener una cuenta y estar logueado. + +### 1.6 Registrarse (`/asociate`) + +Para obtener todos los beneficios del sistema, el visitante puede crear una cuenta. Existen dos vías: + +#### Vía A — Registrarse como Aficionado +1. Ir a `/asociate` y seleccionar la pestaña **"Soy Aficionado"**. +2. Completar el formulario: Nombre, Apellido, DNI, Email, Fecha de Nacimiento (opcional), Teléfono (opcional), Localidad (opcional), Contraseña. +3. Resolver el **captcha de seguridad** (Cloudflare Turnstile). +4. Hacer clic en **Registrarme**. +5. El sistema envía un **correo de bienvenida** a la dirección ingresada. +6. ✅ Listo. Ya se puede iniciar sesión con DNI y contraseña. + +#### Vía B — Activar cuenta como Jugador Federado +> *Para jugadores que ya fueron cargados en el sistema por el administrador de su club.* + +1. Ir a `/asociate` y seleccionar la pestaña **"Soy Jugador"**. +2. Ingresar Nombre, Apellido y DNI (tal como aparecen en la ficha). +3. Aceptar los términos y hacer clic en **Buscar**. +4. El sistema valida los datos con el padrón. Si hay coincidencia, muestra la ficha del jugador (nombre, club, categoría). +5. Completar el formulario de activación: Email, Teléfono (opcional), Contraseña. +6. Resolver el **captcha de seguridad**. +7. Hacer clic en **Activar mi cuenta**. +8. El sistema envía un **correo de bienvenida**. +9. ✅ Listo. La cuenta queda activa y se puede iniciar sesión. + +> **Nota:** Si el DNI no se encuentra en el padrón de jugadores, el sistema sugiere registrarse como Aficionado. + +### 1.7 Iniciar Sesión + +- Desde el menú superior hacer clic en **"Iniciar Sesión"** o ir a la pantalla de login. +- Se muestra un formulario con dos pestañas: + - **Jugadores / Aficionados**: ingresar DNI y contraseña + captcha. + - **Administradores**: ingresar usuario y contraseña + captcha. + +### 1.8 Recuperar Contraseña (`/recuperar`) + +En caso de olvidar la contraseña: +1. Ir a `/recuperar`. +2. Ingresar el **DNI** y la **dirección de email** asociados a la cuenta. +3. El sistema envía un enlace de restablecimiento válido por **1 hora**. +4. Hacer clic en el enlace del correo y establecer la nueva contraseña (mínimo 6 caracteres, requiere confirmación). + +--- + + +## 🏅 Capítulo 2 — Jugador Federado + +Un jugador que ya activó su cuenta (Vía B de `/asociate`) tiene acceso a un **Panel de Usuario** con funcionalidades específicas para deportistas federados. + +### 2.1 Iniciar Sesión + +- En la pantalla de login, pestaña **"Jugadores / Aficionados"**. +- Ingresar **DNI** y **contraseña**. +- El sistema detecta automáticamente si la cuenta corresponde a un Jugador o Aficionado. + +### 2.2 Panel de Usuario (`/panel-usuario`) + +Al acceder al panel, el jugador ve de un vistazo: + +- Sus **datos personales**: nombre, DNI, club, categoría calculada automáticamente por edad. +- Sus **equipos asignados** (puede pertenecer a varios equipos dentro de su club). +- **Resumen de QRs**: cantidad de pases de eventos solicitados. +- **Notificaciones** del sistema (ícono en el menú superior con contador). + +### 2.3 Solicitar QR para un Partido + +Esta es la funcionalidad principal del jugador federado. Permite obtener un **código QR de acceso** a un evento. + +**Pasos:** +1. Desde el menú público o desde el panel, ir a **Eventos** y buscar el partido deseado. +2. Entrar al **detalle del partido**. +3. Si el partido está en estado *Próximo* o *En Curso*, aparece el botón **"Solicitar QR"**. +4. Hacer clic en el botón. El sistema verifica automáticamente: + - Si el jugador **pertenece a uno de los equipos** del partido → genera la cantidad de QRs configurada (por defecto 3, para repartir entre familiares/acompañantes). Tipo: `invitado`. + - Si el jugador es de **categoría Libre** pero no juega ese partido → genera 1 QR con descuento del 50%. Tipo: `libre_50`. + - Si el jugador no cumple ninguna condición → el botón no estará disponible o muestra un mensaje explicativo. +5. ✅ El sistema genera los QRs y envía un **correo con los códigos** al email registrado. +6. El jugador es redirigido automáticamente a **Mis QRs** para ver los códigos generados. + +> **Restricción:** Solo se puede solicitar QR una vez por partido. Si ya se solicitó, el botón queda inhabilitado con un mensaje informativo. + +### 2.4 Mis QRs (`/panel-usuario/mis-qrs`) + +- Lista de todos los códigos QR del jugador, ordenados del más reciente al más antiguo. +- Cada QR muestra: + - Imagen del código QR (escaneable) + - Evento al que pertenece (equipos, fecha, hora) + - Estado: **Válido** / **Usado** (según si fue escaneado en puerta) + - Tipo de QR (invitado, libre_50, etc.) +- Se puede filtrar por evento específico. + +### 2.5 Beneficios de Promociones + +1. Ir a **Promos** desde el menú principal. +2. Ver el mapa/listado de locales con beneficios. +3. Hacer clic en **"Obtener mi QR de beneficio"** en el local deseado. +4. El sistema genera un **QR de descuento único** para ese local. +5. Ver el QR en pantalla para presentarlo en el comercio. + +> **Restricción:** Solo se puede generar 1 QR por local por usuario. + +### 2.6 Seguir Equipos + +- Desde la página pública de un equipo (`/equipos/{id}`), hacer clic en **"Seguir"**. +- Acceder a **Mis Equipos Seguidos** desde el Panel para ver el historial de partidos de los equipos favoritos. +- Hacer clic nuevamente en "Seguir" en un equipo ya seguido lo deja de seguir (toggle). + +### 2.7 Notificaciones (`/notificaciones`) + +- El ícono de campana en el menú muestra la cantidad de notificaciones no leídas. +- Las notificaciones pueden ser generadas por el sistema automáticamente (ej: "Tus QRs para el partido del sábado están disponibles"). +- Desde el centro de notificaciones se puede: + - **Marcar como leída** una notificación individual. + - **Marcar todas como leídas**. + - **Eliminar** notificaciones individuales. + - **Eliminar todas** las notificaciones. + +### 2.8 Editar Datos Personales + +Desde el Panel de Usuario, sección **"Mi Cuenta"**: +- Actualizar **email** y **teléfono**. +- Los jugadores no pueden modificar su nombre, DNI o fecha de nacimiento (esos datos son gestionados por el admin del club). + +### 2.9 Cambiar Contraseña + +Desde el Panel de Usuario, sección **"Seguridad"**: +1. Ingresar la contraseña actual. +2. Ingresar la nueva contraseña (mínimo 6 caracteres). +3. Confirmar la nueva contraseña. +4. Guardar cambios. + +### 2.10 Cerrar Sesión + +- Hacer clic en **"Cerrar Sesión"** en el menú (esquina superior derecha o menú hamburguesa en móvil). +- La sesión se cierra de forma segura. + +--- + + +## 🎉 Capítulo 3 — Aficionado / Hincha + +El aficionado tiene las mismas capacidades que el jugador en lo que respecta a disfrute de la plataforma, con algunas diferencias en la lógica de los QRs. + +### 3.1 Inicio de Sesión y Registro + +Idéntico al Jugador: login con DNI + contraseña. El registro es mediante la **Vía A** descripta en el Capítulo 1. + +### 3.2 Panel de Usuario + +Igual al del Jugador, con las siguientes diferencias visibles: +- **No se muestra** información de club ni categoría federada. +- El campo **"Localidad"** sí es editable (además de email y teléfono). + +### 3.3 Solicitar QR para un Partido + +El aficionado puede solicitar 1 QR por partido. A diferencia del jugador federado: +- No hay distinción por equipo ni categoría. +- Se genera 1 QR de tipo `publico`. +- En el futuro (Fase 6), este QR estará sujeto al pago de la entrada; actualmente se genera de forma directa. + +El proceso es idéntico a los pasos 1–5 del apartado 2.3. + +### 3.4 Mis QRs, Promociones, Notificaciones y Cuenta + +Funciona exactamente igual que para el Jugador (ver apartados 2.4 al 2.10). + +--- + + +## 🏢 Capítulo 4 — Administrador de Club + +El Admin de Club es el responsable designado de gestionar su institución dentro de OnAPB. Accede al panel de administración pero con alcance limitado exclusivamente a los datos de su club. + +### 4.1 Inicio de Sesión + +- En la pantalla de login, pestaña **"Administradores"**. +- Ingresar **usuario** (asignado por un Súper Admin) y **contraseña**. + +### 4.2 Dashboard del Admin de Club (`/admin`) + +Al ingresar, el Admin de Club ve: +- **Estadísticas rápidas** de su club: cantidad de equipos, jugadores y eventos relacionados. +- Nombre e identificación de su club. +- Accesos rápidos a los módulos disponibles. + +### 4.3 Gestión de Jugadores (`/admin/jugadores`) + +#### Ver listado de jugadores +- Lista de todos los jugadores pertenecientes a su club. +- Búsqueda por nombre, apellido o DNI. +- Cada jugador muestra: nombre, DNI, fecha de nacimiento, categoría (calculada automáticamente) y estado (activo/inactivo). + +#### Crear un nuevo jugador +1. Hacer clic en **"Nuevo Jugador"**. +2. Completar el formulario: + - DNI, Nombre, Apellido, Fecha de Nacimiento. + - Club de Origen (puede ser cualquier club del sistema — útil para jugadores con pase). + - El campo "Club Actual" se asigna automáticamente al club del administrador. +3. Guardar. +4. El jugador se crea con estado **inactivo**. Necesitará completar su registro en `/asociate` para activar su cuenta. + +> **Validación:** Si el DNI ya existe en el sistema, se muestra un error indicando a qué club pertenece el jugador actualmente. + +#### Editar un jugador +- Modificar datos básicos (nombre, apellido, fecha de nacimiento, teléfono). +- No puede cambiar el club actual del jugador (eso requiere un pase gestionado por el SuperAdmin). + +#### Eliminar un jugador +- El jugador se marca como eliminado (SoftDelete). No se borra físicamente. + +#### Importar jugadores desde CSV +1. Hacer clic en **"Importar CSV"**. +2. Subir un archivo CSV en formato CAB (Argentina Basketball) o formato interno. +3. El sistema detecta automáticamente el formato y procesa cada fila. +4. Al finalizar, muestra un resumen: nuevos creados, omitidos (ya existían), errores. + +#### Exportar jugadores a CSV +- Descargar el listado completo de jugadores del club en formato CSV. +- Compatible con el reimportador interno del sistema. + +### 4.4 Gestión de Equipos (`/admin/equipos`) + +#### Ver listado de equipos +- Lista de los equipos del club con cantidad de jugadores. + +#### Crear un nuevo equipo +1. Hacer clic en **"Nuevo Equipo"**. +2. Seleccionar **Categoría** (ej: U13, U15, U17, Primera) y Division (A, B, etc.). +3. El club se asigna automáticamente. + +#### Editar y eliminar equipos +- Modificar categoría y división. +- Eliminar (SoftDelete). + +#### Gestionar jugadores del equipo +1. Desde el listado de equipos, hacer clic en el ícono de jugadores (**"Ver Plantel"**). +2. Ver la lista de jugadores asignados a ese equipo. +3. **Agregar jugador**: buscar por nombre/apellido/DNI (búsqueda en tiempo real) y hacer clic en "Agregar". + - Solo se pueden agregar jugadores del mismo club. + - El sistema previene la asignación duplicada. +4. **Remover jugador**: hacer clic en "Quitar" al lado del jugador. + +### 4.5 Editar Identidad Visual del Club (`/admin/clubes/{id}/editar`) + +El Admin de Club puede personalizar la apariencia de su club dentro del sistema: + +- **Logo/Escudo**: subir una imagen (JPEG, PNG, WEBP, máx. 1MB) que aparecerá asociada al club en toda la plataforma. +- **Fondo de QR** (QR Background): subir una imagen que se usará como fondo decorativo en los códigos QR generados para los partidos de su club. +- **Color de texto del QR**: ingresar un color hexadecimal para personalizar la tipografía sobre el QR. + +### 4.6 Gestión de Pases / Traspasos (`/admin/pases`) + +Los pases son solicitudes formales para transferir un jugador de un club a otro. + +#### Solicitar un pase +1. Ir a **Pases** y hacer clic en **"Nuevo Pase"**. +2. Seleccionar el jugador a transferir y el club de destino. +3. Enviar la solicitud. +4. El Súper Admin recibirá la solicitud para aprobarla o rechazarla. + +#### Ver estado de pases +- Listado de todos los pases solicitados por el club. +- Estado posible: **Pendiente**, **Aprobado**, **Rechazado**. + +### 4.7 Escanear QR en Eventos (`/admin/escanear-qr`) + +Esta funcionalidad es para usar en la puerta del evento el día del partido. + +1. Ir a **"Escanear QR"** en el menú. +2. Seleccionar el **evento** (partido) a gestionar. Solo aparecen eventos relacionados con su club. +3. Activar la **cámara** del dispositivo o ingresar manualmente el código del QR. +4. El sistema valida el QR en tiempo real: + - ✅ **QR Válido**: muestra nombre del titular, tipo de QR y pasa el estado a "Usado". + - ❌ **QR Inválido o Ya Usado**: muestra el error correspondiente. + +### 4.8 Cerrar Sesión + +- Hacer clic en **"Cerrar Sesión"** en el menú del panel administrador. + +--- + + +## 👑 Capítulo 5 — Súper Administrador (OnAPB) + +El Súper Admin tiene control total sobre todas las entidades del sistema. Es el personal de la asociación OnAPB. + +### 5.1 Inicio de Sesión + +Igual que el Admin de Club: pestaña "Administradores", usuario y contraseña. + +### 5.2 Dashboard del Súper Admin (`/admin`) + +Al ingresar, el Súper Admin ve: +- **Estadísticas globales**: total de clubes, equipos, jugadores, eventos, promociones y noticias en todo el sistema. +- Accesos rápidos a todos los módulos. + +--- + +### 5.3 Módulo de Clubes (`/admin/clubes`) + +#### Ver todos los clubes +- Lista de todos los clubes registrados con conteo de equipos y jugadores. + +#### Crear un club +1. Clic en **"Nuevo Club"**. +2. Ingresar ID Club (numérico) y Nombre. +3. Guardar. + +#### Editar un club +- Modificar nombre, logo, fondo de QR y color de texto. (Igual que el Admin de Club pero con acceso a cambiar el nombre también). + +#### Eliminar un club +- El club se marca como eliminado (SoftDelete). Los equipos y jugadores asociados quedan preservados. + +--- + +### 5.4 Módulo de Equipos (`/admin/equipos`) + +Idéntico al del Admin de Club pero con visión global (todos los clubes). Al crear un equipo, el Súper Admin puede seleccionar cualquier club del sistema. + +--- + +### 5.5 Módulo de Jugadores (`/admin/jugadores`) + +#### Ver todos los jugadores +- Lista global de todos los jugadores de todos los clubes. +- Filtro por nombre, apellido o DNI. +- Paginación de 25 registros por página. + +#### Crear, editar, eliminar jugador +- Idéntico al Admin de Club pero con acceso a cambiar el **Club Actual** (útil para finiquitar traspasos). + +#### Importar / Exportar CSV +- Importación masiva de jugadores en formato CAB, Interno o Legado. +- Importar para un club específico (seleccionado en el formulario). + +--- + +### 5.6 Módulo de Eventos / Partidos (`/admin/eventos`) + +#### Ver todos los eventos +- Lista de todos los partidos con filtros por estado: Próximos, En Curso, Finalizados. + +#### Crear un nuevo partido +1. Clic en **"Nuevo Evento"**. +2. Completar: + - **Nombre del evento** (generado automáticamente en base a equipos). + - **Equipo Local** y **Equipo Visitante** (deben ser de la misma categoría y grupo si pertenecen a un torneo). + - **Fecha**, **Hora de Inicio** y **Hora de Fin**. + - **Sede**. + - **Torneo** (opcional): asignar el evento a un torneo existente. + - **Límite de QRs por jugador** (configurable). +3. Guardar. El evento queda en estado **"Próximo"**. + +#### Editar un partido +- Modificar cualquier campo del evento. + +#### Registrar resultados +1. Desde el listado de eventos, entrar al evento. +2. Ir a la sección **"Cargar Estadísticas"** o **"Resultado"**. +3. Ingresar marcador local y marcador visitante. +4. Registrar puntos individuales por jugador (para la tabla de goleadores). +5. Guardar. El evento cambia automáticamente a estado **"Finalizado"**. + +#### Eliminar un evento +- El evento se marca como eliminado (SoftDelete). Los QRs asociados se limpian. + +--- + +### 5.7 Módulo de Torneos (`/admin/torneos`) + +#### Crear un torneo +1. Clic en **"Nuevo Torneo"**. +2. Ingresar nombre y año. +3. Guardar. + +#### Añadir equipos al torneo +Desde la vista del torneo: +1. Buscar el equipo a agregar. +2. Asignarle un **grupo** (ej: Grupo A, Grupo B) si aplica. +3. Guardar. + +#### Generar Fixture de Fase Regular +1. Desde el torneo, ir a **"Generar Fixture"**. +2. Configurar la cantidad de vueltas (ida, ida y vuelta). +3. El sistema genera un **preview** de todos los partidos a jugarse. +4. Confirmar para crear los eventos en el sistema. + +#### Importar resultados históricos +- Subir un CSV con resultados de partidos ya jugados para cargar históricos de torneos anteriores. + +#### Gestionar Playoffs +1. Al finalizar la fase regular, ir a **"Playoffs"**. +2. Configurar cuántos equipos clasifican a playoffs. +3. Generar el bracket eliminatorio. +4. A medida que se juegan los partidos, **"Avanzar ganador"** al siguiente cruce. + +#### Ver posiciones y goleadores +- Desde `/torneos/{id}/posiciones`: tabla de posiciones filtrable por grupo/categoría. +- Desde `/torneos/{id}/goleadores`: ranking de anotadores. +- Desde `/torneos/{id}/playoffs`: bracket visual del cuadro eliminatorio. + +--- + +### 5.8 Módulo de Pases / Traspasos (`/admin/pases`) + +#### Ver todos los pases +- Lista de todas las solicitudes de traspaso pendientes, aprobadas y rechazadas. + +#### Aprobar o rechazar un pase +1. Desde el listado, hacer clic en el pase pendiente. +2. Revisar los datos: jugador, club origen, club destino. +3. Hacer clic en **"Aprobar"** → el jugador cambia de club automáticamente. +4. O hacer clic en **"Rechazar"** → el pase queda como rechazado y el jugador permanece en su club actual. + +#### Crear un pase directamente +El Súper Admin puede ejecutar una transferencia sin necesidad de solicitud previa, seleccionando jugador, club destino y guardando. + +--- + +### 5.9 Módulo de Noticias (`/admin/noticias`) + +#### Crear una noticia +1. Clic en **"Nueva Noticia"**. +2. Completar: Título, Contenido (texto largo), Imagen (opcional). +3. Guardar. La noticia aparece en `/noticias`. + +#### Editar y eliminar noticias +- Actualizar cualquier campo. +- Eliminar elimina la noticia del sitio público. + +--- + +### 5.10 Módulo de Promociones (`/admin/promociones`) + +#### Crear una promoción / local con beneficio +1. Clic en **"Nueva Promoción"**. +2. Completar: Nombre del local, Descripción del beneficio, Dirección, Imagen, Coordenadas (para el mapa). +3. Guardar. El local aparece en `/promos`. + +#### Editar y eliminar promociones +- Actualizar información del local. +- Eliminar la promoción del sistema. + +--- + +### 5.11 Módulo de Carrusel / Hero (`/admin/carousel`) + +El carrusel es la sección de diapositivas destacadas en la portada del sitio. + +#### Agregar una diapositiva +1. Clic en **"Nueva Diapositiva"**. +2. Subir una imagen (recomendado: formato ancho/horizontal). +3. Completar un enlace opcional (ej: enlace a una noticia o evento). +4. Guardar. + +#### Editar y eliminar diapositivas +- Actualizar imagen o enlace. +- Eliminar la diapositiva del carrusel. + +--- + +### 5.12 Módulo de Sponsors (`/admin/sponsors`) + +#### Agregar un sponsor +1. Clic en **"Nuevo Sponsor"**. +2. Subir el logo del patrocinador. +3. Ingresar URL del sitio del sponsor (opcional). +4. Guardar. El logo aparece en la franja rotativa del pie de página. + +#### Editar y eliminar sponsors +- Reemplazar logo o cambiar URL. +- Eliminar el sponsor de la franja. + +--- + +### 5.13 Módulo de Usuarios Administradores (`/admin/usuarios`) + +#### Ver todos los administradores +- Lista de todos los usuarios con acceso al panel de administración. + +#### Crear un nuevo administrador +1. Clic en **"Nuevo Usuario Admin"**. +2. Ingresar: + - **Usuario** (nombre de login). + - **Contraseña**. + - **Rol**: `1 = Súper Admin` o `2 = Admin de Club`. + - **Club** (solo si rol 2): asociar al club que administrará. +3. Guardar. + +#### Editar y eliminar administradores +- Cambiar contraseña, rol o club asignado. +- Eliminar el acceso de un administrador. + +--- + +### 5.14 Módulo de Categorías (`/admin/categorias`) + +Las categorías definen los rangos de edad de los jugadores (ej: U13 = 12-13 años). + +#### Crear una categoría +1. Ingresar nombre (ej: "U13"), edad mínima (ej: 12) y edad máxima (ej: 13). +2. Marcar si es **"Categoría Libre"** (los jugadores de esta categoría obtienen 50% de descuento en entradas). +3. Guardar. + +#### Editar y eliminar categorías +- Las categorías modificadas se aplican automáticamente a todos los jugadores ya existentes (la categoría se calcula dinámicamente). + +--- + +### 5.15 Escanear QR en Eventos (`/admin/escanear-qr`) + +Idéntico al del Admin de Club, pero con visión de todos los eventos del sistema. Ver apartado 4.7 para el proceso detallado. + +--- + +### 5.16 Configuración General (`/admin/configuracion`) + +Ajustes globales del sistema: +- Frecuencia de backups automáticos. +- Otros parámetros de comportamiento del sistema. + +--- + +### 5.17 OnAPB Genius — Asistente de IA + +El portal incluye un asistente conversacional basado en IA (Google Gemini) que permite consultar y operar el sistema mediante lenguaje natural. Se invoca desde el botón flotante del chat. + +**Quién puede usar qué:** + +| Rol | Tools disponibles | +|---|---| +| Visitante / Aficionado / Jugador | Chat de ayuda general del portal (sin acceso a operaciones) | +| Administrador de Club | Solo tools de **lectura** | +| Súper Administrador | Lectura + **escritura** + **rollback** | + +**Tools disponibles para Súper Admin:** + +**Lectura (consulta de datos):** +- `listar_torneos` — Lista todos los torneos con ID, nombre y fechas. Usala cuando necesites buscar el ID de un torneo por su nombre. +- `listar_equipos` — Lista equipos. Filtros opcionales: `id_torneo`, `grupo` ("A", "B", ...). +- `listar_eventos` — Lista partidos. Filtros opcionales: `fecha_desde`, `fecha_hasta` (formato YYYY-MM-DD), `id_torneo`. + +**Escritura (modifican la base de datos — requieren tu confirmación explícita):** +- `crear_partido` — Crea un nuevo partido. Campos: `id_equipo_local`, `id_equipo_visitante`, `fecha_evento`, `hora_inicio`, `hora_fin`, `sede`, `id_torneo`. +- `cargar_puntaje` — Actualiza el marcador de un partido existente. Campos: `id_evento` (UUID), `marcador_local`, `marcador_visitante`. +- `redactar_noticia` — Publica una noticia. Campos: `titulo`, `contenido`, `id_torneo` (opcional), `categoria` (opcional). + +**Rollback (deshacer una creación):** +- `eliminar_noticia` — Borra una noticia por su `id_noticia` (numérico). +- `eliminar_partido` — Borra (soft delete) un partido por su `id_evento` (UUID). + +**Cómo se usa (flujo típico):** + +1. Escribí en lenguaje natural lo que querés ("creá una noticia sobre el partido del sábado", "qué equipos hay en el torneo Apertura", "cargá el marcador del partido de ayer 78 a 65"). +2. Si pedís una acción de escritura, Genius **primero te muestra un resumen** con los datos a usar y te pregunta "¿Confirmás?". Tenés que responder "sí", "dale", "confirmo" u "ok" para que ejecute. +3. Tras crear algo, Genius te devuelve el ID del recurso. Guardalo por si querés revertir. +4. Para deshacer: pedile "eliminá la noticia ID X" o "borrá el partido que acabás de crear". Volverá a pedir confirmación antes de borrar. + +**Buenas prácticas:** + +- Si mencionás un torneo/equipo por nombre, Genius usa `listar_torneos` / `listar_equipos` para resolver el ID. No hace falta que lo sepas de memoria. +- Verificá siempre el resumen de confirmación antes de responder "sí". La IA puede interpretar mal fechas o nombres ambiguos. +- Si algo sale mal, revisá `storage/logs/laravel.log` donde quedan registrados los errores de las tools. +- Los límites de la cuenta gratuita de Gemini están configurados en `.env` (`GENIUS_MAX_MESSAGES_PER_SESSION`, `GENIUS_SESSION_WINDOW_MINUTES`). Podés ajustarlos si cambia el uso. + +--- + +## ❓ Preguntas Frecuentes + +**¿Cómo sé si ya tengo una cuenta de jugador?** +Si sos jugador federado, tu DNI ya está en el sistema cargado por el admin de tu club. Solo debés ir a `/asociate` → pestaña "Soy Jugador" e ingresar tus datos para activar la cuenta. + +**¿Puedo tener cuenta de jugador Y de aficionado con el mismo DNI?** +No. El sistema detecta si ya existe un registro (como jugador o aficionado) y te informa antes de permitir el registro. + +**¿Qué pasa si el QR que generé fue escaneado?** +El estado del QR cambia a "Usado" y no puede ser utilizado nuevamente. Cada QR tiene un solo uso. + +**¿Puedo generar el QR de una promo más de una vez?** +No. Por cada usuario y cada promoción, solo se puede generar un QR de beneficio. + +**¿Qué significa cada tipo de QR?** +- `invitado` → Jugador que pertenece a un equipo del partido. Puede generar múltiples (para acompañantes). +- `libre_50` → Jugador de categoría Libre. Obtiene descuento del 50% en la entrada. +- `publico` → Aficionado. Acceso estándar. + +--- + +*Manual redactado para el Proyecto Integrador OnAPB — Taller de Integración, FCYT UADER 2026.* diff --git a/misc/OnAPB - Manual de Usuario.pdf b/misc/OnAPB - Manual de Usuario.pdf new file mode 100644 index 0000000..76ffe70 Binary files /dev/null and b/misc/OnAPB - Manual de Usuario.pdf differ diff --git a/misc/analisis_requerimientos.md b/misc/analisis_requerimientos.md new file mode 100644 index 0000000..0129b6b --- /dev/null +++ b/misc/analisis_requerimientos.md @@ -0,0 +1,42 @@ +# Análisis de Requisitos del Sistema (OnAPB) + +En base a la imagen `requerimientos.jpeg` y la inspección del código fuente actual, aquí está el detalle de qué puntos cumple el sistema, cuáles faltan por desarrollar, y cuáles dependen exclusivamente de la presentación oral. + +## ✅ Requisitos Cumplidos (Implementados en Software) + +| Punto | Descripción | Estado en el Sistema | +| :---: | :--- | :--- | +| **1** | **Innovación** | **Cumple.** La implementación de un sistema de códigos QR digitales para el acceso a eventos y manejo de "Pases" de jugadores digitaliza procesos típicamente manuales o en papel. | +| **2** | **Investigación durante el desarrollo** | **Cumple.** Se evidencia el uso del framework Laravel 11, sistema de autenticación custom (aficionados/jugadores/admin), y estructuración de base de datos relacional. | +| **6** | **Justificación de Ingeniería de Software** | **Cumple.** El sistema utiliza un patrón arquitectónico claro (MVC provisto por Laravel), ORM (Eloquent), migraciones de base de datos y un enrutamiento ordenado. | +| **7** | **Conocimiento del negocio** | **Cumple.** El software modela perfectamente la lógica de una asociación de básquet: Clubes, Equipos, Jugadores, pases interclubes, categorías por edad y gestión de aforos de QRs por partido. | +| **9** | **Completitud de software** | **Parcialmente Cumplido.** El sistema tiene paneles de usuario y admin muy completos (fases 1 a 5 de la Hoja de Ruta). Sin embargo, la **Fase 6 (Pagos con Banco Macro)** está pendiente. | + +--- + +## ❌ Requisitos Faltantes (Deuda Técnica a Resolver) + +| Punto | Descripción | Lo que falta hacer | +| :---: | :--- | :--- | +| **8** | **Pruebas y errores, end-to-end** | **FALTA.** La carpeta `tests/` está vacía (solo tiene el test de ejemplo de Laravel). No hay pruebas unitarias (PHPUnit) ni pruebas de integración o E2E (Laravel Dusk) configuradas ni ejecutadas. | +| **10** | **Recuperación ante fallos/desastres** | **FALTA.** No hay un sistema de copias de seguridad de la base de datos (ej. Laravel Backup). Además, los modelos actuales **no usan SoftDeletes**, por lo que si un admin elimina un equipo, jugador o evento, los datos **se pierden permanentemente** (Hard Delete) y pueden romper relaciones. | +| **13** | **Documentación Técnica y de Usuario** | **FALTA.** El archivo `README.md` del repositorio es el que viene por defecto con Laravel original en inglés. La `HOJA-DE-RUTA.md` es solo un checklist. Se necesita redactar un manual de usuario (ej: cómo usar el panel admin) y un manual técnico (cómo instalar el proyecto, variables de entorno, esquema de BD). | + +--- + +## 🗣️ Requisitos que NO dependen del software (Evaluación Oral/Grupal) + +Estos puntos no se programan, sino que se evaluarán durante la defensa del proyecto: + +* **3 - Tiempo/dedicación en finalizar.** (Se demuestra presentando el volumen de trabajo hecho, que es bastante amplio). +* **4 - Exposición oral.** +* **5 - Evaluación de dinámica grupal.** +* **11 - Revisiones de procesos y sugerencias por parte de los profesionales.** (Conclusiones del grupo). +* **12 - Pruebas y errores durante la exposición (datos reales).** (Asegúrense de tener la base de datos poblada con clubes, jugadores y eventos reales o realistas el día de la presentación). + +--- + +### 🚀 Siguientes pasos recomendados para aprobar: +1. Reemplazar el `README.md` por documentación real técnica y de usuario. +2. Añadir `SoftDeletes` a las tablas críticas (`jugadores`, `clubes`, `equipos`, `eventos`) para cumplir el Punto 10. +3. Escribir al menos 3 o 4 Tests básicos (Feature tests) simulando el login y la emisión de QRs para cubrir el Punto 8. diff --git a/misc/onapb-security-hardening.md b/misc/onapb-security-hardening.md new file mode 100644 index 0000000..2cfc70b --- /dev/null +++ b/misc/onapb-security-hardening.md @@ -0,0 +1,334 @@ +# Blueprint de Seguridad — onapb.com +**Generado por:** The Architect +**Fecha:** 2026-04-01 +**Para ejecutar con:** Claude Code en el repositorio del sistema + +--- + +## Contexto + +Este documento es una instrucción completa y autónoma para que Claude Code implemente todas las mejoras de seguridad detectadas en el sitio **onapb.com**. + +- **Stack:** Laravel (PHP 8.4.11) + LiteSpeed + Hostinger +- **Framework detectado:** Laravel (confirmado por cookies `laravel-session` y `XSRF-TOKEN`) +- **Dev responsable:** único desarrollador con acceso completo al repositorio + +Ejecutá cada paso en orden. No saltes pasos. Al final, hacé deploy a producción. + +--- + +## CLAUDE.md para este proyecto + +``` +Sos el implementador de seguridad del sitio onapb.com. +Tu tarea es implementar los cambios de seguridad descritos en este archivo en orden. +El stack es Laravel. No rompas funcionalidad existente. +Al terminar cada paso, confirmá que los tests pasen antes de avanzar. +``` + +--- + +## Orden de implementación + +### PASO 1 — Middleware de Security Headers + +**Problema:** Faltan 5 headers de seguridad críticos: +- `Strict-Transport-Security` (HSTS) +- `X-Frame-Options` +- `X-Content-Type-Options` +- `X-XSS-Protection` +- `Content-Security-Policy` (actualmente solo tiene `upgrade-insecure-requests`) + +**Qué hacer:** + +1. Crear el archivo `app/Http/Middleware/SecurityHeaders.php`: + +```php +headers->set('X-Frame-Options', 'SAMEORIGIN'); + $response->headers->set('X-Content-Type-Options', 'nosniff'); + $response->headers->set('X-XSS-Protection', '1; mode=block'); + $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin'); + $response->headers->set( + 'Permissions-Policy', + 'camera=(), microphone=(), geolocation=()' + ); + $response->headers->set( + 'Strict-Transport-Security', + 'max-age=31536000; includeSubDomains; preload' + ); + $response->headers->set( + 'Content-Security-Policy', + "default-src 'self'; " . + "script-src 'self' 'unsafe-inline' 'unsafe-eval'; " . + "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " . + "font-src 'self' data: https://fonts.gstatic.com; " . + "img-src 'self' data: https:; " . + "connect-src 'self'; " . + "frame-ancestors 'self';" + ); + + return $response; + } +} +``` + +2. Registrar el middleware en `app/Http/Kernel.php`, dentro de `$middlewareGroups['web']`, al final del array: + +```php +\App\Http\Middleware\SecurityHeaders::class, +``` + +3. Verificar: hacer `php artisan route:list` y luego una request curl local para confirmar que los headers aparecen. + +--- + +### PASO 2 — Ocultar versión de PHP y stack + +**Problema:** El header `X-Powered-By: PHP/8.4.11` y `Server: LiteSpeed` revelan el stack exacto. + +**Qué hacer:** + +1. En el archivo `public/.htaccess`, agregar al inicio (después de `` o antes): + +```apache +# Ocultar headers de servidor + + Header unset X-Powered-By + Header always unset X-Powered-By + Header unset Server + +``` + +2. Si tenés acceso a `php.ini` (en Hostinger hPanel → PHP → php.ini personalizado): + +```ini +expose_php = Off +``` + +3. Si usás un archivo `php.ini` en la raíz del proyecto, agregar esa línea ahí también. + +--- + +### PASO 3 — Forzar HTTPS y HSTS en .htaccess + +**Problema:** El sitio no sirve headers HSTS. El HSTS del Paso 1 solo actúa cuando ya estás en HTTPS, pero si alguien entra por HTTP no hay redirect forzado a nivel servidor. + +**Qué hacer:** + +En `public/.htaccess`, asegurar que exista este bloque (Laravel suele tenerlo pero verificar): + +```apache + + RewriteEngine On + + # Forzar HTTPS + RewriteCond %{HTTPS} off + RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] + + # Resto de reglas de Laravel... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] + +``` + +--- + +### PASO 4 — Proteger archivo .env y rutas sensibles + +**Problema:** Laravel ya protege `.env` por defecto, pero verificar que las rutas de storage no sean accesibles. + +**Qué hacer:** + +En `public/.htaccess`, agregar: + +```apache +# Bloquear acceso a archivos sensibles + + Order allow,deny + Deny from all + + +# Bloquear acceso directo a /storage si está symlinkado + + RewriteRule ^storage/app/(.*)$ - [F,L] + +``` + +--- + +### PASO 5 — Mejorar robots.txt + +**Problema:** El `robots.txt` actual tiene `Disallow: ""` (vacío), lo que permite que todos los bots indexen todo, incluidas rutas como `/recuperar` y rutas de admin. + +**Qué hacer:** + +Reemplazar el contenido de `public/robots.txt` (o crearlo si no existe): + +``` +User-agent: * +Disallow: /admin +Disallow: /recuperar +Disallow: /api/ +Disallow: /storage/ +Disallow: /vendor/ +Allow: / + +Sitemap: https://onapb.com/sitemap.xml +``` + +--- + +### PASO 6 — Agregar security.txt + +**Problema:** No existe `/well-known/security.txt`. Es una buena práctica de divulgación responsable. + +**Qué hacer:** + +1. Crear el directorio `public/.well-known/` +2. Crear el archivo `public/.well-known/security.txt`: + +``` +Contact: mailto:admin@onapb.com +Expires: 2027-04-01T00:00:00Z +Preferred-Languages: es, en +Canonical: https://onapb.com/.well-known/security.txt +``` + +(Reemplazar `admin@onapb.com` con el email real del responsable de seguridad.) + +--- + +### PASO 7 — Rate limiting en rutas críticas + +**Problema:** No se detectó rate limiting explícito. Rutas como `/recuperar` (recuperación de contraseña) son vectores de ataque por fuerza bruta y enumeración de usuarios. + +**Qué hacer:** + +En `routes/web.php` o en el middleware de rutas, asegurar rate limiting en rutas sensibles: + +```php +Route::middleware(['throttle:5,1'])->group(function () { + Route::post('/recuperar', [PasswordController::class, 'sendResetLink']); + Route::post('/login', [AuthController::class, 'login']); +}); +``` + +El `5,1` significa 5 intentos por minuto. Ajustar según la lógica del negocio. + +Si el proyecto usa Laravel Breeze o Fortify, ya tiene esto incorporado — verificar que esté habilitado en `config/fortify.php`: + +```php +'limiters' => [ + 'login' => 'login', +], +``` + +--- + +### PASO 8 — Configurar Content Security Policy estricta (opcional pero recomendado) + +**Problema:** La CSP del Paso 1 usa `'unsafe-inline'` y `'unsafe-eval'` como fallback seguro. Si el proyecto no necesita eval, endurecerla. + +**Qué hacer:** + +Una vez que el sitio esté corriendo con el middleware del Paso 1, revisar la consola del navegador por errores de CSP. Si no hay errores de scripts inline, cambiar en `SecurityHeaders.php`: + +```php +"script-src 'self';" // quitar unsafe-inline y unsafe-eval +``` + +Esto requiere que todos los scripts estén en archivos externos, no inline. + +--- + +## Pasos que requieren acción MANUAL (fuera del repositorio) + +Estos cambios no se hacen en el código — son configuraciones del servidor/DNS. Documentarlos para hacerlos en paralelo: + +### A — Cerrar puerto 3306 (CRÍTICO — hacer YA) +- En Hostinger hPanel → Seguridad → Firewall +- Bloquear acceso externo al puerto 3306 (MySQL) +- Solo debe aceptar conexiones desde `127.0.0.1` (localhost) +- Verificar en `.env`: `DB_HOST=127.0.0.1` + +### B — Deshabilitar FTP (puerto 21) +- En Hostinger hPanel → Archivos → Administrador FTP +- Deshabilitar FTP o cambiar a SFTP (puerto 22) + +### C — Migrar DNS a Cloudflare (recomendado para WAF) +- Crear cuenta en cloudflare.com +- Agregar el dominio `onapb.com` +- Cambiar los nameservers en Registrar.eu (registrar actual) a los de Cloudflare +- Habilitar WAF en plan gratuito +- Habilitar DNSSEC en Cloudflare (un click) +- Habilitar proxy (nube naranja) para ocultar IP real + +### D — Configurar DMARC + endurecer SPF +En el panel DNS (Hostinger o Cloudflare): + +**Cambiar SPF existente** (`~all` → `-all`): +``` +v=spf1 include:_spf.mail.hostinger.com -all +``` + +**Agregar registro DMARC** (nuevo TXT en `_dmarc.onapb.com`): +``` +v=DMARC1; p=quarantine; rua=mailto:admin@onapb.com; fo=1 +``` + +### E — Verificar DKIM +En Hostinger hPanel → Email → Configuración de dominio → habilitar DKIM si no está activo. + +--- + +## Orden de deploy + +Una vez implementados los pasos de código (1 al 8): + +1. Correr tests: `php artisan test` +2. Verificar que la app levanta: `php artisan serve` + revisar consola del browser +3. Hacer commit con mensaje: `security: add security headers middleware and hardening` +4. Push a rama de staging si existe, sino directo a `main` +5. Deploy a producción (según el proceso actual del proyecto) +6. Verificar headers en producción: usar [securityheaders.com](https://securityheaders.com) con `onapb.com` +7. Verificar que el sitio funciona 100% antes de cerrar puertos (paso manual A) + +--- + +## Verificación post-deploy + +Correr estos checks para confirmar que todo quedó bien: + +| Check | Herramienta | URL | +|-------|-------------|-----| +| Headers HTTP | Security Headers | securityheaders.com | +| SSL/TLS | SSL Labs | ssllabs.com/ssltest | +| HSTS | hstspreload.org | hstspreload.org | +| Reputación IP | VirusTotal | virustotal.com | +| Puertos | Shodan | shodan.io | + +--- + +## Resultado esperado + +Al completar todos los pasos, el sitio debe: +- Obtener calificación **A** en securityheaders.com (actualmente F) +- No exponer versión de PHP ni stack en headers +- Tener HSTS activo con preload +- No tener puertos de base de datos expuestos a internet +- Tener protección WAF básica via Cloudflare +- Tener autenticación de email (SPF + DKIM + DMARC) diff --git a/misc/requerimientos.jpeg b/misc/requerimientos.jpeg new file mode 100644 index 0000000..2f44deb Binary files /dev/null and b/misc/requerimientos.jpeg differ