Migrate Dashboard module from hardcoded text to full internationalization
support with Chinese and English translations.
## Changes Made
### Dashboard Components i18n Implementation
- **Dashboard main page** (`index.tsx`): Added i18n for page title, welcome message,
search button, tab labels, and toast notifications
- **StatsCards** (`stats-cards.tsx`): Implemented i18n for 4 grouped cards with
8 data metrics (account data, usage stats, resource consumption, performance metrics)
- **Overview** (`overview.tsx`): Added i18n for chart titles, tooltips, and error states
- **ModelUsageChart** (`model-usage-chart.tsx`): Implemented i18n for chart content
and status messages
- **ModelMonitoringStats** (`model-monitoring-stats.tsx`): Added i18n for monitoring
statistics cards and descriptions
- **ModelMonitoringTable** (`model-monitoring-table.tsx`): Implemented i18n for table
headers, pagination, search functionality, and action menus
### Language Files Updates
- **Chinese** (`zh.json`): Added comprehensive Dashboard translations with proper
key structure and interpolation support
- **English** (`en.json`): Added complete English translations with consistent
terminology and interpolation variables
### Key Structure Improvements
- Organized i18n keys in logical hierarchy: `dashboard.stats.*`, `dashboard.overview.*`,
`dashboard.model_usage.*`, `dashboard.monitoring.*`, `dashboard.search.*`
- Added common UI elements to `common.*` namespace for reusability
- Support for interpolation variables (e.g., `{{name}}`, `{{count}}`, `{{percentage}}`)
### Bug Fixes
- **Fixed duplicate JSON keys**: Resolved conflicts between `dashboard.search` (string)
and `dashboard.search` (object) by renaming to `dashboard.search_button`
- **Fixed duplicate overview keys**: Resolved conflicts between `dashboard.overview`
(string) and `dashboard.overview` (object) by renaming to `dashboard.overview_tab`
- Updated component references to use corrected i18n keys
### Technical Features
- Full React i18next integration with `useTranslation` hook
- Maintains accessibility standards and semantic HTML structure
- Consistent error handling and loading states across all components
- Support for plural forms and complex interpolation scenarios
## Breaking Changes
None - All changes are additive and maintain backward compatibility.
## Testing
- ✅ JSON validation for both language files
- ✅ No linter errors in Dashboard components
- ✅ No duplicate keys in translation files
- ✅ All i18n keys properly referenced in components
Closes: Dashboard i18n migration task
- Move LanguageSwitch into the header action toolbar beside ThemeSwitch on all pages:
- web/src/features/dashboard/index.tsx
- web/src/features/users/index.tsx
- web/src/features/tasks/index.tsx
- web/src/features/apps/index.tsx
- web/src/features/settings/index.tsx
- web/src/features/chats/index.tsx
- web/src/routes/clerk/_authenticated/user-management.tsx
- web/src/routes/_authenticated/errors/$error.tsx
- Remove the previous left-side Language button from Header to avoid duplication:
- web/src/components/layout/header.tsx
- Keep user menu language controls consistent with other items (LanguageMenuItems).
UI/UX:
- Same placement and visual style as Theme switch (ghost, icon-only, rounded, a11y sr-only label).
- Consistent look across all headers and in user menu.
Chore:
- Updated imports accordingly.
- No linter errors.
This commit introduces a complete model monitoring system that provides
real-time insights into model performance and usage statistics.
## ✨ Features Added
### Core Components
- **ModelMonitoringStats**: Four key metric cards displaying total models,
active models, total requests, and average success rate
- **ModelMonitoringTable**: Interactive table with search, filtering, and
pagination for detailed model data
- **useModelMonitoring**: Custom hook for data fetching and state management
### Dashboard Integration
- Added new "模型观测" (Model Monitoring) tab to main dashboard
- Integrated monitoring components with existing dashboard layout
- Maintained consistent UI/UX with shadcn/ui design system
### Data Processing
- Smart data aggregation from existing `/api/data/` endpoints
- Automatic calculation of success rates and average metrics
- Support for both admin and user-specific data views
### Interactive Features
- Real-time search by model name
- Business group filtering
- Pagination with 10 items per page
- Color-coded success rate indicators (green >95%, yellow 90-95%, red <90%)
- Refresh capability for up-to-date data
## 🔧 Technical Implementation
### Type Safety
- Added comprehensive TypeScript interfaces in `@/types/api.ts`
- Defined `ModelInfo`, `ModelMonitoringStats`, and related types
### Utility Functions
- Enhanced color utilities with `modelToColor()` for consistent model identification
- Improved formatters for quota, tokens, and percentage display
- Maintained existing utility function architecture
### Architecture
- Follows established patterns from dashboard components
- Reuses existing HTTP client and authentication utilities
- Consistent error handling and loading states
### Code Quality
- All components pass linter checks
- Proper import organization and formatting
- Responsive design for mobile compatibility
## 🎯 User Experience
### Visual Design
- Color-coded model indicators for quick identification
- Success rate visualization with icons and colors
- Clean table layout with proper spacing and typography
- Skeleton loading states for smooth UX
### Functionality
- Search models by name with instant filtering
- Filter by business groups for organized viewing
- Navigate through paginated results efficiently
- Refresh data manually when needed
## 📋 Files Modified
- `web/src/types/api.ts`: Added model monitoring type definitions
- `web/src/features/dashboard/hooks/use-model-monitoring.ts`: Core data hook
- `web/src/features/dashboard/components/model-monitoring-stats.tsx`: Stats cards
- `web/src/features/dashboard/components/model-monitoring-table.tsx`: Data table
- `web/src/features/dashboard/index.tsx`: Dashboard integration
- Various formatting and import organization improvements
This implementation provides a comprehensive solution for model monitoring
that aligns with the existing codebase architecture while delivering
powerful insights into model performance and usage patterns.
- Call `auth.fetchSelf()` inside a one-time `useEffect` in `web/src/routes/_authenticated/route.tsx`
to avoid re-render triggered loops that spam `/api/user/self`.
- Make the sign-out flow await `auth.logout()`, close the dialog, then navigate to `/sign-in`
with the current location as `redirect` in `web/src/components/sign-out-dialog.tsx`,
guaranteeing the guard and redirect work reliably.
- No changes to old Semi UI archive; no linter errors introduced.
Test plan:
- Click “Sign out”: only one `/api/user/logout` request, no repeated `/api/user/self`,
then redirected to `/sign-in?redirect=<previous_url>`.
- Refresh authenticated pages: at most one `/api/user/self` fetch occurs.
- Added useRef to manage dropdown positioning in UserArea component.
- Wrapped Dropdown in a div with a ref to ensure correct popup container.
- Minor adjustments to maintain existing functionality and styling.
Context:
Clicking a vendor tab triggered “setActivePage is not a function” from ModelsTabs.jsx:43.
Root cause:
ModelsTabs expects `setActivePage` via props (spread from `useModelsData`), but the hook did not expose it in its return object, so the prop resolved to `undefined`.
Fix:
Export `setActivePage` from `useModelsData`’s return object so `ModelsTabs` receives a valid function.
Result:
Tab switching now correctly resets pagination to page 1 and reloads models without runtime errors.
Files:
- web/src/hooks/models/useModelsData.jsx
Test plan:
- Open the Models page
- Click different vendor tabs
- Verify no crash occurs and the list reloads with page reset to 1
Refs: web/src/components/table/models/ModelsTabs.jsx:43
When syncing official models, clicking "Apply overwrite" with zero selected
conflict fields resulted in no request being sent and the modal simply closing.
This blocked creation of missing models/vendors even though the backend
supports an empty `overwrite` array and will still create missing items.
Changes:
- Remove the early-return guard in `UpstreamConflictModal.handleOk`
- Always call `onSubmit(payload)` even when `payload` is empty
- Keep closing behavior when the request succeeds
Behavior:
- Users can now proceed with upstream sync without selecting any conflict fields
- Missing models/vendors are created as expected
- Existing models are not overwritten unless fields are explicitly selected
Affected:
- web/src/components/table/models/modals/UpstreamConflictModal.jsx
Quality:
- Lint passes
- No breaking changes
- No visual/UI changes beyond the intended behavior
Test plan:
1) Open official models sync and trigger a conflicts preview
2) Click "Apply overwrite" without selecting any fields
3) Expect the sync to proceed and a success toast indicating created models
4) Re-try with some fields selected to confirm overwrites still work
Ensure UpstreamConflictModal submits { overwrite: payload, locale } instead of spreading an array into an object
Remove numeric-key fallback from applyUpstreamOverwrite for simpler and explicit logic
Effect: selected fields are now actually updated; success message shows updated model count
Refs: backend SyncUpstreamModels expects overwrite: overwriteField[]
Frontend (web)
- ModelsActions.jsx
- Replace “Sync Official” with “Sync” and open a new two-step SyncWizard.
- Pass selected locale through to preview, sync, and overwrite flows.
- Keep conflict resolution flow; inject locale into overwrite submission.
- New: models/modals/SyncWizardModal.jsx
- Two-step wizard: (1) method selection (config-sync disabled for now), (2) language selection (en/zh/ja).
- Horizontal, centered Radio cards; returns { option, locale } via onConfirm.
- UpstreamConflictModal.jsx
- Add search input (model fuzzy search) and native pagination.
- Column header checkbox now only applies to rows in the current filtered result.
- Fix “Cannot access ‘filteredDataSource’ before initialization”.
- Refactor with useMemo/useCallback; extract helpers to remove duplicated logic:
- getPresentRowsForField, getHeaderState, applyHeaderChange
- Minor code cleanups and stability improvements.
- i18n (en.json)
- Add strings for the sync wizard and related actions (Sync, Sync Wizard, Select method/source/language, etc.).
- Adjust minor translations.
Hooks
- useModelsData.jsx
- Extend previewUpstreamDiff, syncUpstream, applyUpstreamOverwrite to accept options with locale.
- Send locale via query/body accordingly.
Backend (Go)
- controller/model_sync.go
- Accept locale from query/body and resolve i18n upstream URLs.
- Add SYNC_UPSTREAM_BASE for upstream base override (default: https://basellm.github.io/llm-metadata).
- Make HTTP timeouts/retries/limits configurable:
- SYNC_HTTP_TIMEOUT_SECONDS, SYNC_HTTP_RETRY, SYNC_HTTP_MAX_MB
- Add ETag-based caching and support both envelope and pure array JSON formats.
- Concurrently fetch vendors and models; improve error responses with locale and source URLs.
- Include source meta (locale, models_url, vendors_url) in success payloads.
Notes
- No breaking changes expected.
- Lint passes for touched files.
- Set sidebar skeleton background to use theme variable (--semi-color-bg-0) instead of hardcoded white for better dark mode compatibility
- Apply consistent background to both collapsed and expanded skeleton states
- Ensure sidebar container uses theme background when skeleton is loading
- Remove duplicate margin-right classes from skeleton wrapper components that conflicted with CSS definitions
- Simplify navigation text structure by removing unnecessary div wrappers to improve text truncation
- Add proper text layout styles for better truncation handling when menu items have long names
- Standardize icon-to-text spacing across all sidebar navigation items