Skip to content

feat: add per-channel health check settings - #6282

Closed
DawnMoon1542 wants to merge 1 commit into
QuantumNous:mainfrom
DawnMoon1542:feat/channel-health-check-settings
Closed

feat: add per-channel health check settings#6282
DawnMoon1542 wants to merge 1 commit into
QuantumNous:mainfrom
DawnMoon1542:feat/channel-health-check-settings

Conversation

@DawnMoon1542

@DawnMoon1542 DawnMoon1542 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

⚠️ PR Notice

Important

This PR is AI-assisted. The root cause, fix scope, and typecheck results were reviewed before submission.

📝 Description

Support per-channel health check management on the Routing Reliability page.

  • Add a channel-level health check table and adjust the page layout so global monitoring options and per-channel settings live together.
  • Each channel can enable or disable scheduled tests, and optionally override:
    • disable threshold
    • re-enable on success
    • endpoint type
    • stream mode
  • Failure auto-ban continues to use the existing channel auto-ban setting.
  • Scheduled tests and "Test All Channels" skip channels with scheduled health checks disabled.
  • Single-channel manual tests remain available and use the channel endpoint/stream settings as defaults.

Related upstream discussion: #5205 / #5206 cover a simpler skip-auto-test toggle. This PR provides broader per-channel health-check controls rather than a single skip flag.

🚀 Type of change

  • 🐛 Bug fix
  • ✨ New feature
  • ⚡ Performance / Refactor
  • 📝 Documentation

🔗 Related Issue

✅ Checklist

  • Human review: I personally reviewed and finalized this description.
  • Not a duplicate: I searched existing Issues/PRs and this is not a duplicate submission.
  • Bug fix note: N/A for this feature PR.
  • Change understanding: I understand how these changes work and their impact.
  • Focused scope: This PR does not include unrelated changes.
  • Local verification: Local tests / manual validation were completed.
  • Security: No sensitive credentials are included, and the change follows project conventions.

📸 Proof of Work

Backend:

go test ./model ./controller ./service ./router -count=1
# ok
go test ./... -count=1
# all packages ok after local web dist placeholder for embed

Frontend:

cd web/default
bun run typecheck
# pass
# full-repo lint has pre-existing errors outside this change set
# changed files oxlint: 0 error

Manual validation on local docker-compose.dev stack:

  • batch save per-channel health check settings
  • scheduled / test-all skip for health_check.enabled=false
  • stream/endpoint overrides applied during automatic tests
  • auto-ban and re-enable-on-success overrides behave as configured

Summary by CodeRabbit

  • New Features
    • Added per-channel health-check overrides (enablement, disable threshold, endpoint type, stream mode, and re-enable-on-success).
    • Added a batch health-check update API and UI table to edit/save configurations with per-channel results.
    • Updated automatic channel test selection to respect per-channel health-check enablement.
    • Channel test dialog now initializes from the selected channel’s configured defaults.
  • Bug Fixes
    • Health-check execution now applies the effective per-channel endpoint/stream/threshold settings.
  • Tests
    • Added unit tests for channel selection and health-check setting validation/effectiveness.
  • Documentation
    • Updated UI text and i18n strings for scheduled tests and health-check settings.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Per-channel health-check settings now control automatic testing, recovery, and batch updates. Backend APIs, routing, model accessors, frontend editing, settings integration, test defaults, and localized UI strings were added or updated.

Changes

Channel health-check configuration

Layer / File(s) Summary
Health-check settings model
dto/channel_settings.go, model/channel.go, model/channel_health_check_test.go
Adds per-channel overrides, effective-value resolution, transactional updates, validation, and tests.
Automatic test execution and recovery policy
controller/channel-test.go, controller/channel_test_internal_test.go, service/channel.go, service/channel_enable_test.go
Applies channel-specific endpoint, stream, threshold, recovery, and selection policies.
Batch health-check update API
controller/channel.go, router/channel-router.go, router/channel_router_test.go
Adds validated batch updates, per-item results, cache and audit handling, and permission routing.
Batch health-check editor
web/default/src/features/channels/*, web/default/src/features/system-settings/models/channel-health-check-table.tsx
Adds typed payloads, drafts, validation, chunked saves, partial-result handling, filtering, pagination, and controls.
Settings integration and test dialog defaults
web/default/src/features/system-settings/models/routing-reliability-section.tsx, web/default/src/features/channels/components/dialogs/channel-test-dialog.tsx, web/default/src/features/channels/lib/channel-actions.ts
Coordinates global and channel saves, derives dialog defaults, and updates batch-test messaging.
Health-check interface translations
web/default/src/i18n/locales/{en,fr,ja,ru,vi,zh-TW,zh}.json
Adds localized scheduled-test and health-check labels and status messages.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Admin
  participant ChannelHealthCheckTable
  participant batchUpdateChannelHealthCheck
  participant BatchUpdateChannelHealthCheck
  participant UpdateHealthCheckSettings
  participant Database
  Admin->>ChannelHealthCheckTable: Edit channel health-check drafts
  ChannelHealthCheckTable->>batchUpdateChannelHealthCheck: Submit chunked items
  batchUpdateChannelHealthCheck->>BatchUpdateChannelHealthCheck: PUT batch request
  BatchUpdateChannelHealthCheck->>UpdateHealthCheckSettings: Validate and update items
  UpdateHealthCheckSettings->>Database: Lock row and merge settings
  Database-->>BatchUpdateChannelHealthCheck: Return item results
  BatchUpdateChannelHealthCheck-->>ChannelHealthCheckTable: Return succeeded and failed items
  ChannelHealthCheckTable-->>Admin: Show save status
Loading

Possibly related PRs

Suggested reviewers: seefs001

Poem

I’m a rabbit tuning checks in the night,
With streams and endpoints hopping just right.
I batch up each row,
Track success as I go,
And re-enable channels in flight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.83% 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 is concise and accurately summarizes the main change: adding per-channel health check settings.
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.

Actionable comments posted: 3

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (21)
web/default/src/i18n/locales/en.json-3192-3192 (1)

3192-3192: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the capitalization in this UI string.

Use “Please select user groups…” rather than “Please Select user groups…”.

🤖 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 `@web/default/src/i18n/locales/en.json` at line 3192, Update the English locale
entry for “Please Select user groups that can access this channel.” so the
displayed value uses sentence-case capitalization: “Please select user groups
that can access this channel.”
web/default/src/i18n/locales/en.json-4739-4739 (1)

4739-4739: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Remove the trailing space from this translation key.

The key "User groups that can access this channel. " is lookup-fragile and renders unintended whitespace. Use the same string without the trailing space.

Proposed fix
-    "User groups that can access this channel. ": "User groups that can access this channel. ",
+    "User groups that can access this channel.": "User groups that can access this channel.",
🤖 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 `@web/default/src/i18n/locales/en.json` at line 4739, Update the translation
entry in the locale definitions to remove the trailing space from the key, using
the exact string without the final whitespace while preserving its existing
value.
web/default/src/i18n/locales/fr.json-3134-3134 (1)

3134-3134: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the untranslated Chinese fragments.

These French messages contain codes de兑换, leaving Chinese text visible in the UI. Use the existing French terminology for redemption codes.

Proposed fix
-    "Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.": "Les paiements, codes de兑换, forfaits d’abonnement et récompenses d’invitation sont verrouillés jusqu’à ce que l’administrateur racine confirme les conditions de conformité.",
+    "Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.": "Les paiements, codes d’échange, forfaits d’abonnement et récompenses d’invitation sont verrouillés jusqu’à ce que l’administrateur racine confirme les conditions de conformité.",

Apply the same replacement to the values at lines 3486 and 4337.

Also applies to: 3486-3486, 4337-4337

🤖 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 `@web/default/src/i18n/locales/fr.json` at line 3134, Update the French locale
values for the payment/compliance message at all three occurrences, including
the entry at line 3134 and the matching entries near lines 3486 and 4337,
replacing the Chinese fragment in “codes de兑换” with the existing French
terminology for redemption codes. Preserve the rest of each translation
unchanged.
web/default/src/i18n/locales/ja.json-4497-4497 (1)

4497-4497: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use Japanese for this catalog entry.

"Total earned" is translated as the Chinese text "总收入", leaving Chinese UI text in the Japanese locale.

-    "Total earned": "总收入",
+    "Total earned": "総収益",
🤖 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 `@web/default/src/i18n/locales/ja.json` at line 4497, Update the Japanese
locale entry for "Total earned" from the Chinese translation to the appropriate
Japanese translation, leaving the catalog key and surrounding entries unchanged.
web/default/src/i18n/locales/ja.json-1756-1756 (1)

1756-1756: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve placeholders in translated values.

These entries replace {{name}}, {{msg}}, {{count}}, or the encoded email content with __ PH_0 __. The UI will display the placeholder literal instead of the filename, error message, count, or email.

Proposed fix
-    "Failed to parse JSON file: {{name}}": "JSONファイルの解析に失敗しました: __ PH_0 __",
+    "Failed to parse JSON file: {{name}}": "JSONファイルの解析に失敗しました:{{name}}",
-    "Model pull failed: {{msg}}": "モデルのプルに失敗しました: __ PH_0 __",
+    "Model pull failed: {{msg}}": "モデルのプルに失敗しました:{{msg}}",
-    "New API <noreply@example.com>": "新しいAPI __ PH_0 __",
+    "New API <noreply@example.com>": "新しいAPI <noreply@example.com>",
-    "Parsed {{count}} service account file(s)": "__ PH_0 __サービスアカウントファイルを解析しました",
+    "Parsed {{count}} service account file(s)": "{{count}}件のサービスアカウントファイルを解析しました",

Also applies to: 2538-2538, 2650-2650, 3058-3058

🤖 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 `@web/default/src/i18n/locales/ja.json` at line 1756, Update the affected
Japanese translation entries to preserve their original interpolation
placeholders, replacing the literal “__ PH_0 __” values with the corresponding
{{name}}, {{msg}}, {{count}}, or encoded email-content placeholder used by each
source string. Apply this consistently to the entries represented by the visible
key and the additional affected locations.
web/default/src/i18n/locales/ja.json-4868-4868 (1)

4868-4868: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not change “WeChat” to “WeChat Pay”.

This entry labels the WeChat provider as the payment product, while the adjacent "WeChat Pay" entry already represents the payment method.

-    "WeChat": "WeChat Pay",
+    "WeChat": "WeChat",
🤖 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 `@web/default/src/i18n/locales/ja.json` at line 4868, Update the locale entry
for the “WeChat” key to use “WeChat” rather than “WeChat Pay”, leaving the
adjacent “WeChat Pay” translation unchanged.
web/default/src/i18n/locales/ru.json-1319-1319 (1)

1319-1319: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve the batch-validation scope.

The English text specifies that the threshold applies “for all edited channels,” but the Russian translation omits this constraint. Include “для всех изменяемых каналов” so batch-edit users understand the validation scope.

🤖 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 `@web/default/src/i18n/locales/ru.json` at line 1319, Update the Russian
translation for “Disable threshold must be between 0 and 86400 seconds for all
edited channels” to include “для всех изменяемых каналов,” preserving the
validation scope stated in the English source.
web/default/src/i18n/locales/ru.json-4702-4702 (1)

4702-4702: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve the “used” meaning in “Used Quota.”

Лимит потребления means usage limit, whereas the source refers to quota already consumed. Use Использованная квота.

🤖 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 `@web/default/src/i18n/locales/ru.json` at line 4702, Update the Russian
translation for the “Used Quota” key to “Использованная квота” so it preserves
the meaning of quota already consumed.
web/default/src/i18n/locales/ru.json-3260-3260 (1)

3260-3260: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not translate “Pre-consumed” as “prepayment.”

Предоплата means payment made in advance, while this label refers to quota or tokens consumed before final settlement. Use wording such as Предварительно потреблено or Предварительно списано.

🤖 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 `@web/default/src/i18n/locales/ru.json` at line 3260, Update the “Pre-consumed”
translation in the Russian locale from “Предоплата” to wording that conveys
quota or tokens consumed in advance, such as “Предварительно потреблено” or
“Предварительно списано”.
web/default/src/i18n/locales/ru.json-5159-5159 (1)

5159-5159: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not change scheduling into routing.

The translation refers to routing-control mechanisms, which is unrelated to scheduling controls. Translate this fragment as scheduling/planning controls instead.

🤖 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 `@web/default/src/i18n/locales/ru.json` at line 5159, Update the "scheduling
controls" entry in the Russian locale so it conveys scheduling or planning
controls, not routing-control mechanisms. Preserve the existing locale key and
change only its translation value.
web/default/src/i18n/locales/ru.json-2649-2649 (1)

2649-2649: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Preserve the New API project name.

This translates the protected project identity to Новый API. Keep the value as New API; surrounding UI text may be localized, but the project identity must remain unchanged. As per coding guidelines, protected references to the new-api project identity must not be modified.

🤖 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 `@web/default/src/i18n/locales/ru.json` at line 2649, Update the locale entry
for the "New API" key to keep its value exactly "New API" rather than
translating the protected project identity; leave surrounding localized strings
unchanged.

Source: Coding guidelines

web/default/src/i18n/locales/ru.json-475-476 (1)

475-476: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the correct meanings for RPM and TPM.

The translations say “rotations” and “transactions,” but this catalog defines RPM as requests per minute and TPM as tokens per minute at Lines 3417-3418. Use the corresponding Russian terms for requests and tokens.

🤖 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 `@web/default/src/i18n/locales/ru.json` around lines 475 - 476, Update the
Russian translations for the “Average RPM” and “Average TPM” keys to use the
catalog’s defined meanings: requests per minute and tokens per minute,
respectively, matching the terminology used by the corresponding entries near
Lines 3417-3418.
web/default/src/i18n/locales/ru.json-4493-4493 (1)

4493-4493: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Translate “Total check-ins” as a count of check-ins.

Общая проверка means a general inspection, not the number of check-ins. Use Всего отметок or Общее число отметок.

🤖 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 `@web/default/src/i18n/locales/ru.json` at line 4493, Update the Russian
translation for the “Total check-ins” key to express the total count of
check-ins, using “Всего отметок” or “Общее число отметок” instead of the current
inspection-related wording.
web/default/src/i18n/locales/ru.json-736-736 (1)

736-736: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep check-in terminology consistent.

These entries use “registration” and “arrival,” while the same catalog translates check-in as “отметка.” Use daily check-in wording, such as “Ежедневная отметка не выполнена” and “Включить функцию ежедневной отметки.”

Also applies to: 1480-1480

🤖 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 `@web/default/src/i18n/locales/ru.json` at line 736, Update the Russian
translations for the “Check-in failed” and corresponding “Enable check-in”
entries in the locale catalog to use consistent daily check-in terminology with
“отметка,” such as “Ежедневная отметка не выполнена” and “Включить функцию
ежедневной отметки,” rather than registration or arrival wording.
web/default/src/i18n/locales/vi.json-269-269 (1)

269-269: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use “mô hình” consistently for model labels.

The changed translations use “mẫu” for model-management UI (“All Models”, “Model Name”, and “Select Model”), while surrounding entries use “mô hình”. “Mẫu” means sample/template and is misleading here.

Also applies to: 2507-2508, 3847-3847

🤖 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 `@web/default/src/i18n/locales/vi.json` at line 269, Update the Vietnamese
translations for “All Models”, “Model Name”, and “Select Model” in vi.json to
use “mô hình” consistently instead of “mẫu”, matching the surrounding
model-management terminology.
web/default/src/i18n/locales/vi.json-1130-1130 (1)

1130-1130: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Translate the changed Vietnamese values instead of shipping English fallbacks.

These changed entries still render English text in the Vietnamese locale, including “Present value”, “The date and time…”, “Price type”, “Synchronize this model…”, and “View price”. Please translate the values while keeping the English source-string keys unchanged.

Also applies to: 1182-1182, 3312-3312, 4171-4171, 4802-4802

🤖 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 `@web/default/src/i18n/locales/vi.json` at line 1130, Translate the changed
values in the Vietnamese locale, including “Current Value”, “The date and
time…”, “Price type”, “Synchronize this model…”, and “View price”, instead of
leaving English fallback text. Keep each existing English source-string key
unchanged and update only the corresponding Vietnamese translations at the
referenced entries.
web/default/src/i18n/locales/zh-TW.json-287-287 (1)

287-287: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Translate the remaining English values in zh-TW.json.

These changed entries render English in the Traditional Chinese UI, including the new health-check description and stream controls. Replace the values with Traditional Chinese translations.

Also applies to: 922-922, 1160-1160, 1408-1408, 1901-1901, 1914-1918, 3144-3144, 3762-3762

🤖 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 `@web/default/src/i18n/locales/zh-TW.json` at line 287, Translate the English
values at the referenced entries in zh-TW.json into natural Traditional Chinese,
including “All statuses,” the health-check description, and stream-control
labels. Preserve each existing localization key and JSON structure; update only
the values still displayed in English.
web/default/src/i18n/locales/zh-TW.json-415-415 (1)

415-415: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct malformed or inaccurate Traditional Chinese labels.

  • Audio Preview音樂預覽 narrows generic audio to music.
  • Delete Header刪請求頭 is missing .
  • Set Header設請求頭 is missing .

Also applies to: 1221-1221, 3951-3951

🤖 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 `@web/default/src/i18n/locales/zh-TW.json` at line 415, Correct the Traditional
Chinese translations for the affected locale entries: change “Audio Preview” to
a generic audio-preview label rather than “音樂預覽”, and restore the missing
characters in “Delete Header” and “Set Header” so they read “刪除請求頭” and “設定請求頭”.
Apply the same corrections to the additional occurrences identified in the
locale file.
web/default/src/i18n/locales/zh.json-803-803 (1)

803-803: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use Simplified Chinese in the zh catalog.

完成後點擊保存。 contains Traditional Chinese characters (, 點擊). Use 完成后点击保存。; the separate zh-TW catalog should own Traditional Chinese translations.

🤖 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 `@web/default/src/i18n/locales/zh.json` at line 803, Update the zh catalog
translation for "Click save when you're done." to Simplified Chinese, replacing
the Traditional characters with the approved wording "完成后点击保存。"; leave the zh-TW
catalog responsible for the Traditional Chinese version.
web/default/src/i18n/locales/zh.json-415-415 (1)

415-415: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Translate generic audio as “音频,” not “音乐.”

Audio Preview is translated as 音乐预览, which incorrectly limits the feature to music. Use 音频预览 so speech and other audio content are covered.

Proposed fix
-    "Audio Preview": "音乐预览",
+    "Audio Preview": "音频预览",
🤖 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 `@web/default/src/i18n/locales/zh.json` at line 415, Update the “Audio Preview”
translation in the zh locale from “音乐预览” to “音频预览,” preserving the existing
localization key.
controller/channel-test.go-938-941 (1)

938-941: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve positive sub-millisecond thresholds.

A configured value between 0 and 0.001 seconds truncates to zero and is treated as “threshold disabled.” Check the seconds value before conversion and clamp positive results to at least one millisecond.

Proposed fix
-			disableThreshold := int64(channel.EffectiveHealthCheckDisableThresholdSeconds() * 1000)
-			if disableThreshold == 0 {
+			thresholdSeconds := channel.EffectiveHealthCheckDisableThresholdSeconds()
+			disableThreshold := int64(thresholdSeconds * 1000)
+			if thresholdSeconds == 0 {
 				disableThreshold = 10000000 // a impossible value
+			} else if disableThreshold == 0 {
+				disableThreshold = 1
 			}
🤖 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 `@controller/channel-test.go` around lines 938 - 941, Update the threshold
calculation in the channel health-check setup around
EffectiveHealthCheckDisableThresholdSeconds so positive sub-millisecond values
are preserved: inspect the seconds value before converting, and clamp any
positive converted threshold to at least one millisecond. Only treat zero or
non-positive configured values as disabled, retaining the existing large
sentinel behavior.
🧹 Nitpick comments (1)
web/default/src/i18n/locales/en.json (1)

4990-4994: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep locale keys flat and English-source-based.

These entries introduce hierarchical/identifier-style keys instead of the t('English source string') convention. Rename them to flat English source strings, or verify every caller and locale catalog uses these exact identifiers consistently.

As per coding guidelines, locale files must use flat English source strings as keys. Based on learnings, web/default follows this flat-key convention.

Also applies to: 5057-5070

🤖 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 `@web/default/src/i18n/locales/en.json` around lines 4990 - 4994, Rename the
added auth.resetPasswordConfirm locale keys to flat English source-string keys,
including the entries around the retry and success messages, and update every
caller and locale catalog reference to use those exact English strings
consistently. Preserve the existing translations and interpolation placeholder.

Sources: Coding guidelines, Learnings

🤖 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.

Inline comments:
In
`@web/default/src/features/system-settings/models/channel-health-check-table.tsx`:
- Around line 345-367: Update applySucceededDrafts so a successful save removes
a draft only when the current draft still matches the submitted draftsSnapshot
value; retain any newer in-flight edits while advancing that row’s baseline to
the submitted value. Use the current drafts state and draftsSnapshot together,
preserving the existing baseline update for successfully submitted rows.
- Around line 256-270: Update the baseline synchronization effect around
setBaselineById so rows without unsaved drafts refresh their baseline from the
current channels data on each update, instead of preserving every existing
baseline indefinitely. Continue protecting rows with drafts[channel.id], and
retain synchronous draft handling in updateDraft for newly drafted rows.

In
`@web/default/src/features/system-settings/models/routing-reliability-section.tsx`:
- Line 20: Update the form-reset wiring in the routing reliability section so
baselineRef is synchronized with refreshed defaultValues whenever useResetForm
loads them. Ensure later save comparisons use the current defaults rather than
the initial baseline, while preserving the existing reset behavior.

---

Minor comments:
In `@controller/channel-test.go`:
- Around line 938-941: Update the threshold calculation in the channel
health-check setup around EffectiveHealthCheckDisableThresholdSeconds so
positive sub-millisecond values are preserved: inspect the seconds value before
converting, and clamp any positive converted threshold to at least one
millisecond. Only treat zero or non-positive configured values as disabled,
retaining the existing large sentinel behavior.

In `@web/default/src/i18n/locales/en.json`:
- Line 3192: Update the English locale entry for “Please Select user groups that
can access this channel.” so the displayed value uses sentence-case
capitalization: “Please select user groups that can access this channel.”
- Line 4739: Update the translation entry in the locale definitions to remove
the trailing space from the key, using the exact string without the final
whitespace while preserving its existing value.

In `@web/default/src/i18n/locales/fr.json`:
- Line 3134: Update the French locale values for the payment/compliance message
at all three occurrences, including the entry at line 3134 and the matching
entries near lines 3486 and 4337, replacing the Chinese fragment in “codes de兑换”
with the existing French terminology for redemption codes. Preserve the rest of
each translation unchanged.

In `@web/default/src/i18n/locales/ja.json`:
- Line 4497: Update the Japanese locale entry for "Total earned" from the
Chinese translation to the appropriate Japanese translation, leaving the catalog
key and surrounding entries unchanged.
- Line 1756: Update the affected Japanese translation entries to preserve their
original interpolation placeholders, replacing the literal “__ PH_0 __” values
with the corresponding {{name}}, {{msg}}, {{count}}, or encoded email-content
placeholder used by each source string. Apply this consistently to the entries
represented by the visible key and the additional affected locations.
- Line 4868: Update the locale entry for the “WeChat” key to use “WeChat” rather
than “WeChat Pay”, leaving the adjacent “WeChat Pay” translation unchanged.

In `@web/default/src/i18n/locales/ru.json`:
- Line 1319: Update the Russian translation for “Disable threshold must be
between 0 and 86400 seconds for all edited channels” to include “для всех
изменяемых каналов,” preserving the validation scope stated in the English
source.
- Line 4702: Update the Russian translation for the “Used Quota” key to
“Использованная квота” so it preserves the meaning of quota already consumed.
- Line 3260: Update the “Pre-consumed” translation in the Russian locale from
“Предоплата” to wording that conveys quota or tokens consumed in advance, such
as “Предварительно потреблено” or “Предварительно списано”.
- Line 5159: Update the "scheduling controls" entry in the Russian locale so it
conveys scheduling or planning controls, not routing-control mechanisms.
Preserve the existing locale key and change only its translation value.
- Line 2649: Update the locale entry for the "New API" key to keep its value
exactly "New API" rather than translating the protected project identity; leave
surrounding localized strings unchanged.
- Around line 475-476: Update the Russian translations for the “Average RPM” and
“Average TPM” keys to use the catalog’s defined meanings: requests per minute
and tokens per minute, respectively, matching the terminology used by the
corresponding entries near Lines 3417-3418.
- Line 4493: Update the Russian translation for the “Total check-ins” key to
express the total count of check-ins, using “Всего отметок” or “Общее число
отметок” instead of the current inspection-related wording.
- Line 736: Update the Russian translations for the “Check-in failed” and
corresponding “Enable check-in” entries in the locale catalog to use consistent
daily check-in terminology with “отметка,” such as “Ежедневная отметка не
выполнена” and “Включить функцию ежедневной отметки,” rather than registration
or arrival wording.

In `@web/default/src/i18n/locales/vi.json`:
- Line 269: Update the Vietnamese translations for “All Models”, “Model Name”,
and “Select Model” in vi.json to use “mô hình” consistently instead of “mẫu”,
matching the surrounding model-management terminology.
- Line 1130: Translate the changed values in the Vietnamese locale, including
“Current Value”, “The date and time…”, “Price type”, “Synchronize this model…”,
and “View price”, instead of leaving English fallback text. Keep each existing
English source-string key unchanged and update only the corresponding Vietnamese
translations at the referenced entries.

In `@web/default/src/i18n/locales/zh-TW.json`:
- Line 287: Translate the English values at the referenced entries in zh-TW.json
into natural Traditional Chinese, including “All statuses,” the health-check
description, and stream-control labels. Preserve each existing localization key
and JSON structure; update only the values still displayed in English.
- Line 415: Correct the Traditional Chinese translations for the affected locale
entries: change “Audio Preview” to a generic audio-preview label rather than
“音樂預覽”, and restore the missing characters in “Delete Header” and “Set Header”
so they read “刪除請求頭” and “設定請求頭”. Apply the same corrections to the additional
occurrences identified in the locale file.

In `@web/default/src/i18n/locales/zh.json`:
- Line 803: Update the zh catalog translation for "Click save when you're done."
to Simplified Chinese, replacing the Traditional characters with the approved
wording "完成后点击保存。"; leave the zh-TW catalog responsible for the Traditional
Chinese version.
- Line 415: Update the “Audio Preview” translation in the zh locale from “音乐预览”
to “音频预览,” preserving the existing localization key.

---

Nitpick comments:
In `@web/default/src/i18n/locales/en.json`:
- Around line 4990-4994: Rename the added auth.resetPasswordConfirm locale keys
to flat English source-string keys, including the entries around the retry and
success messages, and update every caller and locale catalog reference to use
those exact English strings consistently. Preserve the existing translations and
interpolation placeholder.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7a341939-9e89-4378-b623-06d5038db371

📥 Commits

Reviewing files that changed from the base of the PR and between 5a6c53d and 16ea4ca.

📒 Files selected for processing (23)
  • controller/channel-test.go
  • controller/channel.go
  • controller/channel_test_internal_test.go
  • dto/channel_settings.go
  • model/channel.go
  • model/channel_health_check_test.go
  • router/channel-router.go
  • router/channel_router_test.go
  • service/channel.go
  • service/channel_enable_test.go
  • web/default/src/features/channels/api.ts
  • web/default/src/features/channels/components/dialogs/channel-test-dialog.tsx
  • web/default/src/features/channels/lib/channel-actions.ts
  • web/default/src/features/channels/types.ts
  • web/default/src/features/system-settings/models/channel-health-check-table.tsx
  • web/default/src/features/system-settings/models/routing-reliability-section.tsx
  • web/default/src/i18n/locales/en.json
  • web/default/src/i18n/locales/fr.json
  • web/default/src/i18n/locales/ja.json
  • web/default/src/i18n/locales/ru.json
  • web/default/src/i18n/locales/vi.json
  • web/default/src/i18n/locales/zh-TW.json
  • web/default/src/i18n/locales/zh.json

Comment on lines +256 to +270
useEffect(() => {
if (channels.length === 0) return
setBaselineById((prev) => {
let changed = false
const next = { ...prev }
for (const channel of channels) {
// Never overwrite a baseline once present: drafts may already depend on it.
// Missing baselines for drafted rows are filled synchronously in updateDraft.
if (next[channel.id] || drafts[channel.id]) continue
next[channel.id] = draftFromChannel(channel)
changed = true
}
return changed ? next : prev
})
}, [channels, drafts])

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Refresh baselines for rows without unsaved drafts.

The current guard permanently freezes every visited baseline. Query invalidation or another administrator’s update will not reach the controls, and a later edit can overwrite those newer server values.

Proposed fix
       for (const channel of channels) {
-        // Never overwrite a baseline once present: drafts may already depend on it.
-        // Missing baselines for drafted rows are filled synchronously in updateDraft.
-        if (next[channel.id] || drafts[channel.id]) continue
-        next[channel.id] = draftFromChannel(channel)
+        // Preserve the baseline only while an unsaved draft depends on it.
+        if (drafts[channel.id]) continue
+        const refreshed = draftFromChannel(channel)
+        if (next[channel.id] && draftsEqual(next[channel.id], refreshed)) continue
+        next[channel.id] = refreshed
         changed = true
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (channels.length === 0) return
setBaselineById((prev) => {
let changed = false
const next = { ...prev }
for (const channel of channels) {
// Never overwrite a baseline once present: drafts may already depend on it.
// Missing baselines for drafted rows are filled synchronously in updateDraft.
if (next[channel.id] || drafts[channel.id]) continue
next[channel.id] = draftFromChannel(channel)
changed = true
}
return changed ? next : prev
})
}, [channels, drafts])
useEffect(() => {
if (channels.length === 0) return
setBaselineById((prev) => {
let changed = false
const next = { ...prev }
for (const channel of channels) {
// Preserve the baseline only while an unsaved draft depends on it.
if (drafts[channel.id]) continue
const refreshed = draftFromChannel(channel)
if (next[channel.id] && draftsEqual(next[channel.id], refreshed)) continue
next[channel.id] = refreshed
changed = true
}
return changed ? next : prev
})
}, [channels, drafts])
🤖 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
`@web/default/src/features/system-settings/models/channel-health-check-table.tsx`
around lines 256 - 270, Update the baseline synchronization effect around
setBaselineById so rows without unsaved drafts refresh their baseline from the
current channels data on each update, instead of preserving every existing
baseline indefinitely. Continue protecting rows with drafts[channel.id], and
retain synchronous draft handling in updateDraft for newly drafted rows.

Comment on lines +345 to +367
const applySucceededDrafts = async (
succeededIds: Set<number>,
draftsSnapshot: Record<number, DraftRow>
) => {
if (succeededIds.size === 0) return

setDrafts((prev) => {
const next = { ...prev }
for (const id of succeededIds) {
delete next[id]
}
return next
})
setBaselineById((prev) => {
const next = { ...prev }
for (const id of succeededIds) {
const draft = draftsSnapshot[id]
if (draft) {
next[id] = draft
}
}
return next
})

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not discard edits made while a save is in flight.

A successful response deletes the current draft by ID even if the user changed it after draftsSnapshot was captured. Preserve newer drafts and advance only their baseline to the submitted value.

Proposed fix
     setDrafts((prev) => {
       const next = { ...prev }
       for (const id of succeededIds) {
-        delete next[id]
+        const submitted = draftsSnapshot[id]
+        const current = next[id]
+        if (submitted && current && draftsEqual(current, submitted)) {
+          delete next[id]
+        }
       }
       return next
     })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const applySucceededDrafts = async (
succeededIds: Set<number>,
draftsSnapshot: Record<number, DraftRow>
) => {
if (succeededIds.size === 0) return
setDrafts((prev) => {
const next = { ...prev }
for (const id of succeededIds) {
delete next[id]
}
return next
})
setBaselineById((prev) => {
const next = { ...prev }
for (const id of succeededIds) {
const draft = draftsSnapshot[id]
if (draft) {
next[id] = draft
}
}
return next
})
const applySucceededDrafts = async (
succeededIds: Set<number>,
draftsSnapshot: Record<number, DraftRow>
) => {
if (succeededIds.size === 0) return
setDrafts((prev) => {
const next = { ...prev }
for (const id of succeededIds) {
const submitted = draftsSnapshot[id]
const current = next[id]
if (submitted && current && draftsEqual(current, submitted)) {
delete next[id]
}
}
return next
})
setBaselineById((prev) => {
const next = { ...prev }
for (const id of succeededIds) {
const draft = draftsSnapshot[id]
if (draft) {
next[id] = draft
}
}
return next
})
🤖 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
`@web/default/src/features/system-settings/models/channel-health-check-table.tsx`
around lines 345 - 367, Update applySucceededDrafts so a successful save removes
a draft only when the current draft still matches the submitted draftsSnapshot
value; retain any newer in-flight edits while advancing that row’s baseline to
the submitted value. Use the current drafts state and draftsSnapshot together,
preserving the existing baseline update for successfully submitted rows.

*/
import { zodResolver } from '@hookform/resolvers/zod'
import { useMemo, useRef } from 'react'
import { useMemo, useRef, useState } from 'react'

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Synchronize the comparison baseline when defaultValues change.

useResetForm can load refreshed defaults, but baselineRef remains the initial value. A later save may therefore resend unchanged or stale options.

Proposed fix
-import { useMemo, useRef, useState } from 'react'
+import { useEffect, useMemo, useRef, useState } from 'react'

Add alongside the form-reset wiring:

 useResetForm(form, formDefaults)
+
+useEffect(() => {
+  baselineRef.current = normalizeDefaults(defaultValues)
+}, [defaultValues])

Also applies to: 272-290

🤖 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
`@web/default/src/features/system-settings/models/routing-reliability-section.tsx`
at line 20, Update the form-reset wiring in the routing reliability section so
baselineRef is synchronized with refreshed defaultValues whenever useResetForm
loads them. Ensure later save comparisons use the current defaults rather than
the initial baseline, while preserving the existing reset behavior.

@DawnMoon1542
DawnMoon1542 force-pushed the feat/channel-health-check-settings branch from 16ea4ca to a9b3256 Compare July 18, 2026 10:59
Support per-channel health check management with a channel-level
configuration table and layout updates on the Routing Reliability page.
Each channel can enable or disable scheduled tests and override the
disable threshold, re-enable-on-success policy, endpoint type, and
stream mode. Failure auto-ban continues to use the channel auto-ban
setting.

Scheduled tests and "Test All Channels" skip channels with scheduled
health checks disabled. Single-channel manual tests remain available
and use the channel endpoint/stream settings as defaults.
@DawnMoon1542
DawnMoon1542 force-pushed the feat/channel-health-check-settings branch from a9b3256 to 2224abd Compare July 18, 2026 11:01
@DawnMoon1542

Copy link
Copy Markdown
Contributor Author

Closing this PR for now; will revisit later if needed.

@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.

Actionable comments posted: 11

🧹 Nitpick comments (1)
controller/channel.go (1)

2274-2282: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Provide a descriptive message for partial or total failures.

If succeeded < len(req.Items), success will evaluate to false and the empty message "" will be sent to the frontend. In typical frontend setups, standard global interceptors might display this empty message in an error toast when success is false.

Consider populating message with a summary of the failure if not all updates succeed.

💡 Proposed change
+	message := ""
+	if succeeded < len(req.Items) {
+		message = fmt.Sprintf("更新完成:成功 %d,失败 %d", succeeded, len(req.Items)-succeeded)
+	}
+
 	c.JSON(http.StatusOK, gin.H{
 		"success": succeeded == len(req.Items),
-		"message": "",
+		"message": message,
 		"data": gin.H{
 			"succeeded": succeeded,
 			"failed":    len(req.Items) - succeeded,
 			"results":   results,
 		},
 	})
🤖 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 `@controller/channel.go` around lines 2274 - 2282, Update the response
construction in the channel update handler so the “message” field contains a
descriptive summary whenever succeeded is less than len(req.Items), while
retaining an empty or success-appropriate message when all updates succeed. Use
the existing succeeded and req.Items values to distinguish partial or total
failure without changing the response structure.
🤖 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.

Inline comments:
In `@web/default/src/i18n/locales/fr.json`:
- Line 5173: Update the French translation value for the “All scheduled-test
states” key to use the grammatically correct plural phrasing “Tous les états des
tests planifiés” or the project’s established equivalent.
- Line 5192: Update the French locale entry for “Non-streaming” to use
established streaming terminology, such as “Non-streaming” or “Sans streaming,”
matching the existing translation for “Streaming.”
- Line 5182: Update the French translation for “Disable threshold must be
between 0 and 86400 seconds for all edited channels” to explicitly include that
the threshold applies to all edited channels, preserving the full meaning of the
source message.

In `@web/default/src/i18n/locales/ja.json`:
- Line 5182: Update the Japanese translation for “Disable threshold must be
between 0 and 86400 seconds for all edited channels” to explicitly state that
the 0–86400-second range applies to all edited channels, preserving the existing
validation meaning.

In `@web/default/src/i18n/locales/ru.json`:
- Around line 5178-5180: Update the Russian translations for the batch channel
health check message and the “Channel health check settings” entries to
consistently use “проверка состояния каналов,” matching the existing
terminology, while preserving the messages’ original meaning and grammatical
forms.
- Line 5183: Update the “Endpoint type” entry in the Russian locale to reuse the
established “Тип конечной точки” translation already used elsewhere, replacing
the mixed-language wording while leaving other locale entries unchanged.
- Line 5198: Update the Russian translation for the key “Saved {{succeeded}}
channels, but {{failed}} failed: {{message}}” so it explicitly states that
{{failed}} channels could not be saved, using the requested semicolon and
sentence punctuation while preserving all placeholders.
- Line 5186: Update the Russian translation for the “Follow global” key to a
grammatical, actionable phrase equivalent to “Следовать глобальным настройкам,”
clearly indicating inheritance from global settings.

In `@web/default/src/i18n/locales/zh-TW.json`:
- Line 5174: Update the zh-TW locale entry for the “All statuses” key to use the
existing Traditional Chinese terminology, such as “所有狀態”, instead of the English
value.
- Line 5188: Update both zh-TW locale messages identified by “How often to
recheck auto-disabled channels” and the additionally referenced entry, replacing
the Simplified Chinese “复查” with the Traditional Chinese “複查” while preserving
the remaining translations.

In `@web/default/src/i18n/locales/zh.json`:
- Line 5205: Update the zh.json translation for “Test all eligible channels”
from “测试全部可用渠道” to “测试全部符合条件的渠道”, preserving the intended meaning of eligible
channels.

---

Nitpick comments:
In `@controller/channel.go`:
- Around line 2274-2282: Update the response construction in the channel update
handler so the “message” field contains a descriptive summary whenever succeeded
is less than len(req.Items), while retaining an empty or success-appropriate
message when all updates succeed. Use the existing succeeded and req.Items
values to distinguish partial or total failure without changing the response
structure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9df94115-6832-4284-abcf-0e0a23c1badc

📥 Commits

Reviewing files that changed from the base of the PR and between 16ea4ca and 2224abd.

📒 Files selected for processing (23)
  • controller/channel-test.go
  • controller/channel.go
  • controller/channel_test_internal_test.go
  • dto/channel_settings.go
  • model/channel.go
  • model/channel_health_check_test.go
  • router/channel-router.go
  • router/channel_router_test.go
  • service/channel.go
  • service/channel_enable_test.go
  • web/default/src/features/channels/api.ts
  • web/default/src/features/channels/components/dialogs/channel-test-dialog.tsx
  • web/default/src/features/channels/lib/channel-actions.ts
  • web/default/src/features/channels/types.ts
  • web/default/src/features/system-settings/models/channel-health-check-table.tsx
  • web/default/src/features/system-settings/models/routing-reliability-section.tsx
  • web/default/src/i18n/locales/en.json
  • web/default/src/i18n/locales/fr.json
  • web/default/src/i18n/locales/ja.json
  • web/default/src/i18n/locales/ru.json
  • web/default/src/i18n/locales/vi.json
  • web/default/src/i18n/locales/zh-TW.json
  • web/default/src/i18n/locales/zh.json
🚧 Files skipped from review as they are similar to previous changes (14)
  • web/default/src/features/channels/lib/channel-actions.ts
  • dto/channel_settings.go
  • router/channel_router_test.go
  • service/channel_enable_test.go
  • service/channel.go
  • router/channel-router.go
  • controller/channel_test_internal_test.go
  • model/channel_health_check_test.go
  • web/default/src/features/channels/components/dialogs/channel-test-dialog.tsx
  • web/default/src/features/channels/api.ts
  • web/default/src/features/system-settings/models/channel-health-check-table.tsx
  • controller/channel-test.go
  • model/channel.go
  • web/default/src/features/system-settings/models/routing-reliability-section.tsx

"Zhipu V4": "Zhipu V4",
"Zoom": "Zoom"
"Zoom": "Zoom",
"All scheduled-test states": "Tous les états de test planifié",

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the scheduled-test filter label.

Tous les états de test planifié has a number/agreement mismatch and reads awkwardly. Use Tous les états des tests planifiés (or the project’s preferred equivalent).

🤖 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 `@web/default/src/i18n/locales/fr.json` at line 5173, Update the French
translation value for the “All scheduled-test states” key to use the
grammatically correct plural phrasing “Tous les états des tests planifiés” or
the project’s established equivalent.

"Channel health check settings": "Paramètres de contrôle de santé des canaux",
"Channel health check settings saved": "Paramètres de contrôle de santé des canaux enregistrés",
"Disable threshold": "Seuil de désactivation",
"Disable threshold must be between 0 and 86400 seconds for all edited channels": "Le seuil de désactivation doit être entre 0 et 86400 secondes",

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve the batch-validation scope in French.

The translation omits “for all edited channels”, so users are not told that the threshold applies to every modified channel.

Proposed fix
-    "Disable threshold must be between 0 and 86400 seconds for all edited channels": "Le seuil de désactivation doit être entre 0 et 86400 secondes",
+    "Disable threshold must be between 0 and 86400 seconds for all edited channels": "Le seuil de désactivation doit être compris entre 0 et 86400 secondes pour tous les canaux modifiés",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Disable threshold must be between 0 and 86400 seconds for all edited channels": "Le seuil de désactivation doit être entre 0 et 86400 secondes",
"Disable threshold must be between 0 and 86400 seconds for all edited channels": "Le seuil de désactivation doit être compris entre 0 et 86400 secondes pour tous les canaux modifiés",
🤖 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 `@web/default/src/i18n/locales/fr.json` at line 5182, Update the French
translation for “Disable threshold must be between 0 and 86400 seconds for all
edited channels” to explicitly include that the threshold applies to all edited
channels, preserving the full meaning of the source message.

"How often to run scheduled channel health checks": "Fréquence des contrôles de santé planifiés des canaux",
"Loading channels...": "Chargement des canaux...",
"Manually disabled": "Désactivé manuellement",
"Non-streaming": "Non-flux",

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the established streaming terminology.

Non-flux is not idiomatic French and may be unclear in a stream-mode selector. Use Non-streaming or Sans streaming, consistently with the existing Streaming terminology.

🤖 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 `@web/default/src/i18n/locales/fr.json` at line 5192, Update the French locale
entry for “Non-streaming” to use established streaming terminology, such as
“Non-streaming” or “Sans streaming,” matching the existing translation for
“Streaming.”

"Channel health check settings": "チャネル健全性チェック設定",
"Channel health check settings saved": "チャネル健全性チェック設定を保存しました",
"Disable threshold": "無効化しきい値",
"Disable threshold must be between 0 and 86400 seconds for all edited channels": "無効化しきい値は 0〜86400 秒で入力してください",

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve the batch-validation scope in this translation.

The Japanese text omits “for all edited channels,” so users may not understand that the range applies to every channel being modified.

-    "Disable threshold must be between 0 and 86400 seconds for all edited channels": "無効化しきい値は 0〜86400 秒で入力してください",
+    "Disable threshold must be between 0 and 86400 seconds for all edited channels": "編集したすべてのチャネルの無効化しきい値は、0〜86400秒の範囲である必要があります",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Disable threshold must be between 0 and 86400 seconds for all edited channels": "無効化しきい値は 0〜86400 秒で入力してください",
"Disable threshold must be between 0 and 86400 seconds for all edited channels": "編集したすべてのチャネルの無効化しきい値は、0〜86400秒の範囲である必要があります",
🤖 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 `@web/default/src/i18n/locales/ja.json` at line 5182, Update the Japanese
translation for “Disable threshold must be between 0 and 86400 seconds for all
edited channels” to explicitly state that the 0–86400-second range applies to
all edited channels, preserving the existing validation meaning.

Comment on lines +5178 to +5180
"Batch channel health check started. Channels with scheduled tests disabled are skipped. Refresh to see results.": "Запущена пакетная проверка каналов. Каналы с отключённой плановой проверкой пропускаются. Обновите страницу, чтобы увидеть результаты.",
"Channel health check settings": "Настройки проверки каналов",
"Channel health check settings saved": "Настройки проверки каналов сохранены",

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Preserve “health check” in the Russian terminology.

These translations reduce “health check” to generic “channel test,” unlike the existing “Проверки состояния каналов” at Line 749. Use “проверка состояния каналов” consistently so users can distinguish health checks from manual channel tests.

Also applies to: 5185-5185

🤖 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 `@web/default/src/i18n/locales/ru.json` around lines 5178 - 5180, Update the
Russian translations for the batch channel health check message and the “Channel
health check settings” entries to consistently use “проверка состояния каналов,”
matching the existing terminology, while preserving the messages’ original
meaning and grammatical forms.

"Endpoint type": "Тип endpoint",
"Enter 0-86400 seconds": "Введите 0–86400 секунд",
"Failed to save channel health check settings": "Не удалось сохранить настройки проверки каналов",
"Follow global": "Как глобально",

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Clarify “Follow global.”

“Как глобально” is not grammatical or actionable. Translate it as “Следовать глобальным настройкам” or equivalent to indicate inheritance from global settings.

🤖 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 `@web/default/src/i18n/locales/ru.json` at line 5186, Update the Russian
translation for the “Follow global” key to a grammatical, actionable phrase
equivalent to “Следовать глобальным настройкам,” clearly indicating inheritance
from global settings.

"Probe enabled and auto-disabled channels. Manually disabled channels are skipped.": "Проверяет включённые и автоотключённые каналы. Вручную отключённые пропускаются.",
"Recover auto-disabled only": "Только восстановление автоотключённых",
"Run background health checks on a schedule": "Запускать фоновые проверки каналов по расписанию",
"Saved {{succeeded}} channels, but {{failed}} failed: {{message}}": "Сохранено каналов: {{succeeded}}, с ошибкой: {{failed}}: {{message}}",

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Make the partial-save result message explicit.

The current wording makes it unclear that {{failed}} channels were not saved. Prefer: “Сохранено каналов: {{succeeded}}; не удалось сохранить: {{failed}}. {{message}}”.

🤖 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 `@web/default/src/i18n/locales/ru.json` at line 5198, Update the Russian
translation for the key “Saved {{succeeded}} channels, but {{failed}} failed:
{{message}}” so it explicitly states that {{failed}} channels could not be
saved, using the requested semicolon and sentence punctuation while preserving
all placeholders.

"Zoom": "縮放"
"Zoom": "縮放",
"All scheduled-test states": "全部定期測試狀態",
"All statuses": "All statuses",

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Translate the status label.

Line 5174 still displays English in the zh-TW locale. Use the existing terminology, for example 所有狀態.

🤖 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 `@web/default/src/i18n/locales/zh-TW.json` at line 5174, Update the zh-TW
locale entry for the “All statuses” key to use the existing Traditional Chinese
terminology, such as “所有狀態”, instead of the English value.

"Failed to save channel health check settings": "儲存渠道健康檢查設定失敗",
"Follow global": "遵循全域",
"Global settings were saved, but some channel health check changes failed": "全域設定已儲存,但部分渠道健康檢查設定儲存失敗",
"How often to recheck auto-disabled channels": "复查自動停用渠道的間隔",

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use Traditional Chinese characters.

Replace 复查 with 複查 in both messages; the current values contain Simplified Chinese text in the zh-TW resource.

Also applies to: 5193-5193

🤖 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 `@web/default/src/i18n/locales/zh-TW.json` at line 5188, Update both zh-TW
locale messages identified by “How often to recheck auto-disabled channels” and
the additionally referenced entry, replacing the Simplified Chinese “复查” with
the Traditional Chinese “複查” while preserving the remaining translations.

"Scheduled-test filter applies to the current page only ({{shown}} of {{pageSize}} shown)": "定期测试筛选仅作用于当前页(显示 {{shown}} / {{pageSize}})",
"Search by name or ID": "按名称或 ID 搜索",
"Seconds": "秒",
"Test all eligible channels": "测试全部可用渠道"

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Translate “eligible” as “符合条件” rather than “可用”.

“可用渠道” may imply only currently online channels, while the batch policy can include auto-disabled channels. Use “测试全部符合条件的渠道” to match the source behavior.

🤖 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 `@web/default/src/i18n/locales/zh.json` at line 5205, Update the zh.json
translation for “Test all eligible channels” from “测试全部可用渠道” to “测试全部符合条件的渠道”,
preserving the intended meaning of eligible channels.

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