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.
This commit is contained in:
parent
eb4d670ee0
commit
8f202262ee
61
app.py
61
app.py
@ -15,10 +15,8 @@ from datetime import datetime, UTC
|
|||||||
import csv
|
import csv
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
from starlette.middleware.base import BaseHTTPMiddleware
|
||||||
app = FastAPI()
|
from starlette.types import ASGIApp
|
||||||
templates = Jinja2Templates(directory="templates")
|
|
||||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
||||||
|
|
||||||
# Initialize GeoIP2 reader
|
# Initialize GeoIP2 reader
|
||||||
try:
|
try:
|
||||||
@ -42,6 +40,58 @@ def get_location_from_ip(ip):
|
|||||||
print(f"Error getting location for IP {ip}: {e}")
|
print(f"Error getting location for IP {ip}: {e}")
|
||||||
return None
|
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():
|
def load_all_scales():
|
||||||
scales = {}
|
scales = {}
|
||||||
@ -78,7 +128,8 @@ async def index(request: Request):
|
|||||||
return templates.TemplateResponse("index.html", {
|
return templates.TemplateResponse("index.html", {
|
||||||
"request": request,
|
"request": request,
|
||||||
"tags": tags,
|
"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)
|
@app.get("/tag/{tag}", response_class=HTMLResponse)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!-- <html lang="zh"> -->
|
<html lang="{{ language }}">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user