From d3419a8cc5aa7a447e7ba95b2c2b60f523d8f0df Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 1 Mar 2026 21:24:54 +0000 Subject: [PATCH] feat: translate API error messages to English Co-Authored-By: Claude Opus 4.6 --- apps/web/app/api/bookings/[id]/pay/route.ts | 24 ++++++------- apps/web/app/api/bookings/[id]/route.ts | 34 +++++++++--------- apps/web/app/api/bookings/route.ts | 18 +++++----- apps/web/app/api/clients/[id]/route.ts | 38 ++++++++++----------- apps/web/app/api/clients/route.ts | 14 ++++---- apps/web/app/api/dashboard/stats/route.ts | 4 +-- apps/web/app/api/sites/[id]/route.ts | 16 ++++----- apps/web/app/api/sites/route.ts | 6 ++-- apps/web/app/api/users/route.ts | 14 ++++---- 9 files changed, 84 insertions(+), 84 deletions(-) diff --git a/apps/web/app/api/bookings/[id]/pay/route.ts b/apps/web/app/api/bookings/[id]/pay/route.ts index 9907e78..2f06414 100644 --- a/apps/web/app/api/bookings/[id]/pay/route.ts +++ b/apps/web/app/api/bookings/[id]/pay/route.ts @@ -12,7 +12,7 @@ interface RouteContext { // Validation schema for payment const paymentSchema = z.object({ paymentType: z.enum(['CASH', 'CARD', 'TRANSFER', 'MEMBERSHIP', 'FREE']), - amount: z.number().positive('El monto debe ser mayor a 0').optional(), + amount: z.number().positive('Amount must be greater than 0').optional(), reference: z.string().max(100).optional(), notes: z.string().max(500).optional(), cashRegisterId: z.string().uuid().optional(), @@ -28,7 +28,7 @@ export async function POST( if (!session?.user) { return NextResponse.json( - { error: 'No autorizado' }, + { error: 'Unauthorized' }, { status: 401 } ); } @@ -51,7 +51,7 @@ export async function POST( if (!existingBooking) { return NextResponse.json( - { error: 'Reserva no encontrada' }, + { error: 'Booking not found' }, { status: 404 } ); } @@ -59,7 +59,7 @@ export async function POST( // If user is SITE_ADMIN, verify they have access to this site if (session.user.role === 'SITE_ADMIN' && session.user.siteId !== existingBooking.siteId) { return NextResponse.json( - { error: 'No tiene permiso para procesar pagos en esta reserva' }, + { error: 'You do not have permission to process payments for this booking' }, { status: 403 } ); } @@ -67,7 +67,7 @@ export async function POST( // Check if booking is already cancelled if (existingBooking.status === 'CANCELLED') { return NextResponse.json( - { error: 'No se puede procesar el pago de una reserva cancelada' }, + { error: 'Cannot process payment for a cancelled booking' }, { status: 400 } ); } @@ -81,7 +81,7 @@ export async function POST( if (totalPaid >= totalPrice) { return NextResponse.json( - { error: 'La reserva ya está completamente pagada' }, + { error: 'The booking is already fully paid' }, { status: 400 } ); } @@ -93,7 +93,7 @@ export async function POST( if (!validationResult.success) { return NextResponse.json( { - error: 'Datos de pago inválidos', + error: 'Invalid payment data', details: validationResult.error.flatten().fieldErrors, }, { status: 400 } @@ -108,7 +108,7 @@ export async function POST( if (paymentAmount <= 0) { return NextResponse.json( - { error: 'El monto del pago debe ser mayor a 0' }, + { error: 'Payment amount must be greater than 0' }, { status: 400 } ); } @@ -125,7 +125,7 @@ export async function POST( if (!cashRegister) { return NextResponse.json( - { error: 'Caja registradora no encontrada o no está abierta' }, + { error: 'Cash register not found or is not open' }, { status: 400 } ); } @@ -211,8 +211,8 @@ export async function POST( return NextResponse.json({ message: result.isFullyPaid - ? 'Pago completado. La reserva ha sido confirmada.' - : 'Pago parcial registrado exitosamente.', + ? 'Payment completed. The booking has been confirmed.' + : 'Partial payment recorded successfully.', booking: result.booking, payment: result.payment, remainingAmount: Math.max(0, totalPrice - (totalPaid + paymentAmount)), @@ -220,7 +220,7 @@ export async function POST( } catch (error) { console.error('Error processing payment:', error); return NextResponse.json( - { error: 'Error al procesar el pago' }, + { error: 'Error processing payment' }, { status: 500 } ); } diff --git a/apps/web/app/api/bookings/[id]/route.ts b/apps/web/app/api/bookings/[id]/route.ts index 1da8199..c8b41dc 100644 --- a/apps/web/app/api/bookings/[id]/route.ts +++ b/apps/web/app/api/bookings/[id]/route.ts @@ -26,7 +26,7 @@ export async function GET( if (!session?.user) { return NextResponse.json( - { error: 'No autorizado' }, + { error: 'Unauthorized' }, { status: 401 } ); } @@ -99,7 +99,7 @@ export async function GET( if (!booking) { return NextResponse.json( - { error: 'Reserva no encontrada' }, + { error: 'Booking not found' }, { status: 404 } ); } @@ -108,7 +108,7 @@ export async function GET( } catch (error) { console.error('Error fetching booking:', error); return NextResponse.json( - { error: 'Error al obtener la reserva' }, + { error: 'Error fetching booking' }, { status: 500 } ); } @@ -124,7 +124,7 @@ export async function PUT( if (!session?.user) { return NextResponse.json( - { error: 'No autorizado' }, + { error: 'Unauthorized' }, { status: 401 } ); } @@ -146,7 +146,7 @@ export async function PUT( if (!existingBooking) { return NextResponse.json( - { error: 'Reserva no encontrada' }, + { error: 'Booking not found' }, { status: 404 } ); } @@ -154,7 +154,7 @@ export async function PUT( // If user is SITE_ADMIN, verify they have access to this site if (session.user.role === 'SITE_ADMIN' && session.user.siteId !== existingBooking.siteId) { return NextResponse.json( - { error: 'No tiene permiso para modificar esta reserva' }, + { error: 'You do not have permission to modify this booking' }, { status: 403 } ); } @@ -166,7 +166,7 @@ export async function PUT( if (!validationResult.success) { return NextResponse.json( { - error: 'Datos de actualización inválidos', + error: 'Invalid update data', details: validationResult.error.flatten().fieldErrors, }, { status: 400 } @@ -239,7 +239,7 @@ export async function PUT( } catch (error) { console.error('Error updating booking:', error); return NextResponse.json( - { error: 'Error al actualizar la reserva' }, + { error: 'Error updating booking' }, { status: 500 } ); } @@ -255,7 +255,7 @@ export async function DELETE( if (!session?.user) { return NextResponse.json( - { error: 'No autorizado' }, + { error: 'Unauthorized' }, { status: 401 } ); } @@ -277,7 +277,7 @@ export async function DELETE( if (!existingBooking) { return NextResponse.json( - { error: 'Reserva no encontrada' }, + { error: 'Booking not found' }, { status: 404 } ); } @@ -285,7 +285,7 @@ export async function DELETE( // If user is SITE_ADMIN, verify they have access to this site if (session.user.role === 'SITE_ADMIN' && session.user.siteId !== existingBooking.siteId) { return NextResponse.json( - { error: 'No tiene permiso para cancelar esta reserva' }, + { error: 'You do not have permission to cancel this booking' }, { status: 403 } ); } @@ -294,7 +294,7 @@ export async function DELETE( const hasPayments = existingBooking.payments.length > 0; // Parse optional cancel reason from query params or body - let cancelReason = 'Cancelada por el administrador'; + let cancelReason = 'Cancelled by administrator'; try { const body = await request.json(); if (body.cancelReason) { @@ -316,9 +316,9 @@ export async function DELETE( }); return NextResponse.json({ - message: 'Reserva cancelada exitosamente', + message: 'Booking cancelled successfully', booking, - note: 'La reserva tiene pagos asociados, por lo que fue cancelada en lugar de eliminada', + note: 'The booking has associated payments, so it was cancelled instead of deleted', }); } else { // If no payments, allow hard delete for pending bookings only @@ -328,7 +328,7 @@ export async function DELETE( }); return NextResponse.json({ - message: 'Reserva eliminada exitosamente', + message: 'Booking deleted successfully', }); } else { // For non-pending bookings, soft delete @@ -342,7 +342,7 @@ export async function DELETE( }); return NextResponse.json({ - message: 'Reserva cancelada exitosamente', + message: 'Booking cancelled successfully', booking, }); } @@ -350,7 +350,7 @@ export async function DELETE( } catch (error) { console.error('Error deleting booking:', error); return NextResponse.json( - { error: 'Error al cancelar la reserva' }, + { error: 'Error cancelling booking' }, { status: 500 } ); } diff --git a/apps/web/app/api/bookings/route.ts b/apps/web/app/api/bookings/route.ts index 8db0f31..6c46e82 100644 --- a/apps/web/app/api/bookings/route.ts +++ b/apps/web/app/api/bookings/route.ts @@ -20,7 +20,7 @@ export async function GET(request: NextRequest) { if (!session?.user) { return NextResponse.json( - { error: 'No autorizado' }, + { error: 'Unauthorized' }, { status: 401 } ); } @@ -138,7 +138,7 @@ export async function GET(request: NextRequest) { } catch (error) { console.error('Error fetching bookings:', error); return NextResponse.json( - { error: 'Error al obtener las reservas' }, + { error: 'Error fetching bookings' }, { status: 500 } ); } @@ -151,7 +151,7 @@ export async function POST(request: NextRequest) { if (!session?.user) { return NextResponse.json( - { error: 'No autorizado' }, + { error: 'Unauthorized' }, { status: 401 } ); } @@ -163,7 +163,7 @@ export async function POST(request: NextRequest) { if (!validationResult.success) { return NextResponse.json( { - error: 'Datos de reserva inválidos', + error: 'Invalid booking data', details: validationResult.error.flatten().fieldErrors, }, { status: 400 } @@ -193,14 +193,14 @@ export async function POST(request: NextRequest) { if (!court) { return NextResponse.json( - { error: 'Cancha no encontrada o no pertenece a su organización' }, + { error: 'Court not found or does not belong to your organization' }, { status: 404 } ); } if (court.status !== 'AVAILABLE' || !court.isActive) { return NextResponse.json( - { error: 'La cancha no está disponible para reservas' }, + { error: 'The court is not available for bookings' }, { status: 400 } ); } @@ -232,7 +232,7 @@ export async function POST(request: NextRequest) { if (!client) { return NextResponse.json( - { error: 'Cliente no encontrado o no pertenece a su organización' }, + { error: 'Client not found or does not belong to your organization' }, { status: 404 } ); } @@ -269,7 +269,7 @@ export async function POST(request: NextRequest) { if (existingBooking) { return NextResponse.json( - { error: 'Ya existe una reserva en ese horario. Por favor, seleccione otro horario.' }, + { error: 'A booking already exists for that time slot. Please select another time.' }, { status: 409 } ); } @@ -391,7 +391,7 @@ export async function POST(request: NextRequest) { } catch (error) { console.error('Error creating booking:', error); return NextResponse.json( - { error: 'Error al crear la reserva' }, + { error: 'Error creating booking' }, { status: 500 } ); } diff --git a/apps/web/app/api/clients/[id]/route.ts b/apps/web/app/api/clients/[id]/route.ts index 28207d2..2f6a49b 100644 --- a/apps/web/app/api/clients/[id]/route.ts +++ b/apps/web/app/api/clients/[id]/route.ts @@ -10,11 +10,11 @@ interface RouteContext { // Validation schema for updating client const updateClientSchema = z.object({ - firstName: z.string().min(1, 'El nombre es requerido').optional(), - lastName: z.string().min(1, 'El apellido es requerido').optional(), - email: z.string().email('Email invalido').nullable().optional(), + firstName: z.string().min(1, 'First name is required').optional(), + lastName: z.string().min(1, 'Last name is required').optional(), + email: z.string().email('Invalid email').nullable().optional(), phone: z.string().nullable().optional(), - avatar: z.string().url('URL invalida').nullable().optional(), + avatar: z.string().url('Invalid URL').nullable().optional(), dateOfBirth: z.string().nullable().optional(), address: z.string().nullable().optional(), notes: z.string().nullable().optional(), @@ -32,7 +32,7 @@ export async function GET( if (!session?.user) { return NextResponse.json( - { error: 'No autorizado' }, + { error: 'Unauthorized' }, { status: 401 } ); } @@ -79,7 +79,7 @@ export async function GET( if (!client) { return NextResponse.json( - { error: 'Cliente no encontrado' }, + { error: 'Client not found' }, { status: 404 } ); } @@ -122,7 +122,7 @@ export async function GET( } catch (error) { console.error('Error fetching client:', error); return NextResponse.json( - { error: 'Error al obtener el cliente' }, + { error: 'Error fetching client' }, { status: 500 } ); } @@ -138,7 +138,7 @@ export async function PUT( if (!session?.user) { return NextResponse.json( - { error: 'No autorizado' }, + { error: 'Unauthorized' }, { status: 401 } ); } @@ -155,7 +155,7 @@ export async function PUT( if (!existingClient) { return NextResponse.json( - { error: 'Cliente no encontrado' }, + { error: 'Client not found' }, { status: 404 } ); } @@ -167,7 +167,7 @@ export async function PUT( if (!validationResult.success) { return NextResponse.json( { - error: 'Datos de actualizacion invalidos', + error: 'Invalid update data', details: validationResult.error.flatten().fieldErrors, }, { status: 400 } @@ -201,7 +201,7 @@ export async function PUT( if (emailExists) { return NextResponse.json( - { error: 'Ya existe un cliente con este email' }, + { error: 'A client with this email already exists' }, { status: 409 } ); } @@ -262,13 +262,13 @@ export async function PUT( // Check for unique constraint violation if (error instanceof Error && error.message.includes('Unique constraint')) { return NextResponse.json( - { error: 'Ya existe un cliente con este email o DNI' }, + { error: 'A client with this email or ID number already exists' }, { status: 409 } ); } return NextResponse.json( - { error: 'Error al actualizar el cliente' }, + { error: 'Error updating client' }, { status: 500 } ); } @@ -284,7 +284,7 @@ export async function DELETE( if (!session?.user) { return NextResponse.json( - { error: 'No autorizado' }, + { error: 'Unauthorized' }, { status: 401 } ); } @@ -318,7 +318,7 @@ export async function DELETE( if (!existingClient) { return NextResponse.json( - { error: 'Cliente no encontrado' }, + { error: 'Client not found' }, { status: 404 } ); } @@ -327,7 +327,7 @@ export async function DELETE( if (existingClient.memberships.length > 0) { return NextResponse.json( { - error: 'No se puede desactivar un cliente con membresia activa', + error: 'Cannot deactivate a client with an active membership', details: { activeMemberships: existingClient.memberships.length, }, @@ -340,7 +340,7 @@ export async function DELETE( if (existingClient.bookings.length > 0) { return NextResponse.json( { - error: 'No se puede desactivar un cliente con reservas pendientes', + error: 'Cannot deactivate a client with pending bookings', details: { pendingBookings: existingClient.bookings.length, }, @@ -364,13 +364,13 @@ export async function DELETE( }); return NextResponse.json({ - message: 'Cliente desactivado exitosamente', + message: 'Client deactivated successfully', client, }); } catch (error) { console.error('Error deleting client:', error); return NextResponse.json( - { error: 'Error al desactivar el cliente' }, + { error: 'Error deactivating client' }, { status: 500 } ); } diff --git a/apps/web/app/api/clients/route.ts b/apps/web/app/api/clients/route.ts index 0bcb352..4db3530 100644 --- a/apps/web/app/api/clients/route.ts +++ b/apps/web/app/api/clients/route.ts @@ -11,7 +11,7 @@ export async function GET(request: NextRequest) { if (!session?.user) { return NextResponse.json( - { error: 'No autorizado' }, + { error: 'Unauthorized' }, { status: 401 } ); } @@ -123,7 +123,7 @@ export async function GET(request: NextRequest) { } catch (error) { console.error('Error fetching clients:', error); return NextResponse.json( - { error: 'Error al obtener los clientes' }, + { error: 'Error fetching clients' }, { status: 500 } ); } @@ -136,7 +136,7 @@ export async function POST(request: NextRequest) { if (!session?.user) { return NextResponse.json( - { error: 'No autorizado' }, + { error: 'Unauthorized' }, { status: 401 } ); } @@ -148,7 +148,7 @@ export async function POST(request: NextRequest) { if (!validationResult.success) { return NextResponse.json( { - error: 'Datos del cliente inválidos', + error: 'Invalid client data', details: validationResult.error.flatten().fieldErrors, }, { status: 400 } @@ -181,7 +181,7 @@ export async function POST(request: NextRequest) { if (existingClient) { return NextResponse.json( - { error: 'Ya existe un cliente con este correo electrónico en su organización' }, + { error: 'A client with this email already exists in your organization' }, { status: 409 } ); } @@ -224,13 +224,13 @@ export async function POST(request: NextRequest) { // Check for unique constraint violation if (error instanceof Error && error.message.includes('Unique constraint')) { return NextResponse.json( - { error: 'Ya existe un cliente con este correo electrónico o DNI' }, + { error: 'A client with this email or ID number already exists' }, { status: 409 } ); } return NextResponse.json( - { error: 'Error al crear el cliente' }, + { error: 'Error creating client' }, { status: 500 } ); } diff --git a/apps/web/app/api/dashboard/stats/route.ts b/apps/web/app/api/dashboard/stats/route.ts index 8439dc9..47005e6 100644 --- a/apps/web/app/api/dashboard/stats/route.ts +++ b/apps/web/app/api/dashboard/stats/route.ts @@ -10,7 +10,7 @@ export async function GET(request: NextRequest) { if (!session?.user) { return NextResponse.json( - { error: 'No autorizado' }, + { error: 'Unauthorized' }, { status: 401 } ); } @@ -315,7 +315,7 @@ export async function GET(request: NextRequest) { } catch (error) { console.error('Error fetching dashboard stats:', error); return NextResponse.json( - { error: 'Error al obtener estadísticas del dashboard' }, + { error: 'Error fetching dashboard statistics' }, { status: 500 } ); } diff --git a/apps/web/app/api/sites/[id]/route.ts b/apps/web/app/api/sites/[id]/route.ts index 8b72646..1f227bc 100644 --- a/apps/web/app/api/sites/[id]/route.ts +++ b/apps/web/app/api/sites/[id]/route.ts @@ -35,14 +35,14 @@ export async function GET( }); if (!site) { - return NextResponse.json({ error: 'Sede no encontrada' }, { status: 404 }); + return NextResponse.json({ error: 'Site not found' }, { status: 404 }); } return NextResponse.json({ data: site }); } catch (error) { console.error('Error fetching site:', error); return NextResponse.json( - { error: 'Error al obtener sede' }, + { error: 'Error fetching site' }, { status: 500 } ); } @@ -61,7 +61,7 @@ export async function PUT( } if (!['super_admin', 'site_admin'].includes(session.user.role)) { - return NextResponse.json({ error: 'Sin permisos' }, { status: 403 }); + return NextResponse.json({ error: 'Insufficient permissions' }, { status: 403 }); } const body = await request.json(); @@ -76,7 +76,7 @@ export async function PUT( }); if (!existingSite) { - return NextResponse.json({ error: 'Sede no encontrada' }, { status: 404 }); + return NextResponse.json({ error: 'Site not found' }, { status: 404 }); } const updateData: any = {}; @@ -102,7 +102,7 @@ export async function PUT( } catch (error) { console.error('Error updating site:', error); return NextResponse.json( - { error: 'Error al actualizar sede' }, + { error: 'Error updating site' }, { status: 500 } ); } @@ -121,7 +121,7 @@ export async function DELETE( } if (session.user.role !== 'super_admin') { - return NextResponse.json({ error: 'Sin permisos' }, { status: 403 }); + return NextResponse.json({ error: 'Insufficient permissions' }, { status: 403 }); } // Verify site belongs to organization @@ -133,7 +133,7 @@ export async function DELETE( }); if (!existingSite) { - return NextResponse.json({ error: 'Sede no encontrada' }, { status: 404 }); + return NextResponse.json({ error: 'Site not found' }, { status: 404 }); } // Soft delete @@ -146,7 +146,7 @@ export async function DELETE( } catch (error) { console.error('Error deleting site:', error); return NextResponse.json( - { error: 'Error al eliminar sede' }, + { error: 'Error deleting site' }, { status: 500 } ); } diff --git a/apps/web/app/api/sites/route.ts b/apps/web/app/api/sites/route.ts index c850959..6fbdd71 100644 --- a/apps/web/app/api/sites/route.ts +++ b/apps/web/app/api/sites/route.ts @@ -80,7 +80,7 @@ export async function POST(request: NextRequest) { } if (!['super_admin', 'site_admin'].includes(session.user.role)) { - return NextResponse.json({ error: 'Sin permisos' }, { status: 403 }); + return NextResponse.json({ error: 'Insufficient permissions' }, { status: 403 }); } const body = await request.json(); @@ -88,7 +88,7 @@ export async function POST(request: NextRequest) { if (!name || !address) { return NextResponse.json( - { error: 'Nombre y dirección son requeridos' }, + { error: 'Name and address are required' }, { status: 400 } ); } @@ -116,7 +116,7 @@ export async function POST(request: NextRequest) { } catch (error) { console.error('Error creating site:', error); return NextResponse.json( - { error: 'Error al crear sede' }, + { error: 'Error creating site' }, { status: 500 } ); } diff --git a/apps/web/app/api/users/route.ts b/apps/web/app/api/users/route.ts index fdf10c6..6e29eb1 100644 --- a/apps/web/app/api/users/route.ts +++ b/apps/web/app/api/users/route.ts @@ -8,7 +8,7 @@ export async function GET(request: NextRequest) { const session = await getServerSession(authOptions); if (!session?.user) { - return NextResponse.json({ error: "No autorizado" }, { status: 401 }); + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const users = await db.user.findMany({ @@ -45,7 +45,7 @@ export async function GET(request: NextRequest) { } catch (error) { console.error("Error fetching users:", error); return NextResponse.json( - { error: "Error al obtener usuarios" }, + { error: "Error fetching users" }, { status: 500 } ); } @@ -56,12 +56,12 @@ export async function POST(request: NextRequest) { const session = await getServerSession(authOptions); if (!session?.user) { - return NextResponse.json({ error: "No autorizado" }, { status: 401 }); + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } // Only super_admin and site_admin can create users if (!["super_admin", "site_admin"].includes(session.user.role)) { - return NextResponse.json({ error: "Sin permisos" }, { status: 403 }); + return NextResponse.json({ error: "Insufficient permissions" }, { status: 403 }); } const body = await request.json(); @@ -69,7 +69,7 @@ export async function POST(request: NextRequest) { if (!email || !password || !firstName || !lastName || !role) { return NextResponse.json( - { error: "Faltan campos requeridos" }, + { error: "Missing required fields" }, { status: 400 } ); } @@ -84,7 +84,7 @@ export async function POST(request: NextRequest) { if (existingUser) { return NextResponse.json( - { error: "El email ya está registrado" }, + { error: "This email is already registered" }, { status: 400 } ); } @@ -129,7 +129,7 @@ export async function POST(request: NextRequest) { } catch (error) { console.error("Error creating user:", error); return NextResponse.json( - { error: "Error al crear usuario" }, + { error: "Error creating user" }, { status: 500 } ); }