From 8f202262eefb103c3a4d139236d6ed768b54e648 Mon Sep 17 00:00:00 2001 From: mxr612 Date: Tue, 17 Jun 2025 07:48:38 +0800 Subject: [PATCH] feat: add language detection middleware for request handling - Implemented LanguageMiddleware to determine the user's language based on query parameters, Accept-Language header, or IP address. - Updated the FastAPI app to include the middleware and pass the detected language to templates. - Modified base.html to dynamically set the HTML language attribute based on the detected language. --- app.py | 61 +++++++++++++++++++++++++++++++++++++++++---- templates/base.html | 2 +- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/app.py b/app.py index c5a7241..c4fc746 100644 --- a/app.py +++ b/app.py @@ -15,10 +15,8 @@ from datetime import datetime, UTC import csv from io import StringIO from typing import Dict, List - -app = FastAPI() -templates = Jinja2Templates(directory="templates") -app.mount("/static", StaticFiles(directory="static"), name="static") +from starlette.middleware.base import BaseHTTPMiddleware +from starlette.types import ASGIApp # Initialize GeoIP2 reader try: @@ -42,6 +40,58 @@ def get_location_from_ip(ip): print(f"Error getting location for IP {ip}: {e}") return None +class LanguageMiddleware(BaseHTTPMiddleware): + def __init__(self, app: ASGIApp): + super().__init__(app) + self.default_language = "en" # Default language + self.supported_languages = ["zh", "en"] # Supported languages + + async def dispatch(self, request: Request, call_next): + # Get language from query parameter + lang = request.query_params.get("lang") + + # If no language in query params, try to get from Accept-Language header + if not lang: + accept_language = request.headers.get("accept-language", "") + if accept_language: + # Parse Accept-Language header and get the first language + lang = accept_language.split(",")[0].split(";")[0].strip()[:2] + + # If still no language, try to detect from IP + if not lang and geoip_reader: + try: + ip = request.headers.get("X-Forwarded-For", "").split(",")[0].strip() or \ + request.headers.get("X-Real-IP", "") or \ + request.client.host + response = geoip_reader.city(ip) + country_to_lang = { # Map country to language + "China": "zh", + "Hong Kong": "zh", + "Taiwan": "zh", + "Macau": "zh", + "United States": "en", + "United Kingdom": "en", + } + lang = country_to_lang.get(response.country.name, self.default_language) + except: + lang = self.default_language + + # Ensure language is supported + if lang not in self.supported_languages: + lang = self.default_language + + # Add language to request state + request.state.language = lang + + # Continue processing the request + response = await call_next(request) + return response + +app = FastAPI() +app.add_middleware(LanguageMiddleware) +templates = Jinja2Templates(directory="templates") +app.mount("/static", StaticFiles(directory="static"), name="static") + # 加载所有问卷数据 def load_all_scales(): scales = {} @@ -78,7 +128,8 @@ async def index(request: Request): return templates.TemplateResponse("index.html", { "request": request, "tags": tags, - "readme_content": readme_content # 新增模板变量 + "readme_content": readme_content, + "language": request.state.language # Pass language to template }) @app.get("/tag/{tag}", response_class=HTMLResponse) diff --git a/templates/base.html b/templates/base.html index 6e416af..a65292a 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,5 +1,5 @@ - +