Mejora: Optimización radical de carga del panel mediante pre-calentamiento asíncrono de caché UI (#5)
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
import re
|
||||
import asyncio
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from fastapi import FastAPI, HTTPException, status
|
||||
@@ -67,12 +70,82 @@ def translate_filter(text, lang="es"):
|
||||
|
||||
templates.env.filters["translate"] = translate_filter
|
||||
|
||||
_warmed_languages = set()
|
||||
|
||||
async def pre_warm_ui_translations(lang: str):
|
||||
if lang == "es" or lang in _warmed_languages:
|
||||
return
|
||||
|
||||
_warmed_languages.add(lang)
|
||||
print(f"[Panel] Pre-calentando traducciones para idioma UI: {lang}...")
|
||||
|
||||
strings_to_translate = set()
|
||||
for f in glob.glob(os.path.join(os.path.dirname(__file__), "templates", "*.html")):
|
||||
try:
|
||||
with open(f, "r", encoding="utf-8") as fd:
|
||||
content = fd.read()
|
||||
strings_to_translate.update(re.findall(r'\"([^\"]+)\"\s*\|\s*translate', content))
|
||||
strings_to_translate.update(re.findall(r'\'([^\']+)\'\s*\|\s*translate', content))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
missing_strings = []
|
||||
for text in strings_to_translate:
|
||||
norm_text = _normalize_text(text)
|
||||
if not norm_text: continue
|
||||
|
||||
cache_key = f"{lang}:{norm_text}"
|
||||
if cache_key in _ui_memory_cache: continue
|
||||
|
||||
cached = get_ui_translation(norm_text, lang)
|
||||
if cached:
|
||||
_ui_memory_cache[cache_key] = cached
|
||||
else:
|
||||
missing_strings.append(norm_text)
|
||||
|
||||
if not missing_strings:
|
||||
print(f"[Panel] Pre-calentamiento completo: 0 cadenas faltantes para {lang}")
|
||||
return
|
||||
|
||||
print(f"[Panel] Falta traducir {len(missing_strings)} cadenas UI al {lang}. Empezando concurrencia...")
|
||||
|
||||
from botdiscord.translate import translate_text
|
||||
|
||||
async def _fetch_and_save(text):
|
||||
translated = await translate_text(text, lang)
|
||||
if translated and translated != text:
|
||||
save_ui_translation(text, lang, translated)
|
||||
_ui_memory_cache[f"{lang}:{text}"] = translated
|
||||
|
||||
tasks = [_fetch_and_save(t) for t in missing_strings]
|
||||
await asyncio.gather(*tasks)
|
||||
print(f"[Panel] Pre-calentamiento terminado para {lang}.")
|
||||
|
||||
@app.middleware("http")
|
||||
async def translation_pre_warm_middleware(request: Request, call_next):
|
||||
# Detectamos el idioma que va a usar la página para asegurarnos de que esté cargado
|
||||
if request.url.path.startswith("/static") or request.url.path.startswith("/api"):
|
||||
return await call_next(request)
|
||||
|
||||
lang = request.cookies.get("panel_lang")
|
||||
if not lang:
|
||||
accept_lang = request.headers.get("accept-language", "es")
|
||||
lang = accept_lang.split(",")[0].split("-")[0]
|
||||
|
||||
if lang and len(lang) == 2:
|
||||
await pre_warm_ui_translations(lang)
|
||||
|
||||
return await call_next(request)
|
||||
|
||||
@app.get("/set-lang/{lang}")
|
||||
async def set_lang(lang: str, request: Request):
|
||||
# Validamos que el idioma sea de 2 letras
|
||||
if len(lang) != 2:
|
||||
return RedirectResponse(url="/dashboard")
|
||||
|
||||
# Ejecutamos el calentamiento asíncrono para que la redirección sea instantánea
|
||||
await pre_warm_ui_translations(lang)
|
||||
|
||||
response = RedirectResponse(url=request.headers.get("referer", "/dashboard"))
|
||||
response.set_cookie(key="panel_lang", value=lang, max_age=31536000) # 1 año
|
||||
return response
|
||||
|
||||
Reference in New Issue
Block a user