mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
feat: 基础本地化支持与通用键补充(useConfirm/useChartConfig/format/apiStats 回退 + common.time/errors 等 i18n 键)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Chart } from 'chart.js/auto'
|
||||
import i18n from '@/i18n'
|
||||
|
||||
export function useChartConfig() {
|
||||
// 设置Chart.js默认配置
|
||||
@@ -51,7 +52,9 @@ export function useChartConfig() {
|
||||
label += ': '
|
||||
}
|
||||
if (context.parsed.y !== null) {
|
||||
label += new Intl.NumberFormat('zh-CN').format(context.parsed.y)
|
||||
const localeMap = { 'zh-cn': 'zh-CN', 'zh-tw': 'zh-TW', en: 'en-US' }
|
||||
const currentLocale = localeMap[i18n.global.locale.value] || 'en-US'
|
||||
label += new Intl.NumberFormat(currentLocale).format(context.parsed.y)
|
||||
}
|
||||
return label
|
||||
}
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
import { ref } from 'vue'
|
||||
import i18n from '@/i18n'
|
||||
|
||||
const showConfirmModal = ref(false)
|
||||
const confirmOptions = ref({
|
||||
title: '',
|
||||
message: '',
|
||||
confirmText: '继续',
|
||||
cancelText: '取消'
|
||||
confirmText: i18n.global.t('common.confirmModal.continue'),
|
||||
cancelText: i18n.global.t('common.confirmModal.cancel')
|
||||
})
|
||||
const confirmResolve = ref(null)
|
||||
|
||||
export function useConfirm() {
|
||||
const showConfirm = (title, message, confirmText = '继续', cancelText = '取消') => {
|
||||
const showConfirm = (
|
||||
title,
|
||||
message,
|
||||
confirmText = i18n.global.t('common.confirmModal.continue'),
|
||||
cancelText = i18n.global.t('common.confirmModal.cancel')
|
||||
) => {
|
||||
return new Promise((resolve) => {
|
||||
confirmOptions.value = {
|
||||
title,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// API Stats 专用 API 客户端
|
||||
// 与管理员 API 隔离,不需要认证
|
||||
|
||||
import i18n from '@/i18n'
|
||||
|
||||
class ApiStatsClient {
|
||||
constructor() {
|
||||
this.baseURL = window.location.origin
|
||||
@@ -26,7 +28,9 @@ class ApiStatsClient {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.message || `请求失败: ${response.status}`)
|
||||
throw new Error(
|
||||
data.message || i18n.global.t('common.errors.requestFailed', { status: response.status })
|
||||
)
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
@@ -1,4 +1,47 @@
|
||||
export default {
|
||||
layout: {
|
||||
mainLayout: {
|
||||
comments: {
|
||||
topNavigation: 'Top Navigation',
|
||||
mainContentArea: 'Main Content Area',
|
||||
tabBar: 'Tab Bar',
|
||||
contentArea: 'Content Area'
|
||||
},
|
||||
routing: {
|
||||
routeChangeError: 'Route change failed:',
|
||||
routeNotFound: 'Route not found',
|
||||
defaultToTab: 'Default to dashboard'
|
||||
}
|
||||
},
|
||||
tabBar: {
|
||||
tabs: {
|
||||
dashboard: {
|
||||
name: 'Dashboard',
|
||||
shortName: 'Dashboard'
|
||||
},
|
||||
apiKeys: {
|
||||
name: 'API Keys',
|
||||
shortName: 'API'
|
||||
},
|
||||
accounts: {
|
||||
name: 'Account Management',
|
||||
shortName: 'Accounts'
|
||||
},
|
||||
userManagement: {
|
||||
name: 'User Management',
|
||||
shortName: 'Users'
|
||||
},
|
||||
tutorial: {
|
||||
name: 'Tutorial',
|
||||
shortName: 'Tutorial'
|
||||
},
|
||||
settings: {
|
||||
name: 'System Settings',
|
||||
shortName: 'Settings'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
common: {
|
||||
save: 'Save',
|
||||
cancel: 'Cancel',
|
||||
@@ -10,7 +53,89 @@ export default {
|
||||
update: 'Update',
|
||||
search: 'Search',
|
||||
reset: 'Reset',
|
||||
locale: 'en'
|
||||
locale: 'en',
|
||||
toastNotification: {
|
||||
defaultTitles: {
|
||||
success: 'Success',
|
||||
error: 'Error',
|
||||
warning: 'Warning',
|
||||
info: 'Information'
|
||||
}
|
||||
},
|
||||
confirmDialog: {
|
||||
confirm: 'Confirm',
|
||||
cancel: 'Cancel'
|
||||
},
|
||||
confirmModal: {
|
||||
continue: 'Continue',
|
||||
cancel: 'Cancel'
|
||||
},
|
||||
themeToggle: {
|
||||
light: {
|
||||
label: 'Light Mode',
|
||||
shortLabel: 'Light'
|
||||
},
|
||||
dark: {
|
||||
label: 'Dark Mode',
|
||||
shortLabel: 'Dark'
|
||||
},
|
||||
auto: {
|
||||
label: 'Follow System',
|
||||
shortLabel: 'Auto'
|
||||
},
|
||||
toggleTheme: 'Toggle Theme',
|
||||
clickToSwitch: 'Click to switch theme'
|
||||
},
|
||||
logoTitle: {
|
||||
logoAlt: 'Logo'
|
||||
},
|
||||
languageSwitch: {
|
||||
zhCnName: 'Simplified Chinese',
|
||||
zhTwName: 'Traditional Chinese',
|
||||
enName: 'English',
|
||||
zhCnFlag: 'CN',
|
||||
zhTwFlag: 'TW',
|
||||
enFlag: 'EN'
|
||||
},
|
||||
accountSelector: {
|
||||
searchPlaceholder: 'Search account name...',
|
||||
schedulingGroups: 'Scheduling Groups',
|
||||
membersUnit: ' members',
|
||||
claudeOAuthAccounts: 'Claude OAuth Dedicated Accounts',
|
||||
oauthAccounts: 'OAuth Dedicated Accounts',
|
||||
claudeConsoleAccounts: 'Claude Console Dedicated Accounts',
|
||||
noResultsFound: 'No matching accounts found',
|
||||
selectAccount: 'Please select an account',
|
||||
useSharedPool: 'Use shared account pool',
|
||||
accountStatus: {
|
||||
unknown: 'Unknown',
|
||||
unauthorized: 'Unauthorized',
|
||||
tokenError: 'Token Error',
|
||||
pending: 'Pending',
|
||||
rateLimited: 'Rate Limited',
|
||||
error: 'Error',
|
||||
active: 'Active'
|
||||
},
|
||||
dateFormat: {
|
||||
today: 'Created today',
|
||||
yesterday: 'Created yesterday',
|
||||
daysAgo: ' days ago'
|
||||
}
|
||||
},
|
||||
customDropdown: {
|
||||
placeholder: 'Please select'
|
||||
},
|
||||
// Common time and errors
|
||||
time: {
|
||||
justNow: 'Just now',
|
||||
minutesAgo: '{minutes} minutes ago',
|
||||
hoursAgo: '{hours} hours ago',
|
||||
daysAgo: '{days} days ago'
|
||||
},
|
||||
errors: {
|
||||
requestFailed: 'Request failed: {status}',
|
||||
loadSupportedClientsFailed: 'Failed to load supported clients'
|
||||
}
|
||||
},
|
||||
language: {
|
||||
zh: '简体中文',
|
||||
@@ -210,7 +335,15 @@ export default {
|
||||
securityNoticeMulti:
|
||||
'Your API Keys are only used to query statistical data and will not be stored. Some individual information will not be displayed in aggregate mode.',
|
||||
multiKeyTip:
|
||||
'Tip: Supports querying up to 30 API Keys simultaneously. Use Ctrl+Enter for quick query.'
|
||||
'Tip: Supports querying up to 30 API Keys simultaneously. Use Ctrl+Enter for quick query.',
|
||||
errors: {
|
||||
queryStatsFailed: 'Failed to query statistics, please check your API Key',
|
||||
enterAtLeastOneKey: 'Please enter at least one valid API Key',
|
||||
batchQueryFailed: 'Batch query failed',
|
||||
batchModelStatsFailed: 'Failed to load batch model statistics',
|
||||
loadModelStatsFailed: 'Failed to load model statistics',
|
||||
allInvalidKeys: 'All API Keys are invalid'
|
||||
}
|
||||
},
|
||||
|
||||
// Login page
|
||||
@@ -221,7 +354,9 @@ export default {
|
||||
password: 'Password',
|
||||
passwordPlaceholder: 'Please enter password',
|
||||
loginButton: 'Login',
|
||||
loggingIn: 'Logging in...'
|
||||
loggingIn: 'Logging in...',
|
||||
loginFailed: 'Login failed',
|
||||
loginFailedCheck: 'Login failed, please check username and password'
|
||||
},
|
||||
|
||||
// Dashboard page
|
||||
@@ -262,6 +397,12 @@ export default {
|
||||
tokensPerMinute: 'Tokens per Minute',
|
||||
historicalData: 'Historical Data',
|
||||
minutes: 'minutes',
|
||||
// Uptime display formats
|
||||
uptimeFormat: {
|
||||
daysHours: '{days} days {hours} hours',
|
||||
hoursMinutes: '{hours} hours {minutes} minutes',
|
||||
minutes: '{minutes} minutes'
|
||||
},
|
||||
|
||||
// Charts section
|
||||
modelDistributionAndTrend: 'Model Usage Distribution & Token Usage Trends',
|
||||
@@ -269,6 +410,7 @@ export default {
|
||||
// Date filter presets
|
||||
today: 'Today',
|
||||
yesterday: 'Yesterday',
|
||||
dayBefore: 'Day before yesterday',
|
||||
last7Days: 'Last 7 Days',
|
||||
last30Days: 'Last 30 Days',
|
||||
thisWeek: 'This Week',
|
||||
@@ -322,7 +464,53 @@ export default {
|
||||
time: 'Time',
|
||||
date: 'Date',
|
||||
tokenQuantity: 'Token Quantity',
|
||||
requestsQuantity: 'Requests Count'
|
||||
requestsQuantity: 'Requests Count',
|
||||
|
||||
// Usage Trend component
|
||||
usageTrend: {
|
||||
title: 'Usage Trend',
|
||||
granularity: {
|
||||
byDay: 'By Day',
|
||||
byHour: 'By Hour'
|
||||
},
|
||||
periodOptions: {
|
||||
last24Hours: '24 Hours',
|
||||
last7Days: '7 Days',
|
||||
last30Days: '30 Days',
|
||||
recentDays: 'Last {days} Days'
|
||||
},
|
||||
chartLabels: {
|
||||
requests: 'Request Count',
|
||||
tokens: 'Token Usage',
|
||||
requestsAxis: 'Request Count',
|
||||
tokensAxis: 'Token Usage'
|
||||
}
|
||||
},
|
||||
|
||||
// Model Distribution component
|
||||
modelDistribution: {
|
||||
title: 'Model Usage Distribution',
|
||||
periods: {
|
||||
daily: 'Today',
|
||||
total: 'Total'
|
||||
},
|
||||
noData: 'No model usage data available',
|
||||
units: {
|
||||
requests: 'requests',
|
||||
tokens: 'tokens'
|
||||
},
|
||||
chart: {
|
||||
tooltip: {
|
||||
requests: 'Requests',
|
||||
tokens: 'Tokens'
|
||||
}
|
||||
}
|
||||
},
|
||||
errors: {
|
||||
rangeTooLongHour: 'For hourly granularity, date range cannot exceed 24 hours',
|
||||
rangeTooLongDay: 'Date range cannot exceed 31 days',
|
||||
rangeTooLongHourSwitched: 'Hourly range cannot exceed 24 hours, switched to last 24 hours'
|
||||
}
|
||||
},
|
||||
|
||||
// Accounts page
|
||||
@@ -1316,6 +1504,52 @@ export default {
|
||||
loadStatsFailed: 'Failed to load API keys stats'
|
||||
},
|
||||
|
||||
// User API Keys Manager
|
||||
userApiKeysManager: {
|
||||
title: 'My API Keys',
|
||||
description: 'Manage your API keys to access Claude Relay services',
|
||||
loading: 'Loading API keys...',
|
||||
warnings: {
|
||||
maxKeysReached:
|
||||
'You have reached the maximum number of API keys ({maxApiKeys}). Please delete an existing key to create a new one.'
|
||||
},
|
||||
status: {
|
||||
deleted: 'Deleted',
|
||||
noDescription: 'No description',
|
||||
neverUsed: 'Never used'
|
||||
},
|
||||
dateLabels: {
|
||||
created: 'Created',
|
||||
deleted: 'Deleted',
|
||||
lastUsed: 'Last used',
|
||||
expires: 'Expires'
|
||||
},
|
||||
usage: {
|
||||
requests: 'requests'
|
||||
},
|
||||
actions: {
|
||||
viewApiKey: 'View API Key',
|
||||
deleteApiKey: 'Delete API Key'
|
||||
},
|
||||
buttons: {
|
||||
createApiKey: 'Create API Key',
|
||||
delete: 'Delete'
|
||||
},
|
||||
emptyState: {
|
||||
title: 'No API keys',
|
||||
description: 'Get started by creating your first API key.'
|
||||
},
|
||||
confirmDelete: {
|
||||
title: 'Delete API Key',
|
||||
message: "Are you sure you want to delete '{name}'? This action cannot be undone."
|
||||
},
|
||||
messages: {
|
||||
loadFailed: 'Failed to load API keys',
|
||||
deleteSuccess: 'API key deleted successfully',
|
||||
deleteFailed: 'Failed to delete API key'
|
||||
}
|
||||
},
|
||||
|
||||
// User Login
|
||||
login: {
|
||||
title: 'User Sign In',
|
||||
@@ -1331,7 +1565,50 @@ export default {
|
||||
// Validation and error messages
|
||||
requiredFields: 'Please enter both username and password',
|
||||
loginSuccess: 'Login successful!',
|
||||
loginFailed: 'Login failed'
|
||||
loginFailed: 'Login failed',
|
||||
accountDisabled: 'Your account has been disabled'
|
||||
},
|
||||
|
||||
// View API Key Modal
|
||||
viewApiKeyModal: {
|
||||
title: 'API Key Details',
|
||||
fields: {
|
||||
name: 'Name',
|
||||
description: 'Description',
|
||||
apiKey: 'API Key',
|
||||
status: 'Status',
|
||||
usageStatistics: 'Usage Statistics'
|
||||
},
|
||||
apiKeyDisplay: {
|
||||
notAvailable: 'Not available',
|
||||
keyPreview: 'cr_****',
|
||||
fullKeyNotice: 'Full API key is only shown when first created or regenerated'
|
||||
},
|
||||
buttons: {
|
||||
hide: 'Hide',
|
||||
show: 'Show',
|
||||
copy: 'Copy',
|
||||
close: 'Close'
|
||||
},
|
||||
status: {
|
||||
active: 'Active',
|
||||
disabled: 'Disabled'
|
||||
},
|
||||
usageStats: {
|
||||
requests: 'Requests',
|
||||
inputTokens: 'Input Tokens',
|
||||
outputTokens: 'Output Tokens',
|
||||
totalCost: 'Total Cost'
|
||||
},
|
||||
timestamps: {
|
||||
created: 'Created',
|
||||
lastUsed: 'Last Used',
|
||||
expires: 'Expires'
|
||||
},
|
||||
messages: {
|
||||
copySuccess: 'Copied to clipboard!',
|
||||
copyFailed: 'Failed to copy to clipboard'
|
||||
}
|
||||
},
|
||||
|
||||
// User Management
|
||||
@@ -1501,6 +1778,124 @@ export default {
|
||||
|
||||
// Success message
|
||||
roleUpdated: 'User role updated to {role}'
|
||||
},
|
||||
|
||||
// User Usage Statistics
|
||||
userUsageStats: {
|
||||
// Page header
|
||||
title: 'Usage Statistics',
|
||||
subtitle: 'View your API usage statistics and costs',
|
||||
|
||||
// Time period selection
|
||||
periodSelection: {
|
||||
day: 'Last 24 Hours',
|
||||
week: 'Last 7 Days',
|
||||
month: 'Last 30 Days',
|
||||
quarter: 'Last 90 Days'
|
||||
},
|
||||
|
||||
// Loading state
|
||||
loadingStats: 'Loading usage statistics...',
|
||||
|
||||
// Statistics cards
|
||||
statsCards: {
|
||||
totalRequests: 'Total Requests',
|
||||
inputTokens: 'Input Tokens',
|
||||
outputTokens: 'Output Tokens',
|
||||
totalCost: 'Total Cost'
|
||||
},
|
||||
|
||||
// Daily usage trend chart
|
||||
usageTrend: {
|
||||
title: 'Daily Usage Trend',
|
||||
chartTitle: 'Usage Chart',
|
||||
dailyTrendsDescription: 'Daily usage trends would be displayed here',
|
||||
chartIntegrationNote:
|
||||
'(Chart integration can be added with Chart.js, D3.js, or similar library)'
|
||||
},
|
||||
|
||||
// Usage by model section
|
||||
modelUsage: {
|
||||
title: 'Usage by Model',
|
||||
requests: 'requests',
|
||||
requestsCount: '{count} requests'
|
||||
},
|
||||
|
||||
// Usage by API key table
|
||||
apiKeyUsage: {
|
||||
title: 'Usage by API Key',
|
||||
headers: {
|
||||
apiKey: 'API Key',
|
||||
requests: 'Requests',
|
||||
inputTokens: 'Input Tokens',
|
||||
outputTokens: 'Output Tokens',
|
||||
cost: 'Cost',
|
||||
status: 'Status'
|
||||
},
|
||||
status: {
|
||||
active: 'Active',
|
||||
disabled: 'Disabled',
|
||||
deleted: 'Deleted'
|
||||
}
|
||||
},
|
||||
|
||||
// No data state
|
||||
noData: {
|
||||
title: 'No usage data',
|
||||
description:
|
||||
"You haven't made any API requests yet. Create an API key and start using the service to see usage statistics."
|
||||
},
|
||||
|
||||
// Error messages
|
||||
loadFailed: 'Failed to load usage statistics'
|
||||
},
|
||||
|
||||
// Create API Key Modal
|
||||
createApiKeyModal: {
|
||||
title: 'Create New API Key',
|
||||
|
||||
// Form labels and placeholders
|
||||
form: {
|
||||
nameLabel: 'Name',
|
||||
nameRequired: '*',
|
||||
namePlaceholder: 'Enter API key name',
|
||||
descriptionLabel: 'Description',
|
||||
descriptionPlaceholder: 'Optional description'
|
||||
},
|
||||
|
||||
// Button text
|
||||
buttons: {
|
||||
cancel: 'Cancel',
|
||||
creating: 'Creating...',
|
||||
createApiKey: 'Create API Key',
|
||||
copy: 'Copy',
|
||||
done: 'Done'
|
||||
},
|
||||
|
||||
// Success state
|
||||
success: {
|
||||
title: 'API Key Created Successfully!',
|
||||
warning: {
|
||||
important: 'Important:',
|
||||
message: "Copy your API key now. You won't be able to see it again!"
|
||||
}
|
||||
},
|
||||
|
||||
// Error and validation messages
|
||||
validation: {
|
||||
nameRequired: 'API key name is required'
|
||||
},
|
||||
|
||||
errors: {
|
||||
createFailed: 'Failed to create API key'
|
||||
},
|
||||
|
||||
// Toast messages
|
||||
messages: {
|
||||
createSuccess: 'API key created successfully!',
|
||||
copySuccess: 'API key copied to clipboard!',
|
||||
copyFailed: 'Failed to copy to clipboard'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1527,6 +1922,10 @@ export default {
|
||||
removeIcon: 'Remove',
|
||||
iconFormats: 'Supports .ico, .png, .jpg, .svg formats, max 350KB',
|
||||
iconPreview: 'Icon preview',
|
||||
validation: {
|
||||
iconTooLarge: 'Icon file size must not exceed 350KB',
|
||||
iconTypeNotSupported: 'Unsupported file type, please choose .ico, .png, .jpg or .svg'
|
||||
},
|
||||
|
||||
adminEntry: 'Admin Entry',
|
||||
adminEntryDescription: 'Login button display',
|
||||
|
||||
@@ -1,4 +1,47 @@
|
||||
export default {
|
||||
layout: {
|
||||
mainLayout: {
|
||||
comments: {
|
||||
topNavigation: '顶部导航',
|
||||
mainContentArea: '主内容区域',
|
||||
tabBar: '标签栏',
|
||||
contentArea: '内容区域'
|
||||
},
|
||||
routing: {
|
||||
routeChangeError: '路由切换失败:',
|
||||
routeNotFound: '路由未找到',
|
||||
defaultToTab: '默认选中仪表板'
|
||||
}
|
||||
},
|
||||
tabBar: {
|
||||
tabs: {
|
||||
dashboard: {
|
||||
name: '仪表板',
|
||||
shortName: '仪表板'
|
||||
},
|
||||
apiKeys: {
|
||||
name: 'API Keys',
|
||||
shortName: 'API'
|
||||
},
|
||||
accounts: {
|
||||
name: '账户管理',
|
||||
shortName: '账户'
|
||||
},
|
||||
userManagement: {
|
||||
name: '用户管理',
|
||||
shortName: '用户'
|
||||
},
|
||||
tutorial: {
|
||||
name: '使用教程',
|
||||
shortName: '教程'
|
||||
},
|
||||
settings: {
|
||||
name: '系统设置',
|
||||
shortName: '设置'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
common: {
|
||||
save: '保存',
|
||||
cancel: '取消',
|
||||
@@ -10,7 +53,89 @@ export default {
|
||||
update: '更新',
|
||||
search: '搜索',
|
||||
reset: '重置',
|
||||
locale: 'zh-CN'
|
||||
locale: 'zh-CN',
|
||||
toastNotification: {
|
||||
defaultTitles: {
|
||||
success: '成功',
|
||||
error: '错误',
|
||||
warning: '警告',
|
||||
info: '信息'
|
||||
}
|
||||
},
|
||||
confirmDialog: {
|
||||
confirm: '确认',
|
||||
cancel: '取消'
|
||||
},
|
||||
confirmModal: {
|
||||
continue: '继续',
|
||||
cancel: '取消'
|
||||
},
|
||||
themeToggle: {
|
||||
light: {
|
||||
label: '浅色模式',
|
||||
shortLabel: '浅色'
|
||||
},
|
||||
dark: {
|
||||
label: '深色模式',
|
||||
shortLabel: '深色'
|
||||
},
|
||||
auto: {
|
||||
label: '跟随系统',
|
||||
shortLabel: '自动'
|
||||
},
|
||||
toggleTheme: '切换主题',
|
||||
clickToSwitch: '点击切换主题'
|
||||
},
|
||||
logoTitle: {
|
||||
logoAlt: '标志'
|
||||
},
|
||||
languageSwitch: {
|
||||
zhCnName: '简体中文',
|
||||
zhTwName: '繁体中文',
|
||||
enName: '英语',
|
||||
zhCnFlag: '简',
|
||||
zhTwFlag: '繁',
|
||||
enFlag: 'EN'
|
||||
},
|
||||
accountSelector: {
|
||||
searchPlaceholder: '搜索账号名称...',
|
||||
schedulingGroups: '调度分组',
|
||||
membersUnit: '个成员',
|
||||
claudeOAuthAccounts: 'Claude OAuth 专属账号',
|
||||
oauthAccounts: 'OAuth 专属账号',
|
||||
claudeConsoleAccounts: 'Claude Console 专属账号',
|
||||
noResultsFound: '没有找到匹配的账号',
|
||||
selectAccount: '请选择账号',
|
||||
useSharedPool: '使用共享账号池',
|
||||
accountStatus: {
|
||||
unknown: '未知',
|
||||
unauthorized: '未授权',
|
||||
tokenError: 'Token错误',
|
||||
pending: '待验证',
|
||||
rateLimited: '限流中',
|
||||
error: '异常',
|
||||
active: '正常'
|
||||
},
|
||||
dateFormat: {
|
||||
today: '今天创建',
|
||||
yesterday: '昨天创建',
|
||||
daysAgo: '天前'
|
||||
}
|
||||
},
|
||||
customDropdown: {
|
||||
placeholder: '请选择'
|
||||
},
|
||||
// 通用时间与错误
|
||||
time: {
|
||||
justNow: '刚刚',
|
||||
minutesAgo: '{minutes}分钟前',
|
||||
hoursAgo: '{hours}小时前',
|
||||
daysAgo: '{days}天前'
|
||||
},
|
||||
errors: {
|
||||
requestFailed: '请求失败: {status}',
|
||||
loadSupportedClientsFailed: '加载支持的客户端失败'
|
||||
}
|
||||
},
|
||||
language: {
|
||||
zh: '简体中文',
|
||||
@@ -19,6 +144,38 @@ export default {
|
||||
current: '当前语言',
|
||||
switch: '切换语言'
|
||||
},
|
||||
|
||||
layout: {
|
||||
tabBar: {
|
||||
tabs: {
|
||||
dashboard: {
|
||||
name: '仪表板',
|
||||
shortName: '仪表板'
|
||||
},
|
||||
apiKeys: {
|
||||
name: 'API Keys',
|
||||
shortName: 'API'
|
||||
},
|
||||
accounts: {
|
||||
name: '账户管理',
|
||||
shortName: '账户'
|
||||
},
|
||||
userManagement: {
|
||||
name: '用户管理',
|
||||
shortName: '用户'
|
||||
},
|
||||
tutorial: {
|
||||
name: '使用教程',
|
||||
shortName: '教程'
|
||||
},
|
||||
settings: {
|
||||
name: '系统设置',
|
||||
shortName: '设置'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
header: {
|
||||
adminPanel: '管理后台',
|
||||
userMenu: '用户菜单',
|
||||
@@ -204,7 +361,15 @@ export default {
|
||||
securityNoticeSingle: '您的 API Key 仅用于查询自己的统计数据,不会被存储或用于其他用途',
|
||||
securityNoticeMulti:
|
||||
'您的 API Keys 仅用于查询统计数据,不会被存储。聚合模式下部分个体化信息将不显示。',
|
||||
multiKeyTip: '提示:最多支持同时查询 30 个 API Keys。使用 Ctrl+Enter 快速查询。'
|
||||
multiKeyTip: '提示:最多支持同时查询 30 个 API Keys。使用 Ctrl+Enter 快速查询。',
|
||||
errors: {
|
||||
queryStatsFailed: '查询统计数据失败,请检查您的 API Key 是否正确',
|
||||
enterAtLeastOneKey: '请输入至少一个有效的 API Key',
|
||||
batchQueryFailed: '批量查询失败',
|
||||
batchModelStatsFailed: '加载批量模型统计失败',
|
||||
loadModelStatsFailed: '加载模型统计失败',
|
||||
allInvalidKeys: '所有 API Key 都无效'
|
||||
}
|
||||
},
|
||||
|
||||
// Login page
|
||||
@@ -215,7 +380,9 @@ export default {
|
||||
password: '密码',
|
||||
passwordPlaceholder: '请输入密码',
|
||||
loginButton: '登录',
|
||||
loggingIn: '登录中...'
|
||||
loggingIn: '登录中...',
|
||||
loginFailed: '登录失败',
|
||||
loginFailedCheck: '登录失败,请检查用户名和密码'
|
||||
},
|
||||
|
||||
// Dashboard page
|
||||
@@ -256,6 +423,12 @@ export default {
|
||||
tokensPerMinute: '每分钟Token数',
|
||||
historicalData: '历史数据',
|
||||
minutes: '分钟',
|
||||
// Uptime display formats
|
||||
uptimeFormat: {
|
||||
daysHours: '{days}天 {hours}小时',
|
||||
hoursMinutes: '{hours}小时 {minutes}分钟',
|
||||
minutes: '{minutes}分钟'
|
||||
},
|
||||
|
||||
// Charts section
|
||||
modelDistributionAndTrend: '模型使用分布与Token使用趋势',
|
||||
@@ -263,8 +436,9 @@ export default {
|
||||
// Date filter presets (would be populated from dateFilter.presetOptions)
|
||||
today: '今日',
|
||||
yesterday: '昨日',
|
||||
last7Days: '迗 7 天',
|
||||
last30Days: '迗 30 天',
|
||||
dayBefore: '前天',
|
||||
last7Days: '近7天',
|
||||
last30Days: '近30天',
|
||||
thisWeek: '本周',
|
||||
lastWeek: '上周',
|
||||
thisMonth: '本月',
|
||||
@@ -316,7 +490,53 @@ export default {
|
||||
time: '时间',
|
||||
date: '日期',
|
||||
tokenQuantity: 'Token数量',
|
||||
requestsQuantity: '请求次数'
|
||||
requestsQuantity: '请求次数',
|
||||
|
||||
// Usage Trend component
|
||||
usageTrend: {
|
||||
title: '使用趋势',
|
||||
granularity: {
|
||||
byDay: '按天',
|
||||
byHour: '按小时'
|
||||
},
|
||||
periodOptions: {
|
||||
last24Hours: '24小时',
|
||||
last7Days: '7天',
|
||||
last30Days: '30天',
|
||||
recentDays: '最近{days}天'
|
||||
},
|
||||
chartLabels: {
|
||||
requests: '请求次数',
|
||||
tokens: 'Token使用量',
|
||||
requestsAxis: '请求次数',
|
||||
tokensAxis: 'Token使用量'
|
||||
}
|
||||
},
|
||||
|
||||
// Model Distribution component
|
||||
modelDistribution: {
|
||||
title: '模型使用分布',
|
||||
periods: {
|
||||
daily: '今日',
|
||||
total: '累计'
|
||||
},
|
||||
noData: '暂无模型使用数据',
|
||||
units: {
|
||||
requests: '请求',
|
||||
tokens: 'tokens'
|
||||
},
|
||||
chart: {
|
||||
tooltip: {
|
||||
requests: '请求',
|
||||
tokens: 'Tokens'
|
||||
}
|
||||
}
|
||||
},
|
||||
errors: {
|
||||
rangeTooLongHour: '小时粒度下日期范围不能超过24小时',
|
||||
rangeTooLongDay: '日期范围不能超过 31 天',
|
||||
rangeTooLongHourSwitched: '小时粒度下日期范围不能超过24小时,已切换到近24小时'
|
||||
}
|
||||
},
|
||||
|
||||
// Accounts page
|
||||
@@ -1285,6 +1505,52 @@ export default {
|
||||
loadStatsFailed: 'Failed to load API keys stats'
|
||||
},
|
||||
|
||||
// User API Keys Manager
|
||||
userApiKeysManager: {
|
||||
title: '我的 API Keys',
|
||||
description: '管理您的 API Keys 以访问 Claude Relay 服务',
|
||||
loading: '正在加载 API Keys...',
|
||||
warnings: {
|
||||
maxKeysReached:
|
||||
'您已达到 API Keys 的最大数量限制({maxApiKeys} 个)。请删除现有的 Key 以创建新的。'
|
||||
},
|
||||
status: {
|
||||
deleted: '已删除',
|
||||
noDescription: '无描述',
|
||||
neverUsed: '从未使用'
|
||||
},
|
||||
dateLabels: {
|
||||
created: '创建时间',
|
||||
deleted: '删除时间',
|
||||
lastUsed: '最后使用',
|
||||
expires: '到期时间'
|
||||
},
|
||||
usage: {
|
||||
requests: '次请求'
|
||||
},
|
||||
actions: {
|
||||
viewApiKey: '查看 API Key',
|
||||
deleteApiKey: '删除 API Key'
|
||||
},
|
||||
buttons: {
|
||||
createApiKey: '创建 API Key',
|
||||
delete: '删除'
|
||||
},
|
||||
emptyState: {
|
||||
title: '无 API Keys',
|
||||
description: '创建您的第一个 API Key 开始使用。'
|
||||
},
|
||||
confirmDelete: {
|
||||
title: '删除 API Key',
|
||||
message: "确定要删除 '{name}' 吗?此操作无法撤销。"
|
||||
},
|
||||
messages: {
|
||||
loadFailed: '加载 API Keys 失败',
|
||||
deleteSuccess: 'API Key 删除成功',
|
||||
deleteFailed: '删除 API Key 失败'
|
||||
}
|
||||
},
|
||||
|
||||
// User Login
|
||||
login: {
|
||||
title: 'User Sign In',
|
||||
@@ -1300,7 +1566,50 @@ export default {
|
||||
// Validation and error messages
|
||||
requiredFields: 'Please enter both username and password',
|
||||
loginSuccess: 'Login successful!',
|
||||
loginFailed: 'Login failed'
|
||||
loginFailed: 'Login failed',
|
||||
accountDisabled: '您的账号已被禁用'
|
||||
},
|
||||
|
||||
// View API Key Modal
|
||||
viewApiKeyModal: {
|
||||
title: 'API Key 详情',
|
||||
fields: {
|
||||
name: '名称',
|
||||
description: '描述',
|
||||
apiKey: 'API Key',
|
||||
status: '状态',
|
||||
usageStatistics: '使用统计'
|
||||
},
|
||||
apiKeyDisplay: {
|
||||
notAvailable: '不可用',
|
||||
keyPreview: 'cr_****',
|
||||
fullKeyNotice: '完整 API Key 仅在首次创建或重新生成时显示'
|
||||
},
|
||||
buttons: {
|
||||
hide: '隐藏',
|
||||
show: '显示',
|
||||
copy: '复制',
|
||||
close: '关闭'
|
||||
},
|
||||
status: {
|
||||
active: '启用',
|
||||
disabled: '禁用'
|
||||
},
|
||||
usageStats: {
|
||||
requests: '请求次数',
|
||||
inputTokens: '输入令牌',
|
||||
outputTokens: '输出令牌',
|
||||
totalCost: '总费用'
|
||||
},
|
||||
timestamps: {
|
||||
created: '创建时间',
|
||||
lastUsed: '最后使用',
|
||||
expires: '过期时间'
|
||||
},
|
||||
messages: {
|
||||
copySuccess: '已复制到剪贴板!',
|
||||
copyFailed: '复制到剪贴板失败'
|
||||
}
|
||||
},
|
||||
|
||||
// User Management
|
||||
@@ -1469,6 +1778,123 @@ export default {
|
||||
|
||||
// Success message
|
||||
roleUpdated: '用户角色已更新为 {role}'
|
||||
},
|
||||
|
||||
// User Usage Statistics
|
||||
userUsageStats: {
|
||||
// Page header
|
||||
title: '使用统计',
|
||||
subtitle: '查看您的 API 使用统计和费用',
|
||||
|
||||
// Time period selection
|
||||
periodSelection: {
|
||||
day: '最近24小时',
|
||||
week: '最近7天',
|
||||
month: '最近30天',
|
||||
quarter: '最近90天'
|
||||
},
|
||||
|
||||
// Loading state
|
||||
loadingStats: '正在加载使用统计...',
|
||||
|
||||
// Statistics cards
|
||||
statsCards: {
|
||||
totalRequests: '总请求数',
|
||||
inputTokens: '输入Token',
|
||||
outputTokens: '输出Token',
|
||||
totalCost: '总费用'
|
||||
},
|
||||
|
||||
// Daily usage trend chart
|
||||
usageTrend: {
|
||||
title: '日使用趋势',
|
||||
chartTitle: '使用图表',
|
||||
dailyTrendsDescription: '这里将显示日使用趋势',
|
||||
chartIntegrationNote: '(可集成 Chart.js、D3.js 或类似图表库)'
|
||||
},
|
||||
|
||||
// Usage by model section
|
||||
modelUsage: {
|
||||
title: '按模型使用情况',
|
||||
requests: '请求',
|
||||
requestsCount: '{count} 请求'
|
||||
},
|
||||
|
||||
// Usage by API key table
|
||||
apiKeyUsage: {
|
||||
title: '按 API Key 使用情况',
|
||||
headers: {
|
||||
apiKey: 'API Key',
|
||||
requests: '请求数',
|
||||
inputTokens: '输入Token',
|
||||
outputTokens: '输出Token',
|
||||
cost: '费用',
|
||||
status: '状态'
|
||||
},
|
||||
status: {
|
||||
active: '活跃',
|
||||
disabled: '已禁用',
|
||||
deleted: '已删除'
|
||||
}
|
||||
},
|
||||
|
||||
// No data state
|
||||
noData: {
|
||||
title: '暂无使用数据',
|
||||
description:
|
||||
'您还没有发起任何 API 请求。创建一个 API Key 并开始使用服务后,就能看到使用统计了。'
|
||||
},
|
||||
|
||||
// Error messages
|
||||
loadFailed: '加载使用统计失败'
|
||||
},
|
||||
|
||||
// Create API Key Modal
|
||||
createApiKeyModal: {
|
||||
title: '创建新的 API Key',
|
||||
|
||||
// 表单标签和占位符
|
||||
form: {
|
||||
nameLabel: '名称',
|
||||
nameRequired: '*',
|
||||
namePlaceholder: '为您的 API Key 取一个名称',
|
||||
descriptionLabel: '备注',
|
||||
descriptionPlaceholder: '可选的备注信息'
|
||||
},
|
||||
|
||||
// 按钮文本
|
||||
buttons: {
|
||||
cancel: '取消',
|
||||
creating: '创建中...',
|
||||
createApiKey: '创建 API Key',
|
||||
copy: '复制',
|
||||
done: '完成'
|
||||
},
|
||||
|
||||
// 成功状态
|
||||
success: {
|
||||
title: 'API Key 创建成功!',
|
||||
warning: {
|
||||
important: '重要提示:',
|
||||
message: '请立即复制您的 API Key,您将无法再次查看!'
|
||||
}
|
||||
},
|
||||
|
||||
// 错误和验证消息
|
||||
validation: {
|
||||
nameRequired: 'API Key 名称是必填项'
|
||||
},
|
||||
|
||||
errors: {
|
||||
createFailed: '创建 API Key 失败'
|
||||
},
|
||||
|
||||
// Toast 消息
|
||||
messages: {
|
||||
createSuccess: 'API Key 创建成功!',
|
||||
copySuccess: 'API Key 已复制到剪贴板!',
|
||||
copyFailed: '复制到剪贴板失败'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1495,6 +1921,10 @@ export default {
|
||||
removeIcon: '删除',
|
||||
iconFormats: '支持 .ico, .png, .jpg, .svg 格式,最大 350KB',
|
||||
iconPreview: '图标预览',
|
||||
validation: {
|
||||
iconTooLarge: '图标文件大小不能超过 350KB',
|
||||
iconTypeNotSupported: '不支持的文件类型,请选择 .ico, .png, .jpg 或 .svg 文件'
|
||||
},
|
||||
|
||||
adminEntry: '管理入口',
|
||||
adminEntryDescription: '登录按钮显示',
|
||||
|
||||
@@ -1,4 +1,47 @@
|
||||
export default {
|
||||
layout: {
|
||||
mainLayout: {
|
||||
comments: {
|
||||
topNavigation: '頂部導航',
|
||||
mainContentArea: '主內容區域',
|
||||
tabBar: '標籤欄',
|
||||
contentArea: '內容區域'
|
||||
},
|
||||
routing: {
|
||||
routeChangeError: '路由切換失敗:',
|
||||
routeNotFound: '路由未找到',
|
||||
defaultToTab: '預設選中儀表板'
|
||||
}
|
||||
},
|
||||
tabBar: {
|
||||
tabs: {
|
||||
dashboard: {
|
||||
name: '儀表板',
|
||||
shortName: '儀表板'
|
||||
},
|
||||
apiKeys: {
|
||||
name: 'API Keys',
|
||||
shortName: 'API'
|
||||
},
|
||||
accounts: {
|
||||
name: '帳戶管理',
|
||||
shortName: '帳戶'
|
||||
},
|
||||
userManagement: {
|
||||
name: '用戶管理',
|
||||
shortName: '用戶'
|
||||
},
|
||||
tutorial: {
|
||||
name: '使用教程',
|
||||
shortName: '教程'
|
||||
},
|
||||
settings: {
|
||||
name: '系統設置',
|
||||
shortName: '設置'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
common: {
|
||||
save: '保存',
|
||||
cancel: '取消',
|
||||
@@ -10,7 +53,89 @@ export default {
|
||||
update: '更新',
|
||||
search: '搜尋',
|
||||
reset: '重置',
|
||||
locale: 'zh-TW'
|
||||
locale: 'zh-TW',
|
||||
toastNotification: {
|
||||
defaultTitles: {
|
||||
success: '成功',
|
||||
error: '錯誤',
|
||||
warning: '警告',
|
||||
info: '資訊'
|
||||
}
|
||||
},
|
||||
confirmDialog: {
|
||||
confirm: '確認',
|
||||
cancel: '取消'
|
||||
},
|
||||
confirmModal: {
|
||||
continue: '繼續',
|
||||
cancel: '取消'
|
||||
},
|
||||
themeToggle: {
|
||||
light: {
|
||||
label: '淺色模式',
|
||||
shortLabel: '淺色'
|
||||
},
|
||||
dark: {
|
||||
label: '深色模式',
|
||||
shortLabel: '深色'
|
||||
},
|
||||
auto: {
|
||||
label: '跟隨系統',
|
||||
shortLabel: '自動'
|
||||
},
|
||||
toggleTheme: '切換主題',
|
||||
clickToSwitch: '點擊切換主題'
|
||||
},
|
||||
logoTitle: {
|
||||
logoAlt: '標誌'
|
||||
},
|
||||
languageSwitch: {
|
||||
zhCnName: '簡體中文',
|
||||
zhTwName: '繁體中文',
|
||||
enName: '英語',
|
||||
zhCnFlag: '簡',
|
||||
zhTwFlag: '繁',
|
||||
enFlag: 'EN'
|
||||
},
|
||||
accountSelector: {
|
||||
searchPlaceholder: '搜尋帳號名稱...',
|
||||
schedulingGroups: '調度分組',
|
||||
membersUnit: '個成員',
|
||||
claudeOAuthAccounts: 'Claude OAuth 專屬帳號',
|
||||
oauthAccounts: 'OAuth 專屬帳號',
|
||||
claudeConsoleAccounts: 'Claude Console 專屬帳號',
|
||||
noResultsFound: '沒有找到匹配的帳號',
|
||||
selectAccount: '請選擇帳號',
|
||||
useSharedPool: '使用共享帳號池',
|
||||
accountStatus: {
|
||||
unknown: '未知',
|
||||
unauthorized: '未授權',
|
||||
tokenError: 'Token錯誤',
|
||||
pending: '待驗證',
|
||||
rateLimited: '限流中',
|
||||
error: '異常',
|
||||
active: '正常'
|
||||
},
|
||||
dateFormat: {
|
||||
today: '今天建立',
|
||||
yesterday: '昨天建立',
|
||||
daysAgo: '天前'
|
||||
}
|
||||
},
|
||||
customDropdown: {
|
||||
placeholder: '請選擇'
|
||||
},
|
||||
// 通用時間與錯誤
|
||||
time: {
|
||||
justNow: '剛剛',
|
||||
minutesAgo: '{minutes}分鐘前',
|
||||
hoursAgo: '{hours}小時前',
|
||||
daysAgo: '{days}天前'
|
||||
},
|
||||
errors: {
|
||||
requestFailed: '請求失敗: {status}',
|
||||
loadSupportedClientsFailed: '載入支援的客戶端失敗'
|
||||
}
|
||||
},
|
||||
language: {
|
||||
zh: '簡體中文',
|
||||
@@ -204,7 +329,15 @@ export default {
|
||||
securityNoticeSingle: '您的 API Key 僅用於查詢自己的統計資料,不會被儲存或用於其他用途',
|
||||
securityNoticeMulti:
|
||||
'您的 API Keys 僅用於查詢統計資料,不會被儲存。彙整模式下部分個體化資訊將不顯示。',
|
||||
multiKeyTip: '提示:最多支援同時查詢 30 個 API Keys。使用 Ctrl+Enter 快速查詢。'
|
||||
multiKeyTip: '提示:最多支援同時查詢 30 個 API Keys。使用 Ctrl+Enter 快速查詢。',
|
||||
errors: {
|
||||
queryStatsFailed: '查詢統計資料失敗,請檢查您的 API Key 是否正確',
|
||||
enterAtLeastOneKey: '請輸入至少一個有效的 API Key',
|
||||
batchQueryFailed: '批次查詢失敗',
|
||||
batchModelStatsFailed: '載入批次模型統計失敗',
|
||||
loadModelStatsFailed: '載入模型統計失敗',
|
||||
allInvalidKeys: '所有 API Key 都無效'
|
||||
}
|
||||
},
|
||||
|
||||
// Login page
|
||||
@@ -215,7 +348,9 @@ export default {
|
||||
password: '密碼',
|
||||
passwordPlaceholder: '請輸入密碼',
|
||||
loginButton: '登錄',
|
||||
loggingIn: '登錄中...'
|
||||
loggingIn: '登錄中...',
|
||||
loginFailed: '登入失敗',
|
||||
loginFailedCheck: '登入失敗,請檢查使用者名稱與密碼'
|
||||
},
|
||||
|
||||
// Dashboard page
|
||||
@@ -255,7 +390,13 @@ export default {
|
||||
requestsPerMinute: '每分钟請求數',
|
||||
tokensPerMinute: '每分钟Token數',
|
||||
historicalData: '歷史資料',
|
||||
minutes: '分钟',
|
||||
minutes: '分鐘',
|
||||
// Uptime display formats
|
||||
uptimeFormat: {
|
||||
daysHours: '{days}天 {hours}小時',
|
||||
hoursMinutes: '{hours}小時 {minutes}分鐘',
|
||||
minutes: '{minutes}分鐘'
|
||||
},
|
||||
|
||||
// Charts section
|
||||
modelDistributionAndTrend: '模型使用分佈與Token使用趋勢',
|
||||
@@ -263,6 +404,7 @@ export default {
|
||||
// Date filter presets
|
||||
today: '今日',
|
||||
yesterday: '昨日',
|
||||
dayBefore: '前天',
|
||||
last7Days: '近7天',
|
||||
last30Days: '近30天',
|
||||
thisWeek: '本週',
|
||||
@@ -280,6 +422,13 @@ export default {
|
||||
dateSeparator: '至',
|
||||
maxHours24: '最多24小時',
|
||||
|
||||
// Errors
|
||||
errors: {
|
||||
rangeTooLongHour: '小時粒度下日期範圍不能超過24小時',
|
||||
rangeTooLongDay: '日期範圍不能超過 31 天',
|
||||
rangeTooLongHourSwitched: '小時粒度超過24小時,已切換為近24小時'
|
||||
},
|
||||
|
||||
// Auto refresh controls
|
||||
autoRefresh: '自動刷新',
|
||||
refresh: '刷新',
|
||||
@@ -316,7 +465,48 @@ export default {
|
||||
time: '時間',
|
||||
date: '日期',
|
||||
tokenQuantity: 'Token數量',
|
||||
requestsQuantity: '請求次數'
|
||||
requestsQuantity: '請求次數',
|
||||
|
||||
// Usage Trend component
|
||||
usageTrend: {
|
||||
title: '使用趨勢',
|
||||
granularity: {
|
||||
byDay: '按天',
|
||||
byHour: '按小時'
|
||||
},
|
||||
periodOptions: {
|
||||
last24Hours: '24小時',
|
||||
last7Days: '7天',
|
||||
last30Days: '30天',
|
||||
recentDays: '最近{days}天'
|
||||
},
|
||||
chartLabels: {
|
||||
requests: '請求次數',
|
||||
tokens: 'Token使用量',
|
||||
requestsAxis: '請求次數',
|
||||
tokensAxis: 'Token使用量'
|
||||
}
|
||||
},
|
||||
|
||||
// Model Distribution component
|
||||
modelDistribution: {
|
||||
title: '模型使用分佈',
|
||||
periods: {
|
||||
daily: '今日',
|
||||
total: '累計'
|
||||
},
|
||||
noData: '暫無模型使用資料',
|
||||
units: {
|
||||
requests: '請求',
|
||||
tokens: 'tokens'
|
||||
},
|
||||
chart: {
|
||||
tooltip: {
|
||||
requests: '請求',
|
||||
tokens: 'Tokens'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Accounts page
|
||||
@@ -1246,6 +1436,52 @@ export default {
|
||||
loadStatsFailed: 'Failed to load API keys stats'
|
||||
},
|
||||
|
||||
// User API Keys Manager
|
||||
userApiKeysManager: {
|
||||
title: '我的 API Keys',
|
||||
description: '管理您的 API Keys 以存取 Claude Relay 服務',
|
||||
loading: '正在載入 API Keys...',
|
||||
warnings: {
|
||||
maxKeysReached:
|
||||
'您已達到 API Keys 的最大數量限制({maxApiKeys} 個)。請刪除現有的 Key 以建立新的。'
|
||||
},
|
||||
status: {
|
||||
deleted: '已刪除',
|
||||
noDescription: '無描述',
|
||||
neverUsed: '從未使用'
|
||||
},
|
||||
dateLabels: {
|
||||
created: '建立時間',
|
||||
deleted: '刪除時間',
|
||||
lastUsed: '最後使用',
|
||||
expires: '到期時間'
|
||||
},
|
||||
usage: {
|
||||
requests: '次請求'
|
||||
},
|
||||
actions: {
|
||||
viewApiKey: '檢視 API Key',
|
||||
deleteApiKey: '刪除 API Key'
|
||||
},
|
||||
buttons: {
|
||||
createApiKey: '建立 API Key',
|
||||
delete: '刪除'
|
||||
},
|
||||
emptyState: {
|
||||
title: '無 API Keys',
|
||||
description: '建立您的第一個 API Key 開始使用。'
|
||||
},
|
||||
confirmDelete: {
|
||||
title: '刪除 API Key',
|
||||
message: "確定要刪除 '{name}' 嗎?此操作無法撤銷。"
|
||||
},
|
||||
messages: {
|
||||
loadFailed: '載入 API Keys 失败',
|
||||
deleteSuccess: 'API Key 刪除成功',
|
||||
deleteFailed: '刪除 API Key 失败'
|
||||
}
|
||||
},
|
||||
|
||||
// User Login
|
||||
login: {
|
||||
title: 'User Sign In',
|
||||
@@ -1261,7 +1497,50 @@ export default {
|
||||
// Validation and error messages
|
||||
requiredFields: 'Please enter both username and password',
|
||||
loginSuccess: 'Login successful!',
|
||||
loginFailed: 'Login failed'
|
||||
loginFailed: 'Login failed',
|
||||
accountDisabled: '您的帳號已被停用'
|
||||
},
|
||||
|
||||
// View API Key Modal
|
||||
viewApiKeyModal: {
|
||||
title: 'API Key 詳情',
|
||||
fields: {
|
||||
name: '名稱',
|
||||
description: '描述',
|
||||
apiKey: 'API Key',
|
||||
status: '狀態',
|
||||
usageStatistics: '使用統計'
|
||||
},
|
||||
apiKeyDisplay: {
|
||||
notAvailable: '不可用',
|
||||
keyPreview: 'cr_****',
|
||||
fullKeyNotice: '完整 API Key 僅在首次建立或重新產生時顯示'
|
||||
},
|
||||
buttons: {
|
||||
hide: '隱藏',
|
||||
show: '顯示',
|
||||
copy: '複製',
|
||||
close: '關閉'
|
||||
},
|
||||
status: {
|
||||
active: '啟用',
|
||||
disabled: '停用'
|
||||
},
|
||||
usageStats: {
|
||||
requests: '請求次數',
|
||||
inputTokens: '輸入權杖',
|
||||
outputTokens: '輸出權杖',
|
||||
totalCost: '總費用'
|
||||
},
|
||||
timestamps: {
|
||||
created: '建立時間',
|
||||
lastUsed: '最後使用',
|
||||
expires: '過期時間'
|
||||
},
|
||||
messages: {
|
||||
copySuccess: '已複製到剪貼簿!',
|
||||
copyFailed: '複製到剪貼簿失敗'
|
||||
}
|
||||
},
|
||||
|
||||
// User Management
|
||||
@@ -1432,6 +1711,75 @@ export default {
|
||||
roleUpdated: '使用者角色已更新為 {role}'
|
||||
},
|
||||
|
||||
// User Usage Statistics
|
||||
userUsageStats: {
|
||||
// Page header
|
||||
title: '使用統計',
|
||||
subtitle: '檢視您的 API 使用統計和費用',
|
||||
|
||||
// Time period selection
|
||||
periodSelection: {
|
||||
day: '最近24小時',
|
||||
week: '最近7天',
|
||||
month: '最近30天',
|
||||
quarter: '最近90天'
|
||||
},
|
||||
|
||||
// Loading state
|
||||
loadingStats: '正在載入使用統計...',
|
||||
|
||||
// Statistics cards
|
||||
statsCards: {
|
||||
totalRequests: '總請求數',
|
||||
inputTokens: '輸入Token',
|
||||
outputTokens: '輸出Token',
|
||||
totalCost: '總費用'
|
||||
},
|
||||
|
||||
// Daily usage trend chart
|
||||
usageTrend: {
|
||||
title: '日使用趨勢',
|
||||
chartTitle: '使用圖表',
|
||||
dailyTrendsDescription: '這裡將顯示日使用趨勢',
|
||||
chartIntegrationNote: '(可整合 Chart.js、D3.js 或類似圖表庫)'
|
||||
},
|
||||
|
||||
// Usage by model section
|
||||
modelUsage: {
|
||||
title: '按模型使用情況',
|
||||
requests: '請求',
|
||||
requestsCount: '{count} 請求'
|
||||
},
|
||||
|
||||
// Usage by API key table
|
||||
apiKeyUsage: {
|
||||
title: '按 API Key 使用情況',
|
||||
headers: {
|
||||
apiKey: 'API Key',
|
||||
requests: '請求數',
|
||||
inputTokens: '輸入Token',
|
||||
outputTokens: '輸出Token',
|
||||
cost: '費用',
|
||||
status: '狀態'
|
||||
},
|
||||
status: {
|
||||
active: '活躍',
|
||||
disabled: '已停用',
|
||||
deleted: '已刪除'
|
||||
}
|
||||
},
|
||||
|
||||
// No data state
|
||||
noData: {
|
||||
title: '暫無使用資料',
|
||||
description:
|
||||
'您還沒有發起任何 API 請求。建立一個 API Key 並開始使用服務後,就能看到使用統計了。'
|
||||
},
|
||||
|
||||
// Error messages
|
||||
loadFailed: '載入使用統計失敗'
|
||||
},
|
||||
|
||||
// Usage Detail Modal
|
||||
usageDetailModal: {
|
||||
title: '使用統計詳情',
|
||||
@@ -1470,6 +1818,54 @@ export default {
|
||||
|
||||
// Progress indicators
|
||||
usedPercentage: '已使用 {percentage}%'
|
||||
},
|
||||
|
||||
// Create API Key Modal
|
||||
createApiKeyModal: {
|
||||
title: '建立新的 API Key',
|
||||
|
||||
// 表單標籤和占位符
|
||||
form: {
|
||||
nameLabel: '名稱',
|
||||
nameRequired: '*',
|
||||
namePlaceholder: '為您的 API Key 取一個名稱',
|
||||
descriptionLabel: '備註',
|
||||
descriptionPlaceholder: '可選的備註資訊'
|
||||
},
|
||||
|
||||
// 按鈕文本
|
||||
buttons: {
|
||||
cancel: '取消',
|
||||
creating: '建立中...',
|
||||
createApiKey: '建立 API Key',
|
||||
copy: '複製',
|
||||
done: '完成'
|
||||
},
|
||||
|
||||
// 成功狀態
|
||||
success: {
|
||||
title: 'API Key 建立成功!',
|
||||
warning: {
|
||||
important: '重要提示:',
|
||||
message: '請立即複製您的 API Key,您將無法再次查看!'
|
||||
}
|
||||
},
|
||||
|
||||
// 錯誤和驗證訊息
|
||||
validation: {
|
||||
nameRequired: 'API Key 名稱是必填項'
|
||||
},
|
||||
|
||||
errors: {
|
||||
createFailed: '建立 API Key 失敗'
|
||||
},
|
||||
|
||||
// Toast 訊息
|
||||
messages: {
|
||||
createSuccess: 'API Key 建立成功!',
|
||||
copySuccess: 'API Key 已複製到剪貼簿!',
|
||||
copyFailed: '複製到剪貼簿失敗'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1496,6 +1892,10 @@ export default {
|
||||
removeIcon: '刪除',
|
||||
iconFormats: '支援 .ico, .png, .jpg, .svg 格式,最大 350KB',
|
||||
iconPreview: '圖標預覽',
|
||||
validation: {
|
||||
iconTooLarge: '圖標文件大小不能超過 350KB',
|
||||
iconTypeNotSupported: '不支援的文件類型,請選擇 .ico, .png, .jpg 或 .svg 文件'
|
||||
},
|
||||
|
||||
adminEntry: '管理入口',
|
||||
adminEntryDescription: '登入按鈕顯示',
|
||||
|
||||
@@ -37,7 +37,9 @@ export function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
|
||||
.replace('ss', seconds)
|
||||
}
|
||||
|
||||
// 相对时间格式化
|
||||
// 相对时间格式化(使用 i18n)
|
||||
import i18n from '@/i18n'
|
||||
|
||||
export function formatRelativeTime(date) {
|
||||
if (!date) return ''
|
||||
|
||||
@@ -50,13 +52,13 @@ export function formatRelativeTime(date) {
|
||||
const diffDays = Math.floor(diffHours / 24)
|
||||
|
||||
if (diffDays > 0) {
|
||||
return `${diffDays}天前`
|
||||
return i18n.global.t('common.time.daysAgo', { days: diffDays })
|
||||
} else if (diffHours > 0) {
|
||||
return `${diffHours}小时前`
|
||||
return i18n.global.t('common.time.hoursAgo', { hours: diffHours })
|
||||
} else if (diffMins > 0) {
|
||||
return `${diffMins}分钟前`
|
||||
return i18n.global.t('common.time.minutesAgo', { minutes: diffMins })
|
||||
} else {
|
||||
return '刚刚'
|
||||
return i18n.global.t('common.time.justNow')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user