Conversation
✅ Deploy Preview for pushy ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Warning Review limit reached
Next review available in: 50 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds i18next, browser language detection, and React bindings, then wires locale selection into the app root and Ant Design. Most UI text across shared components, auth screens, user pages, manage pages, and admin pages now comes from translation keys in Changesi18n infrastructure and root wiring
Shared shell and layout text
App detail and modal text
Auth pages
User-facing pages
Manage pages
Admin and realtime pages
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/pages/manage/components/version-table.tsx (1)
153-173: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winFinish localizing the delete dialog body.
This function now translates the modal title, but the body still uses
versionNames.join(','), which leaves Chinese punctuation in English mode. Rendering the names as a list avoids that locale-specific leak.Suggested fix
Modal.confirm({ title: t('version_table.delete_title'), - content: versionNames.join(','), + content: ( + <div className="max-h-48 overflow-y-auto"> + {versionNames.map((name) => ( + <div key={name}>{name}</div> + ))} + </div> + ), maskClosable: true,🤖 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 `@src/pages/manage/components/version-table.tsx` around lines 153 - 173, The delete dialog body in removeSelectedVersions is still building a locale-specific string with versionNames.join(','), which leaks Chinese punctuation into non-Chinese locales. Update the Modal.confirm content to render the selected version names as a locale-aware list instead of joining with a hardcoded delimiter, keeping the existing translation flow used by t('version_table.delete_title') and the versionNames collection logic.
🧹 Nitpick comments (4)
src/pages/register.tsx (1)
129-129: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse
rootRouterPath.loginfor this link.This file already uses
rootRouterPathfor navigation, so hardcoding"/login"creates a second route source that can drift later.♻️ Proposed fix
- <Link to="/login">{t('register.has_account')}</Link> + <Link to={rootRouterPath.login}>{t('register.has_account')}</Link>🤖 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 `@src/pages/register.tsx` at line 129, The register page link is hardcoded to "/login" instead of using the shared router constant, which can drift from the app’s routing source of truth. Update the Link in register page to use rootRouterPath.login, following the existing rootRouterPath usage in this component, so navigation stays consistent and centralized.src/pages/inactivated.tsx (1)
49-50: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReuse
rootRouterPath.loginfor the back button target.The guard above already navigates with
rootRouterPath.login; hardcoding"/user"here makes the destination easier to drift away from the translated “back login” label.♻️ Proposed fix
- <Button key="back" href="/user"> + <Button key="back" href={rootRouterPath.login}> {t('inactivated.back_login')} </Button>,🤖 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 `@src/pages/inactivated.tsx` around lines 49 - 50, The back button in the inactivated page is hardcoding the login destination instead of reusing the shared router constant. Update the Button in the inactivated page to use rootRouterPath.login, matching the existing navigation guard and keeping the target consistent with the “back login” action.src/pages/reset-password/components/success.tsx (1)
10-12: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse the shared login route instead of hardcoding
/#/login.This introduces a second login URL shape in the same flow. Keeping the CTA on the router-managed login path avoids route drift and the forced full-page reload here.
🤖 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 `@src/pages/reset-password/components/success.tsx` around lines 10 - 12, The reset-password success CTA is hardcoding the login URL, which bypasses the shared router path and can cause route drift. Update the Button in the Success component to use the existing login route constant/helper used elsewhere in the app instead of the literal /#/login, so the reset flow stays aligned with the router-managed login path.src/pages/manage/components/publish-feature-table.tsx (1)
20-37: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winKeep tag state separate from translated copy.
The tag color now depends on
text.includes('✓')/text.includes('⚠'). That makes every locale string responsible for preserving those glyphs. Store a semantic status in the row data and translate only the displayed label.Also applies to: 57-89
🤖 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 `@src/pages/manage/components/publish-feature-table.tsx` around lines 20 - 37, The publish feature table is coupling tag color to translated text via the `text.includes('✓')` / `text.includes('⚠')` logic, so the state should be made semantic instead of inferred from localized copy. Update the row data used in `PublishFeatureTable` (and the related entries in the table definition block) to carry an explicit status field for each tag, and keep `t(...)` only for the visible label. Then adjust the tag rendering logic to use that status field for color/variant selection instead of inspecting the translated string.
🤖 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 `@src/components/app-drawer.tsx`:
- Around line 136-142: The app count and check-count translations in app-drawer
should keep their count values numeric for i18next pluralization, rather than
passing locale-formatted strings. Update the calls in the app list and the
checkbox label to pass the raw numeric values from apps.length and the active
check count, and handle any locale-specific formatting only in the rendered text
layer. Use the translation keys and the surrounding AppDrawer rendering logic to
locate the affected count labels.
In `@src/components/daily-check-quota.tsx`:
- Around line 37-40: The tier label in daily-check-quota still falls back to
localized data from quotas.title, which can surface Chinese plan names in
English mode. Update the rendering in daily-check-quota (including the other
affected tier display path) to resolve known tiers through t(...) first, then
fall back to a custom server-provided title, and only use user.tier as the last
resort. Use the existing tier lookup points around quota, quotas[user.tier], and
the tier text rendering to keep the fix consistent.
In `@src/components/top-navigation.tsx`:
- Around line 72-89: The `top-navigation` menu items for documentation and about
are using translated labels but fixed `href`s, so the destination does not match
the active locale. Update the `TopNavigation` link setup for the `document` and
`about` entries to choose the locale-specific URL based on the current language
(using the same i18n/lang source already available in this component), or
otherwise ensure each label points to the matching language page.
In `@src/i18n/locales/zh-CN.json`:
- Around line 49-135: The zh-CN locale bundle is missing several keys that the
new UI expects, so align it with the English key set by adding the absent
entries under user, deps_table, and the full publish_feature_table namespace in
zh-CN.json. Use the existing translation patterns in that file to add localized
strings for symbols like user.fetching_addon_quote, user.per_year,
user.upgrade_button, deps_table.cli_required,
deps_table.native_package_with_name, deps_table.ota_version_with_name,
bind_package.publish, and publish_feature_table so the localized screens don’t
fall back to raw keys.
In `@src/index.tsx`:
- Around line 68-70: The Antd locale lookup in App is using i18n.language
directly, which can remain an unresolved detector value and miss the normalized
translation language. Update the locale selection to use the resolved language
from the i18n instance when indexing antdLocaleMap, so the App component picks
the correct Antd locale instead of falling back to zhCN for English. Keep the
fix localized to the App function and the antdLocaleMap lookup.
In `@src/pages/audit-logs.tsx`:
- Line 217: The audit logs page is using a fixed Day.js locale at module load,
so relative timestamps from date.fromNow() can stay in the wrong language even
after useTranslation switches the UI language. Update the audit-logs page logic
around useTranslation and the time rendering to sync Day.js with the active i18n
language, preferably by setting dayjs.locale from the current language inside
the component lifecycle instead of once at import time.
- Around line 123-129: The audit log action filter is using translated text as
the query value, so `selectedAction` can break across locales and shared URLs.
Update `getActionOptions` (and the related select/query handling in the audit
logs page) to store a stable action key derived from `getActionMap` output, such
as `METHOD + normalizedPath`, and use the translated string only for the
displayed `label`. Make sure the same stable key is used wherever the action
value is written to or read from the URL/query param so filtering and selection
remain consistent after language changes.
In `@src/pages/manage/index.tsx`:
- Line 73: The bulk-select aria-label in the Manage page is collapsing to just
filterLabel because the conditional adds nothing, so screen readers miss the
action description. Update the label in the manage page component to use a
descriptive bulk-select text for the checkbox action, and remove the dead
t('common.save') branch from that aria-label expression.
In `@src/pages/realtime-metrics.tsx`:
- Around line 95-100: The tooltip text in formatTooltipItem is assembling
localized output by concatenating translation fragments, which can produce
awkward spacing and word order. Update the realtime-metrics translations and the
code paths using formatTooltipItem/current_dimension to use full interpolated
messages instead of stitching together checks_suffix or similar fragments, so
the locale controls the complete phrase naturally.
In `@src/pages/reset-password/index.tsx`:
- Around line 21-25: The reset-password success route is still using a step
value that is outside the Steps range, so the progress indicator becomes out of
sync on the success screen. Update the reset-password page logic in the
component that renders Steps so the success route is mapped to display index 2
before passing the value into current, while keeping the existing step routes
and content rendering unchanged.
---
Outside diff comments:
In `@src/pages/manage/components/version-table.tsx`:
- Around line 153-173: The delete dialog body in removeSelectedVersions is still
building a locale-specific string with versionNames.join(','), which leaks
Chinese punctuation into non-Chinese locales. Update the Modal.confirm content
to render the selected version names as a locale-aware list instead of joining
with a hardcoded delimiter, keeping the existing translation flow used by
t('version_table.delete_title') and the versionNames collection logic.
---
Nitpick comments:
In `@src/pages/inactivated.tsx`:
- Around line 49-50: The back button in the inactivated page is hardcoding the
login destination instead of reusing the shared router constant. Update the
Button in the inactivated page to use rootRouterPath.login, matching the
existing navigation guard and keeping the target consistent with the “back
login” action.
In `@src/pages/manage/components/publish-feature-table.tsx`:
- Around line 20-37: The publish feature table is coupling tag color to
translated text via the `text.includes('✓')` / `text.includes('⚠')` logic, so
the state should be made semantic instead of inferred from localized copy.
Update the row data used in `PublishFeatureTable` (and the related entries in
the table definition block) to carry an explicit status field for each tag, and
keep `t(...)` only for the visible label. Then adjust the tag rendering logic to
use that status field for color/variant selection instead of inspecting the
translated string.
In `@src/pages/register.tsx`:
- Line 129: The register page link is hardcoded to "/login" instead of using the
shared router constant, which can drift from the app’s routing source of truth.
Update the Link in register page to use rootRouterPath.login, following the
existing rootRouterPath usage in this component, so navigation stays consistent
and centralized.
In `@src/pages/reset-password/components/success.tsx`:
- Around line 10-12: The reset-password success CTA is hardcoding the login URL,
which bypasses the shared router path and can cause route drift. Update the
Button in the Success component to use the existing login route constant/helper
used elsewhere in the app instead of the literal /#/login, so the reset flow
stays aligned with the router-managed login path.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4bcc56f0-c6ea-4efe-9a44-0ed365d39ffa
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (39)
package.jsonsrc/components/app-detail-header.tsxsrc/components/app-drawer.tsxsrc/components/app-settings-modal.tsxsrc/components/create-app-modal.tsxsrc/components/daily-check-quota.tsxsrc/components/error-boundary.tsxsrc/components/footer.tsxsrc/components/top-navigation.tsxsrc/i18n/index.tssrc/i18n/locales/en.jsonsrc/i18n/locales/zh-CN.jsonsrc/index.tsxsrc/pages/activate.tsxsrc/pages/admin-apps.tsxsrc/pages/admin-config.tsxsrc/pages/admin-metrics.tsxsrc/pages/admin-service-status.tsxsrc/pages/admin-users.tsxsrc/pages/api-tokens.tsxsrc/pages/apps.tsxsrc/pages/audit-logs.tsxsrc/pages/inactivated.tsxsrc/pages/login.tsxsrc/pages/manage/components/bind-package.tsxsrc/pages/manage/components/commit.tsxsrc/pages/manage/components/deps-table.tsxsrc/pages/manage/components/package-list.tsxsrc/pages/manage/components/publish-feature-table.tsxsrc/pages/manage/components/setting-modal.tsxsrc/pages/manage/components/version-table.tsxsrc/pages/manage/index.tsxsrc/pages/realtime-metrics.tsxsrc/pages/register.tsxsrc/pages/reset-password/components/send-email.tsxsrc/pages/reset-password/components/set-password.tsxsrc/pages/reset-password/components/success.tsxsrc/pages/reset-password/index.tsxsrc/pages/welcome.tsx
- Install i18next, react-i18next, i18next-browser-languagedetector - Create i18n config with en and zh-CN locales - Replace hardcoded strings across 36 component/page files - Add Ant Design ConfigProvider with dynamic locale switching - Add language switcher in top navigation (desktop + mobile) Note: user.tsx i18n pending (complex file, separate commit)
- Replace all 63 Chinese strings with t() calls - Convert module-level constants to functions accepting t - Add useTranslation to 7 components - TypeScript and biome checks pass
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/pages/audit-logs.tsx (1)
102-129: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winMemoize
getActionMap(t)to avoid rebuilding it per log/row.
getActionMap(t)recreates a 24-key translated object every call.getActionLabelcalls it per rendered row, andbuildSearchTextcalls it once per log inside thefilteredAuditLogsuseMemo— with up to 1000 logs, that's up to 24k translation lookups recomputed on every search keystroke (debounced) or language change. Consider computing the map once viauseMemo(() => getActionMap(t), [t])and passing it down instead of rebuilding it insidegetActionLabel/buildSearchText.♻️ Suggested approach
-const getActionLabel = ( - t: TranslateFn, - method: string, - path: string, -): string => { - const key = getActionKey(method, path); - return getActionMap(t)[key] || `${method.toUpperCase()} ${path}`; -}; +const getActionLabel = ( + actionMap: Record<string, string>, + method: string, + path: string, +): string => { + const key = getActionKey(method, path); + return actionMap[key] || `${method.toUpperCase()} ${path}`; +};Then compute
const actionMap = useMemo(() => getActionMap(t), [t]);once inAuditLogsand thread it throughbuildSearchText, columns, and the Drawer instead oft.Also applies to: 140-147, 206-221, 295-295
🤖 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 `@src/pages/audit-logs.tsx` around lines 102 - 129, `getActionMap(t)` is being rebuilt repeatedly inside `getActionLabel` and `buildSearchText`, causing unnecessary translation work for every row/log render. Compute the map once in `AuditLogs` with `useMemo(() => getActionMap(t), [t])`, then pass the memoized `actionMap` into `buildSearchText`, `getActionLabel`, and the Drawer/column rendering paths so the existing helpers use the shared map instead of calling `getActionMap` themselves.src/pages/user.tsx (1)
419-449: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winPrefer interpolation over concatenating independently-translated fragments.
Several strings are built by concatenating a raw value with a translated fragment in a fixed order (e.g.
`${months} ${t('user.annual_billing')}`,`${t('user.annual_pay')} ${formatMoney(quote.amount)}`). This bakes in an English/Chinese-compatible word order into the code rather than the translation file, so text ordering can't be adjusted per-locale without a code change.♻️ Suggested approach
-title: isAnnual - ? `${months} ${t('user.annual_billing')}` - : `${months} ${t('user.price_month')}`, +title: isAnnual + ? t('user.annual_billing_months', { months }) + : t('user.price_month_months', { months }),Also applies to: 516-529
🤖 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 `@src/pages/user.tsx` around lines 419 - 449, The `user.tsx` plan/price labels are assembling translated text with fixed string concatenation, which prevents locale-specific word order. Update the affected formatting in the option builder (including the `title` field here and the similar block around the other referenced section) to use translation interpolation/placeholders instead of `${value} ${t(...)}` patterns. Keep the logic in the same `purchase` option construction path, but move the ordering into the translation keys so each locale can define its own phrasing.
🤖 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 `@src/pages/audit-logs.tsx`:
- Around line 102-129: `getActionMap(t)` is being rebuilt repeatedly inside
`getActionLabel` and `buildSearchText`, causing unnecessary translation work for
every row/log render. Compute the map once in `AuditLogs` with `useMemo(() =>
getActionMap(t), [t])`, then pass the memoized `actionMap` into
`buildSearchText`, `getActionLabel`, and the Drawer/column rendering paths so
the existing helpers use the shared map instead of calling `getActionMap`
themselves.
In `@src/pages/user.tsx`:
- Around line 419-449: The `user.tsx` plan/price labels are assembling
translated text with fixed string concatenation, which prevents locale-specific
word order. Update the affected formatting in the option builder (including the
`title` field here and the similar block around the other referenced section) to
use translation interpolation/placeholders instead of `${value} ${t(...)}`
patterns. Keep the logic in the same `purchase` option construction path, but
move the ordering into the translation keys so each locale can define its own
phrasing.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d12da546-a70c-405c-932e-1fe8d0d20ff7
⛔ Files ignored due to path filters (4)
bun.lockis excluded by!**/*.locksrc/assets/favicon.svgis excluded by!**/*.svgsrc/assets/logo-h.svgis excluded by!**/*.svgsrc/assets/logo.svgis excluded by!**/*.svg
📒 Files selected for processing (40)
package.jsonsrc/components/app-detail-header.tsxsrc/components/app-drawer.tsxsrc/components/app-settings-modal.tsxsrc/components/create-app-modal.tsxsrc/components/daily-check-quota.tsxsrc/components/error-boundary.tsxsrc/components/footer.tsxsrc/components/top-navigation.tsxsrc/i18n/index.tssrc/i18n/locales/en.jsonsrc/i18n/locales/zh-CN.jsonsrc/index.tsxsrc/pages/activate.tsxsrc/pages/admin-apps.tsxsrc/pages/admin-config.tsxsrc/pages/admin-metrics.tsxsrc/pages/admin-service-status.tsxsrc/pages/admin-users.tsxsrc/pages/api-tokens.tsxsrc/pages/apps.tsxsrc/pages/audit-logs.tsxsrc/pages/inactivated.tsxsrc/pages/login.tsxsrc/pages/manage/components/bind-package.tsxsrc/pages/manage/components/commit.tsxsrc/pages/manage/components/deps-table.tsxsrc/pages/manage/components/package-list.tsxsrc/pages/manage/components/publish-feature-table.tsxsrc/pages/manage/components/setting-modal.tsxsrc/pages/manage/components/version-table.tsxsrc/pages/manage/index.tsxsrc/pages/realtime-metrics.tsxsrc/pages/register.tsxsrc/pages/reset-password/components/send-email.tsxsrc/pages/reset-password/components/set-password.tsxsrc/pages/reset-password/components/success.tsxsrc/pages/reset-password/index.tsxsrc/pages/user.tsxsrc/pages/welcome.tsx
✅ Files skipped from review due to trivial changes (3)
- src/pages/welcome.tsx
- src/components/app-settings-modal.tsx
- src/i18n/locales/zh-CN.json
🚧 Files skipped from review as they are similar to previous changes (31)
- src/i18n/index.ts
- src/pages/login.tsx
- src/index.tsx
- src/components/footer.tsx
- package.json
- src/pages/inactivated.tsx
- src/pages/reset-password/components/set-password.tsx
- src/pages/manage/components/setting-modal.tsx
- src/pages/apps.tsx
- src/pages/reset-password/components/send-email.tsx
- src/pages/register.tsx
- src/components/app-detail-header.tsx
- src/components/daily-check-quota.tsx
- src/components/create-app-modal.tsx
- src/i18n/locales/en.json
- src/components/error-boundary.tsx
- src/pages/manage/components/version-table.tsx
- src/pages/manage/index.tsx
- src/pages/admin-service-status.tsx
- src/pages/admin-apps.tsx
- src/pages/admin-metrics.tsx
- src/pages/activate.tsx
- src/pages/manage/components/deps-table.tsx
- src/components/app-drawer.tsx
- src/pages/admin-users.tsx
- src/pages/manage/components/commit.tsx
- src/pages/admin-config.tsx
- src/pages/manage/components/package-list.tsx
- src/components/top-navigation.tsx
- src/pages/manage/components/bind-package.tsx
- src/pages/realtime-metrics.tsx
变更内容
待完成
Summary by CodeRabbit
New Features
Bug Fixes