Skip to content

feat(i18n): localize middleware and quota-notify user-facing messages#6247

Open
gaga-rgb wants to merge 1 commit into
QuantumNous:mainfrom
gaga-rgb:feat/i18n-middleware-messages
Open

feat(i18n): localize middleware and quota-notify user-facing messages#6247
gaga-rgb wants to merge 1 commit into
QuantumNous:mainfrom
gaga-rgb:feat/i18n-middleware-messages

Conversation

@gaga-rgb

@gaga-rgb gaga-rgb commented Jul 16, 2026

Copy link
Copy Markdown

⚠️ 提交说明 / PR Notice

📝 变更描述 / Description

English

Motivation

The backend already has an i18n framework (common.TranslateMessage + i18n/locales/{en,zh-CN,zh-TW}.yaml, resolving per request as: user's saved language setting → Accept-Language header → default), but 16 user-facing messages in the middleware layer bypassed it and were hardcoded in Chinese. They were returned in Chinese regardless of the caller's language — which matters for API consumers (the middleware/auth.go messages are OpenAI-format API error responses seen by end customers) and for non-Chinese deployments.

What changed (10 files, +130/−17)

File Change
i18n/keys.go 16 new message-key constants, following the existing naming style
i18n/locales/en.yaml / zh-CN.yaml / zh-TW.yaml +22 lines each: translations for all new keys; templated params use go-i18n syntax ({{.Group}}, {{.Minutes}}, {{.Count}}, {{.Seconds}})
middleware/auth.go 5 sites: IP parse failed, IP not in allowlist, group no access, group deprecated, specific-channel denied. The internal fmt.Errorf return value was deliberately left unchanged (not user-visible)
middleware/model-rate-limit.go 2 sites: both HTTP 429 rate-limit messages
middleware/email-verification-rate-limit.go 2 sites: send-too-frequent messages
middleware/secure_verification.go 4 sites: not logged in / verification required / invalid / expired
middleware/turnstile-check.go 3 sites: token empty / check failed / session save failed
service/quota.go quota-warning notification (email/webhook/Bark/Gotify) — see note below

Behavior guarantees

  • The zh-CN.yaml values are the exact original hardcoded strings, so Chinese-language users see byte-identical text — nothing was removed or reworded.
  • Language resolution order is unchanged (it uses the existing framework as-is).
  • The frontend detects secure_verification.go responses by the code field, not by message text (verified in web/classic/src/helpers/secureApiCall.js), so translating those messages is safe.

Why service/quota.go uses a language switch instead of the bundle

The quota-warning notification runs in an async goroutine with no gin context, and its strings contain the notify system's {{value}} placeholders, which would collide with go-i18n's {{.Var}} template syntax. It therefore uses a simple switch on userSetting.Language: English only when the user's saved setting starts with en, otherwise the original Chinese — preserving the default behavior exactly.

Verification

  • All non-root packages build (the root main package's embed of web/*/dist requires a frontend build — pre-existing, unrelated to this change)
  • go vet ./i18n/ ./middleware/ ./service/ clean
  • go test ./middleware/ ./service/ pass
  • A test exercising the new key/language combinations through the i18n bundle confirmed every key resolves in en / zh-CN / zh-TW, including templated params
  • gofmt applied
  • grep confirms zero remaining hardcoded-Chinese message fields in the 5 modified middleware files

中文

动机

后端已有 i18n 框架(common.TranslateMessage + i18n/locales/{en,zh-CN,zh-TW}.yaml,按请求解析顺序:用户保存的语言设置 → Accept-Language 请求头 → 默认语言),但中间件层有 16 条面向用户的消息绕过了该框架,直接硬编码为中文。无论调用方使用什么语言,这些消息都以中文返回——这对 API 消费者(middleware/auth.go 中的消息是终端客户可见的 OpenAI 格式 API 错误响应)以及非中文部署环境影响较大。

变更内容(10 个文件,+130/−17)

文件 变更
i18n/keys.go 新增 16 个消息键常量,沿用现有命名风格
i18n/locales/en.yaml / zh-CN.yaml / zh-TW.yaml 各 +22 行:所有新键的翻译;模板参数使用 go-i18n 语法({{.Group}}{{.Minutes}}{{.Count}}{{.Seconds}}
middleware/auth.go 5 处:IP 解析失败、IP 不在白名单、分组无权访问、分组已弃用、指定渠道被拒绝。内部 fmt.Errorf 返回值有意保持不变(用户不可见)
middleware/model-rate-limit.go 2 处:两条 HTTP 429 限流消息
middleware/email-verification-rate-limit.go 2 处:发送过于频繁的提示
middleware/secure_verification.go 4 处:未登录 / 需要验证 / 验证无效 / 验证过期
middleware/turnstile-check.go 3 处:token 为空 / 校验失败 / session 保存失败
service/quota.go 额度预警通知(邮件/webhook/Bark/Gotify)——见下方说明

行为保证

  • zh-CN.yaml 中的值与原硬编码字符串逐字节一致,中文用户看到的文本与之前完全相同——没有删除或改写任何内容。
  • 语言解析顺序不变(直接复用现有框架)。
  • 前端通过 code 字段而消息文本识别 secure_verification.go 的响应(已在 web/classic/src/helpers/secureApiCall.js 中核实),因此翻译这些消息是安全的。

为什么 service/quota.go 使用语言 switch 而不是 i18n bundle

额度预警通知在异步 goroutine 中运行,没有 gin context,且其字符串包含通知系统自身的 {{value}} 占位符,会与 go-i18n 的 {{.Var}} 模板语法冲突。因此改为对 userSetting.Language 做简单判断:仅当用户保存的语言设置以 en 开头时输出英文,否则输出原有中文——默认行为完全保持不变。

验证

  • 所有非根包均可编译(根 main 包 embed web/*/dist 需要前端构建——为既有情况,与本变更无关)
  • go vet ./i18n/ ./middleware/ ./service/ 无警告
  • go test ./middleware/ ./service/ 通过
  • 通过 i18n bundle 对所有新增键/语言组合进行了测试,确认每个键在 en / zh-CN / zh-TW 下均能解析,包括模板参数
  • 已执行 gofmt
  • grep 确认 5 个被修改的中间件文件中不再有硬编码中文消息字段

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix)
  • ✨ 新功能 (New feature)
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

  • 无 / None

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 IssuesPRs,确认不是重复提交。
  • Bug fix 说明: 不适用 / N/A(非 Bug fix)
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

$ go vet ./i18n/ ./middleware/ ./service/
(clean, no output)

$ go test ./middleware/ ./service/
ok  	github.com/QuantumNous/new-api/middleware
ok  	github.com/QuantumNous/new-api/service

$ git diff --stat main
 i18n/keys.go                                | 28 ++++++++++++++++++++++++++++
 i18n/locales/en.yaml                        | 22 ++++++++++++++++++++++
 i18n/locales/zh-CN.yaml                     | 22 ++++++++++++++++++++++
 i18n/locales/zh-TW.yaml                     | 22 ++++++++++++++++++++++
 middleware/auth.go                          | 10 +++++-----
 middleware/email-verification-rate-limit.go |  6 +++---
 middleware/model-rate-limit.go              |  5 +++--
 middleware/secure_verification.go           | 11 +++++++----
 middleware/turnstile-check.go               |  7 ++++---
 service/quota.go                            | 14 ++++++++++++++
 10 files changed, 130 insertions(+), 17 deletions(-)

Summary by CodeRabbit

  • New Features

    • Added localized messages for authentication, rate limits, secure verification, and Turnstile checks.
    • Added English, Simplified Chinese, and Traditional Chinese translations for middleware errors.
    • Added English quota-warning notifications based on the configured language.
  • Bug Fixes

    • Replaced hardcoded middleware error messages with translated responses.
    • Included clearer access-denied responses for restricted IPs, groups, and channels.

Migrate 16 hardcoded Chinese user-facing messages to the existing i18n
framework (common.TranslateMessage), resolving per-request via the
user's saved language setting, then Accept-Language, then default.

- i18n/keys.go: add 16 message-key constants (auth, rate limit,
  email verification, secure verify, turnstile)
- i18n/locales/{en,zh-CN,zh-TW}.yaml: add translations for all new
  keys; zh-CN values are byte-identical to the original hardcoded
  strings, so Chinese users see exactly the same text as before
- middleware/auth.go: 5 OpenAI-format API error messages
- middleware/model-rate-limit.go: 2 HTTP 429 messages
- middleware/email-verification-rate-limit.go: 2 messages
- middleware/secure_verification.go: 4 messages (frontend detects
  these by code field, not message text)
- middleware/turnstile-check.go: 3 messages
- service/quota.go: quota-warning notification runs in an async
  goroutine without gin context and its strings contain the notify
  system's {{value}} placeholders (which collide with go-i18n
  templates), so it uses a simple switch on the user's saved
  language setting instead of the bundle
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Middleware error responses now use localized message keys across authentication, rate limiting, secure verification, and Turnstile checks. Quota notifications also select English templates when the user language starts with en.

Changes

Middleware localization

Layer / File(s) Summary
Message keys and translations
i18n/keys.go, i18n/locales/*.yaml
Adds middleware message keys and translations for authentication, rate limiting, secure verification, and Turnstile scenarios.
Auth and rate-limit responses
middleware/auth.go, middleware/*rate-limit.go, middleware/model-rate-limit.go
Replaces hardcoded denial and limit-exceeded messages with translated responses and template parameters.
Secure verification and Turnstile responses
middleware/secure_verification.go, middleware/turnstile-check.go
Localizes login, verification-state, token, validation, and session-save errors.

Quota notification localization

Layer / File(s) Summary
Language-aware quota notifications
service/quota.go
Selects English quota prompts and notification templates when the configured language starts with en.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: seefs001

Poem

A rabbit hops through keys of gold,
Translating errors, clear and bold.
Rate limits speak in tongues anew,
Turnstile signs say what to do.
Quota notes bloom English-bright—
Localization shines tonight! 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: localizing middleware and quota notification user-facing messages.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
middleware/turnstile-check.go (1)

51-53: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use common.DecodeJson for the Turnstile response body.
This middleware is business code, so it should follow the shared JSON wrapper guideline instead of calling json.NewDecoder directly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@middleware/turnstile-check.go` around lines 51 - 53, Replace the direct
json.NewDecoder call in the Turnstile response handling with the shared
common.DecodeJson helper, passing the response body and res destination while
preserving the existing error handling.

Source: Coding guidelines

middleware/auth.go (1)

472-473: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Replace the hardcoded Chinese string in the internal error.

Although the user-facing HTTP response is successfully localized, the internally returned error continues to use a hardcoded Chinese string. Consider replacing it with an English error string to fully standardize internal errors and align with other errors in this file (e.g., "token is nil").

♻️ Proposed refactor
-			abortWithOpenAiMessage(c, http.StatusForbidden, common.TranslateMessage(c, i18n.MsgAuthSpecificChannelDenied))
-			return fmt.Errorf("普通用户不支持指定渠道")
+			abortWithOpenAiMessage(c, http.StatusForbidden, common.TranslateMessage(c, i18n.MsgAuthSpecificChannelDenied))
+			return errors.New("specific channel denied for normal users")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@middleware/auth.go` around lines 472 - 473, Update the error returned
alongside abortWithOpenAiMessage in the affected authorization branch to use an
English message instead of the hardcoded Chinese string, matching the internal
error style used elsewhere in the middleware while leaving the localized
user-facing response unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@middleware/auth.go`:
- Around line 472-473: Update the error returned alongside
abortWithOpenAiMessage in the affected authorization branch to use an English
message instead of the hardcoded Chinese string, matching the internal error
style used elsewhere in the middleware while leaving the localized user-facing
response unchanged.

In `@middleware/turnstile-check.go`:
- Around line 51-53: Replace the direct json.NewDecoder call in the Turnstile
response handling with the shared common.DecodeJson helper, passing the response
body and res destination while preserving the existing error handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b8ca7583-8834-40d4-9737-c9e457e15180

📥 Commits

Reviewing files that changed from the base of the PR and between a63364d and 6a369c1.

📒 Files selected for processing (10)
  • i18n/keys.go
  • i18n/locales/en.yaml
  • i18n/locales/zh-CN.yaml
  • i18n/locales/zh-TW.yaml
  • middleware/auth.go
  • middleware/email-verification-rate-limit.go
  • middleware/model-rate-limit.go
  • middleware/secure_verification.go
  • middleware/turnstile-check.go
  • service/quota.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant