v0.0.21 — 全量中英文国际化 + 配额缓存一致性修复 + tiktoken 离线内嵌
管理后台 / 落地页 / 登录注册 / 条款隐私全部支持中英文实时切换,Arco Design 组件同步本地化;修复 Redis 用户配额缓存与实际余额不一致的多条链路,并修复防火墙环境下 token 计数 panic。tiktoken BPE 编码文件内嵌进二进制,离线开箱即用。
Full zh/en internationalization across the admin console, landing page, auth and legal pages, with Arco Design components localized too. Fixes multiple Redis user-quota cache staleness paths and a token-counting panic in firewalled environments. tiktoken BPE encodings are embedded into the binary for zero-config offline startup.
中文
✨ 新增功能
- 全量中英文国际化(i18n):
- 管理后台全部页面(渠道 / 令牌 / 用户 / 套餐 / 订阅 / 订单 / 管理端订单 / 日志 / 兑换码 / 运营数据 / 系统 / 集群 / 运营 / 定价 / 充值 / 支付 / 个人设置)、控制台、落地页、登录 / 注册 / 重置密码 / OAuth、服务条款与隐私政策全部支持中英文。
- 顶栏与落地页导航新增语言切换组件(
LangSwitcher),选择持久化到localStorage.lang并同步<html lang>。 - 菜单、页面文案、表格列、弹窗、按钮、提示语、表单校验、
Message提示全部随语言实时切换。
- Arco Design 组件多语言:
App.vue通过a-config-provider注入 Arco 语言包(zh-cn/en-us),日期选择器、分页、空态、Popconfirm 等内置组件本地化。 - 语言包按页面模块拆分并自动深合并:新增
src/i18n/pages/*.js页面语言模块,src/i18n/pages.js通过import.meta.glob自动加载并递归深合并,多个模块共用命名空间也不会相互覆盖。 - 令牌界面优化:
- 「剩余 / 已用」额度改为横排展示,
/分隔符同基线对齐。 - 密钥列新增「查看完整密钥」弹窗,含一键复制与关闭。
- 新增「可用模型」列,展示
X个/不限制,点击以网格 + 圆点弹窗展示模型列表;未限制模型时回退展示全部可用模型。
- 「剩余 / 已用」额度改为横排展示,
- tiktoken BPE 离线内嵌:通过
//go:embed将 cl100k_base / o200k_base / p50k_base / r50k_base 4 个 BPE 文件(约 6.4 MB)编入二进制,无需任何环境变量即可精确计数 token,覆盖 gpt-3.5-turbo / gpt-4 / gpt-4o 等标准模型。
🐛 问题修复
- 修复 Redis 用户配额缓存与实际余额不一致(多条链路):
IncreaseUserQuota直接写库后同步刷新 Redis,充值 / 管理员加额 / 邀请奖励后下一次请求立即可见。- 批处理模式(
BatchUpdateEnabled=true)在batchUpdate落库后刷新对应用户缓存,保持users.quota与user_quota:<id>一致。 - 管理员
UpdateUser覆盖quota字段后同步刷新缓存,避免调额后用户被持续误报 403。 preConsumeQuota的「余额充足免预扣」判定前移到 Redis 扣减之前,余额充足的请求不再让缓存逐次漂移;预扣失败时通过RedisIncrease回滚此前的 Redis 扣减。- 提高
user_quota缓存低水位回源阈值(500 → 50_000),缩小高单价模型(如单次预扣约 80_000 quota)导致的「缓存漂移死区」,修复持续误报insufficient_user_quota403 的问题。
- 修复防火墙 / 离线环境下 token 计数 panic:tiktoken 下载超时导致 fallback 不完整,
SyncOptions又把ApproximateTokenEnabled覆盖回false,最终在nil编码器上调用Encode()触发 panic;内嵌 BPE 后整条链路消除。 - 修复令牌「永不过期」被误判为已过期:过期时间 sentinel 从「仅
-1表示永不过期」统一为「<=0均视为永不过期」(model/token.go/controller/token.go),修复历史脏数据或旧前端把「永不过期」写成0后,启用令牌时被误报「令牌已过期」的问题;前端新增buildTokenExpiredTime纯函数,确保「永不过期」始终上报-1。
🔧 重构
httpBpeLoader改为三级查找:内嵌(默认,开箱即用)→TIKTOKEN_CACHE_DIR(高级用户覆盖,可跳过内嵌与 HTTP)→ HTTP 下载(兜底,应对未来 URL 变更);同时取消此前隐式回退到系统临时目录data-gym-cache的行为(该目录用户感知不到,易被go clean -cache误清)。
📚 文档
- README 开发计划更新:将「多语言国际化(i18n)」移入已完成,新增「更多语言支持」规划项;同步简中 / 繁中 / 英 / 日 / 俄 / 德 / 韩 / 阿 共 8 个语言版本。
🧪 测试
preConsumeQuota回归测试:验证纯函数公式、余额不足 403 且不动 DB、免预扣路径不改动user.quota与token.remain_quota、正常预扣路径、Plan 短路。- 用户配额与缓存函数单测:直接写库语义、负数拒绝、加减往返一致性、Redis 关闭时回滚函数为空操作。
- tiktoken embedded loader 三级 fallback 单测:4 个内嵌文件 SHA1 校验、未知 URL 优雅返回、解析 cl100k_base、端到端编码 gpt-3.5 / gpt-4 / gpt-4o、
TIKTOKEN_CACHE_DIR覆盖、HTTP 兜底。 - 令牌过期 sentinel 单测:覆盖「永不过期」提交始终为
-1(永不返回0)、<=0不判过期、>0正常判过期。
⚠️ 升级注意事项
- 零数据库迁移:本次不涉及任何表结构变更。
- 需要重新构建前端:
web/default-pro/的修改需npm run build后重新//go:embed进二进制。 - 后端二进制体积增加约 6.4 MB:内嵌 4 个 tiktoken BPE 文件,用于换取离线可用与启动零阻塞;如需自定义编码,可设置
TIKTOKEN_CACHE_DIR覆盖。 - 语言切换:默认中文;登录后可在顶栏切换,落地页导航也可切换;选择写入
localStorage.lang。 - 构建与测试:
go build ./...通过。go test ./model/ ./controller/ ./middleware/全绿。cd web/default-pro && npm run build通过。