后端: - 新增 AntigravityQuotaRefresher 定时刷新配额 - Client 添加 FetchAvailableModels 方法获取模型配额 - 配额数据存入 account.extra.quota 字段 前端: - AccountUsageCell 支持显示 Antigravity 账户配额 - UsageProgressBar 新增 amber 颜色 - 显示 G3P/G3F/G3I/C4.5 四个配额进度条
1509 lines
58 KiB
TypeScript
1509 lines
58 KiB
TypeScript
export default {
|
|
// Home Page
|
|
home: {
|
|
viewOnGithub: 'View on GitHub',
|
|
viewDocs: 'View Documentation',
|
|
docs: 'Docs',
|
|
switchToLight: 'Switch to Light Mode',
|
|
switchToDark: 'Switch to Dark Mode',
|
|
dashboard: 'Dashboard',
|
|
login: 'Login',
|
|
getStarted: 'Get Started',
|
|
goToDashboard: 'Go to Dashboard',
|
|
tags: {
|
|
subscriptionToApi: 'Subscription to API',
|
|
stickySession: 'Sticky Session',
|
|
realtimeBilling: 'Real-time Billing'
|
|
},
|
|
features: {
|
|
unifiedGateway: 'Unified API Gateway',
|
|
unifiedGatewayDesc:
|
|
'Convert Claude subscriptions to API endpoints. Access AI capabilities through standard /v1/messages interface.',
|
|
multiAccount: 'Multi-Account Pool',
|
|
multiAccountDesc:
|
|
'Manage multiple upstream accounts with smart load balancing. Support OAuth and API Key authentication.',
|
|
balanceQuota: 'Balance & Quota',
|
|
balanceQuotaDesc:
|
|
'Token-based billing with precise usage tracking. Manage quotas and recharge with redeem codes.'
|
|
},
|
|
providers: {
|
|
title: 'Supported Providers',
|
|
description: 'Unified API interface for AI services',
|
|
supported: 'Supported',
|
|
soon: 'Soon',
|
|
claude: 'Claude',
|
|
gemini: 'Gemini',
|
|
more: 'More'
|
|
},
|
|
footer: {
|
|
allRightsReserved: 'All rights reserved.'
|
|
}
|
|
},
|
|
|
|
// Setup Wizard
|
|
setup: {
|
|
title: 'Sub2API Setup',
|
|
description: 'Configure your Sub2API instance',
|
|
database: {
|
|
title: 'Database Configuration',
|
|
host: 'Host',
|
|
port: 'Port',
|
|
username: 'Username',
|
|
password: 'Password',
|
|
databaseName: 'Database Name',
|
|
sslMode: 'SSL Mode',
|
|
passwordPlaceholder: 'Password',
|
|
ssl: {
|
|
disable: 'Disable',
|
|
require: 'Require',
|
|
verifyCa: 'Verify CA',
|
|
verifyFull: 'Verify Full'
|
|
}
|
|
},
|
|
redis: {
|
|
title: 'Redis Configuration',
|
|
host: 'Host',
|
|
port: 'Port',
|
|
password: 'Password (optional)',
|
|
database: 'Database',
|
|
passwordPlaceholder: 'Password'
|
|
},
|
|
admin: {
|
|
title: 'Admin Account',
|
|
email: 'Email',
|
|
password: 'Password',
|
|
confirmPassword: 'Confirm Password',
|
|
passwordPlaceholder: 'Min 6 characters',
|
|
confirmPasswordPlaceholder: 'Confirm password',
|
|
passwordMismatch: 'Passwords do not match'
|
|
},
|
|
ready: {
|
|
title: 'Ready to Install',
|
|
database: 'Database',
|
|
redis: 'Redis',
|
|
adminEmail: 'Admin Email'
|
|
}
|
|
},
|
|
|
|
// Common
|
|
common: {
|
|
loading: 'Loading...',
|
|
save: 'Save',
|
|
cancel: 'Cancel',
|
|
delete: 'Delete',
|
|
edit: 'Edit',
|
|
create: 'Create',
|
|
update: 'Update',
|
|
confirm: 'Confirm',
|
|
reset: 'Reset',
|
|
search: 'Search',
|
|
filter: 'Filter',
|
|
export: 'Export',
|
|
import: 'Import',
|
|
actions: 'Actions',
|
|
status: 'Status',
|
|
name: 'Name',
|
|
email: 'Email',
|
|
password: 'Password',
|
|
submit: 'Submit',
|
|
back: 'Back',
|
|
next: 'Next',
|
|
yes: 'Yes',
|
|
no: 'No',
|
|
all: 'All',
|
|
none: 'None',
|
|
noData: 'No data',
|
|
success: 'Success',
|
|
error: 'Error',
|
|
warning: 'Warning',
|
|
info: 'Info',
|
|
active: 'Active',
|
|
inactive: 'Inactive',
|
|
more: 'More',
|
|
close: 'Close',
|
|
enabled: 'Enabled',
|
|
disabled: 'Disabled',
|
|
total: 'Total',
|
|
balance: 'Balance',
|
|
available: 'Available',
|
|
copiedToClipboard: 'Copied to clipboard',
|
|
copyFailed: 'Failed to copy',
|
|
contactSupport: 'Contact Support',
|
|
selectOption: 'Select an option',
|
|
searchPlaceholder: 'Search...',
|
|
noOptionsFound: 'No options found',
|
|
saving: 'Saving...',
|
|
refresh: 'Refresh',
|
|
time: {
|
|
never: 'Never',
|
|
justNow: 'Just now',
|
|
minutesAgo: '{n}m ago',
|
|
hoursAgo: '{n}h ago',
|
|
daysAgo: '{n}d ago'
|
|
}
|
|
},
|
|
|
|
// Navigation
|
|
nav: {
|
|
dashboard: 'Dashboard',
|
|
apiKeys: 'API Keys',
|
|
usage: 'Usage',
|
|
redeem: 'Redeem',
|
|
profile: 'Profile',
|
|
users: 'Users',
|
|
groups: 'Groups',
|
|
subscriptions: 'Subscriptions',
|
|
accounts: 'Accounts',
|
|
proxies: 'Proxies',
|
|
redeemCodes: 'Redeem Codes',
|
|
settings: 'Settings',
|
|
myAccount: 'My Account',
|
|
lightMode: 'Light Mode',
|
|
darkMode: 'Dark Mode',
|
|
collapse: 'Collapse',
|
|
expand: 'Expand',
|
|
logout: 'Logout',
|
|
github: 'GitHub',
|
|
mySubscriptions: 'My Subscriptions'
|
|
},
|
|
|
|
// Auth
|
|
auth: {
|
|
welcomeBack: 'Welcome Back',
|
|
signInToAccount: 'Sign in to your account to continue',
|
|
signIn: 'Sign In',
|
|
signingIn: 'Signing in...',
|
|
createAccount: 'Create Account',
|
|
signUpToStart: 'Sign up to start using {siteName}',
|
|
signUp: 'Sign up',
|
|
processing: 'Processing...',
|
|
continue: 'Continue',
|
|
rememberMe: 'Remember me',
|
|
dontHaveAccount: "Don't have an account?",
|
|
alreadyHaveAccount: 'Already have an account?',
|
|
registrationDisabled: 'Registration is currently disabled. Please contact the administrator.',
|
|
emailLabel: 'Email',
|
|
emailPlaceholder: 'Enter your email',
|
|
passwordLabel: 'Password',
|
|
passwordPlaceholder: 'Enter your password',
|
|
createPasswordPlaceholder: 'Create a strong password',
|
|
passwordHint: 'At least 6 characters',
|
|
emailRequired: 'Email is required',
|
|
invalidEmail: 'Please enter a valid email address',
|
|
passwordRequired: 'Password is required',
|
|
passwordMinLength: 'Password must be at least 6 characters',
|
|
loginFailed: 'Login failed. Please check your credentials and try again.',
|
|
registrationFailed: 'Registration failed. Please try again.',
|
|
loginSuccess: 'Login successful! Welcome back.',
|
|
accountCreatedSuccess: 'Account created successfully! Welcome to {siteName}.',
|
|
turnstileExpired: 'Verification expired, please try again',
|
|
turnstileFailed: 'Verification failed, please try again',
|
|
completeVerification: 'Please complete the verification',
|
|
verifyYourEmail: 'Verify Your Email',
|
|
sessionExpired: 'Session expired',
|
|
sessionExpiredDesc: 'Please go back to the registration page and start again.',
|
|
verificationCode: 'Verification Code',
|
|
verificationCodeHint: 'Enter the 6-digit code sent to your email',
|
|
sendingCode: 'Sending...',
|
|
clickToResend: 'Click to resend code',
|
|
resendCode: 'Resend verification code',
|
|
oauth: {
|
|
code: 'Code',
|
|
state: 'State',
|
|
fullUrl: 'Full URL'
|
|
}
|
|
},
|
|
|
|
// Dashboard
|
|
dashboard: {
|
|
title: 'Dashboard',
|
|
welcomeMessage: "Welcome back! Here's an overview of your account.",
|
|
balance: 'Balance',
|
|
apiKeys: 'API Keys',
|
|
todayRequests: 'Today Requests',
|
|
todayCost: 'Today Cost',
|
|
todayTokens: 'Today Tokens',
|
|
totalTokens: 'Total Tokens',
|
|
cacheToday: 'Cache (Today)',
|
|
performance: 'Performance',
|
|
avgResponse: 'Avg Response',
|
|
averageTime: 'Average time',
|
|
timeRange: 'Time Range',
|
|
granularity: 'Granularity',
|
|
day: 'Day',
|
|
hour: 'Hour',
|
|
modelDistribution: 'Model Distribution',
|
|
tokenUsageTrend: 'Token Usage Trend',
|
|
noDataAvailable: 'No data available',
|
|
model: 'Model',
|
|
requests: 'Requests',
|
|
tokens: 'Tokens',
|
|
actual: 'Actual',
|
|
standard: 'Standard',
|
|
input: 'Input',
|
|
output: 'Output',
|
|
cache: 'Cache',
|
|
recentUsage: 'Recent Usage',
|
|
last7Days: 'Last 7 days',
|
|
noUsageRecords: 'No usage records',
|
|
startUsingApi: 'Start using the API to see your usage history here.',
|
|
viewAllUsage: 'View all usage',
|
|
quickActions: 'Quick Actions',
|
|
createApiKey: 'Create API Key',
|
|
generateNewKey: 'Generate a new API key',
|
|
viewUsage: 'View Usage',
|
|
checkDetailedLogs: 'Check detailed usage logs',
|
|
redeemCode: 'Redeem Code',
|
|
addBalanceWithCode: 'Add balance with a code'
|
|
},
|
|
|
|
// Groups (shared)
|
|
groups: {
|
|
subscription: 'Sub'
|
|
},
|
|
|
|
// API Keys
|
|
keys: {
|
|
title: 'API Keys',
|
|
description: 'Manage your API keys and access tokens',
|
|
createKey: 'Create API Key',
|
|
editKey: 'Edit API Key',
|
|
deleteKey: 'Delete API Key',
|
|
deleteConfirmMessage: "Are you sure you want to delete '{name}'? This action cannot be undone.",
|
|
apiKey: 'API Key',
|
|
group: 'Group',
|
|
noGroup: 'No group',
|
|
created: 'Created',
|
|
copyToClipboard: 'Copy to clipboard',
|
|
copied: 'Copied!',
|
|
importToCcSwitch: 'Import to CCS',
|
|
enable: 'Enable',
|
|
disable: 'Disable',
|
|
nameLabel: 'Name',
|
|
namePlaceholder: 'My API Key',
|
|
groupLabel: 'Group',
|
|
selectGroup: 'Select a group',
|
|
statusLabel: 'Status',
|
|
selectStatus: 'Select status',
|
|
saving: 'Saving...',
|
|
noKeysYet: 'No API keys yet',
|
|
createFirstKey: 'Create your first API key to get started with the API.',
|
|
keyCreatedSuccess: 'API key created successfully',
|
|
keyUpdatedSuccess: 'API key updated successfully',
|
|
keyDeletedSuccess: 'API key deleted successfully',
|
|
keyEnabledSuccess: 'API key enabled successfully',
|
|
keyDisabledSuccess: 'API key disabled successfully',
|
|
failedToLoad: 'Failed to load API keys',
|
|
failedToSave: 'Failed to save API key',
|
|
failedToDelete: 'Failed to delete API key',
|
|
failedToUpdateStatus: 'Failed to update API key status',
|
|
clickToChangeGroup: 'Click to change group',
|
|
groupChangedSuccess: 'Group changed successfully',
|
|
failedToChangeGroup: 'Failed to change group',
|
|
groupRequired: 'Please select a group',
|
|
usage: 'Usage',
|
|
today: 'Today',
|
|
total: 'Total',
|
|
useKey: 'Use Key',
|
|
useKeyModal: {
|
|
title: 'Use API Key',
|
|
description:
|
|
'Add the following environment variables to your terminal profile or run directly in terminal to configure API access.',
|
|
copy: 'Copy',
|
|
copied: 'Copied',
|
|
note: 'These environment variables will be active in the current terminal session. For permanent configuration, add them to ~/.bashrc, ~/.zshrc, or the appropriate configuration file.',
|
|
noGroupTitle: 'Please assign a group first',
|
|
noGroupDescription: 'This API key has not been assigned to a group. Please click the group column in the key list to assign one before viewing the configuration.',
|
|
openai: {
|
|
description: 'Add the following configuration files to your Codex CLI config directory.',
|
|
configTomlHint: 'Make sure the following content is at the beginning of the config.toml file',
|
|
note: 'Make sure the config directory exists. macOS/Linux users can run mkdir -p ~/.codex to create it.',
|
|
noteWindows: 'Press Win+R and enter %userprofile%\\.codex to open the config directory. Create it manually if it does not exist.',
|
|
},
|
|
},
|
|
customKeyLabel: 'Custom Key',
|
|
customKeyPlaceholder: 'Enter your custom key (min 16 chars)',
|
|
customKeyHint: 'Only letters, numbers, underscores and hyphens allowed. Minimum 16 characters.',
|
|
customKeyTooShort: 'Custom key must be at least 16 characters',
|
|
customKeyInvalidChars: 'Custom key can only contain letters, numbers, underscores, and hyphens',
|
|
customKeyRequired: 'Please enter a custom key'
|
|
},
|
|
|
|
// Usage
|
|
usage: {
|
|
title: 'Usage Records',
|
|
description: 'View and analyze your API usage history',
|
|
totalRequests: 'Total Requests',
|
|
totalTokens: 'Total Tokens',
|
|
totalCost: 'Total Cost',
|
|
standardCost: 'Standard',
|
|
actualCost: 'Actual',
|
|
avgDuration: 'Avg Duration',
|
|
inSelectedRange: 'in selected range',
|
|
perRequest: 'per request',
|
|
apiKeyFilter: 'API Key',
|
|
allApiKeys: 'All API Keys',
|
|
timeRange: 'Time Range',
|
|
exportCsv: 'Export CSV',
|
|
exporting: 'Exporting...',
|
|
preparingExport: 'Preparing export...',
|
|
model: 'Model',
|
|
type: 'Type',
|
|
tokens: 'Tokens',
|
|
cost: 'Cost',
|
|
firstToken: 'First Token',
|
|
duration: 'Duration',
|
|
time: 'Time',
|
|
stream: 'Stream',
|
|
sync: 'Sync',
|
|
in: 'In',
|
|
out: 'Out',
|
|
cacheRead: 'Read',
|
|
cacheWrite: 'Write',
|
|
rate: 'Rate',
|
|
original: 'Original',
|
|
billed: 'Billed',
|
|
noRecords: 'No usage records found. Try adjusting your filters.',
|
|
failedToLoad: 'Failed to load usage logs',
|
|
noDataToExport: 'No data to export',
|
|
exportSuccess: 'Usage data exported successfully',
|
|
exportFailed: 'Failed to export usage data',
|
|
billingType: 'Billing',
|
|
balance: 'Balance',
|
|
subscription: 'Subscription'
|
|
},
|
|
|
|
// Redeem
|
|
redeem: {
|
|
title: 'Redeem Code',
|
|
description: 'Enter your redeem code to add balance or increase concurrency',
|
|
currentBalance: 'Current Balance',
|
|
concurrency: 'Concurrency',
|
|
requests: 'requests',
|
|
redeemCodeLabel: 'Redeem Code',
|
|
redeemCodePlaceholder: 'Enter your redeem code',
|
|
redeemCodeHint: 'Redeem codes are case-sensitive',
|
|
redeeming: 'Redeeming...',
|
|
redeemButton: 'Redeem Code',
|
|
redeemSuccess: 'Code Redeemed Successfully!',
|
|
redeemFailed: 'Redemption Failed',
|
|
added: 'Added',
|
|
concurrentRequests: 'concurrent requests',
|
|
newBalance: 'New Balance',
|
|
newConcurrency: 'New Concurrency',
|
|
aboutCodes: 'About Redeem Codes',
|
|
codeRule1: 'Each code can only be used once',
|
|
codeRule2: 'Codes may add balance, increase concurrency, or grant trial access',
|
|
codeRule3: 'Contact support if you have issues redeeming a code',
|
|
codeRule4: 'Balance and concurrency updates are immediate',
|
|
recentActivity: 'Recent Activity',
|
|
historyWillAppear: 'Your redemption history will appear here',
|
|
balanceAddedRedeem: 'Balance Added (Redeem)',
|
|
balanceAddedAdmin: 'Balance Added (Admin)',
|
|
balanceDeductedAdmin: 'Balance Deducted (Admin)',
|
|
concurrencyAddedRedeem: 'Concurrency Added (Redeem)',
|
|
concurrencyAddedAdmin: 'Concurrency Added (Admin)',
|
|
concurrencyReducedAdmin: 'Concurrency Reduced (Admin)',
|
|
adminAdjustment: 'Admin Adjustment',
|
|
subscriptionAssigned: 'Subscription Assigned',
|
|
subscriptionAssignedDesc: 'You have been granted access to {groupName}',
|
|
subscriptionDays: '{days} days',
|
|
days: ' days',
|
|
codeRedeemSuccess: 'Code redeemed successfully!',
|
|
failedToRedeem: 'Failed to redeem code. Please check the code and try again.',
|
|
subscriptionRefreshFailed: 'Redeemed successfully, but failed to refresh subscription status.'
|
|
},
|
|
|
|
// Profile
|
|
profile: {
|
|
title: 'Profile Settings',
|
|
description: 'Manage your account information and settings',
|
|
accountBalance: 'Account Balance',
|
|
concurrencyLimit: 'Concurrency Limit',
|
|
memberSince: 'Member Since',
|
|
administrator: 'Administrator',
|
|
user: 'User',
|
|
username: 'Username',
|
|
wechat: 'WeChat ID',
|
|
enterUsername: 'Enter username',
|
|
enterWechat: 'Enter WeChat ID',
|
|
editProfile: 'Edit Profile',
|
|
updateProfile: 'Update Profile',
|
|
updating: 'Updating...',
|
|
updateSuccess: 'Profile updated successfully',
|
|
updateFailed: 'Failed to update profile',
|
|
usernameRequired: 'Username is required',
|
|
changePassword: 'Change Password',
|
|
currentPassword: 'Current Password',
|
|
newPassword: 'New Password',
|
|
confirmNewPassword: 'Confirm New Password',
|
|
passwordHint: 'Password must be at least 8 characters long',
|
|
changingPassword: 'Changing...',
|
|
changePasswordButton: 'Change Password',
|
|
passwordsNotMatch: 'New passwords do not match',
|
|
passwordTooShort: 'Password must be at least 8 characters long',
|
|
passwordChangeSuccess: 'Password changed successfully',
|
|
passwordChangeFailed: 'Failed to change password'
|
|
},
|
|
|
|
// Empty States
|
|
empty: {
|
|
noData: 'No data found'
|
|
},
|
|
|
|
// Table
|
|
table: {
|
|
expandActions: 'Expand More Actions',
|
|
collapseActions: 'Collapse Actions'
|
|
},
|
|
|
|
// Pagination
|
|
pagination: {
|
|
showing: 'Showing',
|
|
to: 'to',
|
|
of: 'of',
|
|
results: 'results',
|
|
page: 'Page',
|
|
pageOf: 'Page {page} of {total}',
|
|
previous: 'Previous',
|
|
next: 'Next',
|
|
perPage: 'Per page',
|
|
goToPage: 'Go to page {page}'
|
|
},
|
|
|
|
// Errors
|
|
errors: {
|
|
somethingWentWrong: 'Something went wrong',
|
|
pageNotFound: 'Page not found',
|
|
unauthorized: 'Unauthorized',
|
|
forbidden: 'Forbidden',
|
|
serverError: 'Server error',
|
|
networkError: 'Network error',
|
|
timeout: 'Request timeout',
|
|
tryAgain: 'Please try again'
|
|
},
|
|
|
|
// Dates
|
|
dates: {
|
|
today: 'Today',
|
|
yesterday: 'Yesterday',
|
|
thisWeek: 'This Week',
|
|
lastWeek: 'Last Week',
|
|
thisMonth: 'This Month',
|
|
lastMonth: 'Last Month',
|
|
last7Days: 'Last 7 Days',
|
|
last14Days: 'Last 14 Days',
|
|
last30Days: 'Last 30 Days',
|
|
custom: 'Custom',
|
|
startDate: 'Start Date',
|
|
endDate: 'End Date',
|
|
apply: 'Apply',
|
|
selectDateRange: 'Select date range'
|
|
},
|
|
|
|
// Admin
|
|
admin: {
|
|
// Dashboard
|
|
dashboard: {
|
|
title: 'Admin Dashboard',
|
|
description: 'System overview and real-time statistics',
|
|
apiKeys: 'API Keys',
|
|
accounts: 'Accounts',
|
|
users: 'Users',
|
|
todayRequests: 'Today Requests',
|
|
newUsersToday: 'New Users Today',
|
|
todayTokens: 'Today Tokens',
|
|
totalTokens: 'Total Tokens',
|
|
cacheToday: 'Cache (Today)',
|
|
performance: 'Performance',
|
|
avgResponse: 'Avg Response',
|
|
active: 'active',
|
|
ok: 'ok',
|
|
err: 'err',
|
|
activeUsers: 'active users',
|
|
create: 'Create',
|
|
timeRange: 'Time Range',
|
|
granularity: 'Granularity',
|
|
day: 'Day',
|
|
hour: 'Hour',
|
|
modelDistribution: 'Model Distribution',
|
|
tokenUsageTrend: 'Token Usage Trend',
|
|
userUsageTrend: 'User Usage Trend (Top 12)',
|
|
model: 'Model',
|
|
requests: 'Requests',
|
|
tokens: 'Tokens',
|
|
actual: 'Actual',
|
|
standard: 'Standard',
|
|
noDataAvailable: 'No data available',
|
|
recentUsage: 'Recent Usage',
|
|
failedToLoad: 'Failed to load dashboard statistics'
|
|
},
|
|
|
|
// Users
|
|
users: {
|
|
title: 'User Management',
|
|
description: 'Manage users and their permissions',
|
|
createUser: 'Create User',
|
|
editUser: 'Edit User',
|
|
deleteUser: 'Delete User',
|
|
searchUsers: 'Search users...',
|
|
allRoles: 'All Roles',
|
|
allStatus: 'All Status',
|
|
admin: 'Admin',
|
|
user: 'User',
|
|
disabled: 'Disabled',
|
|
email: 'Email',
|
|
password: 'Password',
|
|
username: 'Username',
|
|
wechat: 'WeChat ID',
|
|
notes: 'Notes',
|
|
enterEmail: 'Enter email',
|
|
enterPassword: 'Enter password',
|
|
enterUsername: 'Enter username (optional)',
|
|
enterWechat: 'Enter WeChat ID (optional)',
|
|
enterNotes: 'Enter notes (admin only)',
|
|
notesHint: 'This note is only visible to administrators',
|
|
enterNewPassword: 'Enter new password (optional)',
|
|
leaveEmptyToKeep: 'Leave empty to keep current password',
|
|
generatePassword: 'Generate random password',
|
|
copyPassword: 'Copy password',
|
|
creating: 'Creating...',
|
|
updating: 'Updating...',
|
|
columns: {
|
|
user: 'User',
|
|
username: 'Username',
|
|
wechat: 'WeChat ID',
|
|
notes: 'Notes',
|
|
role: 'Role',
|
|
subscriptions: 'Subscriptions',
|
|
balance: 'Balance',
|
|
usage: 'Usage',
|
|
concurrency: 'Concurrency',
|
|
status: 'Status',
|
|
created: 'Created',
|
|
actions: 'Actions'
|
|
},
|
|
today: 'Today',
|
|
total: 'Total',
|
|
noSubscription: 'No subscription',
|
|
daysRemaining: '{days}d',
|
|
expired: 'Expired',
|
|
disable: 'Disable',
|
|
enable: 'Enable',
|
|
disableUser: 'Disable User',
|
|
enableUser: 'Enable User',
|
|
viewApiKeys: 'View API Keys',
|
|
groups: 'Groups',
|
|
apiKeys: 'API Keys',
|
|
userApiKeys: 'User API Keys',
|
|
noApiKeys: 'This user has no API keys',
|
|
group: 'Group',
|
|
none: 'None',
|
|
noUsersYet: 'No users yet',
|
|
createFirstUser: 'Create your first user to get started.',
|
|
userCreated: 'User created successfully',
|
|
userUpdated: 'User updated successfully',
|
|
userDeleted: 'User deleted successfully',
|
|
userEnabled: 'User enabled successfully',
|
|
userDisabled: 'User disabled successfully',
|
|
failedToLoad: 'Failed to load users',
|
|
failedToCreate: 'Failed to create user',
|
|
failedToUpdate: 'Failed to update user',
|
|
failedToDelete: 'Failed to delete user',
|
|
failedToToggle: 'Failed to update user status',
|
|
failedToLoadApiKeys: 'Failed to load user API keys',
|
|
deleteConfirm: "Are you sure you want to delete '{email}'? This action cannot be undone.",
|
|
setAllowedGroups: 'Set Allowed Groups',
|
|
allowedGroupsHint:
|
|
'Select which standard groups this user can use. Subscription groups are managed separately.',
|
|
noStandardGroups: 'No standard groups available',
|
|
allowAllGroups: 'Allow All Groups',
|
|
allowAllGroupsHint: 'User can use any non-exclusive group',
|
|
allowedGroupsUpdated: 'Allowed groups updated successfully',
|
|
failedToLoadGroups: 'Failed to load groups',
|
|
failedToUpdateAllowedGroups: 'Failed to update allowed groups',
|
|
deposit: 'Deposit',
|
|
withdraw: 'Withdraw',
|
|
depositAmount: 'Deposit Amount',
|
|
withdrawAmount: 'Withdraw Amount',
|
|
currentBalance: 'Current Balance',
|
|
depositNotesPlaceholder:
|
|
'e.g., New user registration bonus, promotional credit, compensation, etc.',
|
|
withdrawNotesPlaceholder:
|
|
'e.g., Service issue refund, incorrect charge reversal, account closure refund, etc.',
|
|
notesOptional: 'Notes are optional but helpful for record keeping',
|
|
amountHint: 'Please enter a positive amount',
|
|
newBalance: 'New Balance',
|
|
depositing: 'Depositing...',
|
|
withdrawing: 'Withdrawing...',
|
|
confirmDeposit: 'Confirm Deposit',
|
|
confirmWithdraw: 'Confirm Withdraw',
|
|
depositSuccess: 'Deposit successful',
|
|
withdrawSuccess: 'Withdraw successful',
|
|
failedToDeposit: 'Failed to deposit',
|
|
failedToWithdraw: 'Failed to withdraw',
|
|
useDepositWithdrawButtons: 'Please use deposit/withdraw buttons to adjust balance',
|
|
insufficientBalance: 'Insufficient balance, balance cannot be negative after withdrawal'
|
|
},
|
|
|
|
// Groups
|
|
groups: {
|
|
title: 'Group Management',
|
|
description: 'Manage API key groups and rate multipliers',
|
|
createGroup: 'Create Group',
|
|
editGroup: 'Edit Group',
|
|
deleteGroup: 'Delete Group',
|
|
allPlatforms: 'All Platforms',
|
|
allStatus: 'All Status',
|
|
allGroups: 'All Groups',
|
|
exclusive: 'Exclusive',
|
|
nonExclusive: 'Non-Exclusive',
|
|
public: 'Public',
|
|
columns: {
|
|
name: 'Name',
|
|
platform: 'Platform',
|
|
rateMultiplier: 'Rate Multiplier',
|
|
type: 'Type',
|
|
accounts: 'Accounts',
|
|
status: 'Status',
|
|
actions: 'Actions',
|
|
billingType: 'Billing Type'
|
|
},
|
|
rateAndAccounts: '{rate}x rate · {count} accounts',
|
|
accountsCount: '{count} accounts',
|
|
form: {
|
|
name: 'Name',
|
|
description: 'Description',
|
|
platform: 'Platform',
|
|
rateMultiplier: 'Rate Multiplier',
|
|
status: 'Status'
|
|
},
|
|
enterGroupName: 'Enter group name',
|
|
optionalDescription: 'Optional description',
|
|
platformHint: 'Select the platform this group is associated with',
|
|
platformNotEditable: 'Platform cannot be changed after creation',
|
|
rateMultiplierHint: 'Cost multiplier for this group (e.g., 1.5 = 150% of base cost)',
|
|
exclusiveHint: 'Exclusive (requires explicit user access)',
|
|
noGroupsYet: 'No groups yet',
|
|
createFirstGroup: 'Create your first group to organize API keys.',
|
|
creating: 'Creating...',
|
|
updating: 'Updating...',
|
|
limitDay: 'd',
|
|
limitWeek: 'w',
|
|
limitMonth: 'mo',
|
|
groupCreated: 'Group created successfully',
|
|
groupUpdated: 'Group updated successfully',
|
|
groupDeleted: 'Group deleted successfully',
|
|
failedToLoad: 'Failed to load groups',
|
|
failedToCreate: 'Failed to create group',
|
|
failedToUpdate: 'Failed to update group',
|
|
failedToDelete: 'Failed to delete group',
|
|
deleteConfirm:
|
|
"Are you sure you want to delete '{name}'? All associated API keys will no longer belong to any group.",
|
|
deleteConfirmSubscription:
|
|
"Are you sure you want to delete subscription group '{name}'? This will invalidate all API keys bound to this subscription and delete all related subscription records. This action cannot be undone.",
|
|
subscription: {
|
|
title: 'Subscription Settings',
|
|
type: 'Billing Type',
|
|
typeHint:
|
|
'Standard billing deducts from user balance. Subscription mode uses quota limits instead.',
|
|
typeNotEditable: 'Billing type cannot be changed after group creation.',
|
|
standard: 'Standard (Balance)',
|
|
subscription: 'Subscription (Quota)',
|
|
dailyLimit: 'Daily Limit (USD)',
|
|
weeklyLimit: 'Weekly Limit (USD)',
|
|
monthlyLimit: 'Monthly Limit (USD)',
|
|
defaultValidityDays: 'Default Validity (Days)',
|
|
validityHint: 'Number of days the subscription is valid when assigned to a user',
|
|
noLimit: 'No limit'
|
|
}
|
|
},
|
|
|
|
// Subscriptions
|
|
subscriptions: {
|
|
title: 'Subscription Management',
|
|
description: 'Manage user subscriptions and quota limits',
|
|
assignSubscription: 'Assign Subscription',
|
|
extendSubscription: 'Extend Subscription',
|
|
revokeSubscription: 'Revoke Subscription',
|
|
allStatus: 'All Status',
|
|
allGroups: 'All Groups',
|
|
daily: 'Daily',
|
|
weekly: 'Weekly',
|
|
monthly: 'Monthly',
|
|
noLimits: 'No limits configured',
|
|
resetNow: 'Resetting soon',
|
|
windowNotActive: 'Window not active',
|
|
resetInMinutes: 'Resets in {minutes}m',
|
|
resetInHoursMinutes: 'Resets in {hours}h {minutes}m',
|
|
resetInDaysHours: 'Resets in {days}d {hours}h',
|
|
daysRemaining: 'days remaining',
|
|
noExpiration: 'No expiration',
|
|
status: {
|
|
active: 'Active',
|
|
expired: 'Expired',
|
|
revoked: 'Revoked'
|
|
},
|
|
columns: {
|
|
user: 'User',
|
|
group: 'Group',
|
|
usage: 'Usage',
|
|
expires: 'Expires',
|
|
status: 'Status',
|
|
actions: 'Actions'
|
|
},
|
|
form: {
|
|
user: 'User',
|
|
group: 'Subscription Group',
|
|
validityDays: 'Validity (Days)',
|
|
extendDays: 'Extend by (Days)'
|
|
},
|
|
selectUser: 'Select a user',
|
|
selectGroup: 'Select a subscription group',
|
|
groupHint: 'Only groups with subscription billing type are shown',
|
|
validityHint: 'Number of days the subscription will be valid',
|
|
extendingFor: 'Extending subscription for',
|
|
currentExpiration: 'Current expiration',
|
|
assign: 'Assign',
|
|
assigning: 'Assigning...',
|
|
extend: 'Extend',
|
|
extending: 'Extending...',
|
|
revoke: 'Revoke',
|
|
noSubscriptionsYet: 'No subscriptions yet',
|
|
assignFirstSubscription: 'Assign a subscription to get started.',
|
|
subscriptionAssigned: 'Subscription assigned successfully',
|
|
subscriptionExtended: 'Subscription extended successfully',
|
|
subscriptionRevoked: 'Subscription revoked successfully',
|
|
failedToLoad: 'Failed to load subscriptions',
|
|
failedToAssign: 'Failed to assign subscription',
|
|
failedToExtend: 'Failed to extend subscription',
|
|
failedToRevoke: 'Failed to revoke subscription',
|
|
revokeConfirm:
|
|
"Are you sure you want to revoke the subscription for '{user}'? This action cannot be undone."
|
|
},
|
|
|
|
// Accounts
|
|
accounts: {
|
|
title: 'Account Management',
|
|
description: 'Manage AI platform accounts and credentials',
|
|
createAccount: 'Create Account',
|
|
syncFromCrs: 'Sync from CRS',
|
|
syncFromCrsTitle: 'Sync Accounts from CRS',
|
|
syncFromCrsDesc:
|
|
'Sync accounts from claude-relay-service (CRS) into this system (CRS is called server-to-server).',
|
|
crsVersionRequirement: '⚠️ Note: CRS version must be ≥ v1.1.240 to support this feature',
|
|
crsBaseUrl: 'CRS Base URL',
|
|
crsBaseUrlPlaceholder: 'e.g. http://127.0.0.1:3000',
|
|
crsUsername: 'Username',
|
|
crsPassword: 'Password',
|
|
syncProxies: 'Also sync proxies (match by host/port/auth or create)',
|
|
syncNow: 'Sync Now',
|
|
syncing: 'Syncing...',
|
|
syncMissingFields: 'Please fill base URL, username and password',
|
|
syncResult: 'Sync Result',
|
|
syncResultSummary: 'Created {created}, updated {updated}, skipped {skipped}, failed {failed}',
|
|
syncErrors: 'Errors / Skipped Details',
|
|
syncCompleted: 'Sync completed: created {created}, updated {updated}',
|
|
syncCompletedWithErrors:
|
|
'Sync completed with errors: failed {failed} (created {created}, updated {updated})',
|
|
syncFailed: 'Sync failed',
|
|
editAccount: 'Edit Account',
|
|
deleteAccount: 'Delete Account',
|
|
searchAccounts: 'Search accounts...',
|
|
allPlatforms: 'All Platforms',
|
|
allTypes: 'All Types',
|
|
allStatus: 'All Status',
|
|
oauthType: 'OAuth',
|
|
setupToken: 'Setup Token',
|
|
apiKey: 'API Key',
|
|
// Schedulable toggle
|
|
schedulable: 'Schedulable',
|
|
schedulableHint: 'Enable to include this account in API request scheduling',
|
|
schedulableEnabled: 'Scheduling enabled',
|
|
schedulableDisabled: 'Scheduling disabled',
|
|
failedToToggleSchedulable: 'Failed to toggle scheduling status',
|
|
platforms: {
|
|
anthropic: 'Anthropic',
|
|
claude: 'Claude',
|
|
openai: 'OpenAI',
|
|
gemini: 'Gemini',
|
|
antigravity: 'Antigravity'
|
|
},
|
|
types: {
|
|
oauth: 'OAuth',
|
|
chatgptOauth: 'ChatGPT OAuth',
|
|
responsesApi: 'Responses API',
|
|
googleOauth: 'Google OAuth',
|
|
codeAssist: 'Code Assist',
|
|
antigravityOauth: 'Antigravity OAuth'
|
|
},
|
|
columns: {
|
|
name: 'Name',
|
|
platformType: 'Platform/Type',
|
|
platform: 'Platform',
|
|
type: 'Type',
|
|
concurrencyStatus: 'Concurrency',
|
|
status: 'Status',
|
|
schedulable: 'Schedule',
|
|
todayStats: "Today's Stats",
|
|
groups: 'Groups',
|
|
usageWindows: 'Usage Windows',
|
|
priority: 'Priority',
|
|
lastUsed: 'Last Used',
|
|
actions: 'Actions'
|
|
},
|
|
clearRateLimit: 'Clear Rate Limit',
|
|
testConnection: 'Test Connection',
|
|
reAuthorize: 'Re-Authorize',
|
|
refreshToken: 'Refresh Token',
|
|
noAccountsYet: 'No accounts yet',
|
|
createFirstAccount: 'Create your first account to start using AI services.',
|
|
tokenRefreshed: 'Token refreshed successfully',
|
|
accountDeleted: 'Account deleted successfully',
|
|
rateLimitCleared: 'Rate limit cleared successfully',
|
|
bulkActions: {
|
|
selected: '{count} account(s) selected',
|
|
selectCurrentPage: 'Select this page',
|
|
clear: 'Clear selection',
|
|
edit: 'Bulk Edit',
|
|
delete: 'Bulk Delete'
|
|
},
|
|
bulkEdit: {
|
|
title: 'Bulk Edit Accounts',
|
|
selectionInfo:
|
|
'{count} account(s) selected. Only checked or filled fields will be updated; others stay unchanged.',
|
|
baseUrlPlaceholder: 'https://api.anthropic.com or https://api.openai.com',
|
|
baseUrlNotice: 'Applies to API Key accounts only; leave empty to keep existing value',
|
|
submit: 'Update Accounts',
|
|
updating: 'Updating...',
|
|
success: 'Updated {count} account(s)',
|
|
partialSuccess: 'Partially updated: {success} succeeded, {failed} failed',
|
|
failed: 'Bulk update failed',
|
|
noSelection: 'Please select accounts to edit',
|
|
noFieldsSelected: 'Select at least one field to update'
|
|
},
|
|
bulkDeleteTitle: 'Bulk Delete Accounts',
|
|
bulkDeleteConfirm: 'Delete the selected {count} account(s)? This action cannot be undone.',
|
|
bulkDeleteSuccess: 'Deleted {count} account(s)',
|
|
bulkDeletePartial: 'Partially deleted: {success} succeeded, {failed} failed',
|
|
bulkDeleteFailed: 'Bulk delete failed',
|
|
resetStatus: 'Reset Status',
|
|
statusReset: 'Account status reset successfully',
|
|
failedToResetStatus: 'Failed to reset account status',
|
|
failedToLoad: 'Failed to load accounts',
|
|
failedToRefresh: 'Failed to refresh token',
|
|
failedToDelete: 'Failed to delete account',
|
|
failedToClearRateLimit: 'Failed to clear rate limit',
|
|
deleteConfirm: "Are you sure you want to delete '{name}'? This action cannot be undone.",
|
|
// Create/Edit Account Modal
|
|
platform: 'Platform',
|
|
accountName: 'Account Name',
|
|
enterAccountName: 'Enter account name',
|
|
accountType: 'Account Type',
|
|
claudeCode: 'Claude Code',
|
|
claudeConsole: 'Claude Console',
|
|
oauthSetupToken: 'OAuth / Setup Token',
|
|
addMethod: 'Add Method',
|
|
setupTokenLongLived: 'Setup Token (Long-lived)',
|
|
baseUrl: 'Base URL',
|
|
baseUrlHint: 'Leave default for official Anthropic API',
|
|
apiKeyRequired: 'API Key *',
|
|
apiKeyPlaceholder: 'sk-ant-api03-...',
|
|
apiKeyHint: 'Your Claude Console API Key',
|
|
modelRestriction: 'Model Restriction (Optional)',
|
|
modelWhitelist: 'Model Whitelist',
|
|
modelMapping: 'Model Mapping',
|
|
selectAllowedModels: 'Select allowed models. Leave empty to support all models.',
|
|
mapRequestModels:
|
|
'Map request models to actual models. Left is the requested model, right is the actual model sent to API.',
|
|
selectedModels: 'Selected {count} model(s)',
|
|
supportsAllModels: '(supports all models)',
|
|
requestModel: 'Request model',
|
|
actualModel: 'Actual model',
|
|
addMapping: 'Add Mapping',
|
|
mappingExists: 'Mapping for {model} already exists',
|
|
customErrorCodes: 'Custom Error Codes',
|
|
customErrorCodesHint: 'Only stop scheduling for selected error codes',
|
|
customErrorCodesWarning:
|
|
'Only selected error codes will stop scheduling. Other errors will return 500.',
|
|
selectedErrorCodes: 'Selected',
|
|
noneSelectedUsesDefault: 'None selected (uses default policy)',
|
|
enterErrorCode: 'Enter error code (100-599)',
|
|
invalidErrorCode: 'Please enter a valid HTTP error code (100-599)',
|
|
errorCodeExists: 'This error code is already selected',
|
|
interceptWarmupRequests: 'Intercept Warmup Requests',
|
|
interceptWarmupRequestsDesc:
|
|
'When enabled, warmup requests like title generation will return mock responses without consuming upstream tokens',
|
|
proxy: 'Proxy',
|
|
noProxy: 'No Proxy',
|
|
concurrency: 'Concurrency',
|
|
priority: 'Priority',
|
|
priorityHint: 'Higher priority accounts are used first',
|
|
higherPriorityFirst: 'Higher value means higher priority',
|
|
creating: 'Creating...',
|
|
updating: 'Updating...',
|
|
accountCreated: 'Account created successfully',
|
|
accountUpdated: 'Account updated successfully',
|
|
failedToCreate: 'Failed to create account',
|
|
failedToUpdate: 'Failed to update account',
|
|
pleaseEnterAccountName: 'Please enter account name',
|
|
pleaseEnterApiKey: 'Please enter API Key',
|
|
apiKeyIsRequired: 'API Key is required',
|
|
leaveEmptyToKeep: 'Leave empty to keep current key',
|
|
// OAuth flow
|
|
oauth: {
|
|
title: 'Claude Account Authorization',
|
|
authMethod: 'Authorization Method',
|
|
manualAuth: 'Manual Authorization',
|
|
cookieAutoAuth: 'Cookie Auto-Auth',
|
|
cookieAutoAuthDesc:
|
|
'Use claude.ai sessionKey to automatically complete OAuth authorization without manually opening browser.',
|
|
sessionKey: 'sessionKey',
|
|
keysCount: '{count} keys',
|
|
batchCreateAccounts: 'Will batch create {count} accounts',
|
|
sessionKeyPlaceholder:
|
|
'One sessionKey per line, e.g.:\nsk-ant-sid01-xxxxx...\nsk-ant-sid01-yyyyy...',
|
|
sessionKeyPlaceholderSingle: 'sk-ant-sid01-xxxxx...',
|
|
howToGetSessionKey: 'How to get sessionKey',
|
|
step1: 'Login to <strong>claude.ai</strong> in your browser',
|
|
step2: 'Press <kbd>F12</kbd> to open Developer Tools',
|
|
step3: 'Go to <strong>Application</strong> tab',
|
|
step4: 'Find <strong>Cookies</strong> → <strong>https://claude.ai</strong>',
|
|
step5: 'Find the row with key <strong>sessionKey</strong>',
|
|
step6: 'Copy the <strong>Value</strong>',
|
|
sessionKeyFormat: 'sessionKey usually starts with <code>sk-ant-sid01-</code>',
|
|
startAutoAuth: 'Start Auto-Auth',
|
|
authorizing: 'Authorizing...',
|
|
followSteps: 'Follow these steps to authorize your Claude account:',
|
|
step1GenerateUrl: 'Click the button below to generate the authorization URL',
|
|
generateAuthUrl: 'Generate Auth URL',
|
|
generating: 'Generating...',
|
|
regenerate: 'Regenerate',
|
|
step2OpenUrl: 'Open the URL in your browser and complete authorization',
|
|
openUrlDesc:
|
|
'Open the authorization URL in a new tab, log in to your Claude account and authorize.',
|
|
proxyWarning:
|
|
'<strong>Note:</strong> If you configured a proxy, make sure your browser uses the same proxy to access the authorization page.',
|
|
step3EnterCode: 'Enter the Authorization Code',
|
|
authCodeDesc:
|
|
'After authorization is complete, the page will display an <strong>Authorization Code</strong>. Copy and paste it below:',
|
|
authCode: 'Authorization Code',
|
|
authCodePlaceholder: 'Paste the Authorization Code from Claude page...',
|
|
authCodeHint: 'Paste the Authorization Code copied from the Claude page',
|
|
completeAuth: 'Complete Authorization',
|
|
verifying: 'Verifying...',
|
|
pleaseEnterSessionKey: 'Please enter at least one valid sessionKey',
|
|
authFailed: 'Authorization failed',
|
|
cookieAuthFailed: 'Cookie authorization failed',
|
|
keyAuthFailed: 'Key {index}: {error}',
|
|
successCreated: 'Successfully created {count} account(s)',
|
|
// OpenAI specific
|
|
openai: {
|
|
title: 'OpenAI Account Authorization',
|
|
followSteps: 'Follow these steps to complete OpenAI account authorization:',
|
|
step1GenerateUrl: 'Click the button below to generate the authorization URL',
|
|
generateAuthUrl: 'Generate Auth URL',
|
|
step2OpenUrl: 'Open the URL in your browser and complete authorization',
|
|
openUrlDesc:
|
|
'Open the authorization URL in a new tab, log in to your OpenAI account and authorize.',
|
|
importantNotice:
|
|
'<strong>Important:</strong> The page may take a while to load after authorization. Please wait patiently. When the browser address bar changes to <code>http://localhost...</code>, the authorization is complete.',
|
|
step3EnterCode: 'Enter Authorization URL or Code',
|
|
authCodeDesc:
|
|
'After authorization is complete, when the page URL becomes <code>http://localhost:xxx/auth/callback?code=...</code>:',
|
|
authCode: 'Authorization URL or Code',
|
|
authCodePlaceholder:
|
|
'Option 1: Copy the complete URL\n(http://localhost:xxx/auth/callback?code=...)\nOption 2: Copy only the code parameter value',
|
|
authCodeHint:
|
|
'You can copy the entire URL or just the code parameter value, the system will auto-detect'
|
|
},
|
|
// Gemini specific
|
|
gemini: {
|
|
title: 'Gemini Account Authorization',
|
|
followSteps: 'Follow these steps to authorize your Gemini account:',
|
|
step1GenerateUrl: 'Generate the authorization URL',
|
|
generateAuthUrl: 'Generate Auth URL',
|
|
projectIdLabel: 'Project ID (optional)',
|
|
projectIdPlaceholder: 'e.g. my-gcp-project or cloud-ai-companion-xxxxx',
|
|
projectIdHint:
|
|
'Leave empty to auto-detect after code exchange. If auto-detection fails, fill it in and re-generate the auth URL to try again.',
|
|
howToGetProjectId: 'How to get',
|
|
step2OpenUrl: 'Open the URL in your browser and complete authorization',
|
|
openUrlDesc:
|
|
'Open the authorization URL in a new tab, log in to your Google account and authorize.',
|
|
step3EnterCode: 'Enter Authorization URL or Code',
|
|
authCodeDesc:
|
|
'After authorization, copy the callback URL (recommended) or just the <code>code</code> and paste it below.',
|
|
authCode: 'Callback URL or Code',
|
|
authCodePlaceholder:
|
|
'Option 1 (recommended): Paste the callback URL\nOption 2: Paste only the code value',
|
|
authCodeHint: 'The system will auto-extract code/state from the URL.',
|
|
redirectUri: 'Redirect URI',
|
|
redirectUriHint:
|
|
'This must be configured in your Google OAuth client and must match exactly.',
|
|
confirmRedirectUri:
|
|
'I have configured this Redirect URI in the Google OAuth client (must match exactly)',
|
|
invalidRedirectUri: 'Redirect URI must be a valid http(s) URL',
|
|
redirectUriNotConfirmed: 'Please confirm the Redirect URI is configured correctly',
|
|
missingRedirectUri: 'Missing redirect URI',
|
|
failedToGenerateUrl: 'Failed to generate Gemini auth URL',
|
|
missingExchangeParams: 'Missing auth code, session ID, or state',
|
|
failedToExchangeCode: 'Failed to exchange Gemini auth code',
|
|
modelPassthrough: 'Gemini Model Passthrough',
|
|
modelPassthroughDesc:
|
|
'All model requests are forwarded directly to the Gemini API without model restrictions or mappings.',
|
|
stateWarningTitle: 'Note',
|
|
stateWarningDesc: 'Recommended: paste the full callback URL (includes code & state).',
|
|
oauthTypeLabel: 'OAuth Type',
|
|
needsProjectId: 'For GCP Developers',
|
|
needsProjectIdDesc: 'Requires GCP project',
|
|
noProjectIdNeeded: 'For Regular Users',
|
|
noProjectIdNeededDesc: 'Requires admin-configured OAuth client',
|
|
aiStudioNotConfiguredShort: 'Not configured',
|
|
aiStudioNotConfiguredTip:
|
|
'AI Studio OAuth is not configured: set GEMINI_OAUTH_CLIENT_ID / GEMINI_OAUTH_CLIENT_SECRET and add Redirect URI: http://localhost:1455/auth/callback (Consent screen scopes must include https://www.googleapis.com/auth/generative-language.retriever)',
|
|
aiStudioNotConfigured:
|
|
'AI Studio OAuth is not configured: set GEMINI_OAUTH_CLIENT_ID / GEMINI_OAUTH_CLIENT_SECRET and add Redirect URI: http://localhost:1455/auth/callback'
|
|
},
|
|
// Antigravity specific
|
|
antigravity: {
|
|
title: 'Antigravity Account Authorization',
|
|
followSteps: 'Follow these steps to authorize your Antigravity account:',
|
|
step1GenerateUrl: 'Generate the authorization URL',
|
|
generateAuthUrl: 'Generate Auth URL',
|
|
step2OpenUrl: 'Open the URL in your browser and complete authorization',
|
|
openUrlDesc: 'Open the authorization URL in a new tab, log in to your Google account and authorize.',
|
|
importantNotice:
|
|
'<strong>Important:</strong> The page may take a while to load after authorization. Please wait patiently. When the browser address bar shows <code>http://localhost...</code>, authorization is complete.',
|
|
step3EnterCode: 'Enter Authorization URL or Code',
|
|
authCodeDesc:
|
|
'After authorization, when the page URL becomes <code>http://localhost:xxx/auth/callback?code=...</code>:',
|
|
authCode: 'Authorization URL or Code',
|
|
authCodePlaceholder:
|
|
'Option 1: Copy the complete URL\n(http://localhost:xxx/auth/callback?code=...)\nOption 2: Copy only the code parameter value',
|
|
authCodeHint: 'You can copy the entire URL or just the code parameter value, the system will auto-detect',
|
|
failedToGenerateUrl: 'Failed to generate Antigravity auth URL',
|
|
missingExchangeParams: 'Missing code, session ID, or state',
|
|
failedToExchangeCode: 'Failed to exchange Antigravity auth code'
|
|
}
|
|
},
|
|
// Gemini specific (platform-wide)
|
|
gemini: {
|
|
modelPassthrough: 'Gemini Model Passthrough',
|
|
modelPassthroughDesc:
|
|
'All model requests are forwarded directly to the Gemini API without model restrictions or mappings.',
|
|
apiKeyHint: 'Your Gemini API Key (starts with AIza)'
|
|
},
|
|
// Re-Auth Modal
|
|
reAuthorizeAccount: 'Re-Authorize Account',
|
|
claudeCodeAccount: 'Claude Code Account',
|
|
openaiAccount: 'OpenAI Account',
|
|
geminiAccount: 'Gemini Account',
|
|
antigravityAccount: 'Antigravity Account',
|
|
inputMethod: 'Input Method',
|
|
reAuthorizedSuccess: 'Account re-authorized successfully',
|
|
// Test Modal
|
|
testAccountConnection: 'Test Account Connection',
|
|
account: 'Account',
|
|
readyToTest: 'Ready to test. Click "Start Test" to begin...',
|
|
connectingToApi: 'Connecting to API...',
|
|
testCompleted: 'Test completed successfully!',
|
|
testFailed: 'Test failed',
|
|
connectedToApi: 'Connected to API',
|
|
usingModel: 'Using model: {model}',
|
|
sendingTestMessage: 'Sending test message: "hi"',
|
|
response: 'Response:',
|
|
startTest: 'Start Test',
|
|
testing: 'Testing...',
|
|
retry: 'Retry',
|
|
copyOutput: 'Copy output',
|
|
startingTestForAccount: 'Starting test for account: {name}',
|
|
testAccountTypeLabel: 'Account type: {type}',
|
|
selectTestModel: 'Select Test Model',
|
|
testModel: 'Test model',
|
|
testPrompt: 'Prompt: "hi"',
|
|
// Stats Modal
|
|
viewStats: 'View Stats',
|
|
usageStatistics: 'Usage Statistics',
|
|
last30DaysUsage: 'Last 30 days usage statistics (based on actual usage days)',
|
|
stats: {
|
|
totalCost: '30-Day Total Cost',
|
|
accumulatedCost: 'Accumulated cost',
|
|
standardCost: 'Standard',
|
|
totalRequests: '30-Day Total Requests',
|
|
totalCalls: 'Total API calls',
|
|
avgDailyCost: 'Daily Avg Cost',
|
|
basedOnActualDays: 'Based on {days} actual usage days',
|
|
avgDailyRequests: 'Daily Avg Requests',
|
|
avgDailyUsage: 'Average daily usage',
|
|
todayOverview: 'Today Overview',
|
|
cost: 'Cost',
|
|
requests: 'Requests',
|
|
tokens: 'Tokens',
|
|
highestCostDay: 'Highest Cost Day',
|
|
highestRequestDay: 'Highest Request Day',
|
|
date: 'Date',
|
|
accumulatedTokens: 'Accumulated Tokens',
|
|
totalTokens: '30-Day Total',
|
|
dailyAvgTokens: 'Daily Average',
|
|
performance: 'Performance',
|
|
avgResponseTime: 'Avg Response',
|
|
daysActive: 'Days Active',
|
|
recentActivity: 'Recent Activity',
|
|
todayRequests: 'Today Requests',
|
|
todayTokens: 'Today Tokens',
|
|
todayCost: 'Today Cost',
|
|
usageTrend: '30-Day Cost & Request Trend',
|
|
noData: 'No usage data available for this account'
|
|
},
|
|
usageWindow: {
|
|
statsTitle: '5-Hour Window Usage Statistics',
|
|
gemini3Pro: 'G3P',
|
|
gemini3Flash: 'G3F',
|
|
gemini3Image: 'G3I',
|
|
claude45: 'C4.5'
|
|
}
|
|
},
|
|
|
|
// Proxies
|
|
proxies: {
|
|
title: 'Proxy Management',
|
|
description: 'Manage proxy servers for accounts',
|
|
createProxy: 'Create Proxy',
|
|
editProxy: 'Edit Proxy',
|
|
deleteProxy: 'Delete Proxy',
|
|
searchProxies: 'Search proxies...',
|
|
allProtocols: 'All Protocols',
|
|
allStatus: 'All Status',
|
|
columns: {
|
|
name: 'Name',
|
|
protocol: 'Protocol',
|
|
address: 'Address',
|
|
status: 'Status',
|
|
actions: 'Actions'
|
|
},
|
|
testConnection: 'Test Connection',
|
|
batchTest: 'Test All Proxies',
|
|
testFailed: 'Failed',
|
|
name: 'Name',
|
|
protocol: 'Protocol',
|
|
host: 'Host',
|
|
port: 'Port',
|
|
username: 'Username (Optional)',
|
|
password: 'Password (Optional)',
|
|
status: 'Status',
|
|
enterProxyName: 'Enter proxy name',
|
|
leaveEmptyToKeep: 'Leave empty to keep current',
|
|
optionalAuth: 'Optional authentication',
|
|
form: {
|
|
hostPlaceholder: 'proxy.example.com',
|
|
portPlaceholder: '8080'
|
|
},
|
|
noProxiesYet: 'No proxies yet',
|
|
createFirstProxy: 'Create your first proxy to route traffic through it.',
|
|
// Batch import
|
|
standardAdd: 'Standard Add',
|
|
batchAdd: 'Quick Add',
|
|
batchInput: 'Proxy List',
|
|
batchInputPlaceholder:
|
|
"Enter one proxy per line in the following formats:\nsocks5://user:pass@192.168.1.1:1080\nhttp://192.168.1.1:8080\nhttps://user:pass@proxy.example.com:443",
|
|
batchInputHint:
|
|
"Supports http, https, socks5 protocols. Format: protocol://[user:pass@]host:port",
|
|
parsedCount: '{count} valid',
|
|
invalidCount: '{count} invalid',
|
|
duplicateCount: '{count} duplicate',
|
|
importing: 'Importing...',
|
|
importProxies: 'Import {count} proxies',
|
|
batchImportSuccess: 'Successfully imported {created} proxies, skipped {skipped} duplicates',
|
|
batchImportAllSkipped: 'All {skipped} proxies already exist, skipped import',
|
|
failedToImport: 'Failed to batch import',
|
|
// Other messages
|
|
creating: 'Creating...',
|
|
updating: 'Updating...',
|
|
proxyCreated: 'Proxy created successfully',
|
|
proxyUpdated: 'Proxy updated successfully',
|
|
proxyDeleted: 'Proxy deleted successfully',
|
|
proxyWorking: 'Proxy is working!',
|
|
proxyWorkingWithLatency: 'Proxy is working! Latency: {latency}ms',
|
|
proxyTestFailed: 'Proxy test failed',
|
|
failedToLoad: 'Failed to load proxies',
|
|
failedToCreate: 'Failed to create proxy',
|
|
failedToUpdate: 'Failed to update proxy',
|
|
failedToDelete: 'Failed to delete proxy',
|
|
failedToTest: 'Failed to test proxy',
|
|
deleteConfirm:
|
|
"Are you sure you want to delete '{name}'? Accounts using this proxy will have their proxy removed."
|
|
},
|
|
|
|
// Redeem Codes
|
|
redeem: {
|
|
title: 'Redeem Code Management',
|
|
description: 'Generate and manage redeem codes',
|
|
generateCodes: 'Generate Codes',
|
|
searchCodes: 'Search codes...',
|
|
allTypes: 'All Types',
|
|
allStatus: 'All Status',
|
|
balance: 'Balance',
|
|
concurrency: 'Concurrency',
|
|
subscription: 'Subscription',
|
|
unused: 'Unused',
|
|
used: 'Used',
|
|
columns: {
|
|
code: 'Code',
|
|
type: 'Type',
|
|
value: 'Value',
|
|
status: 'Status',
|
|
usedBy: 'Used By',
|
|
usedAt: 'Used At',
|
|
actions: 'Actions'
|
|
},
|
|
userPrefix: 'User #{id}',
|
|
exportCsv: 'Export CSV',
|
|
deleteAllUnused: 'Delete All Unused Codes',
|
|
deleteCode: 'Delete Redeem Code',
|
|
deleteCodeConfirm:
|
|
'Are you sure you want to delete this redeem code? This action cannot be undone.',
|
|
deleteAllUnusedConfirm:
|
|
'Are you sure you want to delete all unused (active) redeem codes? This action cannot be undone.',
|
|
deleteAll: 'Delete All',
|
|
generateCodesTitle: 'Generate Redeem Codes',
|
|
generatedSuccessfully: 'Generated Successfully',
|
|
codesCreated: '{count} redeem code(s) created',
|
|
codeType: 'Code Type',
|
|
amount: 'Amount ($)',
|
|
value: 'Value',
|
|
count: 'Count',
|
|
generating: 'Generating...',
|
|
generate: 'Generate',
|
|
copyAll: 'Copy All',
|
|
copied: 'Copied!',
|
|
download: 'Download',
|
|
codesExported: 'Codes exported successfully',
|
|
codeDeleted: 'Redeem code deleted successfully',
|
|
codesDeleted: 'Successfully deleted {count} unused code(s)',
|
|
noUnusedCodes: 'No unused codes to delete',
|
|
failedToLoad: 'Failed to load redeem codes',
|
|
failedToGenerate: 'Failed to generate codes',
|
|
failedToExport: 'Failed to export codes',
|
|
failedToDelete: 'Failed to delete code',
|
|
failedToDeleteUnused: 'Failed to delete unused codes',
|
|
failedToCopy: 'Failed to copy codes',
|
|
selectGroup: 'Select Group',
|
|
selectGroupPlaceholder: 'Choose a subscription group',
|
|
validityDays: 'Validity Days',
|
|
groupRequired: 'Please select a subscription group',
|
|
days: ' days'
|
|
},
|
|
|
|
// Usage Records
|
|
usage: {
|
|
title: 'Usage Records',
|
|
description: 'View and manage all user usage records',
|
|
userFilter: 'User',
|
|
searchUserPlaceholder: 'Search user by email...',
|
|
selectedUser: 'Selected',
|
|
user: 'User',
|
|
account: 'Account',
|
|
group: 'Group',
|
|
requestId: 'Request ID',
|
|
allModels: 'All Models',
|
|
allAccounts: 'All Accounts',
|
|
allGroups: 'All Groups',
|
|
allTypes: 'All Types',
|
|
allBillingTypes: 'All Billing',
|
|
inputCost: 'Input Cost',
|
|
outputCost: 'Output Cost',
|
|
cacheCreationCost: 'Cache Creation Cost',
|
|
cacheReadCost: 'Cache Read Cost',
|
|
failedToLoad: 'Failed to load usage records'
|
|
},
|
|
|
|
// Settings
|
|
settings: {
|
|
title: 'System Settings',
|
|
description: 'Manage registration, email verification, default values, and SMTP settings',
|
|
registration: {
|
|
title: 'Registration Settings',
|
|
description: 'Control user registration and verification',
|
|
enableRegistration: 'Enable Registration',
|
|
enableRegistrationHint: 'Allow new users to register',
|
|
emailVerification: 'Email Verification',
|
|
emailVerificationHint: 'Require email verification for new registrations'
|
|
},
|
|
turnstile: {
|
|
title: 'Cloudflare Turnstile',
|
|
description: 'Bot protection for login and registration',
|
|
enableTurnstile: 'Enable Turnstile',
|
|
enableTurnstileHint: 'Require Cloudflare Turnstile verification',
|
|
siteKey: 'Site Key',
|
|
secretKey: 'Secret Key',
|
|
siteKeyHint: 'Get this from your Cloudflare Dashboard',
|
|
secretKeyHint: 'Server-side verification key (keep this secret)'
|
|
},
|
|
defaults: {
|
|
title: 'Default User Settings',
|
|
description: 'Default values for new users',
|
|
defaultBalance: 'Default Balance',
|
|
defaultBalanceHint: 'Initial balance for new users',
|
|
defaultConcurrency: 'Default Concurrency',
|
|
defaultConcurrencyHint: 'Maximum concurrent requests for new users'
|
|
},
|
|
site: {
|
|
title: 'Site Settings',
|
|
description: 'Customize site branding',
|
|
siteName: 'Site Name',
|
|
siteNamePlaceholder: 'Sub2API',
|
|
siteNameHint: 'Displayed in emails and page titles',
|
|
siteSubtitle: 'Site Subtitle',
|
|
siteSubtitlePlaceholder: 'Subscription to API Conversion Platform',
|
|
siteSubtitleHint: 'Displayed on login and register pages',
|
|
apiBaseUrl: 'API Base URL',
|
|
apiBaseUrlPlaceholder: 'https://api.example.com',
|
|
apiBaseUrlHint:
|
|
'Used for "Use Key" and "Import to CC Switch" features. Leave empty to use current site URL.',
|
|
contactInfo: 'Contact Info',
|
|
contactInfoPlaceholder: 'e.g., QQ: 123456789',
|
|
contactInfoHint: 'Customer support contact info, displayed on redeem page, profile, etc.',
|
|
docUrl: 'Documentation URL',
|
|
docUrlPlaceholder: 'https://docs.example.com',
|
|
docUrlHint: 'Link to your documentation site. Leave empty to hide the documentation link.',
|
|
siteLogo: 'Site Logo',
|
|
uploadImage: 'Upload Image',
|
|
remove: 'Remove',
|
|
logoHint: 'PNG, JPG, or SVG. Max 300KB. Recommended: 80x80px square image.',
|
|
logoSizeError: 'Image size exceeds 300KB limit ({size}KB)',
|
|
logoTypeError: 'Please select an image file',
|
|
logoReadError: 'Failed to read the image file'
|
|
},
|
|
smtp: {
|
|
title: 'SMTP Settings',
|
|
description: 'Configure email sending for verification codes',
|
|
testConnection: 'Test Connection',
|
|
testing: 'Testing...',
|
|
host: 'SMTP Host',
|
|
hostPlaceholder: 'smtp.gmail.com',
|
|
port: 'SMTP Port',
|
|
portPlaceholder: '587',
|
|
username: 'SMTP Username',
|
|
usernamePlaceholder: "your-email{'@'}gmail.com",
|
|
password: 'SMTP Password',
|
|
passwordPlaceholder: '********',
|
|
passwordHint: 'Leave empty to keep existing password',
|
|
fromEmail: 'From Email',
|
|
fromEmailPlaceholder: "noreply{'@'}example.com",
|
|
fromName: 'From Name',
|
|
fromNamePlaceholder: 'Sub2API',
|
|
useTls: 'Use TLS',
|
|
useTlsHint: 'Enable TLS encryption for SMTP connection'
|
|
},
|
|
testEmail: {
|
|
title: 'Send Test Email',
|
|
description: 'Send a test email to verify your SMTP configuration',
|
|
recipientEmail: 'Recipient Email',
|
|
recipientEmailPlaceholder: "test{'@'}example.com",
|
|
sendTestEmail: 'Send Test Email',
|
|
sending: 'Sending...',
|
|
enterRecipientHint: 'Please enter a recipient email address'
|
|
},
|
|
adminApiKey: {
|
|
title: 'Admin API Key',
|
|
description: 'Global API key for external system integration with full admin access',
|
|
notConfigured: 'Admin API key not configured',
|
|
configured: 'Admin API key is active',
|
|
currentKey: 'Current Key',
|
|
regenerate: 'Regenerate',
|
|
regenerating: 'Regenerating...',
|
|
delete: 'Delete',
|
|
deleting: 'Deleting...',
|
|
create: 'Create Key',
|
|
creating: 'Creating...',
|
|
regenerateConfirm: 'Are you sure? The current key will be immediately invalidated.',
|
|
deleteConfirm:
|
|
'Are you sure you want to delete the admin API key? External integrations will stop working.',
|
|
keyGenerated: 'New admin API key generated',
|
|
keyDeleted: 'Admin API key deleted',
|
|
copyKey: 'Copy Key',
|
|
keyCopied: 'Key copied to clipboard',
|
|
keyWarning: 'This key will only be shown once. Please copy it now.',
|
|
securityWarning: 'Warning: This key provides full admin access. Keep it secure.',
|
|
usage: 'Usage: Add to request header - x-api-key: <your-admin-api-key>'
|
|
},
|
|
saveSettings: 'Save Settings',
|
|
saving: 'Saving...',
|
|
settingsSaved: 'Settings saved successfully',
|
|
smtpConnectionSuccess: 'SMTP connection successful',
|
|
testEmailSent: 'Test email sent successfully',
|
|
failedToLoad: 'Failed to load settings',
|
|
failedToSave: 'Failed to save settings',
|
|
failedToTestSmtp: 'SMTP connection test failed',
|
|
failedToSendTestEmail: 'Failed to send test email'
|
|
}
|
|
},
|
|
|
|
// Subscription Progress (Header component)
|
|
subscriptionProgress: {
|
|
title: 'My Subscriptions',
|
|
viewDetails: 'View subscription details',
|
|
activeCount: '{count} active subscription(s)',
|
|
daily: 'Daily',
|
|
weekly: 'Weekly',
|
|
monthly: 'Monthly',
|
|
daysRemaining: '{days} days left',
|
|
expired: 'Expired',
|
|
expiresToday: 'Expires today',
|
|
expiresTomorrow: 'Expires tomorrow',
|
|
viewAll: 'View all subscriptions',
|
|
noSubscriptions: 'No active subscriptions'
|
|
},
|
|
|
|
// Version Badge
|
|
version: {
|
|
currentVersion: 'Current Version',
|
|
latestVersion: 'Latest Version',
|
|
upToDate: "You're running the latest version.",
|
|
updateAvailable: 'A new version is available!',
|
|
releaseNotes: 'Release Notes',
|
|
noReleaseNotes: 'No release notes',
|
|
viewUpdate: 'View Update',
|
|
viewRelease: 'View Release',
|
|
viewChangelog: 'View Changelog',
|
|
refresh: 'Refresh',
|
|
sourceMode: 'Source Build',
|
|
sourceModeHint: 'Source build, use git pull to update',
|
|
updateNow: 'Update Now',
|
|
updating: 'Updating...',
|
|
updateComplete: 'Update Complete',
|
|
updateFailed: 'Update Failed',
|
|
restartRequired: 'Please restart the service to apply the update',
|
|
restartNow: 'Restart Now',
|
|
restarting: 'Restarting...',
|
|
retry: 'Retry'
|
|
},
|
|
|
|
// User Subscriptions Page
|
|
userSubscriptions: {
|
|
title: 'My Subscriptions',
|
|
description: 'View your subscription plans and usage',
|
|
noActiveSubscriptions: 'No Active Subscriptions',
|
|
noActiveSubscriptionsDesc:
|
|
"You don't have any active subscriptions. Contact administrator to get one.",
|
|
status: {
|
|
active: 'Active',
|
|
expired: 'Expired',
|
|
revoked: 'Revoked'
|
|
},
|
|
usage: 'Usage',
|
|
expires: 'Expires',
|
|
noExpiration: 'No expiration',
|
|
unlimited: 'Unlimited',
|
|
daily: 'Daily',
|
|
weekly: 'Weekly',
|
|
monthly: 'Monthly',
|
|
daysRemaining: '{days} days remaining',
|
|
expiresOn: 'Expires on {date}',
|
|
resetIn: 'Resets in {time}',
|
|
windowNotActive: 'Awaiting first use',
|
|
usageOf: '{used} of {limit}'
|
|
}
|
|
}
|