mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-03 11:20:50 +08:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6837100dec | ||
|
|
8542041981 | ||
|
|
35ceab0dae | ||
|
|
d3fe186df7 | ||
|
|
5aff22a20b | ||
|
|
aa1dedc932 | ||
|
|
61e75eee97 | ||
|
|
3a2d96725f | ||
|
|
8283e99909 | ||
|
|
181cba6886 | ||
|
|
aa729914c5 | ||
|
|
f98f31f2ed | ||
|
|
1e79f918e2 | ||
|
|
257260b1d2 | ||
|
|
8372906820 | ||
|
|
5feea2e345 | ||
|
|
825ad53c2c | ||
|
|
3e9413172c | ||
|
|
89099b58ff | ||
|
|
7509a1eddc | ||
|
|
e92784f951 | ||
|
|
d26695da76 | ||
|
|
8964030ade | ||
|
|
0b9abdf9b1 | ||
|
|
a208a484ff | ||
|
|
369cf52346 | ||
|
|
dcfffc716b | ||
|
|
7de5280824 | ||
|
|
86d60aad77 | ||
|
|
020fccc032 | ||
|
|
c162ab3a54 | ||
|
|
85d12e15d8 | ||
|
|
ebffb49f52 | ||
|
|
316c1ffc0d | ||
|
|
b3e54e7f14 | ||
|
|
fe11bfb48f | ||
|
|
ee0d8f82d7 | ||
|
|
0bbb397df5 |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -27,6 +27,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Build all-in-one HTML
|
- name: Build all-in-one HTML
|
||||||
run: npm run build
|
run: npm run build
|
||||||
|
env:
|
||||||
|
VERSION: ${{ github.ref_name }}
|
||||||
|
|
||||||
- name: Prepare release assets
|
- name: Prepare release assets
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -20,3 +20,8 @@ package-lock.json
|
|||||||
# OS files
|
# OS files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
|
CLAUDE.md
|
||||||
|
.claude
|
||||||
|
AGENTS.md
|
||||||
|
.serena
|
||||||
@@ -10,7 +10,7 @@ Example URL:
|
|||||||
https://remote.router-for.me/
|
https://remote.router-for.me/
|
||||||
|
|
||||||
Minimum required version: ≥ 6.0.0
|
Minimum required version: ≥ 6.0.0
|
||||||
Recommended version: ≥ 6.0.19
|
Recommended version: ≥ 6.2.32
|
||||||
|
|
||||||
Since version 6.0.19, the WebUI has been rolled into the main program. You can access it by going to `/management.html` on the external port after firing up the main project.
|
Since version 6.0.19, the WebUI has been rolled into the main program. You can access it by going to `/management.html` on the external port after firing up the main project.
|
||||||
|
|
||||||
@@ -43,7 +43,6 @@ Since version 6.0.19, the WebUI has been rolled into the main program. You can a
|
|||||||
- Download existing authentication files
|
- Download existing authentication files
|
||||||
- Delete single or all authentication files
|
- Delete single or all authentication files
|
||||||
- Display file details
|
- Display file details
|
||||||
- **Gemini Web Token**: Direct authentication using browser cookies
|
|
||||||
|
|
||||||
### Usage Statistics
|
### Usage Statistics
|
||||||
- **Real-time Analytics**: Track API usage with interactive charts
|
- **Real-time Analytics**: Track API usage with interactive charts
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ https://github.com/router-for-me/CLIProxyAPI
|
|||||||
https://remote.router-for.me/
|
https://remote.router-for.me/
|
||||||
|
|
||||||
最低可用版本 ≥ 6.0.0
|
最低可用版本 ≥ 6.0.0
|
||||||
推荐版本 ≥ 6.0.19
|
|
||||||
|
推荐版本 ≥ 6.2.32
|
||||||
|
|
||||||
自6.0.19起WebUI已经集成在主程序中 可以通过主项目开启的外部端口的`/management.html`访问
|
自6.0.19起WebUI已经集成在主程序中 可以通过主项目开启的外部端口的`/management.html`访问
|
||||||
|
|
||||||
## 功能特点
|
## 功能特点
|
||||||
@@ -40,7 +42,6 @@ https://remote.router-for.me/
|
|||||||
- 下载现有认证文件
|
- 下载现有认证文件
|
||||||
- 删除单个或所有认证文件
|
- 删除单个或所有认证文件
|
||||||
- 显示文件详细信息
|
- 显示文件详细信息
|
||||||
- **Gemini Web Token**: 使用浏览器 Cookie 直接认证
|
|
||||||
|
|
||||||
### 使用统计
|
### 使用统计
|
||||||
- **实时分析**: 通过交互式图表跟踪 API 使用情况
|
- **实时分析**: 通过交互式图表跟踪 API 使用情况
|
||||||
|
|||||||
34
build.js
34
build.js
@@ -49,6 +49,35 @@ function escapeForStyle(content) {
|
|||||||
return content.replace(/<\/(style)/gi, '<\\/$1');
|
return content.replace(/<\/(style)/gi, '<\\/$1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getVersion() {
|
||||||
|
// 1. 优先从环境变量获取(GitHub Actions 会设置)
|
||||||
|
if (process.env.VERSION) {
|
||||||
|
return process.env.VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 尝试从 git tag 获取
|
||||||
|
try {
|
||||||
|
const { execSync } = require('child_process');
|
||||||
|
const gitTag = execSync('git describe --tags --exact-match 2>/dev/null || git describe --tags 2>/dev/null || echo ""', { encoding: 'utf8' }).trim();
|
||||||
|
if (gitTag) {
|
||||||
|
return gitTag;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('无法从 git 获取版本号');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 回退到 package.json
|
||||||
|
try {
|
||||||
|
const packageJson = JSON.parse(fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8'));
|
||||||
|
return 'v' + packageJson.version;
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('无法从 package.json 读取版本号');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 最后使用默认值
|
||||||
|
return 'v0.0.0-dev';
|
||||||
|
}
|
||||||
|
|
||||||
function ensureDistDir() {
|
function ensureDistDir() {
|
||||||
if (fs.existsSync(distDir)) {
|
if (fs.existsSync(distDir)) {
|
||||||
fs.rmSync(distDir, { recursive: true, force: true });
|
fs.rmSync(distDir, { recursive: true, force: true });
|
||||||
@@ -83,6 +112,11 @@ function build() {
|
|||||||
const i18n = escapeForScript(readFile(sourceFiles.i18n));
|
const i18n = escapeForScript(readFile(sourceFiles.i18n));
|
||||||
const app = escapeForScript(readFile(sourceFiles.app));
|
const app = escapeForScript(readFile(sourceFiles.app));
|
||||||
|
|
||||||
|
// 获取版本号并替换
|
||||||
|
const version = getVersion();
|
||||||
|
console.log(`使用版本号: ${version}`);
|
||||||
|
html = html.replace(/__VERSION__/g, version);
|
||||||
|
|
||||||
html = html.replace(
|
html = html.replace(
|
||||||
'<link rel="stylesheet" href="styles.css">',
|
'<link rel="stylesheet" href="styles.css">',
|
||||||
`<style>
|
`<style>
|
||||||
|
|||||||
392
i18n.js
392
i18n.js
@@ -38,6 +38,14 @@ const i18n = {
|
|||||||
'common.base_url': '地址',
|
'common.base_url': '地址',
|
||||||
'common.proxy_url': '代理',
|
'common.proxy_url': '代理',
|
||||||
'common.alias': '别名',
|
'common.alias': '别名',
|
||||||
|
'common.failure': '失败',
|
||||||
|
'common.unknown_error': '未知错误',
|
||||||
|
'common.copy': '复制',
|
||||||
|
'common.custom_headers_label': '自定义请求头',
|
||||||
|
'common.custom_headers_hint': '可选,设置需要附带到请求中的 HTTP 头,名称和值均不能为空。',
|
||||||
|
'common.custom_headers_add': '添加请求头',
|
||||||
|
'common.custom_headers_key_placeholder': 'Header 名称,例如 X-Custom-Header',
|
||||||
|
'common.custom_headers_value_placeholder': 'Header 值',
|
||||||
|
|
||||||
// 页面标题
|
// 页面标题
|
||||||
'title.main': 'CLI Proxy API Management Center',
|
'title.main': 'CLI Proxy API Management Center',
|
||||||
@@ -82,6 +90,8 @@ const i18n = {
|
|||||||
'nav.ai_providers': 'AI 提供商',
|
'nav.ai_providers': 'AI 提供商',
|
||||||
'nav.auth_files': '认证文件',
|
'nav.auth_files': '认证文件',
|
||||||
'nav.usage_stats': '使用统计',
|
'nav.usage_stats': '使用统计',
|
||||||
|
'nav.config_management': '配置管理',
|
||||||
|
'nav.logs': '日志查看',
|
||||||
'nav.system_info': '系统信息',
|
'nav.system_info': '系统信息',
|
||||||
|
|
||||||
// 基础设置
|
// 基础设置
|
||||||
@@ -99,6 +109,10 @@ const i18n = {
|
|||||||
'basic_settings.quota_title': '配额超出行为',
|
'basic_settings.quota_title': '配额超出行为',
|
||||||
'basic_settings.quota_switch_project': '自动切换项目',
|
'basic_settings.quota_switch_project': '自动切换项目',
|
||||||
'basic_settings.quota_switch_preview': '切换到预览模型',
|
'basic_settings.quota_switch_preview': '切换到预览模型',
|
||||||
|
'basic_settings.usage_statistics_title': '使用统计',
|
||||||
|
'basic_settings.usage_statistics_enable': '启用使用统计',
|
||||||
|
'basic_settings.logging_title': '日志记录',
|
||||||
|
'basic_settings.logging_to_file_enable': '启用日志记录到文件',
|
||||||
|
|
||||||
// API 密钥管理
|
// API 密钥管理
|
||||||
'api_keys.title': 'API 密钥管理',
|
'api_keys.title': 'API 密钥管理',
|
||||||
@@ -122,10 +136,14 @@ const i18n = {
|
|||||||
'ai_providers.gemini_empty_desc': '点击上方按钮添加第一个密钥',
|
'ai_providers.gemini_empty_desc': '点击上方按钮添加第一个密钥',
|
||||||
'ai_providers.gemini_item_title': 'Gemini密钥',
|
'ai_providers.gemini_item_title': 'Gemini密钥',
|
||||||
'ai_providers.gemini_add_modal_title': '添加Gemini API密钥',
|
'ai_providers.gemini_add_modal_title': '添加Gemini API密钥',
|
||||||
'ai_providers.gemini_add_modal_key_label': 'API密钥:',
|
'ai_providers.gemini_add_modal_key_label': 'API密钥列表:',
|
||||||
'ai_providers.gemini_add_modal_key_placeholder': '请输入Gemini API密钥',
|
'ai_providers.gemini_add_modal_key_placeholder': '请输入Gemini API密钥(每行一个)',
|
||||||
|
'ai_providers.gemini_add_modal_key_hint': '可一次粘贴多个密钥,每行一个。',
|
||||||
|
'ai_providers.gemini_add_modal_url_label': 'Base URL (可选):',
|
||||||
|
'ai_providers.gemini_add_modal_url_placeholder': '例如: https://generativelanguage.googleapis.com',
|
||||||
'ai_providers.gemini_edit_modal_title': '编辑Gemini API密钥',
|
'ai_providers.gemini_edit_modal_title': '编辑Gemini API密钥',
|
||||||
'ai_providers.gemini_edit_modal_key_label': 'API密钥:',
|
'ai_providers.gemini_edit_modal_key_label': 'API密钥:',
|
||||||
|
'ai_providers.gemini_edit_modal_url_label': 'Base URL (可选):',
|
||||||
'ai_providers.gemini_delete_confirm': '确定要删除这个Gemini密钥吗?',
|
'ai_providers.gemini_delete_confirm': '确定要删除这个Gemini密钥吗?',
|
||||||
|
|
||||||
'ai_providers.codex_title': 'Codex API 配置',
|
'ai_providers.codex_title': 'Codex API 配置',
|
||||||
@@ -213,18 +231,95 @@ const i18n = {
|
|||||||
'auth_files.delete_success': '文件删除成功',
|
'auth_files.delete_success': '文件删除成功',
|
||||||
'auth_files.delete_all_success': '成功删除',
|
'auth_files.delete_all_success': '成功删除',
|
||||||
'auth_files.files_count': '个文件',
|
'auth_files.files_count': '个文件',
|
||||||
|
'auth_files.filter_all': '全部',
|
||||||
|
'auth_files.filter_qwen': 'Qwen',
|
||||||
|
'auth_files.filter_gemini': 'Gemini',
|
||||||
|
'auth_files.filter_gemini-cli': 'GeminiCLI',
|
||||||
|
'auth_files.filter_aistudio': 'AIStudio',
|
||||||
|
'auth_files.filter_claude': 'Claude',
|
||||||
|
'auth_files.filter_codex': 'Codex',
|
||||||
|
'auth_files.filter_iflow': 'iFlow',
|
||||||
|
'auth_files.filter_empty': '空文件',
|
||||||
|
'auth_files.filter_unknown': '其他',
|
||||||
|
'auth_files.type_qwen': 'Qwen',
|
||||||
|
'auth_files.type_gemini': 'Gemini',
|
||||||
|
'auth_files.type_gemini-cli': 'GeminiCLI',
|
||||||
|
'auth_files.type_aistudio': 'AIStudio',
|
||||||
|
'auth_files.type_claude': 'Claude',
|
||||||
|
'auth_files.type_codex': 'Codex',
|
||||||
|
'auth_files.type_iflow': 'iFlow',
|
||||||
|
'auth_files.type_empty': '空文件',
|
||||||
|
'auth_files.type_unknown': '其他',
|
||||||
|
|
||||||
// Gemini Web Token
|
|
||||||
'auth_login.gemini_web_title': 'Gemini Web Token',
|
// Codex OAuth
|
||||||
'auth_login.gemini_web_button': '保存 Gemini Web Token',
|
'auth_login.codex_oauth_title': 'Codex OAuth',
|
||||||
'auth_login.gemini_web_hint': '从浏览器开发者工具中获取 Gemini 网页版的 Cookie 值,用于直接认证访问 Gemini。',
|
'auth_login.codex_oauth_button': '开始 Codex 登录',
|
||||||
'auth_login.secure_1psid_label': '__Secure-1PSID Cookie:',
|
'auth_login.codex_oauth_hint': '通过 OAuth 流程登录 Codex 服务,自动获取并保存认证文件。',
|
||||||
'auth_login.secure_1psid_placeholder': '输入 __Secure-1PSID cookie 值',
|
'auth_login.codex_oauth_url_label': '授权链接:',
|
||||||
'auth_login.secure_1psidts_label': '__Secure-1PSIDTS Cookie:',
|
'auth_login.codex_open_link': '打开链接',
|
||||||
'auth_login.secure_1psidts_placeholder': '输入 __Secure-1PSIDTS cookie 值',
|
'auth_login.codex_copy_link': '复制链接',
|
||||||
'auth_login.gemini_web_label_label': '标签 (可选):',
|
'auth_login.codex_oauth_status_waiting': '等待认证中...',
|
||||||
'auth_login.gemini_web_label_placeholder': '输入标签名称 (可选)',
|
'auth_login.codex_oauth_status_success': '认证成功!',
|
||||||
'auth_login.gemini_web_saved': 'Gemini Web Token 保存成功',
|
'auth_login.codex_oauth_status_error': '认证失败:',
|
||||||
|
'auth_login.codex_oauth_start_error': '启动 Codex OAuth 失败:',
|
||||||
|
'auth_login.codex_oauth_polling_error': '检查认证状态失败:',
|
||||||
|
|
||||||
|
// Anthropic OAuth
|
||||||
|
'auth_login.anthropic_oauth_title': 'Anthropic OAuth',
|
||||||
|
'auth_login.anthropic_oauth_button': '开始 Anthropic 登录',
|
||||||
|
'auth_login.anthropic_oauth_hint': '通过 OAuth 流程登录 Anthropic (Claude) 服务,自动获取并保存认证文件。',
|
||||||
|
'auth_login.anthropic_oauth_url_label': '授权链接:',
|
||||||
|
'auth_login.anthropic_open_link': '打开链接',
|
||||||
|
'auth_login.anthropic_copy_link': '复制链接',
|
||||||
|
'auth_login.anthropic_oauth_status_waiting': '等待认证中...',
|
||||||
|
'auth_login.anthropic_oauth_status_success': '认证成功!',
|
||||||
|
'auth_login.anthropic_oauth_status_error': '认证失败:',
|
||||||
|
'auth_login.anthropic_oauth_start_error': '启动 Anthropic OAuth 失败:',
|
||||||
|
'auth_login.anthropic_oauth_polling_error': '检查认证状态失败:',
|
||||||
|
|
||||||
|
// Gemini CLI OAuth
|
||||||
|
'auth_login.gemini_cli_oauth_title': 'Gemini CLI OAuth',
|
||||||
|
'auth_login.gemini_cli_oauth_button': '开始 Gemini CLI 登录',
|
||||||
|
'auth_login.gemini_cli_oauth_hint': '通过 OAuth 流程登录 Google Gemini CLI 服务,自动获取并保存认证文件。',
|
||||||
|
'auth_login.gemini_cli_project_id_label': 'Google Cloud 项目 ID (可选):',
|
||||||
|
'auth_login.gemini_cli_project_id_placeholder': '输入 Google Cloud 项目 ID (可选)',
|
||||||
|
'auth_login.gemini_cli_project_id_hint': '如果指定了项目 ID,将使用该项目的认证信息。',
|
||||||
|
'auth_login.gemini_cli_oauth_url_label': '授权链接:',
|
||||||
|
'auth_login.gemini_cli_open_link': '打开链接',
|
||||||
|
'auth_login.gemini_cli_copy_link': '复制链接',
|
||||||
|
'auth_login.gemini_cli_oauth_status_waiting': '等待认证中...',
|
||||||
|
'auth_login.gemini_cli_oauth_status_success': '认证成功!',
|
||||||
|
'auth_login.gemini_cli_oauth_status_error': '认证失败:',
|
||||||
|
'auth_login.gemini_cli_oauth_start_error': '启动 Gemini CLI OAuth 失败:',
|
||||||
|
'auth_login.gemini_cli_oauth_polling_error': '检查认证状态失败:',
|
||||||
|
|
||||||
|
// Qwen OAuth
|
||||||
|
'auth_login.qwen_oauth_title': 'Qwen OAuth',
|
||||||
|
'auth_login.qwen_oauth_button': '开始 Qwen 登录',
|
||||||
|
'auth_login.qwen_oauth_hint': '通过设备授权流程登录 Qwen 服务,自动获取并保存认证文件。',
|
||||||
|
'auth_login.qwen_oauth_url_label': '授权链接:',
|
||||||
|
'auth_login.qwen_open_link': '打开链接',
|
||||||
|
'auth_login.qwen_copy_link': '复制链接',
|
||||||
|
'auth_login.qwen_oauth_status_waiting': '等待认证中...',
|
||||||
|
'auth_login.qwen_oauth_status_success': '认证成功!',
|
||||||
|
'auth_login.qwen_oauth_status_error': '认证失败:',
|
||||||
|
'auth_login.qwen_oauth_start_error': '启动 Qwen OAuth 失败:',
|
||||||
|
'auth_login.qwen_oauth_polling_error': '检查认证状态失败:',
|
||||||
|
'auth_login.missing_state': '无法获取认证状态参数',
|
||||||
|
|
||||||
|
// iFlow OAuth
|
||||||
|
'auth_login.iflow_oauth_title': 'iFlow OAuth',
|
||||||
|
'auth_login.iflow_oauth_button': '开始 iFlow 登录',
|
||||||
|
'auth_login.iflow_oauth_hint': '通过 OAuth 流程登录 iFlow 服务,自动获取并保存认证文件。',
|
||||||
|
'auth_login.iflow_oauth_url_label': '授权链接:',
|
||||||
|
'auth_login.iflow_open_link': '打开链接',
|
||||||
|
'auth_login.iflow_copy_link': '复制链接',
|
||||||
|
'auth_login.iflow_oauth_status_waiting': '等待认证中...',
|
||||||
|
'auth_login.iflow_oauth_status_success': '认证成功!',
|
||||||
|
'auth_login.iflow_oauth_status_error': '认证失败:',
|
||||||
|
'auth_login.iflow_oauth_start_error': '启动 iFlow OAuth 失败:',
|
||||||
|
'auth_login.iflow_oauth_polling_error': '检查认证状态失败:',
|
||||||
|
|
||||||
// 使用统计
|
// 使用统计
|
||||||
'usage_stats.title': '使用统计',
|
'usage_stats.title': '使用统计',
|
||||||
@@ -245,6 +340,48 @@ const i18n = {
|
|||||||
'usage_stats.tokens_count': 'Token数量',
|
'usage_stats.tokens_count': 'Token数量',
|
||||||
'usage_stats.models': '模型统计',
|
'usage_stats.models': '模型统计',
|
||||||
'usage_stats.success_rate': '成功率',
|
'usage_stats.success_rate': '成功率',
|
||||||
|
'stats.success': '成功',
|
||||||
|
'stats.failure': '失败',
|
||||||
|
|
||||||
|
// 日志查看
|
||||||
|
'logs.title': '日志查看',
|
||||||
|
'logs.refresh_button': '刷新日志',
|
||||||
|
'logs.clear_button': '清空日志',
|
||||||
|
'logs.download_button': '下载日志',
|
||||||
|
'logs.empty_title': '暂无日志记录',
|
||||||
|
'logs.empty_desc': '当启用"日志记录到文件"功能后,日志将显示在这里',
|
||||||
|
'logs.log_content': '日志内容',
|
||||||
|
'logs.loading': '正在加载日志...',
|
||||||
|
'logs.load_error': '加载日志失败',
|
||||||
|
'logs.clear_confirm': '确定要清空所有日志吗?此操作不可恢复!',
|
||||||
|
'logs.clear_success': '日志已清空',
|
||||||
|
'logs.download_success': '日志下载成功',
|
||||||
|
'logs.auto_refresh': '自动刷新',
|
||||||
|
'logs.auto_refresh_enabled': '自动刷新已开启',
|
||||||
|
'logs.auto_refresh_disabled': '自动刷新已关闭',
|
||||||
|
'logs.lines': '行',
|
||||||
|
'logs.removed': '已删除',
|
||||||
|
'logs.upgrade_required_title': '需要升级 CLI Proxy API',
|
||||||
|
'logs.upgrade_required_desc': '当前服务器版本不支持日志查看功能,请升级到最新版本的 CLI Proxy API 以使用此功能。',
|
||||||
|
|
||||||
|
// 配置管理
|
||||||
|
'config_management.title': '配置管理',
|
||||||
|
'config_management.editor_title': '配置文件',
|
||||||
|
'config_management.reload': '重新加载',
|
||||||
|
'config_management.save': '保存',
|
||||||
|
'config_management.description': '查看并编辑服务器上的 config.yaml 配置文件。保存前请确认语法正确。',
|
||||||
|
'config_management.status_idle': '等待操作',
|
||||||
|
'config_management.status_loading': '加载配置中...',
|
||||||
|
'config_management.status_loaded': '配置已加载',
|
||||||
|
'config_management.status_dirty': '有未保存的更改',
|
||||||
|
'config_management.status_disconnected': '请先连接服务器以加载配置',
|
||||||
|
'config_management.status_load_failed': '加载失败',
|
||||||
|
'config_management.status_saving': '正在保存配置...',
|
||||||
|
'config_management.status_saved': '配置保存完成',
|
||||||
|
'config_management.status_save_failed': '保存失败',
|
||||||
|
'config_management.save_success': '配置已保存',
|
||||||
|
'config_management.error_yaml_not_supported': '服务器未返回 YAML 格式,请确认 /config.yaml 接口可用',
|
||||||
|
'config_management.editor_placeholder': 'key: value',
|
||||||
|
|
||||||
// 系统信息
|
// 系统信息
|
||||||
'system_info.title': '系统信息',
|
'system_info.title': '系统信息',
|
||||||
@@ -264,12 +401,17 @@ const i18n = {
|
|||||||
'notification.retry_updated': '重试设置已更新',
|
'notification.retry_updated': '重试设置已更新',
|
||||||
'notification.quota_switch_project_updated': '项目切换设置已更新',
|
'notification.quota_switch_project_updated': '项目切换设置已更新',
|
||||||
'notification.quota_switch_preview_updated': '预览模型切换设置已更新',
|
'notification.quota_switch_preview_updated': '预览模型切换设置已更新',
|
||||||
|
'notification.usage_statistics_updated': '使用统计设置已更新',
|
||||||
|
'notification.logging_to_file_updated': '日志记录设置已更新',
|
||||||
'notification.api_key_added': 'API密钥添加成功',
|
'notification.api_key_added': 'API密钥添加成功',
|
||||||
'notification.api_key_updated': 'API密钥更新成功',
|
'notification.api_key_updated': 'API密钥更新成功',
|
||||||
'notification.api_key_deleted': 'API密钥删除成功',
|
'notification.api_key_deleted': 'API密钥删除成功',
|
||||||
'notification.gemini_key_added': 'Gemini密钥添加成功',
|
'notification.gemini_key_added': 'Gemini密钥添加成功',
|
||||||
'notification.gemini_key_updated': 'Gemini密钥更新成功',
|
'notification.gemini_key_updated': 'Gemini密钥更新成功',
|
||||||
'notification.gemini_key_deleted': 'Gemini密钥删除成功',
|
'notification.gemini_key_deleted': 'Gemini密钥删除成功',
|
||||||
|
'notification.gemini_multi_input_required': '请先输入至少一个Gemini密钥',
|
||||||
|
'notification.gemini_multi_failed': 'Gemini密钥批量添加失败',
|
||||||
|
'notification.gemini_multi_summary': 'Gemini批量添加完成:成功 {success},跳过 {skipped},失败 {failed}',
|
||||||
'notification.codex_config_added': 'Codex配置添加成功',
|
'notification.codex_config_added': 'Codex配置添加成功',
|
||||||
'notification.codex_config_updated': 'Codex配置更新成功',
|
'notification.codex_config_updated': 'Codex配置更新成功',
|
||||||
'notification.codex_config_deleted': 'Codex配置删除成功',
|
'notification.codex_config_deleted': 'Codex配置删除成功',
|
||||||
@@ -298,6 +440,7 @@ const i18n = {
|
|||||||
'notification.gemini_api_key': 'Gemini API密钥',
|
'notification.gemini_api_key': 'Gemini API密钥',
|
||||||
'notification.codex_api_key': 'Codex API密钥',
|
'notification.codex_api_key': 'Codex API密钥',
|
||||||
'notification.claude_api_key': 'Claude API密钥',
|
'notification.claude_api_key': 'Claude API密钥',
|
||||||
|
'notification.link_copied': '链接已复制到剪贴板',
|
||||||
|
|
||||||
// 语言切换
|
// 语言切换
|
||||||
'language.switch': '语言',
|
'language.switch': '语言',
|
||||||
@@ -312,6 +455,10 @@ const i18n = {
|
|||||||
'theme.switch_to_dark': '切换到暗色模式',
|
'theme.switch_to_dark': '切换到暗色模式',
|
||||||
'theme.auto': '跟随系统',
|
'theme.auto': '跟随系统',
|
||||||
|
|
||||||
|
// 侧边栏
|
||||||
|
'sidebar.toggle_expand': '展开侧边栏',
|
||||||
|
'sidebar.toggle_collapse': '收起侧边栏',
|
||||||
|
|
||||||
// 页脚
|
// 页脚
|
||||||
'footer.version': '版本',
|
'footer.version': '版本',
|
||||||
'footer.author': '作者'
|
'footer.author': '作者'
|
||||||
@@ -347,6 +494,16 @@ const i18n = {
|
|||||||
'common.required': 'Required',
|
'common.required': 'Required',
|
||||||
'common.api_key': 'Key',
|
'common.api_key': 'Key',
|
||||||
'common.base_url': 'Address',
|
'common.base_url': 'Address',
|
||||||
|
'common.proxy_url': 'Proxy',
|
||||||
|
'common.alias': 'Alias',
|
||||||
|
'common.failure': 'Failure',
|
||||||
|
'common.unknown_error': 'Unknown error',
|
||||||
|
'common.copy': 'Copy',
|
||||||
|
'common.custom_headers_label': 'Custom Headers',
|
||||||
|
'common.custom_headers_hint': 'Optional HTTP headers to send with the request. Leave blank to remove.',
|
||||||
|
'common.custom_headers_add': 'Add Header',
|
||||||
|
'common.custom_headers_key_placeholder': 'Header name, e.g. X-Custom-Header',
|
||||||
|
'common.custom_headers_value_placeholder': 'Header value',
|
||||||
|
|
||||||
// Page titles
|
// Page titles
|
||||||
'title.main': 'CLI Proxy API Management Center',
|
'title.main': 'CLI Proxy API Management Center',
|
||||||
@@ -391,6 +548,8 @@ const i18n = {
|
|||||||
'nav.ai_providers': 'AI Providers',
|
'nav.ai_providers': 'AI Providers',
|
||||||
'nav.auth_files': 'Auth Files',
|
'nav.auth_files': 'Auth Files',
|
||||||
'nav.usage_stats': 'Usage Statistics',
|
'nav.usage_stats': 'Usage Statistics',
|
||||||
|
'nav.config_management': 'Config Management',
|
||||||
|
'nav.logs': 'Logs Viewer',
|
||||||
'nav.system_info': 'System Info',
|
'nav.system_info': 'System Info',
|
||||||
|
|
||||||
// Basic settings
|
// Basic settings
|
||||||
@@ -408,6 +567,10 @@ const i18n = {
|
|||||||
'basic_settings.quota_title': 'Quota Exceeded Behavior',
|
'basic_settings.quota_title': 'Quota Exceeded Behavior',
|
||||||
'basic_settings.quota_switch_project': 'Auto Switch Project',
|
'basic_settings.quota_switch_project': 'Auto Switch Project',
|
||||||
'basic_settings.quota_switch_preview': 'Switch to Preview Model',
|
'basic_settings.quota_switch_preview': 'Switch to Preview Model',
|
||||||
|
'basic_settings.usage_statistics_title': 'Usage Statistics',
|
||||||
|
'basic_settings.usage_statistics_enable': 'Enable usage statistics',
|
||||||
|
'basic_settings.logging_title': 'Logging',
|
||||||
|
'basic_settings.logging_to_file_enable': 'Enable logging to file',
|
||||||
|
|
||||||
// API Keys management
|
// API Keys management
|
||||||
'api_keys.title': 'API Keys Management',
|
'api_keys.title': 'API Keys Management',
|
||||||
@@ -431,10 +594,14 @@ const i18n = {
|
|||||||
'ai_providers.gemini_empty_desc': 'Click the button above to add the first key',
|
'ai_providers.gemini_empty_desc': 'Click the button above to add the first key',
|
||||||
'ai_providers.gemini_item_title': 'Gemini Key',
|
'ai_providers.gemini_item_title': 'Gemini Key',
|
||||||
'ai_providers.gemini_add_modal_title': 'Add Gemini API Key',
|
'ai_providers.gemini_add_modal_title': 'Add Gemini API Key',
|
||||||
'ai_providers.gemini_add_modal_key_label': 'API Key:',
|
'ai_providers.gemini_add_modal_key_label': 'API Keys:',
|
||||||
'ai_providers.gemini_add_modal_key_placeholder': 'Please enter Gemini API key',
|
'ai_providers.gemini_add_modal_key_placeholder': 'Enter Gemini API keys (one per line)',
|
||||||
|
'ai_providers.gemini_add_modal_key_hint': 'You can paste multiple keys, one per line.',
|
||||||
|
'ai_providers.gemini_add_modal_url_label': 'Base URL (optional):',
|
||||||
|
'ai_providers.gemini_add_modal_url_placeholder': 'e.g. https://generativelanguage.googleapis.com',
|
||||||
'ai_providers.gemini_edit_modal_title': 'Edit Gemini API Key',
|
'ai_providers.gemini_edit_modal_title': 'Edit Gemini API Key',
|
||||||
'ai_providers.gemini_edit_modal_key_label': 'API Key:',
|
'ai_providers.gemini_edit_modal_key_label': 'API Key:',
|
||||||
|
'ai_providers.gemini_edit_modal_url_label': 'Base URL (optional):',
|
||||||
'ai_providers.gemini_delete_confirm': 'Are you sure you want to delete this Gemini key?',
|
'ai_providers.gemini_delete_confirm': 'Are you sure you want to delete this Gemini key?',
|
||||||
|
|
||||||
'ai_providers.codex_title': 'Codex API Configuration',
|
'ai_providers.codex_title': 'Codex API Configuration',
|
||||||
@@ -447,9 +614,12 @@ const i18n = {
|
|||||||
'ai_providers.codex_add_modal_key_placeholder': 'Please enter Codex API key',
|
'ai_providers.codex_add_modal_key_placeholder': 'Please enter Codex API key',
|
||||||
'ai_providers.codex_add_modal_url_label': 'Base URL (Optional):',
|
'ai_providers.codex_add_modal_url_label': 'Base URL (Optional):',
|
||||||
'ai_providers.codex_add_modal_url_placeholder': 'e.g.: https://api.example.com',
|
'ai_providers.codex_add_modal_url_placeholder': 'e.g.: https://api.example.com',
|
||||||
|
'ai_providers.codex_add_modal_proxy_label': 'Proxy URL (Optional):',
|
||||||
|
'ai_providers.codex_add_modal_proxy_placeholder': 'e.g.: socks5://proxy.example.com:1080',
|
||||||
'ai_providers.codex_edit_modal_title': 'Edit Codex API Configuration',
|
'ai_providers.codex_edit_modal_title': 'Edit Codex API Configuration',
|
||||||
'ai_providers.codex_edit_modal_key_label': 'API Key:',
|
'ai_providers.codex_edit_modal_key_label': 'API Key:',
|
||||||
'ai_providers.codex_edit_modal_url_label': 'Base URL (Optional):',
|
'ai_providers.codex_edit_modal_url_label': 'Base URL (Optional):',
|
||||||
|
'ai_providers.codex_edit_modal_proxy_label': 'Proxy URL (Optional):',
|
||||||
'ai_providers.codex_delete_confirm': 'Are you sure you want to delete this Codex configuration?',
|
'ai_providers.codex_delete_confirm': 'Are you sure you want to delete this Codex configuration?',
|
||||||
|
|
||||||
'ai_providers.claude_title': 'Claude API Configuration',
|
'ai_providers.claude_title': 'Claude API Configuration',
|
||||||
@@ -462,9 +632,12 @@ const i18n = {
|
|||||||
'ai_providers.claude_add_modal_key_placeholder': 'Please enter Claude API key',
|
'ai_providers.claude_add_modal_key_placeholder': 'Please enter Claude API key',
|
||||||
'ai_providers.claude_add_modal_url_label': 'Base URL (Optional):',
|
'ai_providers.claude_add_modal_url_label': 'Base URL (Optional):',
|
||||||
'ai_providers.claude_add_modal_url_placeholder': 'e.g.: https://api.anthropic.com',
|
'ai_providers.claude_add_modal_url_placeholder': 'e.g.: https://api.anthropic.com',
|
||||||
|
'ai_providers.claude_add_modal_proxy_label': 'Proxy URL (Optional):',
|
||||||
|
'ai_providers.claude_add_modal_proxy_placeholder': 'e.g.: socks5://proxy.example.com:1080',
|
||||||
'ai_providers.claude_edit_modal_title': 'Edit Claude API Configuration',
|
'ai_providers.claude_edit_modal_title': 'Edit Claude API Configuration',
|
||||||
'ai_providers.claude_edit_modal_key_label': 'API Key:',
|
'ai_providers.claude_edit_modal_key_label': 'API Key:',
|
||||||
'ai_providers.claude_edit_modal_url_label': 'Base URL (Optional):',
|
'ai_providers.claude_edit_modal_url_label': 'Base URL (Optional):',
|
||||||
|
'ai_providers.claude_edit_modal_proxy_label': 'Proxy URL (Optional):',
|
||||||
'ai_providers.claude_delete_confirm': 'Are you sure you want to delete this Claude configuration?',
|
'ai_providers.claude_delete_confirm': 'Are you sure you want to delete this Claude configuration?',
|
||||||
|
|
||||||
'ai_providers.openai_title': 'OpenAI Compatible Providers',
|
'ai_providers.openai_title': 'OpenAI Compatible Providers',
|
||||||
@@ -478,10 +651,19 @@ const i18n = {
|
|||||||
'ai_providers.openai_add_modal_url_placeholder': 'e.g.: https://openrouter.ai/api/v1',
|
'ai_providers.openai_add_modal_url_placeholder': 'e.g.: https://openrouter.ai/api/v1',
|
||||||
'ai_providers.openai_add_modal_keys_label': 'API Keys (one per line):',
|
'ai_providers.openai_add_modal_keys_label': 'API Keys (one per line):',
|
||||||
'ai_providers.openai_add_modal_keys_placeholder': 'sk-key1\nsk-key2',
|
'ai_providers.openai_add_modal_keys_placeholder': 'sk-key1\nsk-key2',
|
||||||
|
'ai_providers.openai_add_modal_keys_proxy_label': 'Proxy URL (one per line, optional):',
|
||||||
|
'ai_providers.openai_add_modal_keys_proxy_placeholder': 'socks5://proxy.example.com:1080\n',
|
||||||
|
'ai_providers.openai_add_modal_models_label': 'Model List (name[, alias] one per line):',
|
||||||
|
'ai_providers.openai_models_hint': 'Example: gpt-4o-mini or moonshotai/kimi-k2:free, kimi-k2',
|
||||||
|
'ai_providers.openai_model_name_placeholder': 'Model name, e.g. moonshotai/kimi-k2:free',
|
||||||
|
'ai_providers.openai_model_alias_placeholder': 'Model alias (optional)',
|
||||||
|
'ai_providers.openai_models_add_btn': 'Add Model',
|
||||||
'ai_providers.openai_edit_modal_title': 'Edit OpenAI Compatible Provider',
|
'ai_providers.openai_edit_modal_title': 'Edit OpenAI Compatible Provider',
|
||||||
'ai_providers.openai_edit_modal_name_label': 'Provider Name:',
|
'ai_providers.openai_edit_modal_name_label': 'Provider Name:',
|
||||||
'ai_providers.openai_edit_modal_url_label': 'Base URL:',
|
'ai_providers.openai_edit_modal_url_label': 'Base URL:',
|
||||||
'ai_providers.openai_edit_modal_keys_label': 'API Keys (one per line):',
|
'ai_providers.openai_edit_modal_keys_label': 'API Keys (one per line):',
|
||||||
|
'ai_providers.openai_edit_modal_keys_proxy_label': 'Proxy URL (one per line, optional):',
|
||||||
|
'ai_providers.openai_edit_modal_models_label': 'Model List (name[, alias] one per line):',
|
||||||
'ai_providers.openai_delete_confirm': 'Are you sure you want to delete this OpenAI provider?',
|
'ai_providers.openai_delete_confirm': 'Are you sure you want to delete this OpenAI provider?',
|
||||||
'ai_providers.openai_keys_count': 'Keys Count',
|
'ai_providers.openai_keys_count': 'Keys Count',
|
||||||
'ai_providers.openai_models_count': 'Models Count',
|
'ai_providers.openai_models_count': 'Models Count',
|
||||||
@@ -507,18 +689,94 @@ const i18n = {
|
|||||||
'auth_files.delete_success': 'File deleted successfully',
|
'auth_files.delete_success': 'File deleted successfully',
|
||||||
'auth_files.delete_all_success': 'Successfully deleted',
|
'auth_files.delete_all_success': 'Successfully deleted',
|
||||||
'auth_files.files_count': 'files',
|
'auth_files.files_count': 'files',
|
||||||
|
'auth_files.filter_all': 'All',
|
||||||
|
'auth_files.filter_qwen': 'Qwen',
|
||||||
|
'auth_files.filter_gemini': 'Gemini',
|
||||||
|
'auth_files.filter_gemini-cli': 'GeminiCLI',
|
||||||
|
'auth_files.filter_aistudio': 'AIStudio',
|
||||||
|
'auth_files.filter_claude': 'Claude',
|
||||||
|
'auth_files.filter_codex': 'Codex',
|
||||||
|
'auth_files.filter_iflow': 'iFlow',
|
||||||
|
'auth_files.filter_empty': 'Empty',
|
||||||
|
'auth_files.filter_unknown': 'Other',
|
||||||
|
'auth_files.type_qwen': 'Qwen',
|
||||||
|
'auth_files.type_gemini': 'Gemini',
|
||||||
|
'auth_files.type_gemini-cli': 'GeminiCLI',
|
||||||
|
'auth_files.type_aistudio': 'AIStudio',
|
||||||
|
'auth_files.type_claude': 'Claude',
|
||||||
|
'auth_files.type_codex': 'Codex',
|
||||||
|
'auth_files.type_iflow': 'iFlow',
|
||||||
|
'auth_files.type_empty': 'Empty',
|
||||||
|
'auth_files.type_unknown': 'Other',
|
||||||
|
|
||||||
// Gemini Web Token
|
// Codex OAuth
|
||||||
'auth_login.gemini_web_title': 'Gemini Web Token',
|
'auth_login.codex_oauth_title': 'Codex OAuth',
|
||||||
'auth_login.gemini_web_button': 'Save Gemini Web Token',
|
'auth_login.codex_oauth_button': 'Start Codex Login',
|
||||||
'auth_login.gemini_web_hint': 'Obtain the Cookie value of the Gemini web version from the browser\'s developer tools, used for direct authentication to access Gemini.',
|
'auth_login.codex_oauth_hint': 'Login to Codex service through OAuth flow, automatically obtain and save authentication files.',
|
||||||
'auth_login.secure_1psid_label': '__Secure-1PSID Cookie:',
|
'auth_login.codex_oauth_url_label': 'Authorization URL:',
|
||||||
'auth_login.secure_1psid_placeholder': 'Enter __Secure-1PSID cookie value',
|
'auth_login.codex_open_link': 'Open Link',
|
||||||
'auth_login.secure_1psidts_label': '__Secure-1PSIDTS Cookie:',
|
'auth_login.codex_copy_link': 'Copy Link',
|
||||||
'auth_login.secure_1psidts_placeholder': 'Enter __Secure-1PSIDTS cookie value',
|
'auth_login.codex_oauth_status_waiting': 'Waiting for authentication...',
|
||||||
'auth_login.gemini_web_label_label': 'Label (Optional):',
|
'auth_login.codex_oauth_status_success': 'Authentication successful!',
|
||||||
'auth_login.gemini_web_label_placeholder': 'Enter label name (optional)',
|
'auth_login.codex_oauth_status_error': 'Authentication failed:',
|
||||||
'auth_login.gemini_web_saved': 'Gemini Web Token saved successfully',
|
'auth_login.codex_oauth_start_error': 'Failed to start Codex OAuth:',
|
||||||
|
'auth_login.codex_oauth_polling_error': 'Failed to check authentication status:',
|
||||||
|
|
||||||
|
// Anthropic OAuth
|
||||||
|
'auth_login.anthropic_oauth_title': 'Anthropic OAuth',
|
||||||
|
'auth_login.anthropic_oauth_button': 'Start Anthropic Login',
|
||||||
|
'auth_login.anthropic_oauth_hint': 'Login to Anthropic (Claude) service through OAuth flow, automatically obtain and save authentication files.',
|
||||||
|
'auth_login.anthropic_oauth_url_label': 'Authorization URL:',
|
||||||
|
'auth_login.anthropic_open_link': 'Open Link',
|
||||||
|
'auth_login.anthropic_copy_link': 'Copy Link',
|
||||||
|
'auth_login.anthropic_oauth_status_waiting': 'Waiting for authentication...',
|
||||||
|
'auth_login.anthropic_oauth_status_success': 'Authentication successful!',
|
||||||
|
'auth_login.anthropic_oauth_status_error': 'Authentication failed:',
|
||||||
|
'auth_login.anthropic_oauth_start_error': 'Failed to start Anthropic OAuth:',
|
||||||
|
'auth_login.anthropic_oauth_polling_error': 'Failed to check authentication status:',
|
||||||
|
|
||||||
|
// Gemini CLI OAuth
|
||||||
|
'auth_login.gemini_cli_oauth_title': 'Gemini CLI OAuth',
|
||||||
|
'auth_login.gemini_cli_oauth_button': 'Start Gemini CLI Login',
|
||||||
|
'auth_login.gemini_cli_oauth_hint': 'Login to Google Gemini CLI service through OAuth flow, automatically obtain and save authentication files.',
|
||||||
|
'auth_login.gemini_cli_project_id_label': 'Google Cloud Project ID (Optional):',
|
||||||
|
'auth_login.gemini_cli_project_id_placeholder': 'Enter Google Cloud Project ID (optional)',
|
||||||
|
'auth_login.gemini_cli_project_id_hint': 'If a project ID is specified, authentication information for that project will be used.',
|
||||||
|
'auth_login.gemini_cli_oauth_url_label': 'Authorization URL:',
|
||||||
|
'auth_login.gemini_cli_open_link': 'Open Link',
|
||||||
|
'auth_login.gemini_cli_copy_link': 'Copy Link',
|
||||||
|
'auth_login.gemini_cli_oauth_status_waiting': 'Waiting for authentication...',
|
||||||
|
'auth_login.gemini_cli_oauth_status_success': 'Authentication successful!',
|
||||||
|
'auth_login.gemini_cli_oauth_status_error': 'Authentication failed:',
|
||||||
|
'auth_login.gemini_cli_oauth_start_error': 'Failed to start Gemini CLI OAuth:',
|
||||||
|
'auth_login.gemini_cli_oauth_polling_error': 'Failed to check authentication status:',
|
||||||
|
|
||||||
|
// Qwen OAuth
|
||||||
|
'auth_login.qwen_oauth_title': 'Qwen OAuth',
|
||||||
|
'auth_login.qwen_oauth_button': 'Start Qwen Login',
|
||||||
|
'auth_login.qwen_oauth_hint': 'Login to Qwen service through device authorization flow, automatically obtain and save authentication files.',
|
||||||
|
'auth_login.qwen_oauth_url_label': 'Authorization URL:',
|
||||||
|
'auth_login.qwen_open_link': 'Open Link',
|
||||||
|
'auth_login.qwen_copy_link': 'Copy Link',
|
||||||
|
'auth_login.qwen_oauth_status_waiting': 'Waiting for authentication...',
|
||||||
|
'auth_login.qwen_oauth_status_success': 'Authentication successful!',
|
||||||
|
'auth_login.qwen_oauth_status_error': 'Authentication failed:',
|
||||||
|
'auth_login.qwen_oauth_start_error': 'Failed to start Qwen OAuth:',
|
||||||
|
'auth_login.qwen_oauth_polling_error': 'Failed to check authentication status:',
|
||||||
|
'auth_login.missing_state': 'Unable to retrieve authentication state parameter',
|
||||||
|
|
||||||
|
// iFlow OAuth
|
||||||
|
'auth_login.iflow_oauth_title': 'iFlow OAuth',
|
||||||
|
'auth_login.iflow_oauth_button': 'Start iFlow Login',
|
||||||
|
'auth_login.iflow_oauth_hint': 'Login to iFlow service through OAuth flow, automatically obtain and save authentication files.',
|
||||||
|
'auth_login.iflow_oauth_url_label': 'Authorization URL:',
|
||||||
|
'auth_login.iflow_open_link': 'Open Link',
|
||||||
|
'auth_login.iflow_copy_link': 'Copy Link',
|
||||||
|
'auth_login.iflow_oauth_status_waiting': 'Waiting for authentication...',
|
||||||
|
'auth_login.iflow_oauth_status_success': 'Authentication successful!',
|
||||||
|
'auth_login.iflow_oauth_status_error': 'Authentication failed:',
|
||||||
|
'auth_login.iflow_oauth_start_error': 'Failed to start iFlow OAuth:',
|
||||||
|
'auth_login.iflow_oauth_polling_error': 'Failed to check authentication status:',
|
||||||
|
|
||||||
// Usage Statistics
|
// Usage Statistics
|
||||||
'usage_stats.title': 'Usage Statistics',
|
'usage_stats.title': 'Usage Statistics',
|
||||||
@@ -539,6 +797,48 @@ const i18n = {
|
|||||||
'usage_stats.tokens_count': 'Token Count',
|
'usage_stats.tokens_count': 'Token Count',
|
||||||
'usage_stats.models': 'Model Statistics',
|
'usage_stats.models': 'Model Statistics',
|
||||||
'usage_stats.success_rate': 'Success Rate',
|
'usage_stats.success_rate': 'Success Rate',
|
||||||
|
'stats.success': 'Success',
|
||||||
|
'stats.failure': 'Failure',
|
||||||
|
|
||||||
|
// Logs viewer
|
||||||
|
'logs.title': 'Logs Viewer',
|
||||||
|
'logs.refresh_button': 'Refresh Logs',
|
||||||
|
'logs.clear_button': 'Clear Logs',
|
||||||
|
'logs.download_button': 'Download Logs',
|
||||||
|
'logs.empty_title': 'No Logs Available',
|
||||||
|
'logs.empty_desc': 'When "Enable logging to file" is enabled, logs will be displayed here',
|
||||||
|
'logs.log_content': 'Log Content',
|
||||||
|
'logs.loading': 'Loading logs...',
|
||||||
|
'logs.load_error': 'Failed to load logs',
|
||||||
|
'logs.clear_confirm': 'Are you sure you want to clear all logs? This action cannot be undone!',
|
||||||
|
'logs.clear_success': 'Logs cleared successfully',
|
||||||
|
'logs.download_success': 'Logs downloaded successfully',
|
||||||
|
'logs.auto_refresh': 'Auto Refresh',
|
||||||
|
'logs.auto_refresh_enabled': 'Auto refresh enabled',
|
||||||
|
'logs.auto_refresh_disabled': 'Auto refresh disabled',
|
||||||
|
'logs.lines': 'lines',
|
||||||
|
'logs.removed': 'Removed',
|
||||||
|
'logs.upgrade_required_title': 'Please Upgrade CLI Proxy API',
|
||||||
|
'logs.upgrade_required_desc': 'The current server version does not support the logs viewing feature. Please upgrade to the latest version of CLI Proxy API to use this feature.',
|
||||||
|
|
||||||
|
// Config management
|
||||||
|
'config_management.title': 'Config Management',
|
||||||
|
'config_management.editor_title': 'Configuration File',
|
||||||
|
'config_management.reload': 'Reload',
|
||||||
|
'config_management.save': 'Save',
|
||||||
|
'config_management.description': 'View and edit the server-side config.yaml file. Validate the syntax before saving.',
|
||||||
|
'config_management.status_idle': 'Waiting for action',
|
||||||
|
'config_management.status_loading': 'Loading configuration...',
|
||||||
|
'config_management.status_loaded': 'Configuration loaded',
|
||||||
|
'config_management.status_dirty': 'Unsaved changes',
|
||||||
|
'config_management.status_disconnected': 'Connect to the server to load the configuration',
|
||||||
|
'config_management.status_load_failed': 'Load failed',
|
||||||
|
'config_management.status_saving': 'Saving configuration...',
|
||||||
|
'config_management.status_saved': 'Configuration saved',
|
||||||
|
'config_management.status_save_failed': 'Save failed',
|
||||||
|
'config_management.save_success': 'Configuration saved successfully',
|
||||||
|
'config_management.error_yaml_not_supported': 'Server did not return YAML. Verify the /config.yaml endpoint is available.',
|
||||||
|
'config_management.editor_placeholder': 'key: value',
|
||||||
|
|
||||||
// System info
|
// System info
|
||||||
'system_info.title': 'System Information',
|
'system_info.title': 'System Information',
|
||||||
@@ -558,18 +858,25 @@ const i18n = {
|
|||||||
'notification.retry_updated': 'Retry settings updated',
|
'notification.retry_updated': 'Retry settings updated',
|
||||||
'notification.quota_switch_project_updated': 'Project switch settings updated',
|
'notification.quota_switch_project_updated': 'Project switch settings updated',
|
||||||
'notification.quota_switch_preview_updated': 'Preview model switch settings updated',
|
'notification.quota_switch_preview_updated': 'Preview model switch settings updated',
|
||||||
|
'notification.usage_statistics_updated': 'Usage statistics settings updated',
|
||||||
|
'notification.logging_to_file_updated': 'Logging settings updated',
|
||||||
'notification.api_key_added': 'API key added successfully',
|
'notification.api_key_added': 'API key added successfully',
|
||||||
'notification.api_key_updated': 'API key updated successfully',
|
'notification.api_key_updated': 'API key updated successfully',
|
||||||
'notification.api_key_deleted': 'API key deleted successfully',
|
'notification.api_key_deleted': 'API key deleted successfully',
|
||||||
'notification.gemini_key_added': 'Gemini key added successfully',
|
'notification.gemini_key_added': 'Gemini key added successfully',
|
||||||
'notification.gemini_key_updated': 'Gemini key updated successfully',
|
'notification.gemini_key_updated': 'Gemini key updated successfully',
|
||||||
'notification.gemini_key_deleted': 'Gemini key deleted successfully',
|
'notification.gemini_key_deleted': 'Gemini key deleted successfully',
|
||||||
|
'notification.gemini_multi_input_required': 'Please enter at least one Gemini key',
|
||||||
|
'notification.gemini_multi_failed': 'Gemini bulk add failed',
|
||||||
|
'notification.gemini_multi_summary': 'Gemini bulk add finished: {success} added, {skipped} skipped, {failed} failed',
|
||||||
'notification.codex_config_added': 'Codex configuration added successfully',
|
'notification.codex_config_added': 'Codex configuration added successfully',
|
||||||
'notification.codex_config_updated': 'Codex configuration updated successfully',
|
'notification.codex_config_updated': 'Codex configuration updated successfully',
|
||||||
'notification.codex_config_deleted': 'Codex configuration deleted successfully',
|
'notification.codex_config_deleted': 'Codex configuration deleted successfully',
|
||||||
'notification.claude_config_added': 'Claude configuration added successfully',
|
'notification.claude_config_added': 'Claude configuration added successfully',
|
||||||
'notification.claude_config_updated': 'Claude configuration updated successfully',
|
'notification.claude_config_updated': 'Claude configuration updated successfully',
|
||||||
'notification.claude_config_deleted': 'Claude configuration deleted successfully',
|
'notification.claude_config_deleted': 'Claude configuration deleted successfully',
|
||||||
|
'notification.field_required': 'Required fields cannot be empty',
|
||||||
|
'notification.openai_provider_required': 'Please fill in provider name and Base URL',
|
||||||
'notification.openai_provider_added': 'OpenAI provider added successfully',
|
'notification.openai_provider_added': 'OpenAI provider added successfully',
|
||||||
'notification.openai_provider_updated': 'OpenAI provider updated successfully',
|
'notification.openai_provider_updated': 'OpenAI provider updated successfully',
|
||||||
'notification.openai_provider_deleted': 'OpenAI provider deleted successfully',
|
'notification.openai_provider_deleted': 'OpenAI provider deleted successfully',
|
||||||
@@ -590,6 +897,7 @@ const i18n = {
|
|||||||
'notification.gemini_api_key': 'Gemini API key',
|
'notification.gemini_api_key': 'Gemini API key',
|
||||||
'notification.codex_api_key': 'Codex API key',
|
'notification.codex_api_key': 'Codex API key',
|
||||||
'notification.claude_api_key': 'Claude API key',
|
'notification.claude_api_key': 'Claude API key',
|
||||||
|
'notification.link_copied': 'Link copied to clipboard',
|
||||||
|
|
||||||
// Language switch
|
// Language switch
|
||||||
'language.switch': 'Language',
|
'language.switch': 'Language',
|
||||||
@@ -604,6 +912,10 @@ const i18n = {
|
|||||||
'theme.switch_to_dark': 'Switch to dark mode',
|
'theme.switch_to_dark': 'Switch to dark mode',
|
||||||
'theme.auto': 'Follow system',
|
'theme.auto': 'Follow system',
|
||||||
|
|
||||||
|
// Sidebar
|
||||||
|
'sidebar.toggle_expand': 'Expand sidebar',
|
||||||
|
'sidebar.toggle_collapse': 'Collapse sidebar',
|
||||||
|
|
||||||
// Footer
|
// Footer
|
||||||
'footer.version': 'Version',
|
'footer.version': 'Version',
|
||||||
'footer.author': 'Author'
|
'footer.author': 'Author'
|
||||||
@@ -613,8 +925,8 @@ const i18n = {
|
|||||||
// 获取翻译文本
|
// 获取翻译文本
|
||||||
t(key, params = {}) {
|
t(key, params = {}) {
|
||||||
const translation = this.translations[this.currentLanguage]?.[key] ||
|
const translation = this.translations[this.currentLanguage]?.[key] ||
|
||||||
this.translations[this.fallbackLanguage]?.[key] ||
|
this.translations[this.fallbackLanguage]?.[key] ||
|
||||||
key;
|
key;
|
||||||
|
|
||||||
// 简单的参数替换
|
// 简单的参数替换
|
||||||
return translation.replace(/\{(\w+)\}/g, (match, param) => {
|
return translation.replace(/\{(\w+)\}/g, (match, param) => {
|
||||||
@@ -653,6 +965,30 @@ const i18n = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 更新所有包含 data-i18n-placeholder 的输入框占位符
|
||||||
|
document.querySelectorAll('[data-i18n-placeholder]').forEach(element => {
|
||||||
|
const key = element.getAttribute('data-i18n-placeholder');
|
||||||
|
element.placeholder = this.t(key);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新 data-i18n-title
|
||||||
|
document.querySelectorAll('[data-i18n-title]').forEach(element => {
|
||||||
|
const key = element.getAttribute('data-i18n-title');
|
||||||
|
element.title = this.t(key);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新 data-i18n-tooltip
|
||||||
|
document.querySelectorAll('[data-i18n-tooltip]').forEach(element => {
|
||||||
|
const key = element.getAttribute('data-i18n-tooltip');
|
||||||
|
element.setAttribute('data-tooltip', this.t(key));
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新 data-i18n-text(常用于按钮或标签)
|
||||||
|
document.querySelectorAll('[data-i18n-text]').forEach(element => {
|
||||||
|
const key = element.getAttribute('data-i18n-text');
|
||||||
|
element.textContent = this.t(key);
|
||||||
|
});
|
||||||
|
|
||||||
// 更新所有带有 data-i18n-html 属性的元素(支持HTML)
|
// 更新所有带有 data-i18n-html 属性的元素(支持HTML)
|
||||||
document.querySelectorAll('[data-i18n-html]').forEach(element => {
|
document.querySelectorAll('[data-i18n-html]').forEach(element => {
|
||||||
const key = element.getAttribute('data-i18n-html');
|
const key = element.getAttribute('data-i18n-html');
|
||||||
|
|||||||
1141
index.html
1141
index.html
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,5 @@
|
|||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "local"
|
"url": "local"
|
||||||
},
|
}
|
||||||
"dependencies": {}
|
|
||||||
}
|
}
|
||||||
|
|||||||
1760
styles.css
1760
styles.css
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user