mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-09 02:47:45 +08:00
Merge origin/main into main
Integrate upstream updates while preserving the local analytics dashboards and schema-only migration changes. Combine user account analysis with upstream user/group usage statistics in separate tabs, retain all migration versions, and keep the deleted audit document removed. Validation: gateway all-target cargo check, frontend type check and 57 focused tests, 48 migration tests, schema composition checks, and diff whitespace checks.
This commit is contained in:
@@ -50,6 +50,10 @@ describe('translation coverage', () => {
|
||||
['1 维度', '1 dimension'],
|
||||
['14天0时', '14d 0h'],
|
||||
['5天 0:00:00', '5d 0:00:00'],
|
||||
['确定删除选中的 3 个模型吗?\n\n此操作不可撤销。', 'Delete the selected 3 models?\n\nThis cannot be undone.'],
|
||||
['确定删除选中的 1 个模型吗?\n\n此操作不可撤销。', 'Delete the selected 1 model?\n\nThis cannot be undone.'],
|
||||
['成功删除 2 个模型', 'Deleted 2 models'],
|
||||
['1 个模型删除失败', 'Failed to delete 1 model'],
|
||||
])('translates %s as a complete message', (source, expected) => {
|
||||
expect(translateLegacyText(source, 'en-US')).toBe(expected)
|
||||
})
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
export const legacyAdminEnglishMessages: Record<string, string> = {
|
||||
'缺少 OAuth 认证信息,请先授权/刷新 Token': 'Missing OAuth credentials; please authorize or refresh the token first',
|
||||
'Key 状态写入失败': 'Failed to save key status',
|
||||
'找不到有效的 claude:messages 端点': 'No active claude:messages endpoint found',
|
||||
'响应中未包含配额信息': 'The response contains no quota information',
|
||||
'响应中未包含额度窗口': 'The response contains no quota windows',
|
||||
'oauth/usage 请求执行失败': 'oauth/usage request failed',
|
||||
'oauth/usage 返回 401,Token 可能已失效,请刷新 Token': 'oauth/usage returned 401. The token may have expired; please refresh it',
|
||||
'oauth/usage 返回 403,该账号缺少 user:profile 权限(如 Setup Token),无法查询额度': 'oauth/usage returned 403. This account lacks the user:profile scope (e.g. a Setup Token), so quota cannot be queried',
|
||||
'oauth/usage 被限流,请稍后重试': 'oauth/usage was rate limited; please retry later',
|
||||
'配置额度、流量限制、会员权益和组合套餐': 'Configure credit, usage limits, membership benefits, and bundled plans',
|
||||
'新建套餐': 'Create plan',
|
||||
'套餐列表': 'Plans',
|
||||
@@ -613,6 +622,8 @@ export const legacyAdminEnglishMessages: Record<string, string> = {
|
||||
'系统调账': 'System adjustment',
|
||||
'退款扣减': 'Refund debit',
|
||||
'退款回补': 'Refund recredit',
|
||||
'另一个标签页正在处理钱包批量调整,请稍后刷新状态再试。此次未发送新请求。': 'Another tab is processing a wallet batch adjustment. Refresh the status and try again later. No new request was sent from this tab.',
|
||||
'当前浏览器无法保护跨标签页的钱包批量请求,请使用支持此功能的浏览器。请求未发送。': 'This browser cannot protect wallet batch requests across tabs. Use a browser that supports this feature. The request was not sent.',
|
||||
'兑换码批次已创建': 'Redemption code batch created',
|
||||
'CSV 已导出': 'CSV exported',
|
||||
'批次已停用': 'Batch disabled',
|
||||
|
||||
@@ -711,7 +711,7 @@ export const legacyUiEnglishMessages: Record<string, string> = {
|
||||
'测试请求头必须是 JSON 对象': 'Test request headers must be a JSON object',
|
||||
'号池调度模式': 'Pool scheduling mode',
|
||||
'Responses WebSocket 模式': 'Responses WebSocket mode',
|
||||
'允许此提供商处理标准 Responses API WebSocket 请求。仅在已验证兼容性后启用。': 'Allow this provider to handle standard Responses API WebSocket requests. Enable only after verifying compatibility.',
|
||||
'允许此提供商处理标准 Responses API WebSocket 请求。': 'Allow this provider to handle standard Responses API WebSocket requests.',
|
||||
'发放成功后,冲突的旧套餐及其组合权益会整包失效。确定继续发放吗?': 'Granting this plan will replace conflicting plans and all their bundled benefits. Continue?',
|
||||
'确认替换旧套餐': 'Confirm plan replacement',
|
||||
'继续发放': 'Grant plan',
|
||||
@@ -1420,6 +1420,7 @@ export const legacyUiEnglishMessages: Record<string, string> = {
|
||||
'批量导入': 'Bulk import',
|
||||
'继续确认重置': 'Continue checking reset',
|
||||
'临近过期': 'Expiring soon',
|
||||
'Claude 重置机会': 'Claude quota reset',
|
||||
'暂无密钥配置': 'No keys configured',
|
||||
'暂无账号配置': 'No accounts configured',
|
||||
'点击上方"添加密钥"按钮创建第一个密钥': 'Add your first key to get started',
|
||||
@@ -1662,6 +1663,8 @@ export const legacyUiEnglishMessages: Record<string, string> = {
|
||||
'依据窗口成本/Token 用量,缺失时回退配额使用率': 'Use window cost or token usage, falling back to quota utilization if unavailable',
|
||||
'调度策略元数据加载失败,请重试': 'Failed to load scheduling policy metadata. Try again.',
|
||||
'号池调度已保存': 'Pool scheduling saved',
|
||||
'保留最低额度': 'Reserve minimum quota',
|
||||
'账号剩余额度不高于 1% 时提前标记为额度耗尽并停止调度,待额度恢复后再使用。': 'Mark accounts as exhausted and stop scheduling when remaining quota is 1% or less, until quota recovers.',
|
||||
'自适应热池': 'Adaptive warm pool',
|
||||
'自动维护热池,缺口时异步补位。': 'Maintain a warm pool and replenish missing capacity asynchronously.',
|
||||
'账号自检': 'Account self-check',
|
||||
|
||||
@@ -6,6 +6,11 @@ import { legacyGuideEnglishMessages } from './legacy-guide-messages'
|
||||
export const messages = {
|
||||
'zh-CN': {
|
||||
'common.loading': '加载中...',
|
||||
'poolQuota.claudeCode.window5h': '5H',
|
||||
'poolQuota.claudeCode.weekly': '周',
|
||||
'poolQuota.claudeCode.weeklySonnet': '周 Sonnet',
|
||||
'poolQuota.claudeCode.weeklyFable': '周 Fable',
|
||||
'poolQuota.claudeCode.unknownWindow': '额度',
|
||||
'common.confirmRead': '确认已读',
|
||||
'common.confirming': '确认中...',
|
||||
'common.copy': '复制',
|
||||
@@ -346,6 +351,45 @@ export const messages = {
|
||||
'nav.usageStats': '使用统计',
|
||||
'nav.operations': '运维总览',
|
||||
'nav.userStats': '用户分析',
|
||||
'userStats.title': '用户统计',
|
||||
'userStats.description': '按用户或当前用户组成员查看排行榜与使用趋势',
|
||||
'userStats.scope.placeholder': '统计维度',
|
||||
'userStats.scope.user': '按用户',
|
||||
'userStats.ungrouped': '未分组',
|
||||
'userStats.scope.userGroup': '按用户组',
|
||||
'userStats.search.user': '搜索用户',
|
||||
'userStats.search.userGroup': '搜索用户组',
|
||||
'userStats.select.user': '选择用户',
|
||||
'userStats.select.userGroup': '选择用户组',
|
||||
'userStats.compare.placeholder': '对比对象(可选)',
|
||||
'userStats.compare.none': '不对比',
|
||||
'userStats.leaderboard.user': '用户排行榜',
|
||||
'userStats.leaderboard.userGroup': '用户组排行榜',
|
||||
'userStats.pagination.summary': '共 {total} 项 · 第 {page} 页',
|
||||
'userStats.pagination.previous': '上一页',
|
||||
'userStats.pagination.next': '下一页',
|
||||
'userStats.summary.user': '用户摘要',
|
||||
'userStats.summary.userGroup': '用户组摘要',
|
||||
'userStats.selectPrompt': '请选择统计对象',
|
||||
'userStats.members.current': '当前成员',
|
||||
'userStats.members.active': '活跃成员',
|
||||
'userStats.memberLeaderboard': '组内成员排行',
|
||||
'userStats.trend.user': '用户使用趋势',
|
||||
'userStats.trend.userGroup': '用户组使用趋势',
|
||||
'userStats.comparisonTrend.user': '用户对比趋势',
|
||||
'userStats.comparisonTrend.userGroup': '用户组对比趋势',
|
||||
'userStats.chart.current': '当前对象',
|
||||
'userStats.chart.comparison': '对比对象',
|
||||
'stats.metric.placeholder': '指标',
|
||||
'stats.metric.requests': '请求数',
|
||||
'stats.metric.tokens': 'Tokens',
|
||||
'stats.metric.cost': '成本',
|
||||
'stats.metric.errorRate': '错误率',
|
||||
'stats.empty.title': '暂无数据',
|
||||
'stats.empty.description': '当前时间范围内没有统计结果',
|
||||
'stats.column.rank': '排名',
|
||||
'stats.column.name': '名称',
|
||||
'stats.column.members': '成员',
|
||||
'nav.costAnalysis': '成本分析',
|
||||
'nav.performanceAnalysis': '性能分析',
|
||||
'nav.userManagement': '用户管理',
|
||||
@@ -452,6 +496,11 @@ export const messages = {
|
||||
},
|
||||
'en-US': {
|
||||
'common.loading': 'Loading...',
|
||||
'poolQuota.claudeCode.window5h': '5H',
|
||||
'poolQuota.claudeCode.weekly': 'Weekly',
|
||||
'poolQuota.claudeCode.weeklySonnet': 'Weekly Sonnet',
|
||||
'poolQuota.claudeCode.weeklyFable': 'Weekly Fable',
|
||||
'poolQuota.claudeCode.unknownWindow': 'Quota',
|
||||
'common.confirmRead': 'Confirm read',
|
||||
'common.confirming': 'Confirming...',
|
||||
'common.copy': 'Copy',
|
||||
@@ -792,6 +841,45 @@ export const messages = {
|
||||
'nav.usageStats': 'Usage stats',
|
||||
'nav.operations': 'Operations',
|
||||
'nav.userStats': 'User analysis',
|
||||
'userStats.title': 'User statistics',
|
||||
'userStats.description': 'View leaderboards and usage trends by user or current user-group membership',
|
||||
'userStats.scope.placeholder': 'Statistics scope',
|
||||
'userStats.scope.user': 'By user',
|
||||
'userStats.ungrouped': 'Ungrouped',
|
||||
'userStats.scope.userGroup': 'By user group',
|
||||
'userStats.search.user': 'Search users',
|
||||
'userStats.search.userGroup': 'Search user groups',
|
||||
'userStats.select.user': 'Select a user',
|
||||
'userStats.select.userGroup': 'Select a user group',
|
||||
'userStats.compare.placeholder': 'Comparison (optional)',
|
||||
'userStats.compare.none': 'No comparison',
|
||||
'userStats.leaderboard.user': 'User leaderboard',
|
||||
'userStats.leaderboard.userGroup': 'User-group leaderboard',
|
||||
'userStats.pagination.summary': '{total} items · Page {page}',
|
||||
'userStats.pagination.previous': 'Previous',
|
||||
'userStats.pagination.next': 'Next',
|
||||
'userStats.summary.user': 'User summary',
|
||||
'userStats.summary.userGroup': 'User-group summary',
|
||||
'userStats.selectPrompt': 'Select a statistics entity',
|
||||
'userStats.members.current': 'Current members',
|
||||
'userStats.members.active': 'Active members',
|
||||
'userStats.memberLeaderboard': 'Group member leaderboard',
|
||||
'userStats.trend.user': 'User usage trend',
|
||||
'userStats.trend.userGroup': 'User-group usage trend',
|
||||
'userStats.comparisonTrend.user': 'User comparison trend',
|
||||
'userStats.comparisonTrend.userGroup': 'User-group comparison trend',
|
||||
'userStats.chart.current': 'Current entity',
|
||||
'userStats.chart.comparison': 'Comparison entity',
|
||||
'stats.metric.placeholder': 'Metric',
|
||||
'stats.metric.requests': 'Requests',
|
||||
'stats.metric.tokens': 'Tokens',
|
||||
'stats.metric.cost': 'Cost',
|
||||
'stats.metric.errorRate': 'Error rate',
|
||||
'stats.empty.title': 'No data',
|
||||
'stats.empty.description': 'No statistics are available for the current time range',
|
||||
'stats.column.rank': 'Rank',
|
||||
'stats.column.name': 'Name',
|
||||
'stats.column.members': 'Members',
|
||||
'nav.costAnalysis': 'Cost analysis',
|
||||
'nav.performanceAnalysis': 'Performance analysis',
|
||||
'nav.userManagement': 'Users',
|
||||
@@ -1380,6 +1468,27 @@ const legacyExactEnglishMessages: Record<string, string> = {
|
||||
'暂无选项': 'No options',
|
||||
'用户批量操作': 'User batch actions',
|
||||
'按当前选择批量调整用户状态、角色和额度': 'Batch update user status, role, and quota for the current selection',
|
||||
'按当前选择批量调整用户状态、角色、额度和钱包余额': 'Batch update user status, role, quota, and wallet balances for the current selection',
|
||||
'调整余额': 'Adjust balance',
|
||||
'批量增加或扣减钱包余额': 'Add or deduct wallet balances in bulk',
|
||||
'调整金额 (USD)': 'Adjustment amount (USD)',
|
||||
'余额调整方式': 'Balance adjustment mode',
|
||||
'增加': 'Add',
|
||||
'扣减': 'Deduct',
|
||||
'请输入大于 0 的有限金额': 'Enter a finite amount greater than 0',
|
||||
'扣减超过单个用户可用余额时,该用户余额将归零。': 'Deductions above an individual user’s available balance will be clamped to zero.',
|
||||
'用户钱包不可用': 'User wallet is unavailable',
|
||||
'当前为只读模式,无法批量调整用户钱包余额': 'Cannot adjust user wallet balances in read-only mode',
|
||||
'余额调整结果未确认,批次已中止,请核对钱包后再重试': 'Balance adjustment result is uncertain; the batch stopped. Verify the wallet before retrying.',
|
||||
'用户钱包更新结果未确认,批次已中止,请核对钱包后再重试': 'User wallet update result is uncertain; the batch stopped. Verify the wallet before retrying.',
|
||||
'用户更新结果未确认,批次已中止,请核对后再重试': 'User update result is uncertain; the batch stopped. Verify the result before retrying.',
|
||||
'读取用户状态失败,批次已中止,该用户未执行': 'Could not read user state; the batch stopped before processing this user.',
|
||||
'因前序错误未执行': 'Not processed because an earlier operation failed',
|
||||
'请核对余额后再重试,勿直接重试整批': 'Verify balances before retrying; do not retry the entire batch blindly.',
|
||||
'查看批次中断详情': 'View interrupted batch details',
|
||||
'已完成用户 ID': 'Completed user IDs',
|
||||
'结果待核对用户 ID': 'User IDs with uncertain results',
|
||||
'尚未执行用户 ID': 'Unprocessed user IDs',
|
||||
'影响用户:': 'Affected users:',
|
||||
'目标为当前筛选条件匹配的全部用户,执行前后端会重新解析。': 'Targets all users matching the current filters; the backend will resolve the selection again before execution.',
|
||||
'目标为当前已勾选的用户,重复 ID 会自动去重。': 'Targets the currently selected users; duplicate IDs are deduplicated automatically.',
|
||||
@@ -1722,6 +1831,8 @@ const legacyExactEnglishMessages: Record<string, string> = {
|
||||
'模拟缓存模式': 'Simulated cache mode',
|
||||
'启用后仅对 Kiro 请求模拟 prompt cache 读写计量。': 'When enabled, only Kiro requests simulate prompt cache read/write accounting.',
|
||||
'Codex 指纹收敛': 'Codex fingerprint convergence',
|
||||
'Codex 指纹收敛(推荐开启)': 'Codex fingerprint convergence (recommended)',
|
||||
'开启后,Aether 会根据当前账号身份为出站请求统一生成并写入以下标识,使同一 Codex 账号在上游看来始终是同一设备与会话:\n\n• 请求头:installation_id、session_id、thread_id、window_id、turn_id 等\n• 请求体(Responses 格式):client_metadata 与 prompt_cache_key 中的对应字段\n\n关闭时保持客户端原始透传,不做任何改写。建议开启以提升上游指纹稳定性与会话连续性。': 'When enabled, Aether generates and writes consistent identifiers for outbound requests based on the current account identity, so the same Codex account always appears as the same device and session upstream:\n\n• Request headers: installation_id, session_id, thread_id, window_id, turn_id, etc.\n• Request body (Responses format): corresponding fields in client_metadata and prompt_cache_key\n\nWhen disabled, the original client values are passed through unchanged. Enabling is recommended for better upstream fingerprint stability and session continuity.',
|
||||
'统一同一 Codex 身份的设备与会话标识;关闭时保持现有透传行为。': 'Use consistent device and session identifiers for the same Codex identity. When disabled, preserve the existing pass-through behavior.',
|
||||
'请前往模块管理-敏感信息保护中配置详细规则。': 'Configure detailed rules in Modules - Sensitive information protection.',
|
||||
'验证失败': 'Validation failed',
|
||||
@@ -2149,7 +2260,10 @@ const legacyExactEnglishMessages: Record<string, string> = {
|
||||
'账号不可用': 'Account unavailable',
|
||||
'日额度': 'Daily quota',
|
||||
'周额度': 'Weekly quota',
|
||||
'月额度': 'Monthly quota',
|
||||
'剩余额度': 'Remaining quota',
|
||||
'预付额度': 'Prepaid credits',
|
||||
'按需额度': 'On-demand credits',
|
||||
'点击编辑优先级': 'Edit priority',
|
||||
'点击编辑倍率': 'Edit multiplier',
|
||||
'同步失败': 'Sync failed',
|
||||
@@ -2965,6 +3079,9 @@ const legacyDynamicPatterns: Array<[RegExp, (match: RegExpMatchArray) => string]
|
||||
[/^(1[0-2]|[1-9])月$/u, match => new Intl.DateTimeFormat('en-US', { month: 'short', timeZone: 'UTC' }).format(new Date(Date.UTC(2020, Number(match[1]) - 1, 1)))],
|
||||
[/^总可用:(.+)$/u, match => `Total available: ${match[1]}`],
|
||||
[/^余额:(.+)$/u, match => `Balance: ${match[1]}`],
|
||||
[/^oauth\/usage 返回状态码 (\d+)$/u, match => `oauth/usage returned status ${match[1]}`],
|
||||
[/^共 (\d+) 次机会$/u, match => `${match[1]} ${match[1] === '1' ? 'chance' : 'chances'} in total`],
|
||||
[/^已处理 (\d+) 个 Key$/u, match => `Processed ${match[1]} ${match[1] === '1' ? 'key' : 'keys'}`],
|
||||
[/^(.+) 秒$/u, match => `${translateLegacyText(match[1], 'en-US')}s`],
|
||||
[/^(.+) 分钟$/u, match => `${translateLegacyText(match[1], 'en-US')} min`],
|
||||
[/^(.+) 小时$/u, match => `${translateLegacyText(match[1], 'en-US')} h`],
|
||||
@@ -2974,6 +3091,7 @@ const legacyDynamicPatterns: Array<[RegExp, (match: RegExpMatchArray) => string]
|
||||
[/^确认(启用|禁用|删除|重置)((.+))$/u, match => `Confirm ${translateLegacyText(match[1], 'en-US').toLowerCase()} (${match[2]})`],
|
||||
[/^成功 (.+) 个,失败 (.+) 个$/u, match => `Succeeded ${match[1]}, failed ${match[2]}`],
|
||||
[/^批量操作完成:成功 (.+) 个,失败 (.+) 个$/u, match => `Batch action complete: succeeded ${match[1]}, failed ${match[2]}`],
|
||||
[/^批量操作中断:成功 (.+) 个,结果待确认 (.+) 个,尚未执行 (.+) 个$/u, match => `Batch interrupted: succeeded ${match[1]}, uncertain ${match[2]}, not processed ${match[3]}`],
|
||||
[/^匹配 (.+) 个,当前页 (.+) 个,已选 (.+) 个$/u, match => `Matched ${match[1]} items, current page ${match[2]} items, selected ${match[3]} items`],
|
||||
[/^已选 (.+) 个$/u, match => `Selected ${match[1]} items`],
|
||||
[/^已强制下线 (.+) 个设备$/u, match => `Signed out ${match[1]} devices`],
|
||||
@@ -2981,6 +3099,9 @@ const legacyDynamicPatterns: Array<[RegExp, (match: RegExpMatchArray) => string]
|
||||
[/^(.+) 个用户$/u, match => `${match[1]} users`],
|
||||
[/^有 (.+) 条格式错误$/u, match => `${match[1]} format errors`],
|
||||
[/^还有 (.+) 条错误未显示$/u, match => `${match[1]} more errors hidden`],
|
||||
[/^确定删除选中的 (\d+) 个模型吗?\n\n此操作不可撤销。$/u, match => `Delete the selected ${match[1]} ${match[1] === '1' ? 'model' : 'models'}?\n\nThis cannot be undone.`],
|
||||
[/^成功删除 (\d+) 个模型$/u, match => `Deleted ${match[1]} ${match[1] === '1' ? 'model' : 'models'}`],
|
||||
[/^(\d+) 个模型删除失败$/u, match => `Failed to delete ${match[1]} ${match[1] === '1' ? 'model' : 'models'}`],
|
||||
[/^确定删除套餐「(.+)」吗?\n\n已有订单或权益的套餐不能删除,请改为停用。删除后无法恢复。$/u, match => `Delete plan "${match[1]}"?\n\nPlans with existing orders or entitlements cannot be deleted. Disable it instead. This cannot be undone.`],
|
||||
[/^确定要删除映射 "(.+)" 吗?\n\n注意:这只会删除映射记录,不会删除 Google 上的实际文件。$/u, match => `Delete mapping "${match[1]}"?\n\nThis only deletes the mapping record and will not delete the actual file on Google.`],
|
||||
[/^确认删除批次「(.+)」吗?删除后无法恢复。$/u, match => `Delete batch "${match[1]}"? This cannot be undone.`],
|
||||
|
||||
Reference in New Issue
Block a user