""" Módulo de internacionalización para Beyond API. Proporciona traducciones para mensajes de error, validaciones y clasificaciones. """ from typing import Literal Language = Literal["es", "en"] # Diccionario de traducciones MESSAGES = { "es": { # Errores de autenticación "auth.credentials_required": "Credenciales requeridas", "auth.incorrect_credentials": "Credenciales incorrectas", # Errores de análisis "analysis.invalid_type": "analysis debe ser 'basic' o 'premium'.", "analysis.invalid_economy_json": "economy_json no es un JSON válido.", "analysis.no_cached_file": "No hay archivo cacheado en el servidor. Sube un archivo primero.", "analysis.execution_error": "Error ejecutando análisis: {error}", # Errores de validación "validation.field_not_numeric": "El campo '{field}' debe ser numérico (float). Valor recibido: {value}", "validation.segments_not_dict": "customer_segments debe ser un diccionario {segment: level}", "validation.segment_value_not_str": "El valor de customer_segments['{key}'] debe ser str. Valor recibido: {value}", "validation.csv_not_found": "El CSV no existe: {path}", "validation.not_csv_file": "La ruta no apunta a un fichero CSV: {path}", "validation.missing_columns": "Faltan columnas obligatorias para {metric}: {missing}", # Clasificaciones Agentic Readiness "agentic.ready_for_copilot": "Listo para Copilot", "agentic.ready_for_copilot_desc": "Procesos con predictibilidad y simplicidad suficientes para asistencia IA (sugerencias en tiempo real, autocompletado).", "agentic.optimize_first": "Optimizar primero", "agentic.optimize_first_desc": "Estandarizar procesos y reducir variabilidad antes de implementar asistencia IA.", "agentic.requires_human": "Requiere gestión humana", "agentic.requires_human_desc": "Procesos complejos o variables que necesitan intervención humana antes de considerar automatización.", }, "en": { # Authentication errors "auth.credentials_required": "Credentials required", "auth.incorrect_credentials": "Incorrect credentials", # Analysis errors "analysis.invalid_type": "analysis must be 'basic' or 'premium'.", "analysis.invalid_economy_json": "economy_json is not valid JSON.", "analysis.no_cached_file": "No cached file on server. Upload a file first.", "analysis.execution_error": "Error executing analysis: {error}", # Validation errors "validation.field_not_numeric": "Field '{field}' must be numeric (float). Received value: {value}", "validation.segments_not_dict": "customer_segments must be a dictionary {segment: level}", "validation.segment_value_not_str": "Value of customer_segments['{key}'] must be str. Received value: {value}", "validation.csv_not_found": "CSV does not exist: {path}", "validation.not_csv_file": "Path does not point to a CSV file: {path}", "validation.missing_columns": "Missing required columns for {metric}: {missing}", # Agentic Readiness classifications "agentic.ready_for_copilot": "Ready for Copilot", "agentic.ready_for_copilot_desc": "Processes with sufficient predictability and simplicity for AI assistance (real-time suggestions, autocomplete).", "agentic.optimize_first": "Optimize first", "agentic.optimize_first_desc": "Standardize processes and reduce variability before implementing AI assistance.", "agentic.requires_human": "Requires human management", "agentic.requires_human_desc": "Complex or variable processes that need human intervention before considering automation.", } } def t(key: str, lang: Language = "es", **kwargs) -> str: """ Traduce un mensaje al idioma especificado. Args: key: Clave del mensaje (ej: 'auth.credentials_required') lang: Idioma ('es' o 'en'). Por defecto 'es' **kwargs: Variables para interpolación (ej: field='nombre', value='123') Returns: Mensaje traducido con variables interpoladas Examples: >>> t('auth.credentials_required', 'en') 'Credentials required' >>> t('validation.field_not_numeric', 'en', field='age', value='abc') "Field 'age' must be numeric (float). Received value: abc" """ messages = MESSAGES.get(lang, MESSAGES["es"]) message = messages.get(key, key) # Interpolar variables si se proporcionan if kwargs: try: return message.format(**kwargs) except KeyError: # Si falta alguna variable, devolver el mensaje sin interpolar return message return message def get_language_from_header(accept_language: str | None) -> Language: """ Extrae el idioma preferido del header Accept-Language. Args: accept_language: Valor del header Accept-Language (ej: 'en-US,en;q=0.9,es;q=0.8') Returns: 'en' si el idioma preferido es inglés, 'es' en caso contrario Examples: >>> get_language_from_header('en-US,en;q=0.9') 'en' >>> get_language_from_header('es-ES,es;q=0.9') 'es' >>> get_language_from_header(None) 'es' """ if not accept_language: return "es" # Extraer el primer idioma del header primary_lang = accept_language.split(',')[0].split('-')[0].strip().lower() return "en" if primary_lang == "en" else "es"