87df61ab15
Run Tests on Branches / Detect Changes (push) Successful in 14s
Run Tests on Branches / Backend Tests (push) Successful in 2m24s
Run Tests on Branches / Frontend Tests (push) Successful in 1m57s
Run Tests on Branches / Frontend Mobile Tests (push) Has been skipped
Run Tests on Branches / Parapharmacy API Tests (push) Has been skipped
Run Tests on Branches / PIP Platform Tests (push) Has been skipped
- Add Mailpit SMTP container to docker-compose for dev email capture - Add nodemailer dependency for email sending - Add password_reset_tokens table (PG + SQLite) - Add POST /api/auth/forgot-username endpoint - Add POST /api/auth/forgot-password endpoint (token-based, 1h expiry) - Add POST /api/auth/reset-password endpoint - Create ForgotPasswordModal component (choose mode → email → sent) - Create ResetPasswordView (token-based new password form) - Add forgot/recovery links to LoginModal - Add i18n translations (ES/CA) for the full flow
495 lines
25 KiB
JavaScript
495 lines
25 KiB
JavaScript
const es = {
|
||
// BottomNav
|
||
'nav.home': 'Inicio',
|
||
'nav.search': 'Buscar',
|
||
'nav.scan': 'Escanear',
|
||
'nav.alerts': 'Avisos',
|
||
'nav.profile': 'Usuario',
|
||
|
||
// HomeView
|
||
'home.description': 'Encuentra tus medicamentos en farmacias cercanas',
|
||
'home.searchMedicine': 'Buscar Medicamento',
|
||
'home.scanTSI': 'Escanear TSI',
|
||
|
||
// SearchBar
|
||
'search.placeholder': 'Escriba el nombre del medicamento',
|
||
'search.clear': 'Limpiar búsqueda',
|
||
|
||
// SearchView
|
||
'search.suggestions': 'Sugerencias',
|
||
'search.recentResults': 'Resultados Recientes',
|
||
'search.findNearby': 'Encontrar cerca',
|
||
'search.resultsFound': 'resultados encontrados',
|
||
'search.parapharmacy': 'Parafarmacia',
|
||
'search.activeIngredient': 'Ingrediente Activo',
|
||
'search.dosage': 'Dosis',
|
||
'search.form': 'Forma',
|
||
'search.backToSearch': '← Volver a búsqueda',
|
||
'search.sortByDistance': '📍 Ordenar por distancia',
|
||
'search.sortBySavedLocation': '📍 Ordenar por ubicación guardada',
|
||
'search.sortedByDistance': '📍 Ordenado por distancia · Reset',
|
||
'search.locating': '📍 Localizando…',
|
||
'search.usingSavedAddress': 'Usando tu dirección guardada',
|
||
'search.usingRecentLocation': 'Usando ubicación reciente',
|
||
'search.retry': 'Reintentar',
|
||
'search.locationDenied': 'Permiso de ubicación denegado. Permite el acceso a la ubicación en tu navegador.',
|
||
'search.locationUnavailable': 'Ubicación no disponible. Verifica que el GPS esté activado.',
|
||
'search.locationTimeout': 'La ubicación tardó demasiado. Intenta de nuevo o verifica tu conexión.',
|
||
'search.locationError': 'No se pudo obtener tu ubicación',
|
||
'search.searching': 'Buscando...',
|
||
|
||
// MedicineResults
|
||
'medicine.noResults': 'No se encontraron medicamentos para',
|
||
'medicine.principioActivo': 'Principio Activo:',
|
||
'medicine.dosis': 'Dosis:',
|
||
'medicine.forma': 'Forma:',
|
||
'medicine.viewPharmacies': 'Ver farmacias →',
|
||
'medicine.loginForNotifications': 'Inicia sesión para activar notificaciones',
|
||
'medicine.disableNotifications': 'Desactivar notificaciones para este medicamento',
|
||
'medicine.enableNotifications': 'Notificarme cuando esté disponible',
|
||
'medicine.notificationsActivated': 'Notificaciones activadas — clic para desactivar',
|
||
'medicine.notifyWhenAvailable': 'Notificarme cuando este medicamento esté en una farmacia',
|
||
'medicine.subscriptionError': 'No se pudo actualizar la suscripción',
|
||
|
||
// PharmacyList
|
||
'pharmacy.loading': 'Cargando farmacias...',
|
||
'pharmacy.notFound': 'No se encontraron farmacias con este medicamento',
|
||
'pharmacy.availableAt': 'Disponible en',
|
||
'pharmacy.pharmacy': 'farmacia',
|
||
'pharmacy.pharmacies': 'farmacias',
|
||
'pharmacy.howToGet': 'Cómo llegar',
|
||
'pharmacy.inStock': '✓ En Stock',
|
||
'pharmacy.lowStock': '⚠ Stock Bajo',
|
||
'pharmacy.outOfStock': '✗ Sin Stock',
|
||
'pharmacy.loginForNotifications': 'Inicia sesión para activar notificaciones',
|
||
'pharmacy.disableNotificationsPharmacy': 'Desactivar notificaciones para esta farmacia',
|
||
'pharmacy.notifyWhenArrives': 'Notificarme cuando llegue a esta farmacia',
|
||
'pharmacy.notificationsActivatedPharmacy': 'Notificaciones activadas para esta farmacia — clic para desactivar',
|
||
'pharmacy.notificationsRequired': 'Las notificaciones requieren iOS 16.4+ y este sitio instalado como app (Compartir → Añadir a Pantalla de Inicio).',
|
||
'pharmacy.openNow': 'Abierto · Cierra a las {{time}}',
|
||
'pharmacy.closedAllDay': 'Cerrado',
|
||
'pharmacy.opensAt': 'Cerrado · Abre a las {{time}}',
|
||
'pharmacy.opensTomorrow': 'Cerrado · Abre mañana a las {{time}}',
|
||
'pharmacy.opensDay': 'Cerrado · Abre el {{day}} a las {{time}}',
|
||
'pharmacy.alwaysOpen': 'Abierto 24h',
|
||
'pharmacy.filterOpenNow': 'Mostrar solo abiertas ahora',
|
||
'pharmacy.filterOpenNowActive': 'Solo abiertas ahora',
|
||
'pharmacy.badge24h': '24h',
|
||
'pharmacy.noHours': 'Sin horario disponible',
|
||
'pharmacy.filterNoResults': 'Ninguna farmacia abierta ahora. Desactiva el filtro para ver todas.',
|
||
|
||
// ProductResults
|
||
'product.sinReceta': 'Sin Receta',
|
||
'product.parapharmacy': 'Parafarmacia',
|
||
'product.dermocosmetica': 'Dermocosmética',
|
||
'product.formulasLacteas': 'Fórmulas lácteas',
|
||
'product.vitamins': 'Vitaminas',
|
||
'product.analgesics': 'Analgésicos',
|
||
'product.noResults': 'No se encontraron productos',
|
||
'product.brand': 'Marca:',
|
||
'product.price': 'Precio:',
|
||
'product.activeIngredient': 'Principio Activo:',
|
||
'product.dosage': 'Dosis:',
|
||
'product.viewDetails': 'Ver detalles →',
|
||
|
||
// ProductView (detail)
|
||
'productView.loading': 'Cargando...',
|
||
'productView.back': 'Volver',
|
||
'productView.notFound': 'Producto no encontrado',
|
||
'productView.parapharmacy': 'Parafarmacia',
|
||
'productView.activeIngredient': 'Principio activo',
|
||
'productView.dosage': 'Dosis',
|
||
'productView.form': 'Forma farmacéutica',
|
||
'productView.prescription': 'Prescripción',
|
||
'productView.commercialized': 'Comercializado',
|
||
'productView.yes': 'Sí',
|
||
'productView.no': 'No',
|
||
'productView.price': 'Precio',
|
||
'productView.previousPrice': 'Precio anterior',
|
||
'productView.category': 'Categoría',
|
||
'productView.brand': 'Marca',
|
||
'productView.source': 'Fuente',
|
||
'productView.loadingPharmacies': 'Cargando farmacias...',
|
||
'productView.availableInPharmacies': 'Disponible en {{count}} farmacia(s)',
|
||
'productView.locating': '📍 Localizando…',
|
||
'productView.sortedByDistance': '📍 Ordenado por distancia · Reset',
|
||
'productView.sortByDistance': '📍 Ordenar por distancia',
|
||
'productView.usingLocation': 'Usando tu ubicación',
|
||
'productView.retry': 'Reintentar',
|
||
'productView.productNotFound': 'Producto no encontrado',
|
||
|
||
// LoginModal
|
||
'login.login': 'Iniciar sesión',
|
||
'login.register': 'Crear cuenta',
|
||
'login.welcomeBack': 'Bienvenido de nuevo',
|
||
'login.createAccount': 'Crea tu cuenta',
|
||
'login.registerDescription': 'Guarda tu dirección y recibe notificaciones cuando lleguen medicamentos.',
|
||
'login.loginDescription': 'Inicia sesión para gestionar tu perfil y notificaciones.',
|
||
'login.username': 'Usuario',
|
||
'login.usernameHint': '3–32 caracteres: letras, dígitos o guión bajo.',
|
||
'login.password': 'Contraseña',
|
||
'login.passwordHint': 'Al menos 8 caracteres.',
|
||
'login.cancel': 'Cancelar',
|
||
'login.creating': 'Creando…',
|
||
'login.loggingIn': 'Iniciando sesión…',
|
||
'login.createAccountBtn': 'Crear cuenta',
|
||
'login.loginBtn': 'Iniciar sesión',
|
||
'login.passwordError': 'La contraseña debe tener al menos 8 caracteres',
|
||
'login.registerError': 'No se pudo crear la cuenta',
|
||
'login.loginError': 'Inicio de sesión fallido',
|
||
'login.networkError': 'Error de red — inténtalo de nuevo',
|
||
|
||
// AlertsView
|
||
'alerts.title': 'Mis Avisos',
|
||
'alerts.subtitle': 'Mantente al día con tus medicamentos.',
|
||
'alerts.loading': 'Cargando avisos...',
|
||
'alerts.loginRequired': 'Por favor, inicia sesión para ver tus avisos.',
|
||
'alerts.loadError': 'No se pudieron cargar los avisos.',
|
||
'alerts.availability': 'Disponibilidad',
|
||
'alerts.noSubscriptions': 'No tienes suscripciones de disponibilidad.',
|
||
'alerts.notifyWhenAvailable': 'Notificarme cuando esté disponible',
|
||
'alerts.deleteError': 'No se pudo eliminar la alerta de disponibilidad.',
|
||
'alerts.pharmacy': 'Farmacia',
|
||
|
||
// ScannerView
|
||
'scanner.title': 'Escanear TSI',
|
||
'scanner.description': 'Escanea el código de barras de tu tarjeta sanitaria para ver tus recetas activas',
|
||
'scanner.openCamera': 'Abrir cámara',
|
||
'scanner.orUploadPhoto': 'O sube una foto de tu TSI',
|
||
'scanner.takePhoto': 'Hacer foto',
|
||
'scanner.uploadFromGallery': 'Subir de galería',
|
||
'scanner.scanImage': 'Escanear imagen',
|
||
'scanner.discard': 'Descartar',
|
||
'scanner.enterCIP': 'O introduce el código CIP manualmente',
|
||
'scanner.cipPlaceholder': 'Código CIP de 16 dígitos',
|
||
'scanner.search': 'Buscar',
|
||
'scanner.scanning': 'Apunta al código de barras',
|
||
'scanner.openingCamera': 'Abriendo cámara…',
|
||
'scanner.processingImage': 'Procesando imagen…',
|
||
'scanner.tsiScanned': 'TSI Escaneada',
|
||
'scanner.activePrescriptions': 'Recetas Activas',
|
||
'scanner.tapToFind': 'Toca un medicamento para ver disponibilidad en farmacias cercanas.',
|
||
'scanner.loadingPrescriptions': 'Cargando recetas…',
|
||
'scanner.noPrescriptions': 'No se encontraron recetas activas para esta tarjeta.',
|
||
'scanner.scanAnother': 'Escanear otra tarjeta',
|
||
'scanner.tryAgain': 'Intentar de nuevo',
|
||
'scanner.scannerUnavailable': 'El escáner no está disponible en este dispositivo.',
|
||
'scanner.cameraPermissionDenied': 'Permiso de cámara denegado. Actívalo en ajustes o introduce el código CIP manualmente.',
|
||
'scanner.invalidBarcode': 'Código de barras inválido. Intenta de nuevo o introduce el CIP manualmente.',
|
||
'scanner.cameraNotAvailable': 'Cámara no disponible en este navegador.',
|
||
'scanner.invalidCIP': 'Formato CIP inválido. Debe tener 16 caracteres alfanuméricos.',
|
||
'scanner.enterCIPError': 'Introduce un código CIP.',
|
||
'scanner.cameraPermissionWeb': 'Permiso de cámara denegado. Permite el acceso e intenta de nuevo.',
|
||
'scanner.noCamera': 'No se detectó ninguna cámara. Introduce el código CIP manualmente.',
|
||
'scanner.imageReadError': 'No se pudo leer la imagen. Intenta con otra foto.',
|
||
'scanner.invalidCIPDetected': 'CIP detectado no tiene formato válido. Introduce el código manualmente.',
|
||
'scanner.scanError': 'Error al escanear:',
|
||
'scanner.unknownError': 'Error desconocido',
|
||
'scanner.cameraError': 'Error de cámara:',
|
||
'scanner.imageProcessError': 'Error al procesar la imagen:',
|
||
|
||
// ProfileView
|
||
'profile.name': 'Nombre',
|
||
'profile.lastName': 'Apellidos',
|
||
'profile.config': 'Configuración',
|
||
'profile.myAddresses': 'Mis Direcciones',
|
||
'profile.theme': 'Tema',
|
||
'profile.themeAuto': 'Automático',
|
||
'profile.themeLight': 'Claro',
|
||
'profile.themeDark': 'Oscuro',
|
||
'profile.admin': 'Panel de Administración',
|
||
'profile.logout': 'Cerrar Sesión',
|
||
'profile.uploadingPhoto': 'Subiendo foto...',
|
||
'profile.recentSearches': 'Tus búsquedas recientes:',
|
||
'profile.delete': 'Eliminar',
|
||
'profile.changeAvatar': 'Cambiar Avatar',
|
||
'profile.presetAvatar': 'Prediseñado',
|
||
'profile.colors': 'Colores',
|
||
'profile.upload': 'Subir',
|
||
'profile.chooseFromGallery': 'Elegir de galería',
|
||
'profile.selectExistingImage': 'Selecciona una imagen existente',
|
||
'profile.imageTooBig': 'La imagen no puede superar los 5 MB',
|
||
'profile.imageSaveError': 'Error al guardar la imagen. Intenta con otra foto.',
|
||
'profile.imageConnectionError': 'Error de conexión al guardar la imagen.',
|
||
'profile.imageProcessError': 'Error al procesar la imagen.',
|
||
'profile.configTitle': 'Configuración',
|
||
'profile.firstName': 'Nombre',
|
||
'profile.firstNamePlaceholder': 'Tu nombre',
|
||
'profile.lastNamePlaceholder': 'Tus apellidos',
|
||
'profile.email': 'Correo electrónico',
|
||
'profile.emailPlaceholder': 'tu@email.com',
|
||
'profile.city': 'Ciudad',
|
||
'profile.cityPlaceholder': 'Tu ciudad',
|
||
'profile.address': 'Dirección',
|
||
'profile.addressPlaceholder': 'Calle Mayor 1, Madrid',
|
||
'profile.cancel': 'Cancelar',
|
||
'profile.saving': 'Guardando...',
|
||
'profile.save': 'Guardar',
|
||
'profile.profileSaved': 'Perfil guardado.',
|
||
'profile.saveError': 'Error al guardar',
|
||
'profile.addressesTitle': 'Mis Direcciones',
|
||
'profile.addressLabel': 'Dirección',
|
||
'profile.addressOptional': 'Etiqueta (opcional)',
|
||
'profile.addressLabelPlaceholder': 'Ej: Casa, Trabajo, Segunda residencia',
|
||
'profile.defaultAddress': 'Dirección predeterminada',
|
||
'profile.add': 'Añadir',
|
||
'profile.update': 'Actualizar',
|
||
'profile.loadingAddresses': 'Cargando direcciones...',
|
||
'profile.mainAddress': 'Dirección principal',
|
||
'profile.default': 'Predeterminada',
|
||
'profile.setDefault': 'Establecer como predeterminada',
|
||
'profile.addMore': 'Añadir más',
|
||
'profile.addressRequired': 'La dirección es obligatoria',
|
||
'profile.addressSaveError': 'Error al guardar la dirección',
|
||
'profile.themeTitle': 'Tema de visualización',
|
||
'profile.themeDescription': 'Elige cómo se ve la aplicación. En modo automático, se adapta al tema de tu dispositivo.',
|
||
'profile.themeAutoDesc': 'Seguir sistema',
|
||
'profile.themeLightDesc': 'Siempre claro',
|
||
'profile.themeDarkDesc': 'Siempre oscuro',
|
||
'profile.language': 'Idioma',
|
||
'profile.languageTitle': 'Idioma de la aplicación',
|
||
'profile.languageCatalan': 'Català',
|
||
'profile.languageSpanish': 'Castellano',
|
||
|
||
// ForgotPasswordModal
|
||
'forgot.title': '¿Problemas para acceder?',
|
||
'forgot.subtitle': 'Elige qué necesitas recuperar',
|
||
'forgot.password': 'He olvidado mi contraseña',
|
||
'forgot.passwordDesc': 'Te enviaremos un enlace para crear una nueva',
|
||
'forgot.username': 'He olvidado mi usuario',
|
||
'forgot.usernameDesc': 'Te enviaremos tu nombre de usuario',
|
||
'forgot.resetTitle': 'Restablecer contraseña',
|
||
'forgot.resetDesc': 'Introduce tu correo electrónico y te enviaremos un enlace para crear una nueva contraseña.',
|
||
'forgot.usernameTitle': 'Recuperar usuario',
|
||
'forgot.usernameDesc2': 'Introduce tu correo electrónico y te enviaremos tu nombre de usuario.',
|
||
'forgot.email': 'Correo electrónico',
|
||
'forgot.emailPlaceholder': 'tu@email.com',
|
||
'forgot.send': 'Enviar',
|
||
'forgot.sending': 'Enviando...',
|
||
'forgot.cancel': 'Cancelar',
|
||
'forgot.back': 'Volver',
|
||
'forgot.backToLogin': 'Volver a iniciar sesión',
|
||
'forgot.sentTitle': 'Correo enviado',
|
||
'forgot.sentText': 'Si la dirección de correo existe en nuestra base de datos, recibirás un mensaje en unos minutos. Revisa tu bandeja de entrada.',
|
||
'forgot.close': 'Cerrar',
|
||
'forgot.error': 'Error al procesar la solicitud',
|
||
'forgot.forgotPassword': '¿Olvidaste tu contraseña?',
|
||
'forgot.forgotUsername': '¿Olvidaste tu usuario?',
|
||
|
||
// ResetPasswordView
|
||
'reset.title': 'Crear nueva contraseña',
|
||
'reset.subtitle': 'Introduce tu nueva contraseña',
|
||
'reset.newPassword': 'Nueva contraseña',
|
||
'reset.confirmPassword': 'Confirmar contraseña',
|
||
'reset.saveBtn': 'Cambiar contraseña',
|
||
'reset.saving': 'Guardando...',
|
||
'reset.passwordsDontMatch': 'Las contraseñas no coinciden',
|
||
'reset.successTitle': 'Contraseña actualizada',
|
||
'reset.successText': 'Tu contraseña se ha actualizado correctamente. Ya puedes iniciar sesión con tu nueva contraseña.',
|
||
'reset.goToLogin': 'Ir a iniciar sesión',
|
||
'reset.error': 'Error al restablecer la contraseña',
|
||
'reset.invalidToken': 'Enlace inválido o expirado. Solicita un nuevo restablecimiento de contraseña.',
|
||
|
||
// SavedNotifications
|
||
'savedNotifications.title': '🔔 Notificaciones Guardadas',
|
||
'savedNotifications.close': 'Cerrar',
|
||
'savedNotifications.loading': 'Cargando…',
|
||
'savedNotifications.empty': 'Aún no hay notificaciones guardadas. Toca la campana 🔕 en una farmacia sin stock para recibir notificaciones cuando se reponga.',
|
||
'savedNotifications.anyPharmacy': 'Cualquier farmacia',
|
||
'savedNotifications.delete': 'Eliminar notificación',
|
||
'savedNotifications.loadError': 'No se pudieron cargar las notificaciones guardadas',
|
||
'savedNotifications.deleteError': 'No se pudo eliminar la notificación',
|
||
|
||
// ErrorBoundary
|
||
'error.title': 'Algo salió mal',
|
||
'error.description': 'Ha ocurrido un error inesperado. Por favor, recarga la página.',
|
||
'error.reload': 'Recargar',
|
||
|
||
// AdminView
|
||
'admin.title': '⚙️ Panel de Administración',
|
||
'admin.authRequired': 'Autenticación requerida',
|
||
'admin.managePharmacies': 'Gestiona farmacias y medicamentos',
|
||
'admin.logout': 'Cerrar sesión',
|
||
'admin.checkingAuth': 'Comprobando autenticación...',
|
||
'admin.pharmacies': '🏥 Farmacias',
|
||
'admin.medicines': '💊 Medicamentos',
|
||
'admin.linkMedicine': '🔗 Vincular Medicamento a Farmacia',
|
||
'admin.linkProduct': '🍎 Vincular Producto a Farmacia',
|
||
|
||
// LoginForm
|
||
'admin.login.title': '🔐 Acceso Administración',
|
||
'admin.login.description': 'Introduce tus credenciales para acceder al panel de administración',
|
||
'admin.login.username': 'Usuario',
|
||
'admin.login.usernamePlaceholder': 'Introduce usuario',
|
||
'admin.login.password': 'Contraseña',
|
||
'admin.login.passwordPlaceholder': 'Introduce contraseña',
|
||
'admin.login.loggingIn': 'Iniciando sesión...',
|
||
'admin.login.loginBtn': 'Iniciar sesión',
|
||
'admin.login.defaultCredentials': 'Credenciales por defecto:',
|
||
'admin.login.changePasswordWarning': '⚠️ ¡Cambia la contraseña por defecto tras el primer inicio de sesión!',
|
||
'admin.login.failed': 'Inicio de sesión fallido',
|
||
'admin.login.invalidCredentials': 'Usuario o contraseña inválidos',
|
||
|
||
// PharmacyManagement
|
||
'admin.pharmacy.title': 'Gestionar Farmacias',
|
||
'admin.pharmacy.addNew': '+ Añadir Nueva Farmacia',
|
||
'admin.pharmacy.edit': 'Editar Farmacia',
|
||
'admin.pharmacy.add': 'Añadir Nueva Farmacia',
|
||
'admin.pharmacy.name': 'Nombre *',
|
||
'admin.pharmacy.address': 'Dirección *',
|
||
'admin.pharmacy.phone': 'Teléfono',
|
||
'admin.pharmacy.latitude': 'Latitud',
|
||
'admin.pharmacy.longitude': 'Longitud',
|
||
'admin.pharmacy.radius': 'Radio',
|
||
'admin.pharmacy.openingHours': 'Horario de apertura',
|
||
'admin.pharmacy.closed': 'Cerrado',
|
||
'admin.pharmacy.opensAt': 'abre a las',
|
||
'admin.pharmacy.closesAt': 'cierra a las',
|
||
'admin.pharmacy.saving': 'Guardando...',
|
||
'admin.pharmacy.update': 'Actualizar',
|
||
'admin.pharmacy.create': 'Añadir',
|
||
'admin.pharmacy.cancel': 'Cancelar',
|
||
'admin.pharmacy.loading': 'Cargando farmacias...',
|
||
'admin.pharmacy.showing': 'Mostrando',
|
||
'admin.pharmacy.of': 'de',
|
||
'admin.pharmacy.withinRadio': '(dentro del radio)',
|
||
'admin.pharmacy.empty': 'Aún no hay farmacias. Importa desde webhook o añade una manualmente.',
|
||
'admin.pharmacy.noResults': 'No hay farmacias en este radio con coordenadas. Amplía el radio, busca otra ciudad o desactiva el filtro de región.',
|
||
'admin.pharmacy.editBtn': 'Editar',
|
||
'admin.pharmacy.deleteBtn': 'Eliminar',
|
||
'admin.pharmacy.deleteConfirm': '¿Estás seguro de que quieres eliminar esta farmacia?',
|
||
'admin.pharmacy.updated': '¡Farmacia actualizada!',
|
||
'admin.pharmacy.created': '¡Farmacia añadida!',
|
||
'admin.pharmacy.deleted': '¡Farmacia eliminada!',
|
||
'admin.pharmacy.loadError': 'Error al cargar farmacias',
|
||
'admin.pharmacy.saveError': 'Error al guardar farmacia',
|
||
'admin.pharmacy.updateError': 'Error al actualizar farmacia',
|
||
'admin.pharmacy.createError': 'Error al crear farmacia',
|
||
'admin.pharmacy.deleteError': 'Error al eliminar farmacia',
|
||
'admin.pharmacy.citySearch': 'Ciudad, región e importación',
|
||
'admin.pharmacy.searchCity': 'Buscar ciudad',
|
||
'admin.pharmacy.chooseOne': 'Elije una',
|
||
'admin.pharmacy.openDataUrl': 'URL de datos abiertos',
|
||
'admin.pharmacy.cityPlaceholder': 'Ej: Rubí, Madrid, Valencia…',
|
||
'admin.pharmacy.searching': 'Buscando…',
|
||
'admin.pharmacy.areaPreset': 'Preset de área',
|
||
'admin.pharmacy.customCoordinates': 'Coordenadas personalizadas',
|
||
'admin.pharmacy.areaExample': 'Ejemplo: Área de Rubí (1.5 km)',
|
||
'admin.pharmacy.enterCity': 'Introduce una ciudad o lugar.',
|
||
'admin.pharmacy.setCoordinates': 'Establece latitud, longitud y radio (usa Buscar ciudad o un preset).',
|
||
'admin.pharmacy.dataSource': 'Fuente de datos',
|
||
'admin.pharmacy.webhookLegacy': 'n8n webhook (heredado)',
|
||
'admin.pharmacy.openDataJson': 'URL de datos abiertos JSON',
|
||
'admin.pharmacy.jsonUrl': 'URL JSON',
|
||
'admin.pharmacy.importing': 'Importando…',
|
||
'admin.pharmacy.importWebhook': 'Importar desde webhook',
|
||
'admin.pharmacy.importUrl': 'Importar desde URL',
|
||
'admin.pharmacy.importFrom': 'Importar desde',
|
||
'admin.pharmacy.showWithinRadio': 'Mostrar solo farmacias dentro del radio',
|
||
'admin.pharmacy.sessionExpired': 'Sesión expirada o no has iniciado sesión. Inicia sesión de nuevo en el panel Admin y reintenta.',
|
||
'admin.pharmacy.apiNotFound': 'La app no pudo conectar con la API (404). Usa http://localhost:3000 con frontend y backend activos.',
|
||
'admin.pharmacy.geocodingNotFound': 'Servicio de geocodificación no encontrado. Actualiza el backend y reinícialo.',
|
||
'admin.pharmacy.searchFailed': 'Búsqueda fallida (HTTP',
|
||
'admin.pharmacy.alwaysOpen': '24 horas (abierta todo el día)',
|
||
'admin.pharmacy.confirmDisable24h': '¿Desactivar 24h? Se descartarán los horarios actuales.',
|
||
'admin.pharmacy.dayClosed': 'Marca un día como Cerrado si la farmacia no abre ese día.',
|
||
'admin.pharmacy.saveError': 'Error al guardar farmacia',
|
||
'admin.pharmacy.radius': 'Radio (m)',
|
||
|
||
// MedicineManagement
|
||
'admin.medicine.title': 'Buscar Medicamentos (API CIMA)',
|
||
'admin.medicine.description': 'Los medicamentos ahora se obtienen directamente de la',
|
||
'admin.medicine.cimaApi': 'API de CIMA',
|
||
'admin.medicine.cimaDescription': '(Agencia Española de Medicamentos y Productos Sanitarios).',
|
||
'admin.medicine.linkDescription': 'Busca medicamentos para vincularlos a farmacias en la pestaña "Link Medicine".',
|
||
'admin.medicine.search': 'Buscar medicamentos',
|
||
'admin.medicine.searchPlaceholder': 'Escribe el nombre de un medicamento...',
|
||
'admin.medicine.searching': 'Buscando en API CIMA...',
|
||
'admin.medicine.found': 'Se encontraron',
|
||
'admin.medicine.medications': 'medicamentos',
|
||
'admin.medicine.activeIngredient': 'Principio Activo:',
|
||
'admin.medicine.dosage': 'Dosis:',
|
||
'admin.medicine.form': 'Forma:',
|
||
'admin.medicine.laboratory': 'Laboratorio:',
|
||
'admin.medicine.registrationNumber': 'Nº Registro:',
|
||
'admin.medicine.generic': 'Genérico',
|
||
'admin.medicine.brand': 'Marca',
|
||
'admin.medicine.noResults': 'No se encontraron medicamentos con ese nombre.',
|
||
'admin.medicine.loadError': 'Error al buscar medicamentos en la API CIMA',
|
||
|
||
// PharmacyMedicineLink
|
||
'admin.linkMedicine.title': 'Vincular Medicamento a Farmacia',
|
||
'admin.linkMedicine.pharmacy': 'Farmacia *',
|
||
'admin.linkMedicine.searchPharmacy': 'Buscar entre',
|
||
'admin.linkMedicine.pharmacies': 'farmacias por nombre o dirección…',
|
||
'admin.linkMedicine.loadingPharmacies': 'Cargando farmacias…',
|
||
'admin.linkMedicine.noPharmacies': 'No hay farmacias que coincidan con',
|
||
'admin.linkMedicine.changePharmacy': 'Cambiar farmacia',
|
||
'admin.linkMedicine.medicine': 'Buscar Medicamento (API CIMA) *',
|
||
'admin.linkMedicine.searchMedicine': 'Escribe para buscar medicamentos en CIMA...',
|
||
'admin.linkMedicine.searching': 'Buscando...',
|
||
'admin.linkMedicine.activeIngredient': 'Principio activo:',
|
||
'admin.linkMedicine.dosage': 'Dosis:',
|
||
'admin.linkMedicine.registrationNumber': 'Nº Registro:',
|
||
'admin.linkMedicine.changeMedicine': 'Cambiar medicamento',
|
||
'admin.linkMedicine.price': 'Precio (€)',
|
||
'admin.linkMedicine.stock': 'Stock',
|
||
'admin.linkMedicine.linkBtn': 'Vincular Medicamento',
|
||
'admin.linkMedicine.reset': 'Reiniciar',
|
||
'admin.linkMedicine.medicationsIn': 'Medicamentos en',
|
||
'admin.linkMedicine.loading': 'Cargando...',
|
||
'admin.linkMedicine.empty': 'Aún no hay medicamentos vinculados a esta farmacia.',
|
||
'admin.linkMedicine.priceLabel': 'Precio:',
|
||
'admin.linkMedicine.undefined': 'No definido',
|
||
'admin.linkMedicine.newPrice': 'Introduce nuevo precio:',
|
||
'admin.linkMedicine.newStock': 'Introduce nuevo stock:',
|
||
'admin.linkMedicine.update': 'Actualizar',
|
||
'admin.linkMedicine.delete': 'Eliminar',
|
||
'admin.linkMedicine.selectMedicineFirst': 'Por favor, selecciona un medicamento primero',
|
||
'admin.linkMedicine.linkSuccess': '¡Medicamento vinculado a la farmacia correctamente!',
|
||
'admin.linkMedicine.linkError': 'Error al vincular medicamento a farmacia',
|
||
'admin.linkMedicine.updateSuccess': '¡Actualizado correctamente!',
|
||
'admin.linkMedicine.updateError': 'Error al actualizar',
|
||
'admin.linkMedicine.deleteConfirm': '¿Eliminar este medicamento de la farmacia?',
|
||
'admin.linkMedicine.deleteSuccess': '¡Medicamento eliminado de la farmacia!',
|
||
'admin.linkMedicine.deleteError': 'Error al eliminar medicamento',
|
||
|
||
// PharmacyProductLink
|
||
'admin.linkProduct.title': 'Vincular Producto a Farmacia',
|
||
'admin.linkProduct.pharmacy': 'Farmacia *',
|
||
'admin.linkProduct.searchPharmacy': 'Buscar entre',
|
||
'admin.linkProduct.pharmacies': 'farmacias por nombre o dirección…',
|
||
'admin.linkProduct.loadingPharmacies': 'Cargando farmacias…',
|
||
'admin.linkProduct.noPharmacies': 'No hay farmacias que coincidan con',
|
||
'admin.linkProduct.changePharmacy': 'Cambiar farmacia',
|
||
'admin.linkProduct.product': 'Buscar Producto (CIMA / Parafarmacia) *',
|
||
'admin.linkProduct.searchProduct': 'Escribe para buscar medicamentos o productos de parafarmacia...',
|
||
'admin.linkProduct.searching': 'Buscando...',
|
||
'admin.linkProduct.brand': 'Marca:',
|
||
'admin.linkProduct.price': 'Precio:',
|
||
'admin.linkProduct.changeProduct': 'Cambiar producto',
|
||
'admin.linkProduct.priceInput': 'Precio (€)',
|
||
'admin.linkProduct.stock': 'Stock',
|
||
'admin.linkProduct.linkBtn': 'Vincular Producto',
|
||
'admin.linkProduct.reset': 'Reiniciar',
|
||
'admin.linkProduct.productsIn': 'Productos en',
|
||
'admin.linkProduct.loading': 'Cargando...',
|
||
'admin.linkProduct.empty': 'Aún no hay productos vinculados a esta farmacia.',
|
||
'admin.linkProduct.priceLabel': 'Precio:',
|
||
'admin.linkProduct.undefined': 'No definido',
|
||
'admin.linkProduct.newPrice': 'Introduce nuevo precio:',
|
||
'admin.linkProduct.newStock': 'Introduce nuevo stock:',
|
||
'admin.linkProduct.update': 'Actualizar',
|
||
'admin.linkProduct.delete': 'Eliminar',
|
||
'admin.linkProduct.selectProductFirst': 'Por favor, selecciona un producto primero',
|
||
'admin.linkProduct.linkSuccess': '¡Producto vinculado a la farmacia correctamente!',
|
||
'admin.linkProduct.linkError': 'Error al vincular producto a farmacia',
|
||
'admin.linkProduct.updateSuccess': '¡Actualizado correctamente!',
|
||
'admin.linkProduct.updateError': 'Error al actualizar',
|
||
'admin.linkProduct.deleteConfirm': '¿Eliminar este producto de la farmacia?',
|
||
'admin.linkProduct.deleteSuccess': '¡Producto eliminado de la farmacia!',
|
||
'admin.linkProduct.deleteError': 'Error al eliminar producto',
|
||
};
|
||
|
||
export default es;
|