diff --git a/app/Http/Middleware/SetLocale.php b/app/Http/Middleware/SetLocale.php new file mode 100644 index 0000000..a17bea5 --- /dev/null +++ b/app/Http/Middleware/SetLocale.php @@ -0,0 +1,54 @@ +locale; + if ($userLocale && in_array($userLocale, ['en', 'es'])) { + $locale = $userLocale; + } + } + + // 2. From session + if (!$locale && Session::has('locale')) { + $sessionLocale = Session::get('locale'); + if (in_array($sessionLocale, ['en', 'es'])) { + $locale = $sessionLocale; + } + } + + // 3. From browser Accept-Language + if (!$locale) { + $browserLang = substr($request->server('HTTP_ACCEPT_LANGUAGE', 'en'), 0, 2); + if (in_array($browserLang, ['en', 'es'])) { + $locale = $browserLang; + } + } + + // 4. Default to English + if (!$locale) { + $locale = 'en'; + } + + App::setLocale($locale); + Session::put('locale', $locale); + + return $next($request); + } +} \ No newline at end of file diff --git a/app/Livewire/LanguageSwitcher.php b/app/Livewire/LanguageSwitcher.php new file mode 100644 index 0000000..f74bee5 --- /dev/null +++ b/app/Livewire/LanguageSwitcher.php @@ -0,0 +1,42 @@ +currentLocale = App::getLocale(); + } + + public function switchLanguage($locale) + { + if (!in_array($locale, ['en', 'es'])) { + return; + } + + App::setLocale($locale); + Session::put('locale', $locale); + + if (Auth::check()) { + $user = Auth::user(); + $user->locale = $locale; + $user->save(); + } + + $this->currentLocale = $locale; + $this->dispatch('localeChanged', $locale); + } + + public function render() + { + return view('livewire.language-switcher'); + } +} \ No newline at end of file diff --git a/bootstrap/app.php b/bootstrap/app.php index c183276..a538094 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -11,7 +11,7 @@ return Application::configure(basePath: dirname(__DIR__)) health: '/up', ) ->withMiddleware(function (Middleware $middleware): void { - // + $middleware->appendToGroup('web', \App\Http\Middleware\SetLocale::class); }) ->withExceptions(function (Exceptions $exceptions): void { // diff --git a/database/migrations/2026_05_09_220000_add_locale_to_users_table.php b/database/migrations/2026_05_09_220000_add_locale_to_users_table.php new file mode 100644 index 0000000..e985039 --- /dev/null +++ b/database/migrations/2026_05_09_220000_add_locale_to_users_table.php @@ -0,0 +1,22 @@ +string('locale', 5)->default('en')->after('remember_token'); + }); + } + + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('locale'); + }); + } +}; \ No newline at end of file diff --git a/lang/en.json b/lang/en.json new file mode 100644 index 0000000..9e85cf4 --- /dev/null +++ b/lang/en.json @@ -0,0 +1,140 @@ +{ + "Dashboard": "Dashboard", + "Projects": "Projects", + "Project": "Project", + "Create Project": "Create Project", + "Edit Project": "Edit Project", + "New Project": "New Project", + "Delete Project": "Delete Project", + "Project name": "Project name", + "Name": "Name", + "Address": "Address", + "Status": "Status", + "Progress": "Progress", + "Phases": "Phases", + "Phase": "Phase", + "Layer": "Layer", + "Layers": "Layers", + "Features": "Features", + "Feature": "Element", + "Create": "Create", + "Edit": "Edit", + "Delete": "Delete", + "Save": "Save", + "Update": "Update", + "Cancel": "Cancel", + "Search": "Search", + "Filter": "Filter", + "Back": "Back", + "Actions": "Actions", + "Map": "Map", + "View Map": "View Map", + "Manage Layers": "Manage Layers", + "Upload Layer": "Upload Layer", + "Upload file": "Upload file", + "Download": "Download", + "Fullscreen": "Fullscreen", + "Close": "Close", + "Are you sure?": "Are you sure?", + "No results": "No results", + "Loading": "Loading", + "Active projects": "Active projects", + "Total projects": "Total projects", + "Total phases": "Total phases", + "Total features": "Total elements", + "Global progress": "Global progress", + "Recent projects": "Recent projects", + "Recent inspections": "Recent inspections", + "Planning": "Planning", + "In progress": "In progress", + "Paused": "Paused", + "Completed": "Completed", + "Progress updated": "Progress updated", + "Save progress": "Save progress", + "Responsible": "Responsible", + "Comment": "Comment", + "History": "History", + "Inspection": "Inspection", + "Template": "Template", + "Templates": "Templates", + "Create Template": "Create Template", + "Inspection template": "Inspection template", + "Field": "Field", + "Fields": "Fields", + "Field name": "Field name", + "Field type": "Field type", + "Required": "Required", + "Options": "Options", + "Show images on map": "Show images on map", + "Project files": "Project files", + "Media": "Media", + "Images": "Images", + "Documents": "Documents", + "Upload images": "Upload images", + "Upload documents": "Upload documents", + "Upload files": "Upload files", + "Drop files here": "Drop files here", + "File": "File", + "Files": "Files", + "Category": "Category", + "Description": "Description", + "Size": "Size", + "Uploaded by": "Uploaded by", + "Uploaded at": "Uploaded at", + "No files yet": "No files yet", + "Delete file": "Delete file", + "Layer name": "Layer name", + "Layer color": "Layer color", + "Import file": "Import file", + "Empty layer": "Empty layer", + "Create empty layer": "Create empty layer", + "Select phase": "Select phase", + "Select project": "Select project", + "Visible layers": "Visible layers", + "Edit layer": "Edit layer", + "Delete layer": "Delete layer", + "Sign in": "Sign in", + "Sign out": "Sign out", + "Register": "Register", + "Email": "Email", + "Password": "Password", + "Confirm password": "Confirm password", + "Forgot password": "Forgot password", + "Remember me": "Remember me", + "Profile": "Profile", + "Update profile": "Update profile", + "Language": "Language", + "English": "English", + "Spanish": "Spanish", + "Select language": "Select language", + "Notifications": "Notifications", + "Permissions": "Permissions", + "Administrator": "Administrator", + "Users": "Users", + "Roles": "Roles", + "Click on an element to edit": "Click on an element to edit", + "No templates yet": "No templates yet", + "Create an inspection template": "Create an inspection template", + "No phases yet": "No phases yet", + "Start date": "Start date", + "Estimated end date": "Estimated end date", + "Centered in project": "Centered in project", + "My location": "My location", + "File type not allowed": "File type not allowed", + "Upload failed": "Upload failed", + "Conversion failed": "Conversion failed", + "All": "All", + "Latitude": "Latitude", + "Longitude": "Longitude", + "Register inspection": "Register inspection", + "Files of element": "Files of element", + "Fases and layers": "Phases and layers", + "Elements": "Elements", + "optional": "optional", + "each": "each", + "Image": "Image", + "Document": "Document", + "Other": "Other", + "Color": "Color", + "Upload": "Upload" +} diff --git a/lang/en/auth.php b/lang/en/auth.php new file mode 100644 index 0000000..6598e2c --- /dev/null +++ b/lang/en/auth.php @@ -0,0 +1,20 @@ + 'These credentials do not match our records.', + 'password' => 'The provided password is incorrect.', + 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', + +]; diff --git a/lang/en/pagination.php b/lang/en/pagination.php new file mode 100644 index 0000000..d481411 --- /dev/null +++ b/lang/en/pagination.php @@ -0,0 +1,19 @@ + '« Previous', + 'next' => 'Next »', + +]; diff --git a/lang/en/passwords.php b/lang/en/passwords.php new file mode 100644 index 0000000..fad3a7d --- /dev/null +++ b/lang/en/passwords.php @@ -0,0 +1,22 @@ + 'Your password has been reset.', + 'sent' => 'We have emailed your password reset link.', + 'throttled' => 'Please wait before retrying.', + 'token' => 'This password reset token is invalid.', + 'user' => "We can't find a user with that email address.", + +]; diff --git a/lang/en/validation.php b/lang/en/validation.php new file mode 100644 index 0000000..63ec29a --- /dev/null +++ b/lang/en/validation.php @@ -0,0 +1,200 @@ + 'The :attribute field must be accepted.', + 'accepted_if' => 'The :attribute field must be accepted when :other is :value.', + 'active_url' => 'The :attribute field must be a valid URL.', + 'after' => 'The :attribute field must be a date after :date.', + 'after_or_equal' => 'The :attribute field must be a date after or equal to :date.', + 'alpha' => 'The :attribute field must only contain letters.', + 'alpha_dash' => 'The :attribute field must only contain letters, numbers, dashes, and underscores.', + 'alpha_num' => 'The :attribute field must only contain letters and numbers.', + 'any_of' => 'The :attribute field is invalid.', + 'array' => 'The :attribute field must be an array.', + 'ascii' => 'The :attribute field must only contain single-byte alphanumeric characters and symbols.', + 'before' => 'The :attribute field must be a date before :date.', + 'before_or_equal' => 'The :attribute field must be a date before or equal to :date.', + 'between' => [ + 'array' => 'The :attribute field must have between :min and :max items.', + 'file' => 'The :attribute field must be between :min and :max kilobytes.', + 'numeric' => 'The :attribute field must be between :min and :max.', + 'string' => 'The :attribute field must be between :min and :max characters.', + ], + 'boolean' => 'The :attribute field must be true or false.', + 'can' => 'The :attribute field contains an unauthorized value.', + 'confirmed' => 'The :attribute field confirmation does not match.', + 'contains' => 'The :attribute field is missing a required value.', + 'current_password' => 'The password is incorrect.', + 'date' => 'The :attribute field must be a valid date.', + 'date_equals' => 'The :attribute field must be a date equal to :date.', + 'date_format' => 'The :attribute field must match the format :format.', + 'decimal' => 'The :attribute field must have :decimal decimal places.', + 'declined' => 'The :attribute field must be declined.', + 'declined_if' => 'The :attribute field must be declined when :other is :value.', + 'different' => 'The :attribute field and :other must be different.', + 'digits' => 'The :attribute field must be :digits digits.', + 'digits_between' => 'The :attribute field must be between :min and :max digits.', + 'dimensions' => 'The :attribute field has invalid image dimensions.', + 'distinct' => 'The :attribute field has a duplicate value.', + 'doesnt_contain' => 'The :attribute field must not contain any of the following: :values.', + 'doesnt_end_with' => 'The :attribute field must not end with one of the following: :values.', + 'doesnt_start_with' => 'The :attribute field must not start with one of the following: :values.', + 'email' => 'The :attribute field must be a valid email address.', + 'encoding' => 'The :attribute field must be encoded in :encoding.', + 'ends_with' => 'The :attribute field must end with one of the following: :values.', + 'enum' => 'The selected :attribute is invalid.', + 'exists' => 'The selected :attribute is invalid.', + 'extensions' => 'The :attribute field must have one of the following extensions: :values.', + 'file' => 'The :attribute field must be a file.', + 'filled' => 'The :attribute field must have a value.', + 'gt' => [ + 'array' => 'The :attribute field must have more than :value items.', + 'file' => 'The :attribute field must be greater than :value kilobytes.', + 'numeric' => 'The :attribute field must be greater than :value.', + 'string' => 'The :attribute field must be greater than :value characters.', + ], + 'gte' => [ + 'array' => 'The :attribute field must have :value items or more.', + 'file' => 'The :attribute field must be greater than or equal to :value kilobytes.', + 'numeric' => 'The :attribute field must be greater than or equal to :value.', + 'string' => 'The :attribute field must be greater than or equal to :value characters.', + ], + 'hex_color' => 'The :attribute field must be a valid hexadecimal color.', + 'image' => 'The :attribute field must be an image.', + 'in' => 'The selected :attribute is invalid.', + 'in_array' => 'The :attribute field must exist in :other.', + 'in_array_keys' => 'The :attribute field must contain at least one of the following keys: :values.', + 'integer' => 'The :attribute field must be an integer.', + 'ip' => 'The :attribute field must be a valid IP address.', + 'ipv4' => 'The :attribute field must be a valid IPv4 address.', + 'ipv6' => 'The :attribute field must be a valid IPv6 address.', + 'json' => 'The :attribute field must be a valid JSON string.', + 'list' => 'The :attribute field must be a list.', + 'lowercase' => 'The :attribute field must be lowercase.', + 'lt' => [ + 'array' => 'The :attribute field must have less than :value items.', + 'file' => 'The :attribute field must be less than :value kilobytes.', + 'numeric' => 'The :attribute field must be less than :value.', + 'string' => 'The :attribute field must be less than :value characters.', + ], + 'lte' => [ + 'array' => 'The :attribute field must not have more than :value items.', + 'file' => 'The :attribute field must be less than or equal to :value kilobytes.', + 'numeric' => 'The :attribute field must be less than or equal to :value.', + 'string' => 'The :attribute field must be less than or equal to :value characters.', + ], + 'mac_address' => 'The :attribute field must be a valid MAC address.', + 'max' => [ + 'array' => 'The :attribute field must not have more than :max items.', + 'file' => 'The :attribute field must not be greater than :max kilobytes.', + 'numeric' => 'The :attribute field must not be greater than :max.', + 'string' => 'The :attribute field must not be greater than :max characters.', + ], + 'max_digits' => 'The :attribute field must not have more than :max digits.', + 'mimes' => 'The :attribute field must be a file of type: :values.', + 'mimetypes' => 'The :attribute field must be a file of type: :values.', + 'min' => [ + 'array' => 'The :attribute field must have at least :min items.', + 'file' => 'The :attribute field must be at least :min kilobytes.', + 'numeric' => 'The :attribute field must be at least :min.', + 'string' => 'The :attribute field must be at least :min characters.', + ], + 'min_digits' => 'The :attribute field must have at least :min digits.', + 'missing' => 'The :attribute field must be missing.', + 'missing_if' => 'The :attribute field must be missing when :other is :value.', + 'missing_unless' => 'The :attribute field must be missing unless :other is :value.', + 'missing_with' => 'The :attribute field must be missing when :values is present.', + 'missing_with_all' => 'The :attribute field must be missing when :values are present.', + 'multiple_of' => 'The :attribute field must be a multiple of :value.', + 'not_in' => 'The selected :attribute is invalid.', + 'not_regex' => 'The :attribute field format is invalid.', + 'numeric' => 'The :attribute field must be a number.', + 'password' => [ + 'letters' => 'The :attribute field must contain at least one letter.', + 'mixed' => 'The :attribute field must contain at least one uppercase and one lowercase letter.', + 'numbers' => 'The :attribute field must contain at least one number.', + 'symbols' => 'The :attribute field must contain at least one symbol.', + 'uncompromised' => 'The given :attribute has appeared in a data leak. Please choose a different :attribute.', + ], + 'present' => 'The :attribute field must be present.', + 'present_if' => 'The :attribute field must be present when :other is :value.', + 'present_unless' => 'The :attribute field must be present unless :other is :value.', + 'present_with' => 'The :attribute field must be present when :values is present.', + 'present_with_all' => 'The :attribute field must be present when :values are present.', + 'prohibited' => 'The :attribute field is prohibited.', + 'prohibited_if' => 'The :attribute field is prohibited when :other is :value.', + 'prohibited_if_accepted' => 'The :attribute field is prohibited when :other is accepted.', + 'prohibited_if_declined' => 'The :attribute field is prohibited when :other is declined.', + 'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.', + 'prohibits' => 'The :attribute field prohibits :other from being present.', + 'regex' => 'The :attribute field format is invalid.', + 'required' => 'The :attribute field is required.', + 'required_array_keys' => 'The :attribute field must contain entries for: :values.', + 'required_if' => 'The :attribute field is required when :other is :value.', + 'required_if_accepted' => 'The :attribute field is required when :other is accepted.', + 'required_if_declined' => 'The :attribute field is required when :other is declined.', + 'required_unless' => 'The :attribute field is required unless :other is in :values.', + 'required_with' => 'The :attribute field is required when :values is present.', + 'required_with_all' => 'The :attribute field is required when :values are present.', + 'required_without' => 'The :attribute field is required when :values is not present.', + 'required_without_all' => 'The :attribute field is required when none of :values are present.', + 'same' => 'The :attribute field must match :other.', + 'size' => [ + 'array' => 'The :attribute field must contain :size items.', + 'file' => 'The :attribute field must be :size kilobytes.', + 'numeric' => 'The :attribute field must be :size.', + 'string' => 'The :attribute field must be :size characters.', + ], + 'starts_with' => 'The :attribute field must start with one of the following: :values.', + 'string' => 'The :attribute field must be a string.', + 'timezone' => 'The :attribute field must be a valid timezone.', + 'unique' => 'The :attribute has already been taken.', + 'uploaded' => 'The :attribute failed to upload.', + 'uppercase' => 'The :attribute field must be uppercase.', + 'url' => 'The :attribute field must be a valid URL.', + 'ulid' => 'The :attribute field must be a valid ULID.', + 'uuid' => 'The :attribute field must be a valid UUID.', + + /* + |-------------------------------------------------------------------------- + | Custom Validation Language Lines + |-------------------------------------------------------------------------- + | + | Here you may specify custom validation messages for attributes using the + | convention "attribute.rule" to name the lines. This makes it quick to + | specify a specific custom language line for a given attribute rule. + | + */ + + 'custom' => [ + 'attribute-name' => [ + 'rule-name' => 'custom-message', + ], + ], + + /* + |-------------------------------------------------------------------------- + | Custom Validation Attributes + |-------------------------------------------------------------------------- + | + | The following language lines are used to swap our attribute placeholder + | with something more reader friendly such as "E-Mail Address" instead + | of "email". This simply helps us make our message more expressive. + | + */ + + 'attributes' => [], + +]; diff --git a/lang/es.json b/lang/es.json new file mode 100644 index 0000000..684e924 --- /dev/null +++ b/lang/es.json @@ -0,0 +1,141 @@ +{ + "Dashboard": "Panel de control", + "Projects": "Proyectos", + "Project": "Proyecto", + "Create Project": "Crear proyecto", + "Edit Project": "Editar proyecto", + "New Project": "Nuevo proyecto", + "Delete Project": "Eliminar proyecto", + "Project name": "Nombre del proyecto", + "Name": "Nombre", + "Address": "Dirección", + "Status": "Estado", + "Progress": "Progreso", + "Phases": "Fases", + "Phase": "Fase", + "Layer": "Capa", + "Layers": "Capas", + "Features": "Elementos", + "Feature": "Elemento", + "Create": "Crear", + "Edit": "Editar", + "Delete": "Eliminar", + "Save": "Guardar", + "Update": "Actualizar", + "Cancel": "Cancelar", + "Search": "Buscar", + "Filter": "Filtro", + "Back": "Volver", + "Actions": "Acciones", + "Map": "Mapa", + "View Map": "Ver mapa", + "Manage Layers": "Gestionar capas", + "Upload Layer": "Subir capa", + "Upload file": "Subir archivo", + "Download": "Descargar", + "Fullscreen": "Pantalla completa", + "Close": "Cerrar", + "Are you sure?": "¿Estás seguro?", + "No results": "Sin resultados", + "Loading": "Cargando", + "Active projects": "Proyectos activos", + "Total projects": "Proyectos totales", + "Total phases": "Fases totales", + "Total features": "Elementos totales", + "Global progress": "Progreso global", + "Recent projects": "Proyectos recientes", + "Recent inspections": "Inspecciones recientes", + "Planning": "Planificación", + "In progress": "En obra", + "Paused": "Pausado", + "Completed": "Finalizado", + "Progress updated": "Progreso actualizado", + "Save progress": "Guardar progreso", + "Responsible": "Responsable", + "Comment": "Comentario", + "History": "Historial", + "Inspection": "Inspección", + "Template": "Plantilla", + "Templates": "Plantillas", + "Create Template": "Crear plantilla", + "Inspection template": "Plantilla de inspección", + "Field": "Campo", + "Fields": "Campos", + "Field name": "Nombre del campo", + "Field type": "Tipo de campo", + "Required": "Obligatorio", + "Options": "Opciones", + "Show images on map": "Mostrar imágenes en mapa", + "Project files": "Archivos del proyecto", + "Media": "Archivos", + "Images": "Imágenes", + "Documents": "Documentos", + "Upload images": "Subir imágenes", + "Upload documents": "Subir documentos", + "Upload files": "Subir archivos", + "Drop files here": "Suelta archivos aquí", + "File": "Archivo", + "Files": "Archivos", + "Category": "Categoría", + "Description": "Descripción", + "Size": "Tamaño", + "Uploaded by": "Subido por", + "Uploaded at": "Subido el", + "No files yet": "Aún no hay archivos", + "Delete file": "Eliminar archivo", + "Layer name": "Nombre de capa", + "Layer color": "Color de capa", + "Import file": "Importar archivo", + "Empty layer": "Capa vacía", + "Create empty layer": "Crear capa vacía", + "Select phase": "Seleccionar fase", + "Select project": "Seleccionar proyecto", + "Visible layers": "Capas visibles", + "Edit layer": "Editar capa", + "Delete layer": "Eliminar capa", + "Sign in": "Iniciar sesión", + "Sign out": "Cerrar sesión", + "Register": "Registrarse", + "Email": "Correo", + "Password": "Contraseña", + "Confirm password": "Confirmar contraseña", + "Forgot password": "Olvidé mi contraseña", + "Remember me": "Recordarme", + "Profile": "Perfil", + "Update profile": "Actualizar perfil", + "Language": "Idioma", + "English": "Inglés", + "Spanish": "Español", + "Select language": "Seleccionar idioma", + "Notifications": "Notificaciones", + "Permissions": "Permisos", + "Administrator": "Administrador", + "Users": "Usuarios", + "Roles": "Roles", + "Click on an element to edit": "Haz clic en un elemento para editarlo", + "No templates yet": "No hay plantillas aún", + "Create an inspection template": "Crea una plantilla de inspección", + "No phases yet": "No hay fases aún", + "Start date": "Fecha de inicio", + "Estimated end date": "Fecha estimada de fin", + "Centered in project": "Centrar en proyecto", + "My location": "Mi ubicación", + "File type not allowed": "Tipo de archivo no permitido", + "Upload failed": "Error al subir", + "Conversion failed": "Error de conversión", + "All": "Todos", + "Latitude": "Latitud", + "Longitude": "Longitud", + "Register inspection": "Registrar inspección", + "Files of element": "Archivos del elemento", + "Fases and layers": "Fases y capas", + "Elements": "Elementos", + "Log Out": "Cerrar sesión", + "optional": "opcional", + "each": "cada", + "Image": "Imagen", + "Document": "Documento", + "Other": "Otro", + "Color": "Color", + "Upload": "Subir" +} diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php index 97a1596..e619c19 100644 --- a/resources/views/dashboard.blade.php +++ b/resources/views/dashboard.blade.php @@ -10,46 +10,46 @@ {{-- Stats cards --}}
-
Proyectos activos
+
{{ __('Active projects') }}
{{ $stats['active_projects'] }}
-
Proyectos totales
+
{{ __('Total projects') }}
{{ $stats['total_projects'] }}
-
Fases totales
+
{{ __('Total phases') }}
{{ $stats['total_phases'] }}
-
Elementos (features)
+
{{ __('Total features') }}
{{ $stats['total_features'] }}
- {{-- Barra de progreso global --}} + {{-- Global progress bar --}}
-

Progreso global

+

{{ __('Global progress') }}

{{ $stats['global_progress'] }}%

- {{-- Proyectos recientes --}} + {{-- Recent projects --}}
-

Proyectos recientes

- Ver todos +

{{ __('Recent projects') }}

+ {{ __('View Map') }}
- - - - + + + + @@ -67,13 +67,7 @@ default => 'badge-ghost' }; @endphp - {{ match($project->status) { - 'planning' => 'Planificación', - 'in_progress' => 'En obra', - 'paused' => 'Pausado', - 'completed' => 'Finalizado', - default => $project->status - } }} + {{ __(ucfirst(str_replace('_', ' ', $project->status))) }} @empty - + @endforelse
NombreEstadoFasesProgreso{{ __('Name') }}{{ __('Status') }}{{ __('Phases') }}{{ __('Progress') }}
{{ $project->phases_count }} @@ -86,26 +80,26 @@ - Mapa + {{ __('Map') }}
No hay proyectos aún
{{ __('No results') }}
- {{-- Inspecciones recientes --}} + {{-- Recent inspections --}} @if($recentInspections->isNotEmpty())
-

Inspecciones recientes

+

{{ __('Recent inspections') }}

@foreach($recentInspections as $inspection)
- {{ $inspection->template?->name ?? 'Inspección' }} + {{ $inspection->template?->name ?? __('Inspection') }} {{ $inspection->feature?->name }}
{{ $inspection->created_at->diffForHumans() }} diff --git a/resources/views/livewire/language-switcher.blade.php b/resources/views/livewire/language-switcher.blade.php new file mode 100644 index 0000000..005c37f --- /dev/null +++ b/resources/views/livewire/language-switcher.blade.php @@ -0,0 +1,9 @@ +
+ @foreach(['en' => '🇬🇧 EN', 'es' => '🇪🇸 ES'] as $code => $label) + + @endforeach +
\ No newline at end of file diff --git a/resources/views/livewire/layer-upload.blade.php b/resources/views/livewire/layer-upload.blade.php index 16ea93d..0eeccee 100644 --- a/resources/views/livewire/layer-upload.blade.php +++ b/resources/views/livewire/layer-upload.blade.php @@ -8,13 +8,13 @@
-

Subir capa

+

{{ __("Upload Layer") }}

- + - + @foreach($phases as $ph) @endforeach @@ -32,24 +32,24 @@
- + @error('layerName') {{ $message }} @enderror
- - + +
- + @error('uploadFile') {{ $message }} @enderror
diff --git a/resources/views/livewire/layers/layer-manager.blade.php b/resources/views/livewire/layers/layer-manager.blade.php index 032927c..5098a16 100644 --- a/resources/views/livewire/layers/layer-manager.blade.php +++ b/resources/views/livewire/layers/layer-manager.blade.php @@ -1,8 +1,8 @@
{{-- Cabecera fija --}}
-

Gestión de elementos - {{ $phase->name }}

- ← Volver al mapa +

{{ __("Manage Layers") }} - {{ $phase->name }}

+ ← {{ __("Back") }}
@@ -11,10 +11,10 @@
-

Importar archivo

+

{{ __("Import file") }}

- +
@@ -26,15 +26,15 @@ @error('uploadFile') {{ $message }} @enderror
- +
- +
-

Capas existentes

+

{{ __("Layers") }}

@foreach($layers as $layer)
@@ -50,12 +50,12 @@
- +
@endforeach @if($layers->isEmpty()) -

Sin capas. Crea una o importa.

+

{{ __("No results") }}. Crea una o importa.

@endif
@@ -66,7 +66,7 @@
-

Editor gráfico

+

{{ __("Edit") }}

@if($selectedLayer)
diff --git a/resources/views/livewire/layout/navigation.blade.php b/resources/views/livewire/layout/navigation.blade.php index 8c7510e..1e64067 100644 --- a/resources/views/livewire/layout/navigation.blade.php +++ b/resources/views/livewire/layout/navigation.blade.php @@ -44,8 +44,13 @@ new class extends Component
- + + + +
@@ -42,7 +42,7 @@ @if($images->isNotEmpty())
-

Imágenes ({{ $images->count() }})

+

{{ __("Images") }} ({{ $images->count() }})

@foreach($images as $media)
@@ -61,11 +61,11 @@
@endif - {{-- Documentos --}} + {{-- {{ __("Document") }}s --}} @if($documents->isNotEmpty())
-

Documentos ({{ $documents->count() }})

+

{{ __("Document") }}s ({{ $documents->count() }})

@foreach($documents as $media)
@@ -95,7 +95,7 @@ @if($mediaItems->isEmpty())

📁

-

No hay archivos. Sube imágenes o documentos.

+

{{ __("No files yet") }}. Sube imágenes o documentos.

@endif diff --git a/resources/views/livewire/phase-progress.blade.php b/resources/views/livewire/phase-progress.blade.php index e6f4587..7054f44 100644 --- a/resources/views/livewire/phase-progress.blade.php +++ b/resources/views/livewire/phase-progress.blade.php @@ -5,7 +5,7 @@
-

Progreso de fase: {{ $phase->name }}

+

{{ __('Progress') }}: {{ $phase->name }}

{{ $phase->project->name ?? '' }}

@@ -17,7 +17,7 @@
- +
0%25%50%75%100% @@ -26,16 +26,16 @@
- - + +
- + @if($phase->progressUpdates->count() > 0)
-

Historial

+

{{ __('History') }}

@foreach($phase->progressUpdates()->latest()->take(10)->get() as $update)
@@ -55,6 +55,6 @@
-
\ No newline at end of file +
diff --git a/resources/views/livewire/projects/project-list.blade.php b/resources/views/livewire/projects/project-list.blade.php index 2d74455..d2d6b8b 100644 --- a/resources/views/livewire/projects/project-list.blade.php +++ b/resources/views/livewire/projects/project-list.blade.php @@ -1,38 +1,38 @@
- + @can('create projects') - + Nuevo Proyecto + + {{ __('New Project') }} @endcan
- + @foreach($projects as $project) - + @@ -41,4 +41,4 @@
NombreDirecciónEstadoProgreso globalAcciones
{{ __('Name') }}{{ __('Address') }}{{ __('Status') }}{{ __('Progress') }}{{ __('Actions') }}
{{ $project->name }} {{ $project->address }}{{ ucfirst($project->status) }}{{ __(ucfirst(str_replace('_', ' ', $project->status))) }}
- Ver Mapa + {{ __('Map') }} @can('edit projects') - Editar + {{ __('Edit') }} @endcan
{{ $projects->links() }} -
\ No newline at end of file +
diff --git a/resources/views/livewire/projects/project-map.blade.php b/resources/views/livewire/projects/project-map.blade.php index b586459..b37d108 100644 --- a/resources/views/livewire/projects/project-map.blade.php +++ b/resources/views/livewire/projects/project-map.blade.php @@ -6,7 +6,7 @@
-

Fases y capas

+

{{ __("Fases and layers") }}

@foreach($phases as $phase)
@@ -36,10 +36,10 @@ {{-- Botón para ir a gestión de capas de esta fase --}}
@@ -50,7 +50,7 @@
- +
-

Editor

+

{{ __("Edit") }}

@@ -91,9 +91,9 @@

Capa: {{ $selectedFeature->layer?->name ?? '—' }}

- {{-- Progreso --}} + {{-- {{ __("Progress") }} --}}
- +
0%50%100% @@ -101,18 +101,18 @@
- +
{{-- Gestor de archivos del feature --}}
- 📎 Archivos del elemento + 📎 {{ __("Files of element") }}
@livewire('media-manager', [ @@ -124,7 +124,7 @@ {{-- Templates / Inspecciones --}} @if($templates->isNotEmpty()) -
Inspección
+
{{ __("Inspection") }}
- +
- +
- +
- +
- +
- +
- \ No newline at end of file + diff --git a/resources/views/projects/edit.blade.php b/resources/views/projects/edit.blade.php index 56e52d2..eec49c6 100644 --- a/resources/views/projects/edit.blade.php +++ b/resources/views/projects/edit.blade.php @@ -1,52 +1,52 @@
-

Editar Proyecto: {{ $project->name }}

+

{{ __('Edit Project') }}: {{ $project->name }}

@csrf @method('PUT')
- +
- +
- +
- +
- +
- +
- +
- +

-

Fases del proyecto

+

{{ __('Phases') }}

-
\ No newline at end of file + diff --git a/resources/views/projects/index.blade.php b/resources/views/projects/index.blade.php index ade1bb4..f7148b2 100644 --- a/resources/views/projects/index.blade.php +++ b/resources/views/projects/index.blade.php @@ -1,12 +1,11 @@ -
-

Mis Proyectos

+

{{ __('Projects') }}

@can('create projects') - + Nuevo Proyecto + + {{ __('New Project') }} @endcan
-
\ No newline at end of file +