From 14707efbc360c21e37e4c6ee7102148cca510826 Mon Sep 17 00:00:00 2001 From: thuanpham582002 Date: Tue, 24 Mar 2026 23:35:15 +0700 Subject: [PATCH 1/2] fix: replace `[key: string]: any` with specific types in SelectOption Replace the loose `any` index signature with explicit union type `string | number | boolean | null | undefined` and add optional `disabled` property to align with the Select.vue component interface. --- frontend/src/types/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 2656a28d62..3ba2ca1980 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -7,7 +7,8 @@ export interface SelectOption { value: string | number | boolean | null label: string - [key: string]: any // Support extra properties for custom templates + disabled?: boolean + [key: string]: string | number | boolean | null | undefined } export interface BasePaginationResponse { From 719907eac13da51e478d3a4170ba58d0e85fc1ba Mon Sep 17 00:00:00 2001 From: thuanpham582002 Date: Tue, 24 Mar 2026 23:52:27 +0700 Subject: [PATCH 2/2] Add 182 missing i18n English translation keys Add English translations for all keys present in zh.ts but missing in en.ts, covering admin dashboard, users, groups, accounts, proxies, redeem codes, and ops monitoring sections. --- frontend/src/i18n/locales/en.ts | 206 +++++++++++++++++++++++++++++++- 1 file changed, 202 insertions(+), 4 deletions(-) diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts index ad916a6571..d39d68ef54 100644 --- a/frontend/src/i18n/locales/en.ts +++ b/frontend/src/i18n/locales/en.ts @@ -994,6 +994,29 @@ export default { spendShort: 'Spend', requestsShort: 'Req', tokensShort: 'Tok', + totalApiKeys: 'Total API Keys', + activeApiKeys: 'Active API Keys', + totalUsers: 'Total Users', + totalAccounts: 'Total Accounts', + activeAccounts: 'Active Accounts', + totalRequests: 'Total Requests', + todayCost: "Today's Cost", + totalCost: 'Total Cost', + input: 'Input', + output: 'Output', + averageTime: 'Average Time', + cache: 'Cache', + last7Days: 'Last 7 Days', + noUsageRecords: 'No Usage Records', + startUsingApi: 'Usage history will appear here once you start using the API.', + viewAllUsage: 'View All', + quickActions: 'Quick Actions', + manageUsers: 'Manage Users', + viewUserAccounts: 'View and manage user accounts', + manageAccounts: 'Manage Accounts', + configureAiAccounts: 'Configure AI platform accounts', + systemSettings: 'System Settings', + configureSystem: 'Configure system settings', failedToLoad: 'Failed to load dashboard statistics' }, @@ -1300,6 +1323,11 @@ export default { allGroups: 'All Groups', searchGroups: 'Search groups...', fuzzySearch: 'Fuzzy search', + deleteConfirmMessage: "Are you sure you want to delete user '{email}'? This action cannot be undone.", + searchPlaceholder: 'Search by email/username/notes/API Key...', + roleFilter: 'Filter by Role', + statusFilter: 'Filter by Status', + allStatuses: 'All Statuses', admin: 'Admin', user: 'User', disabled: 'Disabled', @@ -1333,6 +1361,23 @@ export default { created: 'Created', actions: 'Actions' }, + form: { + emailLabel: 'Email', + emailPlaceholder: 'Enter email', + usernameLabel: 'Username', + usernamePlaceholder: 'Enter username (optional)', + notesLabel: 'Notes', + notesPlaceholder: 'Enter notes (admin only)', + notesHint: 'These notes are only visible to admins', + passwordLabel: 'Password', + passwordPlaceholder: 'Enter password (leave empty to keep unchanged)', + roleLabel: 'Role', + selectRole: 'Select role', + balanceLabel: 'Balance', + concurrencyLabel: 'Concurrency', + statusLabel: 'Status', + selectStatus: 'Select status' + }, today: 'Today', total: 'Last 30d', noSubscription: 'No subscription', @@ -1368,6 +1413,21 @@ export default { failedToDelete: 'Failed to delete user', failedToToggle: 'Failed to update user status', failedToLoadApiKeys: 'Failed to load user API keys', + adjustBalance: 'Adjust Balance', + adjustConcurrency: 'Adjust Concurrency', + adjustmentAmount: 'Adjustment Amount', + adjustmentAmountHint: 'Positive to increase, negative to decrease', + currentConcurrency: 'Current Concurrency', + saving: 'Saving...', + noUsers: 'No Users', + noUsersDescription: 'Create your first user to get started.', + userCreatedSuccess: 'User created successfully', + userUpdatedSuccess: 'User updated successfully', + userDeletedSuccess: 'User deleted successfully', + balanceAdjustedSuccess: 'Balance adjusted successfully', + concurrencyAdjustedSuccess: 'Concurrency adjusted successfully', + failedToSave: 'Failed to save user', + failedToAdjust: 'Failed to adjust', emailRequired: 'Please enter email', concurrencyMin: 'Concurrency must be at least 1', soraStorageQuota: 'Sora Storage Quota', @@ -1536,6 +1596,9 @@ export default { status: 'Status', actions: 'Actions', billingType: 'Billing Type', + exclusive: 'Exclusive', + priority: 'Priority', + apiKeys: 'API Keys', userName: 'Username', userEmail: 'Email', userNotes: 'Notes', @@ -1555,7 +1618,22 @@ export default { platform: 'Platform', rateMultiplier: 'Rate Multiplier', status: 'Status', - exclusive: 'Exclusive Group' + exclusive: 'Exclusive Group', + nameLabel: 'Group Name', + namePlaceholder: 'Enter group name', + descriptionLabel: 'Description', + descriptionPlaceholder: 'Enter description (optional)', + rateMultiplierLabel: 'Rate Multiplier', + rateMultiplierHint: '1.0 = standard rate, 0.5 = half price, 2.0 = double', + exclusiveLabel: 'Exclusive Group', + exclusiveHint: 'Exclusive group, can be manually assigned to users', + platformLabel: 'Platform Restriction', + platformPlaceholder: 'Select platform (leave empty for no restriction)', + accountsLabel: 'Assigned Accounts', + accountsPlaceholder: 'Select accounts (leave empty for no restriction)', + priorityLabel: 'Priority', + priorityHint: 'Lower value = higher priority, used for account scheduling', + statusLabel: 'Status' }, enterGroupName: 'Enter group name', optionalDescription: 'Optional description', @@ -1569,6 +1647,18 @@ export default { example: 'Use case:', exampleContent: 'Public group rate is 0.8. Create an exclusive group with 0.7 rate, manually assign VIP users to give them better pricing.' }, + exclusiveObj: { + yes: 'Yes', + no: 'No' + }, + saving: 'Saving...', + noGroups: 'No Groups', + noGroupsDescription: 'Create groups to better manage API keys and rates.', + groupCreatedSuccess: 'Group created successfully', + groupUpdatedSuccess: 'Group updated successfully', + groupDeletedSuccess: 'Group deleted successfully', + failedToSave: 'Failed to save group', + exclusiveFilter: 'Exclusive', noGroupsYet: 'No groups yet', createFirstGroup: 'Create your first group to organize API keys.', creating: 'Creating...', @@ -1898,6 +1988,9 @@ export default { crsBack: 'Back', editAccount: 'Edit Account', deleteAccount: 'Delete Account', + deleteConfirmMessage: "Are you sure you want to delete account '{name}'?", + refreshCookie: 'Refresh Cookie', + testAccount: 'Test Account', searchAccounts: 'Search accounts...', notes: 'Notes', notesPlaceholder: 'Enter notes', @@ -1917,6 +2010,29 @@ export default { schedulableDisabled: 'Scheduling disabled', failedToToggleSchedulable: 'Failed to toggle scheduling status', groupCountTotal: '{count} groups total', + form: { + nameLabel: 'Account Name', + namePlaceholder: 'Enter account name', + platformLabel: 'Platform', + selectPlatform: 'Select platform', + typeLabel: 'Type', + selectType: 'Select type', + credentialsLabel: 'Credentials', + credentialsPlaceholder: 'Enter Cookie or API Key', + priorityLabel: 'Priority', + priorityHint: 'Lower value = higher priority', + weightLabel: 'Weight', + weightHint: 'Weight value for load balancing', + statusLabel: 'Status' + }, + filters: { + platform: 'Platform', + allPlatforms: 'All Platforms', + type: 'Type', + allTypes: 'All Types', + status: 'Status', + allStatuses: 'All Statuses' + }, platforms: { anthropic: 'Anthropic', claude: 'Claude', @@ -1938,7 +2054,9 @@ export default { soraBaseUrlRequired: 'Sora API Key account requires a Base URL', soraBaseUrlInvalidScheme: 'Base URL must start with http:// or https://', upstream: 'Upstream', - upstreamDesc: 'Connect via Base URL + API Key' + upstreamDesc: 'Connect via Base URL + API Key', + api_key: 'API Key', + cookie: 'Cookie' }, status: { active: 'Active', @@ -2090,6 +2208,16 @@ export default { testConnection: 'Test Connection', reAuthorize: 'Re-Authorize', refreshToken: 'Refresh Token', + saving: 'Saving...', + refreshing: 'Refreshing...', + noAccounts: 'No Accounts', + noAccountsDescription: 'Add AI platform accounts to start using the API gateway.', + accountCreatedSuccess: 'Account created successfully', + accountUpdatedSuccess: 'Account updated successfully', + accountDeletedSuccess: 'Account deleted successfully', + cookieRefreshedSuccess: 'Cookie refreshed successfully', + testSuccess: 'Account test passed', + failedToSave: 'Failed to save account', noAccountsYet: 'No accounts yet', createFirstAccount: 'Create your first account to start using AI services.', tokenRefreshed: 'Token refreshed successfully', @@ -2862,6 +2990,8 @@ export default { createProxy: 'Create Proxy', editProxy: 'Edit Proxy', deleteProxy: 'Delete Proxy', + deleteConfirmMessage: "Are you sure you want to delete proxy '{name}'?", + testProxy: 'Test Proxy', dataImport: 'Import', dataExportSelected: 'Export Selected', dataImportTitle: 'Import Proxies', @@ -2903,7 +3033,27 @@ export default { status: 'Status', accounts: 'Accounts', latency: 'Latency', - actions: 'Actions' + actions: 'Actions', + nameLabel: 'Name', + namePlaceholder: 'Enter proxy name', + protocolLabel: 'Protocol', + selectProtocol: 'Select protocol', + hostLabel: 'Host', + hostPlaceholder: 'Enter host address', + portLabel: 'Port', + portPlaceholder: 'Enter port', + usernameLabel: 'Username (optional)', + usernamePlaceholder: 'Enter username', + passwordLabel: 'Password (optional)', + passwordPlaceholder: 'Enter password', + priorityLabel: 'Priority', + statusLabel: 'Status' + }, + filters: { + protocol: 'Protocol', + allProtocols: 'All Protocols', + status: 'Status', + allStatuses: 'All Statuses' }, testConnection: 'Test Connection', qualityCheck: 'Quality Check', @@ -2941,6 +3091,15 @@ export default { hostPlaceholder: 'proxy.example.com', portPlaceholder: '8080' }, + saving: 'Saving...', + testing: 'Testing...', + noProxies: 'No Proxies', + noProxiesDescription: 'Add proxy servers to improve API access stability.', + proxyCreatedSuccess: 'Proxy created successfully', + proxyUpdatedSuccess: 'Proxy updated successfully', + proxyDeletedSuccess: 'Proxy deleted successfully', + testSuccess: 'Proxy test passed', + failedToSave: 'Failed to save proxy', noProxiesYet: 'No proxies yet', createFirstProxy: 'Create your first proxy to route traffic through it.', // Batch import @@ -3025,6 +3184,7 @@ export default { status: 'Status', usedBy: 'Used By', usedAt: 'Used At', + createdAt: 'Created At', actions: 'Actions' }, userPrefix: 'User #{id}', @@ -3067,11 +3227,43 @@ export default { admin_balance: 'Balance (Admin)', admin_concurrency: 'Concurrency (Admin)' }, + form: { + typeLabel: 'Type', + selectType: 'Select type', + valueLabel: 'Value', + valuePlaceholder: 'Enter value', + balanceHint: 'Balance amount (USD)', + concurrencyHint: 'Concurrency increment', + countLabel: 'Count', + countPlaceholder: 'Enter count', + countHint: 'Number of redemption codes to generate', + prefixLabel: 'Prefix (optional)', + prefixPlaceholder: 'e.g., GIFT', + expiresLabel: 'Expiration Date (optional)' + }, + filters: { + type: 'Type', + allTypes: 'All Types', + status: 'Status', + allStatuses: 'All Statuses', + search: 'Search redemption codes' + }, selectGroup: 'Select Group', selectGroupPlaceholder: 'Choose a subscription group', validityDays: 'Validity Days', groupRequired: 'Please select a subscription group', days: ' days', + copyCode: 'Copy', + disableCode: 'Disable', + enableCode: 'Enable', + deleteConfirmMessage: 'Are you sure you want to delete this redemption code?', + noCodes: 'No Redemption Codes', + noCodesDescription: 'Generate redemption codes to distribute balance or concurrency to users.', + codesGeneratedSuccess: '{count} redemption codes generated successfully', + codeDisabledSuccess: 'Redemption code disabled', + codeEnabledSuccess: 'Redemption code enabled', + codeDeletedSuccess: 'Redemption code deleted successfully', + failedToUpdate: 'Failed to update redemption code', status: { unused: 'Unused', used: 'Used', @@ -3308,6 +3500,7 @@ export default { lastRun: 'last_run:', lastSuccess: 'last_success:', lastError: 'last_error:', + result: 'Result', noData: 'No data.', loadingText: 'loading', ready: 'ready', @@ -3382,7 +3575,8 @@ export default { '6h': 'Last 6 hours', '24h': 'Last 24 hours', '7d': 'Last 7 days', - '30d': 'Last 30 days' + '30d': 'Last 30 days', + custom: 'Custom' }, openaiTokenStats: { title: 'OpenAI Token Request Stats', @@ -3404,6 +3598,10 @@ export default { requestsWithFirstToken: 'Requests With First Token' } }, + customTimeRange: { + startTime: 'Start Time', + endTime: 'End Time' + }, fullscreen: { enter: 'Enter Fullscreen' },