Add English language support with i18n implementation
Implemented comprehensive internationalization (i18n) for both frontend and backend: Frontend: - Added react-i18next configuration with Spanish (default) and English - Created translation files (locales/es.json, locales/en.json) - Refactored core components to use i18n: LoginPage, DashboardHeader, DataUploader - Created LanguageSelector component with toggle between ES/EN - Updated API client to send Accept-Language header Backend: - Created i18n module with translation dictionary for error messages - Updated security.py to return localized authentication errors - Updated api/analysis.py to return localized validation errors - Implemented language detection from Accept-Language header Spanish remains the default language ensuring backward compatibility. Users can switch between languages using the language selector in the dashboard header. https://claude.ai/code/session_1N9VX
This commit is contained in:
@@ -2,8 +2,11 @@ from __future__ import annotations
|
||||
|
||||
import os
|
||||
import secrets
|
||||
from fastapi import Depends, HTTPException, status
|
||||
from fastapi import Depends, HTTPException, status, Header
|
||||
from fastapi.security import HTTPBasic, HTTPBasicCredentials
|
||||
from typing import Optional
|
||||
|
||||
from .i18n import t, get_language_from_header
|
||||
|
||||
# auto_error=False para que no dispare el popup nativo del navegador automáticamente
|
||||
security = HTTPBasic(auto_error=False)
|
||||
@@ -13,16 +16,21 @@ BASIC_USER = os.getenv("BASIC_AUTH_USERNAME", "beyond")
|
||||
BASIC_PASS = os.getenv("BASIC_AUTH_PASSWORD", "beyond2026")
|
||||
|
||||
|
||||
def get_current_user(credentials: HTTPBasicCredentials | None = Depends(security)) -> str:
|
||||
def get_current_user(
|
||||
credentials: HTTPBasicCredentials | None = Depends(security),
|
||||
accept_language: Optional[str] = Header(None)
|
||||
) -> str:
|
||||
"""
|
||||
Valida el usuario/contraseña vía HTTP Basic.
|
||||
NO envía WWW-Authenticate para evitar el popup nativo del navegador
|
||||
(el frontend tiene su propio formulario de login).
|
||||
"""
|
||||
lang = get_language_from_header(accept_language)
|
||||
|
||||
if credentials is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Credenciales requeridas",
|
||||
detail=t("auth.credentials_required", lang),
|
||||
)
|
||||
|
||||
correct_username = secrets.compare_digest(credentials.username, BASIC_USER)
|
||||
@@ -31,7 +39,7 @@ def get_current_user(credentials: HTTPBasicCredentials | None = Depends(security
|
||||
if not (correct_username and correct_password):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Credenciales incorrectas",
|
||||
detail=t("auth.incorrect_credentials", lang),
|
||||
)
|
||||
|
||||
return credentials.username
|
||||
|
||||
Reference in New Issue
Block a user