Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions backend/api/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ async def add_account(request: Request):

is_valid = await client.verify_token(token)
if not is_valid:
return {"ok": False, "error": "Invalid token (验证失败,请确认Token有效)"}
return {"ok": False, "error": "Invalid token. Please ensure the Token is valid."}

await pool.add(acc)
return {"ok": True, "email": acc.email}
Expand Down Expand Up @@ -173,17 +173,17 @@ async def register_new_account(request: Request):
# 简单的频率限制保护
current = len(pool.accounts)
if current >= 100:
return {"ok": False, "error": "账号池已满,请先清理死号"}
return {"ok": False, "error": "Account pool is full. Please clean up dead accounts first."}

try:
acc = await register_qwen_account()
if acc:
await pool.add(acc)
log.info(f"[注册] 注册成功: {acc.email}(当前账号数: {len(pool.accounts)}/100)")
return {"ok": True, "email": acc.email, "message": "新账号注册成功并已入池"}
return {"ok": False, "error": "自动化注册失败,可能遇到风控或页面元素改变"}
return {"ok": True, "email": acc.email, "message": "New account registered and added to the pool."}
return {"ok": False, "error": "Auto-registration failed. May be due to anti-bot detection or page changes."}
except Exception as e:
return {"ok": False, "error": f"注册发生异常: {str(e)}"}
return {"ok": False, "error": f"Registration error: {str(e)}"}

@router.post("/verify", dependencies=[Depends(verify_admin)])
async def verify_all_accounts(request: Request):
Expand Down Expand Up @@ -222,7 +222,7 @@ async def activate_account(email: str, request: Request):

# 防止并发点击:检查一个运行时标志
if getattr(acc, "_is_activating", False):
return {"ok": False, "error": "该账号正在激活中,请勿重复点击"}
return {"ok": False, "error": "This account is being activated. Please do not click repeatedly."}

try:
setattr(acc, "_is_activating", True)
Expand All @@ -231,8 +231,8 @@ async def activate_account(email: str, request: Request):
acc.valid = True
acc.activation_pending = False
await pool.add(acc) # 这会触发覆盖保存
return {"ok": True, "message": "账号激活成功"}
return {"ok": False, "error": "未能找到激活链接或获取Token"}
return {"ok": True, "message": "Account activated successfully."}
return {"ok": False, "error": "Could not find activation link or obtain Token."}
finally:
setattr(acc, "_is_activating", False)

Expand Down
16 changes: 8 additions & 8 deletions backend/core/account_pool/pool_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ def get_status_code(self) -> str:

def get_status_text(self) -> str:
status_map = {
"valid": "正常",
"pending_activation": "待激活",
"rate_limited": "限流",
"banned": "封禁",
"auth_error": "鉴权失败",
"invalid": "失效",
"unknown": "未知",
"valid": "Available",
"pending_activation": "Pending activation",
"rate_limited": "Rate-limited",
"banned": "Banned",
"auth_error": "Auth error",
"invalid": "Invalid",
"unknown": "Unknown",
}
return status_map.get(self.get_status_code(), "未知")
return status_map.get(self.get_status_code(), "Unknown")

def to_dict(self):
return {
Expand Down
90 changes: 89 additions & 1 deletion frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
"@tailwindcss/vite": "^4.2.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"i18next": "^23.16.0",
"i18next-browser-languagedetector": "^8.0.0",
"lucide-react": "^1.7.0",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-i18next": "^15.1.0",
"react-router-dom": "^7.14.0",
"sonner": "^2.0.7",
"tailwind-merge": "^3.5.0"
Expand Down
32 changes: 32 additions & 0 deletions frontend/src/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import i18n from "i18next"
import LanguageDetector from "i18next-browser-languagedetector"
import { initReactI18next } from "react-i18next"

import en from "./locales/en.json"
import ptBR from "./locales/pt-BR.json"
import zh from "./locales/zh.json"

export const SUPPORTED_LNGS = ["en", "pt-BR", "zh"] as const
export type SupportedLng = (typeof SUPPORTED_LNGS)[number]

i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources: {
en: { translation: en },
"pt-BR": { translation: ptBR },
zh: { translation: zh },
},
fallbackLng: "en",
supportedLngs: SUPPORTED_LNGS as unknown as string[],
nonExplicitSupportedLngs: true,
interpolation: { escapeValue: false },
detection: {
order: ["localStorage", "navigator", "htmlTag"],
caches: ["localStorage"],
lookupLocalStorage: "qwen2api_lang",
},
})

export default i18n
Loading