@@ -7,16 +7,70 @@ from fastapi.responses import HTMLResponse
from pydantic import BaseModel , HttpUrl
from app . core . config import get_settings
from app . legal_docs import PRIVACY_POLICY_MD , TERMS_OF_USE_MD , choose_content_by_lang , render_as_simple_html
from app . legal_docs import (
PRIVACY_POLICY_MD ,
TERMS_OF_USE_MD ,
choose_content_by_lang ,
render_as_simple_html ,
split_bilingual_markdown ,
)
router = APIRouter ( prefix = " /v1/legal " , tags = [ " legal " ] )
INTERNAL_SENTINEL = " __internal__ "
# 技术支持页文案( EN / TC)
SUPPORT_MD = """ Dear Mama | Technical Support
Last updated: February 2026
If you need technical support for Dear Mama, please contact us:
- Support email: leitinglan@project-c.org
Support scope (including but not limited to):
- App installation or update issues
- App crashes, freezes, or abnormal behavior
- Notification or widget related issues
- Difficulty accessing privacy policy or terms pages
To help us process your request faster, please include:
- Device model and OS version
- App version
- A brief issue description and occurrence time
- Screenshots or screen recording (if available)
Service commitment:
- We generally respond within 3-5 business days
- Emergency availability may vary by holidays and local time
---
Dear Mama| 技術支援
最後更新日期: 2026 年 2 月
如需 Dear Mama 的技術支援,請透過以下方式聯絡我們:
- 支援信箱: leitinglan@project-c.org
支援範圍(包含但不限於):
- App 安裝或更新問題
- App 閃退、卡頓或異常行為
- 通知或小組件相關問題
- 隱私政策或使用條款頁面無法開啟
為了加快處理,建議提供:
- 裝置型號與系統版本
- App 版本號
- 問題描述與發生時間
- 截圖或螢幕錄影(如有)
服務承諾:
- 一般會在 3-5 個工作日內回覆
- 節假日或時區差異時,回覆時間可能延長
"""
# 当前多语言仅支持 EN / TC( 繁体)
ResolvedLang = Literal [ " en " , " tc " ]
BILINGUAL_CONTENT_LANGUAGE = " en, zh-Hant "
class LegalLinksResponse ( BaseModel ) :
@@ -85,6 +139,18 @@ def _normalize_internal_url(request: Request, url: str, internal_path: str) -> s
return _join_base_url ( str ( request . base_url ) , internal_path )
def _build_bilingual_content ( text : str ) - > str :
"""
固定输出双语协议内容: EN 在前, TC 在后。
若缺少 TC, 则仅返回 EN。
"""
en , tc = split_bilingual_markdown ( text )
if not tc :
return en
return f " { en } \n \n --- \n { tc } "
@router.get ( " /links " , response_model = LegalLinksResponse )
async def get_legal_links ( request : Request ) - > LegalLinksResponse :
"""
@@ -109,11 +175,18 @@ async def get_privacy_policy(request: Request) -> HTMLResponse:
"""
accept_language = request . headers . get ( " accept-language " )
if accept_language :
lang = _resolve_lang ( accept_language )
content , resolved = choose_content_by_lang ( PRIVACY_POLICY_MD , lang )
title = " Dear Mama | Privacy Policy " if resolved == " en " else " Dear Mama| 隱私權政策 "
page = render_as_simple_html ( title = title , content = conte nt)
return HTMLResponse ( content = pag e, headers = { " Content-Language " : " en " if resolved == " en " else " zh-Hant " } )
html_lang = " en " if resolved == " en " else " zh-Ha nt"
page = render_as_simple_html ( title = titl e, content = content , html_lang = html_lang )
return HTMLResponse ( content = page , headers = { " Content-Language " : html_lang } )
content = _build_bilingual_content ( PRIVACY_POLICY_MD )
title = " Dear Mama | Privacy Policy / 隱私權政策 "
page = render_as_simple_html ( title = title , content = content , html_lang = " en " )
return HTMLResponse ( content = page , headers = { " Content-Language " : BILINGUAL_CONTENT_LANGUAGE } )
@router.get ( " /terms " , response_class = HTMLResponse )
@@ -123,9 +196,37 @@ async def get_terms_of_use(request: Request) -> HTMLResponse:
"""
accept_language = request . headers . get ( " accept-language " )
if accept_language :
lang = _resolve_lang ( accept_language )
content , resolved = choose_content_by_lang ( TERMS_OF_USE_MD , lang )
title = " Dear Mama – Terms of Use " if resolved == " en " else " Dear Mama 使用條款 "
page = render_as_simple_html ( title = title , content = conte nt)
return HTMLResponse ( content = pag e, headers = { " Content-Language " : " en " if resolved == " en " else " zh-Hant " } )
html_lang = " en " if resolved == " en " else " zh-Ha nt"
page = render_as_simple_html ( title = titl e, content = content , html_lang = html_lang )
return HTMLResponse ( content = page , headers = { " Content-Language " : html_lang } )
content = _build_bilingual_content ( TERMS_OF_USE_MD )
title = " Dear Mama – Terms of Use / 使用條款 "
page = render_as_simple_html ( title = title , content = content , html_lang = " en " )
return HTMLResponse ( content = page , headers = { " Content-Language " : BILINGUAL_CONTENT_LANGUAGE } )
@router.get ( " /support " , response_class = HTMLResponse )
async def get_support_page ( request : Request ) - > HTMLResponse :
"""
技术支持页面(用于 App 审核的可访问 URL) 。
"""
accept_language = request . headers . get ( " accept-language " )
if accept_language :
lang = _resolve_lang ( accept_language )
content , resolved = choose_content_by_lang ( SUPPORT_MD , lang )
title = " Dear Mama | Technical Support " if resolved == " en " else " Dear Mama| 技術支援 "
html_lang = " en " if resolved == " en " else " zh-Hant "
page = render_as_simple_html ( title = title , content = content , html_lang = html_lang )
return HTMLResponse ( content = page , headers = { " Content-Language " : html_lang } )
content = _build_bilingual_content ( SUPPORT_MD )
title = " Dear Mama | Technical Support / 技術支援 "
page = render_as_simple_html ( title = title , content = content , html_lang = " en " )
return HTMLResponse ( content = page , headers = { " Content-Language " : BILINGUAL_CONTENT_LANGUAGE } )