Skip to content

Commit 900eb2d

Browse files
perf: Internationalization (i18n) for In‑line Error Prompts
1 parent 4ee923c commit 900eb2d

5 files changed

Lines changed: 64 additions & 15 deletions

File tree

backend/apps/system/api/assistant.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,53 +40,62 @@ async def info(request: Request, response: Response, session: SessionDep, trans:
4040
# 校验 SQLBOT-EMBEDDED-SIGN 请求头
4141
sign_header = request.headers.get("SQLBOT-EMBEDDED-SIGN")
4242
if not sign_header:
43-
raise RuntimeError(trans('i18n_embedded.invalid_origin', origin=''))
43+
raise RuntimeError(trans('i18n_embedded.missing_sign'))
4444

45-
sign_data = await decrypt_embedded_sign(sign_header)
45+
try:
46+
sign_data = await decrypt_embedded_sign(sign_header)
47+
except Exception:
48+
raise RuntimeError(trans('i18n_embedded.invalid_sign'))
4649

4750
# 校验 assistant_id 与 id 参数一致
4851
if str(sign_data.get("assistant_id")) != str(id):
49-
raise RuntimeError(trans('i18n_embedded.invalid_origin', origin=''))
52+
raise RuntimeError(trans('i18n_embedded.assistant_id_mismatch'))
5053

5154
# 校验 target(来源域名)是否合法
5255
target = sign_data.get("target", "")
5356

5457
request_origin = request.headers.get("origin") or get_origin_from_referer(request)
5558
if not request_origin:
56-
raise RuntimeError(trans('i18n_embedded.invalid_origin', origin=request_origin or ''))
59+
raise RuntimeError(trans('i18n_embedded.missing_origin'))
5760
request_origin = request_origin.rstrip('/')
5861
if not target or target == "null":
5962
target = request_origin
6063
elif target != request_origin:
61-
raise RuntimeError(trans('i18n_embedded.invalid_origin', origin=target or ''))
64+
raise RuntimeError(trans('i18n_embedded.target_origin_mismatch'))
6265

6366
if not origin_match_domain(target, db_model.domain):
6467
raise RuntimeError(trans('i18n_embedded.invalid_origin', origin=target or ''))
6568

6669
# 校验 sign_time 是否在 10 秒内
6770
sign_time_str = sign_data.get("sign_time", "")
68-
sign_time = datetime.fromisoformat(sign_time_str)
71+
try:
72+
sign_time = datetime.fromisoformat(sign_time_str)
73+
except (ValueError, TypeError):
74+
raise RuntimeError(trans('i18n_embedded.sign_time_invalid'))
6975
now_utc = datetime.now(timezone.utc)
7076
sign_time_utc = sign_time.astimezone(timezone.utc)
7177
if abs((now_utc - sign_time_utc).total_seconds()) > 10:
72-
raise RuntimeError(trans('i18n_embedded.invalid_origin', origin=target or ''))
78+
raise RuntimeError(trans('i18n_embedded.sign_time_expired'))
7379

7480
# 校验是否为真实浏览器请求(非自动化工具)
7581
if sign_data.get("webdriver", False):
76-
raise RuntimeError(trans('i18n_embedded.invalid_origin', origin=target or ''))
82+
raise RuntimeError(trans('i18n_embedded.automation_tool_detected'))
7783

7884
# 校验 User-Agent 一致性(签名中的 navigator.userAgent 与请求头一致)
7985
sign_user_agent = sign_data.get("user_agent", "")
8086
request_user_agent = request.headers.get("User-Agent", "")
8187
if sign_user_agent != request_user_agent:
82-
raise RuntimeError(trans('i18n_embedded.invalid_origin', origin=target or ''))
88+
raise RuntimeError(trans('i18n_embedded.user_agent_mismatch'))
8389

8490
# 校验 timezone 与 sign_time 偏移一致性(防时区伪造)
8591
tz_name = sign_data.get("timezone", "")
86-
tz = ZoneInfo(tz_name)
92+
try:
93+
tz = ZoneInfo(tz_name)
94+
except Exception:
95+
raise RuntimeError(trans('i18n_embedded.timezone_mismatch'))
8796
sign_time_naive = sign_time.replace(tzinfo=None)
8897
if tz.utcoffset(sign_time_naive) != sign_time.utcoffset():
89-
raise RuntimeError(trans('i18n_embedded.invalid_origin', origin=target or ''))
98+
raise RuntimeError(trans('i18n_embedded.timezone_mismatch'))
9099

91100
origin = target.rstrip('/')
92101

backend/locales/en.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,17 @@
5454
"i18n_ds_invalid": "Datasource connection is invalid",
5555
"i18n_ds_upload_error": "Upload Failed",
5656
"i18n_embedded": {
57-
"invalid_origin": "Domain name validation failed【{origin}】"
57+
"invalid_origin": "Domain name validation failed【{origin}】",
58+
"missing_sign": "Missing embedded signature (SQLBOT-EMBEDDED-SIGN); cannot verify the embedding party's identity.",
59+
"assistant_id_mismatch": "The assistant ID in the signature does not match the current request; cannot verify the embedding party's identity.",
60+
"missing_origin": "The current page is missing source information (Origin/Referer); cannot verify the embedding party's identity.",
61+
"target_origin_mismatch": "The source domain in the signature does not match the current page domain; cannot verify the embedding party's identity.",
62+
"invalid_sign": "The embedded signature is invalid or corrupted; cannot verify the embedding party's identity.",
63+
"sign_time_expired": "The synchronization delay between the server (SQLBot) and the current page (embedding site) exceeds 10 seconds, causing the connection to be interrupted.",
64+
"sign_time_invalid": "Invalid signature time format; cannot verify the embedding party's identity.",
65+
"automation_tool_detected": "Automated tool access detected. Embedding has been blocked.",
66+
"user_agent_mismatch": "The browser identifier in the signature does not match the current request. Embedding has been blocked.",
67+
"timezone_mismatch": "The timezone information in the signature does not match the signing time. Embedding has been blocked."
5868
},
5969
"i18n_chat": {
6070
"record_id_in_mcp": "Answer ID: "

backend/locales/ko-KR.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,17 @@
5454
"i18n_ds_invalid": "데이터 소스 연결이 무효합니다",
5555
"i18n_ds_upload_error": "파일 업로드 실패",
5656
"i18n_embedded": {
57-
"invalid_origin": "도메인 이름 검증 실패 【{origin}】"
57+
"invalid_origin": "도메인 이름 검증 실패 【{origin}】",
58+
"missing_sign": "임베드 서명(SQLBOT-EMBEDDED-SIGN)이 누락되어 임베드 당사자의 신원을 확인할 수 없습니다.",
59+
"assistant_id_mismatch": "서명의 어시스턴트 ID가 현재 요청과 일치하지 않아 임베드 당사자의 신원을 확인할 수 없습니다.",
60+
"missing_origin": "현재 페이지에 출처 정보(Origin/Referer)가 없어 임베드 당사자의 신원을 확인할 수 없습니다.",
61+
"target_origin_mismatch": "서명의 출처 도메인이 현재 페이지 도메인과 일치하지 않아 임베드 당사자의 신원을 확인할 수 없습니다.",
62+
"invalid_sign": "임베드 서명이 유효하지 않거나 손상되어 임베드 당사자의 신원을 확인할 수 없습니다.",
63+
"sign_time_expired": "서버(SQLBot)와 현재 페이지(임베드 사이트) 간 동기화 지연이 10초를 초과하여 연결이 중단되었습니다.",
64+
"sign_time_invalid": "서명 시간 형식이 유효하지 않아 임베드 당사자의 신원을 확인할 수 없습니다.",
65+
"automation_tool_detected": "자동화 도구 접근이 감지되어 임베드를 차단했습니다.",
66+
"user_agent_mismatch": "서명의 브라우저 식별 정보가 현재 요청과 일치하지 않아 임베드를 차단했습니다.",
67+
"timezone_mismatch": "서명의 시간대 정보가 서명 시간과 일치하지 않아 임베드를 차단했습니다."
5868
},
5969
"i18n_chat": {
6070
"record_id_in_mcp": "응답 ID: "

backend/locales/zh-CN.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,17 @@
5454
"i18n_ds_invalid": "数据源连接无效",
5555
"i18n_ds_upload_error": "上传文件失败",
5656
"i18n_embedded": {
57-
"invalid_origin": "域名校验失败【{origin}】"
57+
"invalid_origin": "域名校验失败【{origin}】",
58+
"missing_sign": "缺少嵌入签名(SQLBOT-EMBEDDED-SIGN),无法验证嵌入方身份。",
59+
"assistant_id_mismatch": "签名中的助手标识与当前请求不一致,无法验证嵌入方身份。",
60+
"missing_origin": "当前页面缺少来源信息(Origin/Referer),无法验证嵌入方身份。",
61+
"target_origin_mismatch": "签名中的来源域名与当前页面域名不一致,无法验证嵌入方身份。",
62+
"invalid_sign": "嵌入签名无效或已损坏,无法验证嵌入方身份。",
63+
"sign_time_expired": "服务端(SQLBot)与当前页面(嵌入端)的同步延迟超过10秒,导致连接中断。",
64+
"sign_time_invalid": "签名时间格式无效,无法验证嵌入方身份。",
65+
"automation_tool_detected": "检测到自动化工具访问,已阻止嵌入。",
66+
"user_agent_mismatch": "签名中的浏览器标识与当前请求不一致,已阻止嵌入。",
67+
"timezone_mismatch": "签名中的时区信息与签名时间不一致,已阻止嵌入。"
5868
},
5969
"i18n_chat": {
6070
"record_id_in_mcp": "响应ID: "

backend/locales/zh-TW.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,17 @@
5454
"i18n_ds_invalid": "數據源連接無效",
5555
"i18n_ds_upload_error": "上傳文件失敗",
5656
"i18n_embedded": {
57-
"invalid_origin": "網域校驗失敗【{origin}】"
57+
"invalid_origin": "網域校驗失敗【{origin}】",
58+
"missing_sign": "缺少嵌入簽名(SQLBOT-EMBEDDED-SIGN),無法驗證嵌入方身分。",
59+
"assistant_id_mismatch": "簽名中的助手標識與當前請求不一致,無法驗證嵌入方身分。",
60+
"missing_origin": "當前頁面缺少來源資訊(Origin/Referer),無法驗證嵌入方身分。",
61+
"target_origin_mismatch": "簽名中的來源網域與當前頁面網域不一致,無法驗證嵌入方身分。",
62+
"invalid_sign": "嵌入簽名無效或已損壞,無法驗證嵌入方身分。",
63+
"sign_time_expired": "服務端(SQLBot)與當前頁面(嵌入端)的同步延遲超過10秒,導致連線中斷。",
64+
"sign_time_invalid": "簽名時間格式無效,無法驗證嵌入方身分。",
65+
"automation_tool_detected": "偵測到自動化工具存取,已阻止嵌入。",
66+
"user_agent_mismatch": "簽名中的瀏覽器標識與當前請求不一致,已阻止嵌入。",
67+
"timezone_mismatch": "簽名中的時區資訊與簽名時間不一致,已阻止嵌入。"
5868
},
5969
"i18n_chat": {
6070
"record_id_in_mcp": "響應ID: "

0 commit comments

Comments
 (0)