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:
parent
8f202262ee
commit
27794895c9
15
app.py
15
app.py
@ -89,8 +89,10 @@ class LanguageMiddleware(BaseHTTPMiddleware):
|
|||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
app.add_middleware(LanguageMiddleware)
|
app.add_middleware(LanguageMiddleware)
|
||||||
templates = Jinja2Templates(directory="templates")
|
|
||||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
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():
|
def load_all_scales():
|
||||||
@ -125,17 +127,16 @@ async def index(request: Request):
|
|||||||
readme_content = markdown.markdown(f.read())
|
readme_content = markdown.markdown(f.read())
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass # 如果README不存在则静默失败
|
pass # 如果README不存在则静默失败
|
||||||
return templates.TemplateResponse("index.html", {
|
return templates[request.state.language].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)
|
||||||
async def list(request: Request, tag: str):
|
async def list(request: Request, tag: str):
|
||||||
tags, scales = load_all_scales()
|
tags, scales = load_all_scales()
|
||||||
return templates.TemplateResponse("list.html", {
|
return templates[request.state.language].TemplateResponse("list.html", {
|
||||||
"request": request,
|
"request": request,
|
||||||
"tags": tags,
|
"tags": tags,
|
||||||
"scales": scales,
|
"scales": scales,
|
||||||
@ -147,7 +148,7 @@ async def scale(request: Request, scale_id: str):
|
|||||||
tags, scales = load_all_scales()
|
tags, scales = load_all_scales()
|
||||||
scale = scales.get(scale_id)
|
scale = scales.get(scale_id)
|
||||||
if scale:
|
if scale:
|
||||||
return templates.TemplateResponse("scale.html", {
|
return templates[request.state.language].TemplateResponse("scale.html", {
|
||||||
"request": request,
|
"request": request,
|
||||||
"scale_id": scale_id,
|
"scale_id": scale_id,
|
||||||
"scale": scale,
|
"scale": scale,
|
||||||
@ -195,7 +196,7 @@ async def result(request: Request, scale_id: str, db: Session = Depends(get_db))
|
|||||||
db.commit()
|
db.commit()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
return templates.TemplateResponse("result.html", {
|
return templates[request.state.language].TemplateResponse("result.html", {
|
||||||
"request": request,
|
"request": request,
|
||||||
"responses": responses,
|
"responses": responses,
|
||||||
"average": average,
|
"average": average,
|
||||||
|
42
templates/en/base.html
Normal file
42
templates/en/base.html
Normal 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
13
templates/en/index.html
Normal 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
16
templates/en/list.html
Normal 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
17
templates/en/result.html
Normal 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
24
templates/en/scale.html
Normal 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 %}
|
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{ language }}">
|
<html lang="zh">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
@ -1,13 +1,13 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block head_extra %}
|
{% block head_extra %}
|
||||||
<title>心尺.Org</title>
|
<title>心尺.Org</title>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
{% if readme_content %}
|
{% if readme_content %}
|
||||||
<div class="readme-section">
|
<div class="readme-section">
|
||||||
{{ readme_content|safe }}
|
{{ readme_content|safe }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -1,17 +1,17 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block head_extra %}
|
{% block head_extra %}
|
||||||
<title>{{scale.title}}</title>
|
<title>{{scale.title}}</title>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<h1>{{ scale.title }} </h1>
|
<h1>{{ scale.title }} </h1>
|
||||||
<ul>
|
<ul>
|
||||||
{% for key, value in responses.items() %}
|
{% for key, value in responses.items() %}
|
||||||
<li>{{ key }}: 在 {{options[key][0]}} 到 {{options[key][1]}} 的量表中得分 {{ value }},均分 {{ average[key] }};</li>
|
<li>{{ key }}: 在 {{options[key][0]}} 到 {{options[key][1]}} 的量表中得分 {{ value }},均分 {{ average[key] }};</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
<div>
|
<div>
|
||||||
{{scale.descriptions|safe}}
|
{{scale.descriptions|safe}}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -1,24 +1,24 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block head_extra %}
|
{% block head_extra %}
|
||||||
<title>{{ scale.title }}</title>
|
<title>{{ scale.title }}</title>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<h1>{{ scale.title }}</h1>
|
<h1>{{ scale.title }}</h1>
|
||||||
<div>
|
<div>
|
||||||
{{ scale.instructions|safe }}
|
{{ scale.instructions|safe }}
|
||||||
</div>
|
</div>
|
||||||
<form class="scale" action="/scales/{{ scale_id }}" method="post">
|
<form class="scale" action="/scales/{{ scale_id }}" method="post">
|
||||||
{% for id, question in scale['items'].items() %}
|
{% for id, question in scale['items'].items() %}
|
||||||
<label for="{{ id }}">{{ id }}. {{ question }}</label>
|
<label for="{{ id }}">{{ id }}. {{ question }}</label>
|
||||||
<div class="scale-button">
|
<div class="scale-button">
|
||||||
{% for option, label in scale.options.items() %}
|
{% for option, label in scale.options.items() %}
|
||||||
<input type="radio" id="{{ id }}_{{ option }}" name="{{ id }}" value="{{ option }}" required>
|
<input type="radio" id="{{ id }}_{{ option }}" name="{{ id }}" value="{{ option }}" required>
|
||||||
<label for="{{ id }}_{{ option }}" title="{{label}}">{{ option }}</label>
|
<label for="{{ id }}_{{ option }}" title="{{label}}">{{ option }}</label>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<input type="submit" value="提交">
|
<input type="submit" value="提交">
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user