feat: implement multilingual template support

- Updated app.py to dynamically load Jinja2 templates based on the detected language.
- Created new template files for English and Chinese, including base, index, list, scale, and result pages.
- Modified template rendering logic to utilize the appropriate language-specific templates based on user preferences.
This commit is contained in:
Miu Li 2025-06-17 08:08:18 +08:00
parent 8f202262ee
commit 27794895c9
11 changed files with 172 additions and 59 deletions

15
app.py
View File

@ -89,8 +89,10 @@ class LanguageMiddleware(BaseHTTPMiddleware):
app = FastAPI()
app.add_middleware(LanguageMiddleware)
templates = Jinja2Templates(directory="templates")
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = {}
for lang in os.listdir("templates"):
templates[lang] = Jinja2Templates(directory="templates/"+lang)
# 加载所有问卷数据
def load_all_scales():
@ -125,17 +127,16 @@ async def index(request: Request):
readme_content = markdown.markdown(f.read())
except FileNotFoundError:
pass # 如果README不存在则静默失败
return templates.TemplateResponse("index.html", {
return templates[request.state.language].TemplateResponse("index.html", {
"request": request,
"tags": tags,
"readme_content": readme_content,
"language": request.state.language # Pass language to template
"readme_content": readme_content
})
@app.get("/tag/{tag}", response_class=HTMLResponse)
async def list(request: Request, tag: str):
tags, scales = load_all_scales()
return templates.TemplateResponse("list.html", {
return templates[request.state.language].TemplateResponse("list.html", {
"request": request,
"tags": tags,
"scales": scales,
@ -147,7 +148,7 @@ async def scale(request: Request, scale_id: str):
tags, scales = load_all_scales()
scale = scales.get(scale_id)
if scale:
return templates.TemplateResponse("scale.html", {
return templates[request.state.language].TemplateResponse("scale.html", {
"request": request,
"scale_id": scale_id,
"scale": scale,
@ -195,7 +196,7 @@ async def result(request: Request, scale_id: str, db: Session = Depends(get_db))
db.commit()
except Exception as e:
print(e)
return templates.TemplateResponse("result.html", {
return templates[request.state.language].TemplateResponse("result.html", {
"request": request,
"responses": responses,
"average": average,

42
templates/en/base.html Normal file
View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="PsychoScales心理学专业量表数据库提供标准化心理测评工具包含人格测试、症状评估等2000+临床心理学量表,支持在线测评及科研数据导出。">
<meta name="keywords" content="心尺, PsychoScales, 心理学量表,专业心理测评,抑郁症测试,焦虑症自评,在线心理测评系统,心理咨询师工具, 心理测验, 报告解读, 测试题">
<meta name="baidu-site-verification" content="codeva-mPOBUr0rLS" />
<link rel="stylesheet" href="/static/styles.css">
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
{% block head_extra %}{% endblock %}
</head>
<body>
<nav>
<div class="nav-left">
<a href="/" class="logo">PsychoScales.Org</a>
</div>
<div class="menu-toggle" onclick="document.querySelector('.nav-links').classList.toggle('active')"></div>
<ul class="nav-links">
<li><a href="https://doc.psychoscales.com/"">Docs</a></li>
{% for tag in tags %}
<li><a href=" /tag/{{ tag }}"">{{ tag }}</a></li>
{% endfor %}
</ul>
</nav>
<main>
{% block main %}{% endblock %}
</main>
<!-- 添加KaTeX支持 -->
<link rel=" stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js" onload="renderMathInElement(document.body, {delimiters: [
{left: '$$', right: '$$', display: true},
{left: '$', right: '$', display: false}]});">
</script>
</body>
</html>

13
templates/en/index.html Normal file
View File

@ -0,0 +1,13 @@
{% extends 'base.html' %}
{% block head_extra %}
<title>PsychoScales.Org</title>
{% endblock %}
{% block main %}
{% if readme_content %}
<div class="readme-section">
{{ readme_content|safe }}
</div>
{% endif %}
{% endblock %}

16
templates/en/list.html Normal file
View File

@ -0,0 +1,16 @@
{% extends 'base.html' %}
{% block head_extra %}
<title>{{ tag }}</title>
{% endblock %}
{% block main %}
<div class="scale-list">
{% for scale_id, scale in scales.items() %}
{% if scale.tag == tag %}
<a class="title" href="/scales/{{ scale_id }}">{{ scale.get('title','Untitled') }}</a>
<p>{{ scale.abstract|safe }}</p>
{% endif %}
{% endfor %}
</div>
{% endblock %}

17
templates/en/result.html Normal file
View File

@ -0,0 +1,17 @@
{% extends 'base.html' %}
{% block head_extra %}
<title>{{scale.title}}</title>
{% endblock %}
{% block main %}
<h1>{{ scale.title }} </h1>
<ul>
{% for key, value in responses.items() %}
<li>{{ key }}: Got {{ value }} in a {{options[key][0]}} to {{options[key][1]}} scale, with {{ average[key] }} in average</li>
{% endfor %}
</ul>
<div>
{{scale.descriptions|safe}}
</div>
{% endblock %}

24
templates/en/scale.html Normal file
View File

@ -0,0 +1,24 @@
{% extends 'base.html' %}
{% block head_extra %}
<title>{{ scale.title }}</title>
{% endblock %}
{% block main %}
<h1>{{ scale.title }}</h1>
<div>
{{ scale.instructions|safe }}
</div>
<form class="scale" action="/scales/{{ scale_id }}" method="post">
{% for id, question in scale['items'].items() %}
<label for="{{ id }}">{{ id }}. {{ question }}</label>
<div class="scale-button">
{% for option, label in scale.options.items() %}
<input type="radio" id="{{ id }}_{{ option }}" name="{{ id }}" value="{{ option }}" required>
<label for="{{ id }}_{{ option }}" title="{{label}}">{{ option }}</label>
{% endfor %}
</div>
{% endfor %}
<input type="submit" value="Submit">
</form>
{% endblock %}

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="{{ language }}">
<html lang="zh">
<head>
<meta charset="UTF-8">