mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-06 08:06:19 +00:00
feat(frontend): add reactive localization and refine admin layouts (#501)
* feat(frontend): add English and Traditional Chinese locales * fix(frontend): capitalize the English login key label * fix(frontend): capitalize standalone English labels * feat(frontend): add reactive localization and refine admin layouts Replace DOM text translation with domain-based Vue I18n resources for English, Simplified Chinese, and Traditional Chinese. Localize shared controls, notifications, charts, and key usage while refining table alignment, menus, and compact labels. Expose semantic usage-window and trend-metric identifiers from the API. Pin the UI and workbench dependencies to published feature commits and preserve the original font defaults. Co-authored-by: Codex <noreply@openai.com> --------- Co-authored-by: Jimbb <14995924+jimbb@users.noreply.github.com> Co-authored-by: Zyy <zyycn@users.noreply.github.com> Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -84,7 +84,7 @@ pub(super) fn account_view(
|
||||
let usage_period = quota.usage_window().map(|(_, period)| period);
|
||||
let mut usage = account_usage_view(usage, usage_period, now, time);
|
||||
if account.authentication_kind == "api_key" {
|
||||
usage.window_label_display = "通用额度".to_owned();
|
||||
usage.window_kind = AccountUsageWindowKind::General;
|
||||
}
|
||||
let (quota, refresh_token_expires_at) = account_quota_view(quota, cooldown, now, time);
|
||||
AccountView {
|
||||
@@ -344,12 +344,11 @@ pub(super) fn account_usage_view(
|
||||
"known"
|
||||
};
|
||||
AccountUsageView {
|
||||
window_label_display: match period {
|
||||
Some(AccountUsagePeriod::Weekly) => "周额度窗口",
|
||||
Some(AccountUsagePeriod::Monthly) => "月额度窗口",
|
||||
None => "周/月额度窗口",
|
||||
}
|
||||
.to_owned(),
|
||||
window_kind: match period {
|
||||
Some(AccountUsagePeriod::Weekly) => AccountUsageWindowKind::Weekly,
|
||||
Some(AccountUsagePeriod::Monthly) => AccountUsageWindowKind::Monthly,
|
||||
None => AccountUsageWindowKind::Quota,
|
||||
},
|
||||
request_count: Some(usage.request_count),
|
||||
request_count_display: format_number(usage.request_count),
|
||||
input_tokens: usage.input_tokens,
|
||||
@@ -470,7 +469,7 @@ pub(super) fn display_optional_tokens(value: Option<u64>) -> String {
|
||||
|
||||
pub(super) fn empty_account_usage() -> AccountUsageView {
|
||||
AccountUsageView {
|
||||
window_label_display: "周/月额度窗口".to_owned(),
|
||||
window_kind: AccountUsageWindowKind::Quota,
|
||||
request_count: None,
|
||||
request_count_display: "—".to_owned(),
|
||||
input_tokens: None,
|
||||
|
||||
@@ -425,11 +425,21 @@ pub struct AccountQuotaWindowView {
|
||||
pub reset_at_display: String,
|
||||
}
|
||||
|
||||
/// 账号用量窗口的语义标识,展示名称由管理端本地化
|
||||
#[derive(Debug, Clone, Copy, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum AccountUsageWindowKind {
|
||||
General,
|
||||
Weekly,
|
||||
Monthly,
|
||||
Quota,
|
||||
}
|
||||
|
||||
/// 账号观测用量
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AccountUsageView {
|
||||
pub window_label_display: String,
|
||||
pub window_kind: AccountUsageWindowKind,
|
||||
pub request_count: Option<u64>,
|
||||
pub request_count_display: String,
|
||||
pub input_tokens: Option<u64>,
|
||||
|
||||
@@ -735,34 +735,34 @@ pub(crate) fn trend_summary_view(
|
||||
match kind {
|
||||
TrendKind::Usage => vec![
|
||||
TrendSummaryView {
|
||||
label: "输入".to_owned(),
|
||||
metric: TrendMetric::InputTokens,
|
||||
value: format_compact_number(summary.input_tokens),
|
||||
ratio: None,
|
||||
},
|
||||
TrendSummaryView {
|
||||
label: "输出".to_owned(),
|
||||
metric: TrendMetric::OutputTokens,
|
||||
value: format_compact_number(summary.output_tokens),
|
||||
ratio: None,
|
||||
},
|
||||
TrendSummaryView {
|
||||
label: "缓存".to_owned(),
|
||||
metric: TrendMetric::CachedInputTokens,
|
||||
value: format_compact_number(summary.cached_input_tokens),
|
||||
ratio: None,
|
||||
},
|
||||
],
|
||||
TrendKind::Latency => vec![
|
||||
TrendSummaryView {
|
||||
label: "首字 P95".to_owned(),
|
||||
metric: TrendMetric::FirstTokenP95Ms,
|
||||
value: display_duration_f64(summary.peak_first_token_p95_ms),
|
||||
ratio: None,
|
||||
},
|
||||
TrendSummaryView {
|
||||
label: "总耗时 P95".to_owned(),
|
||||
metric: TrendMetric::LatencyP95Ms,
|
||||
value: display_duration_f64(summary.peak_latency_p95_ms),
|
||||
ratio: None,
|
||||
},
|
||||
TrendSummaryView {
|
||||
label: "速率 P50".to_owned(),
|
||||
metric: TrendMetric::OutputThroughputP50,
|
||||
value: summary
|
||||
.minimum_output_throughput_p50
|
||||
.map_or_else(|| "—".to_owned(), |value| format!("{value} tok/s")),
|
||||
@@ -771,19 +771,19 @@ pub(crate) fn trend_summary_view(
|
||||
],
|
||||
TrendKind::Errors => vec![
|
||||
TrendSummaryView {
|
||||
label: "错误数".to_owned(),
|
||||
metric: TrendMetric::Errors,
|
||||
value: format_compact_number(summary.service_failure_count),
|
||||
ratio: None,
|
||||
},
|
||||
TrendSummaryView {
|
||||
label: "成功率".to_owned(),
|
||||
metric: TrendMetric::SuccessRate,
|
||||
value: "—".to_owned(),
|
||||
ratio: summary
|
||||
.success_rate
|
||||
.map(|value| format!("{:.1}%", value * 100.0)),
|
||||
},
|
||||
TrendSummaryView {
|
||||
label: "总请求".to_owned(),
|
||||
metric: TrendMetric::Requests,
|
||||
value: format_compact_number(summary.request_count),
|
||||
ratio: None,
|
||||
},
|
||||
|
||||
@@ -323,10 +323,25 @@ pub struct TrendPointView {
|
||||
pub capacity_utilization: Option<f64>,
|
||||
}
|
||||
|
||||
/// 趋势指标的稳定身份,展示名称由管理端本地化
|
||||
#[derive(Debug, Clone, Copy, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum TrendMetric {
|
||||
InputTokens,
|
||||
OutputTokens,
|
||||
CachedInputTokens,
|
||||
FirstTokenP95Ms,
|
||||
LatencyP95Ms,
|
||||
OutputThroughputP50,
|
||||
Errors,
|
||||
SuccessRate,
|
||||
Requests,
|
||||
}
|
||||
|
||||
/// Dashboard 趋势摘要
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct TrendSummaryView {
|
||||
pub label: String,
|
||||
pub metric: TrendMetric,
|
||||
pub value: String,
|
||||
pub ratio: Option<String>,
|
||||
}
|
||||
|
||||
@@ -476,13 +476,13 @@ fn single_update_should_reject_oversized_notes_and_control_characters() {
|
||||
}
|
||||
|
||||
mod response {
|
||||
use gateway_api::admin::accounts::AccountUsageView;
|
||||
use gateway_api::admin::accounts::{AccountUsageView, AccountUsageWindowKind};
|
||||
use gateway_api::admin::presenter::format_decimal_currency;
|
||||
|
||||
#[test]
|
||||
fn account_usage_view_should_keep_unobserved_numbers_null() {
|
||||
let view = AccountUsageView {
|
||||
window_label_display: "周/月额度窗口".to_owned(),
|
||||
window_kind: AccountUsageWindowKind::Quota,
|
||||
request_count: None,
|
||||
request_count_display: "-".to_owned(),
|
||||
input_tokens: None,
|
||||
@@ -516,7 +516,7 @@ mod response {
|
||||
models: Vec::new(),
|
||||
};
|
||||
let value = serde_json::to_value(view).expect("serialize account usage");
|
||||
assert_eq!(value["windowLabelDisplay"], "周/月额度窗口");
|
||||
assert_eq!(value["windowKind"], "quota");
|
||||
assert!(value["inputTokens"].is_null());
|
||||
assert!(value["totalTokens"].is_null());
|
||||
assert!(value["reasoningOutputTokens"].is_null());
|
||||
|
||||
@@ -1464,3 +1464,69 @@ async fn usage_status_query_accepts_three_modes_and_rejects_unknown_values() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn dashboard_summary_should_identify_metrics_without_localized_labels() {
|
||||
use axum::{
|
||||
body::{Body, to_bytes},
|
||||
http::{Request, StatusCode, header},
|
||||
};
|
||||
use chrono::Duration;
|
||||
use gateway_admin::model::observability::{DashboardObservation, TimeRange};
|
||||
use gateway_api::admin::observability;
|
||||
use tower::ServiceExt as _;
|
||||
|
||||
use crate::admin::{AdminTestFixture, AdminTestState};
|
||||
|
||||
let fixture = AdminTestFixture::new().await;
|
||||
fixture.auth.insert_session("valid-session");
|
||||
let now = Utc::now();
|
||||
*fixture.dashboard_observation.lock().unwrap() = Some(DashboardObservation {
|
||||
yesterday: Default::default(),
|
||||
analytics: Default::default(),
|
||||
runtime_slots: None,
|
||||
range: TimeRange::new(now - Duration::hours(1), now).unwrap(),
|
||||
totals: Default::default(),
|
||||
provider_accounts: Default::default(),
|
||||
trend: Vec::new(),
|
||||
account_usage: Vec::new(),
|
||||
recent_requests: Vec::new(),
|
||||
});
|
||||
|
||||
for (kind, metrics) in [
|
||||
(
|
||||
"usage",
|
||||
["inputTokens", "outputTokens", "cachedInputTokens"],
|
||||
),
|
||||
(
|
||||
"latency",
|
||||
["firstTokenP95Ms", "latencyP95Ms", "outputThroughputP50"],
|
||||
),
|
||||
("errors", ["errors", "successRate", "requests"]),
|
||||
] {
|
||||
let response = observability::router::<AdminTestState>()
|
||||
.with_state(fixture.state())
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.uri(format!("/api/admin/dashboard/summary?kind={kind}"))
|
||||
.header(header::COOKIE, "cpr_session=valid-session")
|
||||
.header(header::ACCEPT_LANGUAGE, "en")
|
||||
.header("x-request-id", format!("req_trend_metrics_{kind}"))
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let status = response.status();
|
||||
let body = to_bytes(response.into_body(), 1024 * 1024).await.unwrap();
|
||||
let value: serde_json::Value = serde_json::from_slice(&body).unwrap();
|
||||
assert_eq!(status, StatusCode::OK, "{kind}: {value}");
|
||||
let summary = value["data"]["trend"]["summary"].as_array().unwrap();
|
||||
assert_eq!(summary.len(), metrics.len());
|
||||
for (item, metric) in summary.iter().zip(metrics) {
|
||||
assert_eq!(item["metric"], metric);
|
||||
assert!(item.get("label").is_none());
|
||||
assert!(item["value"].is_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-4
@@ -158,6 +158,8 @@ Codex PAT 验证服务不可用和身份响应无效分别返回 `50301`、`5020
|
||||
`YYYY-MM-DD HH:mm:ss`,短时间、相对时间和图表标签按对应视图返回;缺失时间的展示字段为 `null` 或占位文本。
|
||||
调用者直接显示文本,使用原始时间点进行排序、比较和输入,不把展示文本转回请求时间
|
||||
|
||||
账号、模型用量和 Key 列表的最近使用时间由前端根据原始 RFC3339 时间点,通过 VueUse `useTimeAgoIntl` 按界面语言显示短相对时间,并随时间更新;悬停的完整日期仍使用后端 `lastUsedAtFullDisplay`,不使用浏览器本地时区重算
|
||||
|
||||
账号冷却返回 RFC3339 `rateLimitedUntil` 和 `rateLimitRecoveryDisplay`,后者包含剩余时长、
|
||||
到期时间或等待恢复探测的提示,随账号数据刷新;前端不解析展示文本或自行计算恢复提示
|
||||
|
||||
@@ -1034,7 +1036,7 @@ API Key 账号与 OAuth 共用现有 Responses、Images 和 standalone Search
|
||||
包括 Responses Lite 和原生压缩协议的透传,实际支持情况由上游决定;不提供独立 compact 路由。
|
||||
模型目录、连接测试和本地用量统计可用;OAuth 刷新/重新授权、ChatGPT 额度、个人资料、订阅和重置卡不适用。
|
||||
客户端的 `image_generation` 和 `X-OpenAI-Actor-Authorization` 声明不改变账号的实际能力。
|
||||
账号列表和详情的 API Key `usage` 汇总该账号创建后仍保留的本地请求记录,`windowLabelDisplay` 为 `通用额度`;
|
||||
账号列表和详情的 API Key `usage` 汇总该账号创建后仍保留的本地请求记录,`usage.windowKind` 为 `general`,管理端按当前语言显示通用额度;
|
||||
日志清理会影响累计范围,不代表上游余额。OAuth 账号仍按实际周/月额度窗口统计
|
||||
|
||||
批量导入 AT / RT 使用 `accounts` JSON 数组,最多 200 项,不接受纯文本 token 列表。例如:
|
||||
@@ -1165,10 +1167,10 @@ OAuth start 使用:
|
||||
- 正常 Responses 请求会解析上游响应的 rate-limit headers,合并进同一 quota 快照并同步状态。Free、
|
||||
K12 等套餐共用该状态机;套餐只参与账号展示和按套餐隔离的模型目录 cache,不存在 K12 专属额度路径
|
||||
- 账号详情的 Token 统计、模型排行和列表 Token 汇总优先使用账号级周额度窗口,无可统计的周窗口时
|
||||
使用月额度窗口;`usage.windowLabelDisplay` 随选中的窗口返回“周额度窗口”或“月额度窗口”。查询边界
|
||||
使用月额度窗口;`usage.windowKind` 随选中的窗口返回 `weekly` 或 `monthly`。查询边界
|
||||
严格为 `[resetAt - windowSeconds, resetAt)`,不是自然周/月或最近 7/30 天;额度刷新若返回了更早的
|
||||
重置时间,会按新边界重新聚合。没有边界完整、可归属到账号的周/月窗口时显示无数据,标签为
|
||||
“周/月额度窗口”,不回退到 5 小时、日窗口或历史累计。
|
||||
重置时间,会按新边界重新聚合。没有边界完整、可归属到账号的周/月窗口时显示无数据,`usage.windowKind` 为 `quota`
|
||||
(周/月额度窗口),不回退到 5 小时、日窗口或历史累计。
|
||||
金额原值保持完整精度,USD 展示值
|
||||
小于 1 美元时最多保留四位小数,其余保留两位
|
||||
|
||||
@@ -1989,6 +1991,18 @@ errorCode, errorMessage, startedAt, completedAt, expiresAt, createdAt, updatedAt
|
||||
| `GET` | `/api/admin/operations/errors` | 运维错误分页列表 |
|
||||
| `GET` | `/api/admin/diagnostics/export` | 按 `requestId` 或 `errorId` 下载诊断 ZIP 附件 |
|
||||
|
||||
### Dashboard 趋势指标
|
||||
|
||||
趋势摘要 `summary[]` 返回稳定的 `metric`、展示数值 `value` 和可空的 `ratio`,指标名称由前端本地化
|
||||
|
||||
| kind | metric |
|
||||
| --- | --- |
|
||||
| `usage` | `inputTokens`、`outputTokens`、`cachedInputTokens` |
|
||||
| `latency` | `firstTokenP95Ms`、`latencyP95Ms`、`outputThroughputP50` |
|
||||
| `errors` | `errors`、`successRate`、`requests` |
|
||||
|
||||
图表颜色、系列身份和选中状态使用 `metric`,不根据译文或数组位置推断指标
|
||||
|
||||
### Dashboard 容量与账号用量
|
||||
|
||||
Dashboard 的 `capacityInfo` 统计普通容量,不含独立审批池;`maxConcurrentPerAccount` 为默认账号并发上限,`0` 表示不限制。
|
||||
|
||||
@@ -91,7 +91,7 @@ Pinia 持久化、登录、路由和业务请求由各应用持有
|
||||
|
||||
部署时区由 Host 配置拥有,组合根把不可变的 `DeploymentTimeZone` 传给各模块。
|
||||
Core 的 `time` 只提供时区与日历边界换算;Admin/Provider 拥有查询范围与调度规则,Store 绑定显式 UTC 边界并维护事务。
|
||||
API 的时间 presenter 负责页面及事件展示文本,前端消费投影,不解释时区或格式化日期。
|
||||
API 的时间 presenter 负责部署时区下的日期及事件展示文本,前端不重新解释时区或格式化绝对日期;最近使用的相对时间本地化边界见 [API 页面时间](api.md#页面时间合同)。
|
||||
持久化、协议传输、排序与 TTL 使用 UTC 时间点或持续时长,不依赖进程、浏览器及数据库会话的本地时区。
|
||||
请求位置中的时区属于 Provider 请求身份,与部署日历规则独立。配置操作见[部署时区](../deploy/README.md#部署时区)
|
||||
|
||||
@@ -342,6 +342,7 @@ Client Key 费用账本独立累计各次 attempt 的实际费用,不能因请
|
||||
| `presenter.ts`、页面 `utils/` | 纯展示投影或该页面拥有的业务转换,不启动请求 |
|
||||
| `components/usage/`、`components/account/` | 跨页面复用的用量、健康时间线、套餐和额度窗口展示 |
|
||||
| `composables/` | 请求取消与过期结果隔离、分页、选择、异步动作、目录加载等共享机制 |
|
||||
| `i18n/` | Vue I18n 实例、三语资源和应用语言策略;从全局 Composer 派生 UI 库语言,不翻译用户数据或远端自由文本 |
|
||||
| `utils/` | 按用途分开的数据解析、数字与时长格式化、位置校验、客户端配置、插件导航及颜色工具 |
|
||||
|
||||
JSON、原始字节与流式请求共用会话恢复和身份代际校验,身份变化后的迟到结果按取消处理。
|
||||
|
||||
+17
-1
@@ -45,7 +45,7 @@
|
||||
- **文案不使用句号和分号**:自行编写的标题、标签、按钮、表单帮助、空状态、提示和错误文案不使用 `。`、句末 `.`、`;` 或 `;`,优先写成短语或简短分句
|
||||
需要表达多个要点时,按内容关系拆成字段、短行或列表,不把长段落机械替换成逗号串
|
||||
这项约定针对界面文案,URL、版本号、小数、代码、原始日志和用户输入保留原样
|
||||
- **说明只补必要信息**:标题、字段值和操作已能表达的内容不再重复,不同时用帮助文字、状态行和说明卡解释同一事实
|
||||
- **页面直显以简洁为主**:标题、标签、按钮使用简短明确的名称或动作,说明只补必要信息,不重复标题、字段值和操作已能表达的内容,不同时用多种说明形式解释同一事实
|
||||
页面保留当前决策必需的短提示,详细规则、背景原因、示例和低频帮助优先收进已有 Popover 或就近的帮助入口,不把实现细节写成用户教程
|
||||
重要说明可以在 Popover 中展开,但影响当前选择的关键限制、错误原因和不可逆后果需在操作处保留简明提示,不能全部藏起来
|
||||
- **按内容选择提示方式**:Tooltip 用于短名称或单句补充,Popover 用于需要阅读、多段说明或含链接的内容,复用项目现有组件
|
||||
@@ -62,10 +62,26 @@
|
||||
| 页面头部 | `@codex-proxy/ui` 的 `ZPageHeader`、[系统概览](../frontend/src/views/dashboard/components/DashboardContent.vue) | 简短标题、必要的统计范围或状态、就近操作 |
|
||||
| 内容与指标 | `@codex-proxy/ui` 的 `ZCard`、[用量概览卡片](../frontend/src/views/usage/components/UsageSummaryCards.vue) | 可选说明、紧凑摘要、数值与辅助信息的主次 |
|
||||
| 表单帮助 | [API Key 账号字段](../frontend/src/views/accounts/components/AccountApiKeyFields.vue) | 直接命名字段,在对应位置提供短提示和示例 |
|
||||
| 详细规则 | [自动审批并发帮助](../frontend/src/views/settings/components/ConcurrencyPolicyCard.vue) | 标签旁帮助图标打开 Popover,页面保留短提示,浮层补充规则和示例 |
|
||||
| 账号与用量展示 | [账号额度窗口](../frontend/src/components/account/account-usage-window/index.vue)、[共用用量表格](../frontend/src/components/usage/UsageRecordsTable.vue) | 复用后端展示字段和共享 presenter,管理端与 Key 页保持同一展示口径 |
|
||||
|
||||
页面查询、表单状态与纯展示逻辑的归属见 [前端模块职责](architecture.md#34-前端模块职责)
|
||||
|
||||
## 语言与字体
|
||||
|
||||
应用使用 Vue I18n Composition API,语言标识为 `en`、`zh-Hans`、`zh-Hant`。资源按领域存放在 `frontend/src/i18n/locales/`,使用 `领域.功能.用途` 的语义 key,例如 `accounts.connectionTest.description`,三种语言保持相同 key 和具名参数
|
||||
|
||||
- 标签、帮助、ARIA、通知和图表显式取消息;列定义、选项和展示投影使用响应式计算,不把翻译结果存进业务数据
|
||||
- 完整句子使用具名参数,含组件的消息使用 `I18nT`;数量使用 Vue I18n 复数规则,不拆词拼接
|
||||
- 专业缩写在三种语言中保留原样及规范大小写,例如 `TTFT`、`RPM`、`TPM`、`API`、`HTTP`、`WS`、`RC`,直接显示时不翻译或展开,必要的全称和解释放入帮助提示
|
||||
- 英文使用句首大写和美式拼写,统一 Account、Proxy、Usage、Rate limit、API key、TTFT 等术语,协议标识和用户值保留原样
|
||||
- 繁体中文只转换简体原文的字形,保持措辞与语序,不替换地区用词,例如 `数据 → 數據`、`设置 → 設置`
|
||||
- 只翻译应用拥有的文本,具体后端错误、上游诊断、日志和独立插件内容保留原文;固定错误码在请求层映射,业务分类码优先保留后端公开的具体原因,无原因时使用本地兜底文案
|
||||
- 侧边栏语言图标展开就地选项,选择后切换并收起;品牌区固定显示 `Codex Proxy`、`Rust build` 和版本号
|
||||
- UI 库默认文案由 `ZConfigProvider` 提供,命令式通知通过 `utils/notification.ts` 绑定同一个语言来源,组件约定见 [UI 国际化](../modules/ui/playground/guide/i18n.md)
|
||||
|
||||
正文默认使用 Inter Variable,中文及缺失字形按系统无衬线字体栈回退。代码使用 JetBrains Mono Variable,中文由系统字体补齐,不随语言切换额外修改字重。默认值由 UI 库持有,应用负责加载字体包,图表读取同一字体 Token
|
||||
|
||||
## 架构概览
|
||||
|
||||
```mermaid
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @env node
|
||||
import type { ESLint, Rule } from 'eslint'
|
||||
import antfu from '@antfu/eslint-config'
|
||||
import vueI18n from '@intlify/eslint-plugin-vue-i18n'
|
||||
|
||||
type LocatedRuleNode = Rule.Node & {
|
||||
loc: NonNullable<Rule.Node['loc']>
|
||||
@@ -99,4 +100,25 @@ export default antfu(
|
||||
'vue/mustache-interpolation-spacing': ['error', 'always'],
|
||||
},
|
||||
},
|
||||
...vueI18n.configs.base,
|
||||
{
|
||||
settings: {
|
||||
'vue-i18n': {
|
||||
localeDir: {
|
||||
pattern: './src/i18n/locales/*/*.json',
|
||||
localeKey: 'path',
|
||||
localePattern: /\/locales\/(?<locale>[^/]+)\//,
|
||||
},
|
||||
messageSyntaxVersion: '^11.0.0',
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'@intlify/vue-i18n/no-missing-keys': 'error',
|
||||
'@intlify/vue-i18n/no-missing-keys-in-other-locales': 'error',
|
||||
'@intlify/vue-i18n/no-duplicate-keys-in-locale': 'error',
|
||||
'@intlify/vue-i18n/valid-message-syntax': 'error',
|
||||
'@intlify/vue-i18n/valid-plural-forms': 'error',
|
||||
'@intlify/vue-i18n/no-unused-keys': ['error', { extensions: ['.ts', '.vue'] }],
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@boxicons/vue": "1.0.1",
|
||||
"@codex-proxy/ui": "github:zyycn/codex-proxy-ui#v0.5.0",
|
||||
"@codex-proxy/ui": "github:zyycn/codex-proxy-ui#acd8578f82a91dc5d6da70b68c3bd354a1dde061",
|
||||
"@fontsource-variable/inter": "^5.3.0",
|
||||
"@fontsource-variable/jetbrains-mono": "^5.3.0",
|
||||
"@lucide/vue": "^1.59.0",
|
||||
@@ -34,10 +34,13 @@
|
||||
"semver": "^7.8.5",
|
||||
"sortablejs": "^1.15.7",
|
||||
"vue": "^3.5.44",
|
||||
"vue-i18n": "11.4.16",
|
||||
"vue-router": "^5.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^9.5.1",
|
||||
"@intlify/eslint-plugin-vue-i18n": "4.5.1",
|
||||
"@intlify/unplugin-vue-i18n": "11.2.7",
|
||||
"@tailwindcss/vite": "^4.3.3",
|
||||
"@types/css-tree": "^3.2.0",
|
||||
"@types/node": "^26.6.5",
|
||||
|
||||
Generated
+874
-5
File diff suppressed because it is too large
Load Diff
@@ -3,3 +3,4 @@ autoInstallPeers: false
|
||||
# Git 依赖通过 prepack 生成产物;信任自有 UI 仓库,实际提交仍由锁文件固定。
|
||||
allowBuilds:
|
||||
'@codex-proxy/ui@git+https://github.com/zyycn/codex-proxy-ui.git': true
|
||||
esbuild@0.25.12: true
|
||||
|
||||
+11
-1
@@ -1,7 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import { ZConfigProvider } from '@codex-proxy/ui'
|
||||
import { watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { RouterView } from 'vue-router'
|
||||
import { applyLocale } from '@/i18n/locale'
|
||||
import { uiLocale } from '@/i18n/ui'
|
||||
|
||||
const { locale } = useI18n({ useScope: 'global' })
|
||||
watch(locale, applyLocale, { immediate: true })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterView />
|
||||
<ZConfigProvider :locale="uiLocale">
|
||||
<RouterView />
|
||||
</ZConfigProvider>
|
||||
</template>
|
||||
|
||||
@@ -87,7 +87,7 @@ export interface AccountModelUsage {
|
||||
}
|
||||
|
||||
export interface AccountUsage {
|
||||
windowLabelDisplay: string
|
||||
windowKind: 'general' | 'weekly' | 'monthly' | 'quota'
|
||||
requestCount: number | null
|
||||
requestCountDisplay: string
|
||||
inputTokens: number | null
|
||||
|
||||
@@ -42,8 +42,13 @@ export interface DashboardTrendPoint {
|
||||
capacityUtilization: number | null
|
||||
}
|
||||
|
||||
export type DashboardTrendMetric
|
||||
= 'inputTokens' | 'outputTokens' | 'cachedInputTokens'
|
||||
| 'firstTokenP95Ms' | 'latencyP95Ms' | 'outputThroughputP50'
|
||||
| 'errors' | 'successRate' | 'requests'
|
||||
|
||||
export interface DashboardTrendSummaryItem {
|
||||
label: string
|
||||
metric: DashboardTrendMetric
|
||||
value: string
|
||||
ratio: string | null
|
||||
}
|
||||
|
||||
@@ -9,11 +9,6 @@ export interface KeyUsageConfig {
|
||||
plaintextKey: string
|
||||
}
|
||||
|
||||
export interface KeyUsageVersion {
|
||||
version: string
|
||||
gitSha: string
|
||||
}
|
||||
|
||||
export interface KeyUsageMetrics {
|
||||
requests: number
|
||||
inputTokens: number
|
||||
@@ -109,14 +104,6 @@ export function getKeyUsageOverview(data: KeyUsageQuery, options: RequestOptions
|
||||
})
|
||||
}
|
||||
|
||||
export function getKeyUsageVersion(options: RequestOptions = {}) {
|
||||
return request<KeyUsageVersion>({
|
||||
url: '/api/key-usage/version',
|
||||
method: 'GET',
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
export function getKeyUsageConfig(options: RequestOptions = {}) {
|
||||
return request<KeyUsageConfig>({
|
||||
url: '/api/key-usage/config',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { AxiosError, AxiosResponse, AxiosResponseHeaders, RawAxiosResponseHeaders } from 'axios'
|
||||
import type { RequestContext, RequestNext } from './index'
|
||||
import { isAxiosError } from 'axios'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
export type ApiErrorKind = 'api' | 'timeout' | 'network' | 'http' | 'cancelled'
|
||||
|
||||
@@ -45,16 +46,16 @@ export function normalizeApiError(error: AxiosError<unknown>) {
|
||||
const requestId = responseHeader(error.response?.headers, 'x-request-id')
|
||||
|
||||
if (error.code === 'ERR_CANCELED') {
|
||||
return new ApiError('请求已取消', status, undefined, requestId, 'cancelled')
|
||||
return new ApiError(t('common.errors.canceled'), status, undefined, requestId, 'cancelled')
|
||||
}
|
||||
const apiError = error.response && normalizeApiResponseError(error.response)
|
||||
if (apiError)
|
||||
return apiError
|
||||
if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || error.code === 'ERR_TIMEOUT') {
|
||||
return new ApiError('请求超时,请稍后重试', status, undefined, requestId, 'timeout')
|
||||
return new ApiError(t('common.errors.timeout'), status, undefined, requestId, 'timeout')
|
||||
}
|
||||
if (!error.response) {
|
||||
return new ApiError('网络连接失败,请检查网络后重试', 0, undefined, requestId, 'network')
|
||||
return new ApiError(t('common.errors.network'), 0, undefined, requestId, 'network')
|
||||
}
|
||||
return new ApiError(httpFallback(status), status, undefined, requestId, 'http')
|
||||
}
|
||||
@@ -63,8 +64,9 @@ export function normalizeApiResponseError(response: AxiosResponse<unknown>) {
|
||||
const envelope = adminErrorEnvelope(response.data)
|
||||
if (!envelope || envelope.code === 200)
|
||||
return undefined
|
||||
const message = adminErrorMessage(envelope) || httpFallback(response.status >= 400 ? response.status : 0)
|
||||
return new ApiError(
|
||||
envelope.message || httpFallback(response.status >= 400 ? response.status : 0),
|
||||
message,
|
||||
response.status,
|
||||
envelope.code,
|
||||
responseHeader(response.headers, 'x-request-id'),
|
||||
@@ -82,6 +84,25 @@ function adminErrorEnvelope(value: unknown): AdminErrorEnvelope | null {
|
||||
return { code: record.code, message }
|
||||
}
|
||||
|
||||
// 固定错误码使用本地文案,业务分类码保留后端已公开的具体原因
|
||||
function adminErrorMessage(error: AdminErrorEnvelope): string {
|
||||
switch (error.code) {
|
||||
case 40000: return t('common.errors.malformedJson')
|
||||
case 40002: return t('common.errors.invalidTimeRange')
|
||||
case 40101: return t('common.errors.signInRequired')
|
||||
case 40102: return t('common.errors.invalidCredentials')
|
||||
case 40103: return t('common.errors.invalidAdminApiKey')
|
||||
case 40301: return t('common.errors.forbidden')
|
||||
case 42901: return t('common.errors.tooManyLoginAttempts')
|
||||
case 42902: return error.message || t('common.errors.rateLimited')
|
||||
case 50001: return t('common.errors.internal')
|
||||
case 50201: return error.message || t('common.errors.upstreamFailure')
|
||||
case 50202: return error.message || t('common.errors.upstreamResultUnknown')
|
||||
case 50301: return error.message || t('common.errors.unavailable')
|
||||
default: return error.message
|
||||
}
|
||||
}
|
||||
|
||||
function responseHeader(
|
||||
headers: RawAxiosResponseHeaders | AxiosResponseHeaders | undefined,
|
||||
name: string,
|
||||
@@ -95,35 +116,35 @@ function responseHeader(
|
||||
function httpFallback(status: number) {
|
||||
switch (status) {
|
||||
case 400:
|
||||
return '请求参数不合法'
|
||||
return t('common.errors.invalidParameters')
|
||||
case 401:
|
||||
return '需要登录'
|
||||
return t('common.errors.signInRequired')
|
||||
case 403:
|
||||
return '没有权限执行此操作'
|
||||
return t('common.errors.forbidden')
|
||||
case 404:
|
||||
return '请求的接口不存在'
|
||||
return t('common.errors.notFound')
|
||||
case 408:
|
||||
return '请求超时,请稍后重试'
|
||||
return t('common.errors.timeout')
|
||||
case 409:
|
||||
return '资源状态冲突,请刷新后重试'
|
||||
return t('common.errors.conflict')
|
||||
case 413:
|
||||
return '请求内容过大'
|
||||
return t('common.errors.payloadTooLarge')
|
||||
case 415:
|
||||
return '请求格式不受支持'
|
||||
return t('common.errors.unsupportedFormat')
|
||||
case 422:
|
||||
return '请求内容不合法'
|
||||
return t('common.errors.invalidContent')
|
||||
case 429:
|
||||
return '请求过于频繁,请稍后重试'
|
||||
return t('common.errors.rateLimited')
|
||||
case 500:
|
||||
return '服务内部错误'
|
||||
return t('common.errors.internal')
|
||||
case 502:
|
||||
return '上游服务请求失败'
|
||||
return t('common.errors.upstreamFailure')
|
||||
case 503:
|
||||
return '服务暂不可用,请稍后重试'
|
||||
return t('common.errors.unavailable')
|
||||
case 504:
|
||||
return '上游服务响应超时'
|
||||
return t('common.errors.upstreamTimeout')
|
||||
default:
|
||||
return status > 0 ? `请求失败(HTTP ${status})` : '请求失败'
|
||||
return status > 0 ? t('common.errors.http', { status }) : t('common.errors.request')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { RequestContext, RequestNext } from './index'
|
||||
import { ZNotification } from '@codex-proxy/ui'
|
||||
import { notification as ZNotification } from '@/utils/notification'
|
||||
import { ApiError, isSessionRequired } from './error'
|
||||
|
||||
// 共享刷新 Promise 的同一个失败只提示一次,弱引用不保留已结束请求
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { RequestContext, RequestNext } from './index'
|
||||
import { t } from '@/i18n'
|
||||
import { ApiError, normalizeApiResponseError } from './error'
|
||||
|
||||
export interface RawResponseMeta {
|
||||
@@ -50,7 +51,7 @@ export async function rawPlugin(context: RequestContext, next: RequestNext) {
|
||||
}
|
||||
const body = response.data as ArrayBuffer
|
||||
if (body.byteLength > options.maximumBytes)
|
||||
throw new ApiError('响应内容超过大小限制', 502, undefined, rawHeader(response.headers, 'x-request-id'), 'http')
|
||||
throw new ApiError(t('common.errors.responseTooLarge'), 502, undefined, rawHeader(response.headers, 'x-request-id'), 'http')
|
||||
return {
|
||||
...response,
|
||||
data: {
|
||||
@@ -69,7 +70,7 @@ export async function rawPlugin(context: RequestContext, next: RequestNext) {
|
||||
if (normalized)
|
||||
throw normalized
|
||||
throw new ApiError(
|
||||
response.status >= 400 ? `请求失败(HTTP ${response.status})` : '服务返回了不受支持的响应',
|
||||
response.status >= 400 ? t('common.errors.http', { status: response.status }) : t('common.errors.unsupportedResponse'),
|
||||
response.status,
|
||||
undefined,
|
||||
rawHeader(response.headers, 'x-request-id'),
|
||||
@@ -90,7 +91,7 @@ async function readErrorBody(body: ReadableStream<Uint8Array> | null, maximumByt
|
||||
break
|
||||
length += value.byteLength
|
||||
if (length > maximumBytes)
|
||||
throw new ApiError('响应内容超过大小限制', 502, undefined, undefined, 'http')
|
||||
throw new ApiError(t('common.errors.responseTooLarge'), 502, undefined, undefined, 'http')
|
||||
chunks.push(value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { RequestContext, RequestNext } from './index'
|
||||
import { t } from '@/i18n'
|
||||
import { ApiError, isTransientApiError } from './error'
|
||||
|
||||
export async function retryPlugin(context: RequestContext, next: RequestNext) {
|
||||
@@ -6,7 +7,7 @@ export async function retryPlugin(context: RequestContext, next: RequestNext) {
|
||||
const retry = config.retry ?? ['GET', 'HEAD'].includes((config.method ?? 'GET').toUpperCase())
|
||||
for (let attempt = 0; ; attempt += 1) {
|
||||
if (!context.isCurrent())
|
||||
throw new ApiError('请求已取消', 0, undefined, undefined, 'cancelled')
|
||||
throw new ApiError(t('common.errors.canceled'), 0, undefined, undefined, 'cancelled')
|
||||
try {
|
||||
return await next()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { RequestConfig } from '../index'
|
||||
import type { RequestContext, RequestNext } from './index'
|
||||
import { ZNotification } from '@codex-proxy/ui'
|
||||
import { t } from '@/i18n'
|
||||
import { notification as ZNotification } from '@/utils/notification'
|
||||
import { ApiError, isSessionRequired } from './error'
|
||||
|
||||
// 会话失效是后端业务事实,登录凭据错误和 403 不清除已有会话
|
||||
@@ -65,15 +66,15 @@ export async function sessionPlugin(context: RequestContext, send: RequestNext)
|
||||
const isCurrent = context.isCurrent
|
||||
context.isCurrent = () => isCurrent() && generation === sessionGeneration
|
||||
if (!config.skipSessionRecovery && sessionRecovery && !await sessionRecovery)
|
||||
return expireSession(new ApiError('登录已失效,请重新登录', 401, SESSION_REQUIRED), config, generation)
|
||||
return expireSession(new ApiError(t('common.errors.sessionExpired'), 401, SESSION_REQUIRED), config, generation)
|
||||
if (config.signal?.aborted || generation !== sessionGeneration)
|
||||
throw new ApiError('请求已取消', 0, undefined, undefined, 'cancelled')
|
||||
throw new ApiError(t('common.errors.canceled'), 0, undefined, undefined, 'cancelled')
|
||||
const sendCurrent: RequestNext = async () => {
|
||||
const response = await send()
|
||||
if (context.isCurrent())
|
||||
return response
|
||||
// 身份已切换时丢弃迟到结果,流式传输由请求层终止
|
||||
throw new ApiError('请求已取消', 0, undefined, undefined, 'cancelled')
|
||||
throw new ApiError(t('common.errors.canceled'), 0, undefined, undefined, 'cancelled')
|
||||
}
|
||||
const recovered = successfulRecoveries
|
||||
try {
|
||||
|
||||
@@ -3,6 +3,8 @@ import type { AccountGroupRef } from '@/api'
|
||||
|
||||
import { ZCheckbox } from '@codex-proxy/ui'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
groups: AccountGroupRef[]
|
||||
@@ -15,6 +17,8 @@ withDefaults(
|
||||
},
|
||||
)
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const selectedGroupIds = defineModel<string[]>({ required: true })
|
||||
|
||||
function updateGroup(groupId: string, selected: boolean) {
|
||||
@@ -42,10 +46,10 @@ function updateGroup(groupId: string, selected: boolean) {
|
||||
@update:model-value="updateGroup(group.id, $event)"
|
||||
/>
|
||||
</span>
|
||||
<span v-if="!group.enabled" class="shrink-0 text-cp-xs font-emphasis text-cp-text-quaternary"> 已禁用 </span>
|
||||
<span v-if="!group.enabled" class="shrink-0 text-cp-xs font-emphasis text-cp-text-quaternary"> {{ t('common.status.disabled') }} </span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-else class="m-0 rounded-cp bg-cp-fill-quaternary px-3.5 py-3 text-cp-sm font-emphasis text-cp-text-secondary">
|
||||
{{ loading ? '正在加载分组...' : '暂无分组,请先在分组管理中创建' }}
|
||||
{{ loading ? t('groups.selector.loading') : t('groups.selector.empty') }}
|
||||
</p>
|
||||
</template>
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import type { AccountGroupRef } from '@/api'
|
||||
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const props = defineProps<{
|
||||
groups: AccountGroupRef[]
|
||||
}>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const fullNames = computed(() =>
|
||||
props.groups.map(group => (group.enabled ? group.name : `${group.name}(已禁用)`)).join('、'),
|
||||
props.groups.map(group => (group.enabled ? group.name : t('common.status.disabledName', { name: group.name }))).join('、'),
|
||||
)
|
||||
</script>
|
||||
|
||||
|
||||
@@ -2,22 +2,26 @@
|
||||
import { ZButton, ZDialog, ZIconButton, ZScrollbar, ZSegmented, ZSwitch } from '@codex-proxy/ui'
|
||||
|
||||
import { Apple, Copy, Monitor, Upload } from '@lucide/vue'
|
||||
|
||||
import { computed, shallowRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { buildCodexCcSwitchImportDeeplink, buildCodexConfig, CODEX_WEBSOCKET_ENABLED_BY_DEFAULT } from '@/utils/client'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
const props = defineProps<{
|
||||
title?: string
|
||||
apiKey: {
|
||||
name?: string
|
||||
key?: string
|
||||
} | null
|
||||
apiBaseUrl: string
|
||||
}>(), { title: '使用密钥' })
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
copy: [text: string]
|
||||
}>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const open = defineModel<boolean>({ default: false })
|
||||
|
||||
const activePlatform = shallowRef('unix')
|
||||
@@ -54,16 +58,16 @@ function importToCcs() {
|
||||
<template>
|
||||
<ZDialog
|
||||
v-model="open"
|
||||
:title="title"
|
||||
description="保存或合并下方配置后重启 Codex"
|
||||
:title="title ?? t('keys.configuration.title')"
|
||||
:description="t('keys.configuration.description')"
|
||||
width="48rem"
|
||||
>
|
||||
<div class="flex flex-col gap-5">
|
||||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||||
<ZSegmented v-model="activePlatform" aria-label="配置平台" :options="platformOptions" />
|
||||
<ZSegmented v-model="activePlatform" :aria-label="t('keys.configuration.platform')" :options="platformOptions" />
|
||||
<ZSwitch
|
||||
v-model="websocketEnabled"
|
||||
aria-label="切换 WebSocket 配置"
|
||||
:aria-label="t('keys.configuration.toggleWebSocket')"
|
||||
active-text="WS"
|
||||
inactive-text="WS"
|
||||
inline-prompt
|
||||
@@ -81,7 +85,7 @@ function importToCcs() {
|
||||
<ZIconButton
|
||||
variant="solid"
|
||||
size="small"
|
||||
aria-label="复制"
|
||||
:aria-label="t('common.actions.copy')"
|
||||
@click="emit('copy', codexConfig)"
|
||||
>
|
||||
<Copy class="size-3.5" />
|
||||
@@ -101,10 +105,10 @@ function importToCcs() {
|
||||
<template #footer>
|
||||
<ZButton :disabled="!keyValue" @click="importToCcs">
|
||||
<Upload class="size-4" />
|
||||
导入 CCSwitch
|
||||
{{ t('keys.configuration.importCcSwitch') }}
|
||||
</ZButton>
|
||||
<ZButton type="primary" @click="open = false">
|
||||
关闭
|
||||
{{ t('common.actions.close') }}
|
||||
</ZButton>
|
||||
</template>
|
||||
</ZDialog>
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { Github } from '@boxicons/vue'
|
||||
import { ZDialog } from '@codex-proxy/ui'
|
||||
import { ExternalLink } from '@lucide/vue'
|
||||
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
version: { version: string, gitSha: string } | null
|
||||
}>()
|
||||
|
||||
const open = defineModel<boolean>({ default: false })
|
||||
|
||||
const author = 'Zyy'
|
||||
const githubUrl = 'https://github.com/zyycn/codex-proxy-rs'
|
||||
|
||||
function normalizeBuildValue(value: string | undefined) {
|
||||
const normalized = value?.trim()
|
||||
|
||||
if (!normalized) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return ['unknown', 'null'].includes(normalized.toLowerCase()) ? '' : normalized
|
||||
}
|
||||
|
||||
const versionDisplay = computed(() => {
|
||||
const versionText = normalizeBuildValue(props.version?.version).replace(/^v/i, '')
|
||||
return versionText ? `v${versionText}` : ''
|
||||
})
|
||||
const gitShaDisplay = computed(() => {
|
||||
const gitSha = normalizeBuildValue(props.version?.gitSha)
|
||||
return gitSha ? gitSha.slice(0, 8) : ''
|
||||
})
|
||||
|
||||
const versionLine = computed(() => {
|
||||
const parts = [versionDisplay.value, gitShaDisplay.value].filter(Boolean)
|
||||
return parts.length ? `版本 ${parts.join(' · ')}` : '版本信息不可用'
|
||||
})
|
||||
|
||||
const linkItems = [
|
||||
{
|
||||
label: 'GitHub',
|
||||
value: 'codex-proxy-rs',
|
||||
href: githubUrl,
|
||||
icon: Github,
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ZDialog v-model="open" title="关于" width="28rem">
|
||||
<div class="grid gap-5">
|
||||
<section class="flex min-w-0 items-center gap-3">
|
||||
<span
|
||||
class="inline-flex size-9 shrink-0 items-center justify-center rounded-cp bg-cp-fill-quaternary font-mono text-cp-xl leading-none font-extrabold text-cp-text"
|
||||
>
|
||||
Z
|
||||
</span>
|
||||
<div class="min-w-0">
|
||||
<p class="m-0 truncate text-cp-xl leading-none font-heavy text-cp-text">
|
||||
{{ author }}
|
||||
</p>
|
||||
<p class="mt-1.5 mb-0 text-cp-sm leading-none font-emphasis text-cp-text-secondary">
|
||||
Built by Zyy · Codex Proxy RS
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid gap-1">
|
||||
<div
|
||||
v-for="item in linkItems"
|
||||
:key="item.label"
|
||||
class="group flex min-w-0 items-center justify-between gap-3 rounded-cp px-1 py-2.5 transition-colors hover:bg-cp-fill-quaternary"
|
||||
>
|
||||
<div class="flex min-w-0 items-center gap-3">
|
||||
<span
|
||||
class="inline-flex size-8 shrink-0 items-center justify-center rounded-cp bg-cp-fill-tertiary text-cp-text"
|
||||
>
|
||||
<component :is="item.icon" class="size-5" />
|
||||
</span>
|
||||
<div class="min-w-0">
|
||||
<p class="m-0 text-cp-xs leading-none font-heavy text-cp-text-quaternary">
|
||||
{{ item.label }}
|
||||
</p>
|
||||
<p
|
||||
class="mt-2 mb-0 truncate font-mono text-cp-sm leading-none font-bold text-cp-text"
|
||||
:title="item.value"
|
||||
>
|
||||
{{ item.value }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a
|
||||
:href="item.href"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
class="inline-flex size-7 shrink-0 items-center justify-center rounded-cp text-cp-text-quaternary transition-colors hover:bg-cp-fill-tertiary hover:text-cp-link"
|
||||
:aria-label="`打开 ${item.label}`"
|
||||
>
|
||||
<ExternalLink class="size-3.5" />
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p class="m-0 font-mono text-cp-xs leading-none font-emphasis text-cp-text-quaternary">
|
||||
{{ versionLine }}
|
||||
</p>
|
||||
</div>
|
||||
</ZDialog>
|
||||
</template>
|
||||
@@ -0,0 +1,66 @@
|
||||
<script setup lang="ts">
|
||||
import type { IconButtonProps } from '@codex-proxy/ui'
|
||||
import type { Locale } from '@/i18n/locale'
|
||||
import { ZIconButton, ZMenuItem, ZPopover } from '@codex-proxy/ui'
|
||||
import { Check, Languages } from '@lucide/vue'
|
||||
import chineseFlag from 'circle-flags/flags/cn.svg?url&no-inline'
|
||||
import englishFlag from 'circle-flags/flags/us.svg?url&no-inline'
|
||||
import { computed, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useLocale } from '@/composables/useLocale'
|
||||
|
||||
withDefaults(defineProps<{ size?: IconButtonProps['size'], variant?: IconButtonProps['variant'] }>(), {
|
||||
size: 'small',
|
||||
variant: 'text',
|
||||
})
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
const { locale, localeOptions, setLocale } = useLocale()
|
||||
const localeFlags: Record<Locale, string> = {
|
||||
'zh-Hans': chineseFlag,
|
||||
'zh-Hant': chineseFlag,
|
||||
'en': englishFlag,
|
||||
}
|
||||
const choices = useTemplateRef<HTMLElement>('choices')
|
||||
const label = computed(() => t('navigation.switchLanguage', {
|
||||
value: localeOptions.find(option => option.value === locale.value)?.label ?? 'English',
|
||||
}))
|
||||
|
||||
function focusSelected() {
|
||||
choices.value?.querySelector<HTMLButtonElement>('button[aria-pressed="true"]')?.focus()
|
||||
}
|
||||
|
||||
function selectLocale(value: Locale, close: () => void) {
|
||||
setLocale(value)
|
||||
close()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ZPopover placement="top-end" @opened="focusSelected">
|
||||
<template #reference="{ id, open }">
|
||||
<ZIconButton :size="size" :variant="variant" :aria-label="label" :aria-expanded="open" :aria-controls="id">
|
||||
<Languages :size="size === 'small' ? 18 : 19" />
|
||||
</ZIconButton>
|
||||
</template>
|
||||
<template #default="{ close }">
|
||||
<div ref="choices" role="group" :aria-label="t('common.language')" class="grid min-w-40 gap-1 p-1.5">
|
||||
<ZMenuItem
|
||||
v-for="option in localeOptions"
|
||||
:key="option.value"
|
||||
:aria-pressed="option.value === locale"
|
||||
class="aria-pressed:bg-cp-control-item-bg-active aria-pressed:text-cp-primary-text aria-pressed:hover:bg-cp-control-item-bg-active"
|
||||
@click="selectLocale(option.value, close)"
|
||||
>
|
||||
<template #icon>
|
||||
<img :src="localeFlags[option.value]" alt="" aria-hidden="true" class="size-4.5 shrink-0">
|
||||
</template>
|
||||
<span class="flex items-center justify-between gap-3">
|
||||
<span :lang="option.value">{{ option.label }}</span>
|
||||
<Check v-if="option.value === locale" class="size-4 shrink-0" aria-hidden="true" />
|
||||
</span>
|
||||
</ZMenuItem>
|
||||
</div>
|
||||
</template>
|
||||
</ZPopover>
|
||||
</template>
|
||||
@@ -1,5 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{ value: string | null, display: string, fullDisplay: string | null }>()
|
||||
import { useTimeAgoIntl } from '@vueuse/core'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const props = defineProps<{ value: string | null, fullDisplay: string | null }>()
|
||||
const { locale } = useI18n({ useScope: 'global' })
|
||||
|
||||
const display = useTimeAgoIntl(() => props.value ?? 0, {
|
||||
get locale() { return locale.value },
|
||||
relativeTimeFormatOptions: { numeric: 'auto', style: 'short' },
|
||||
insertSpace: false,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import { ZSegmented } from '@codex-proxy/ui'
|
||||
|
||||
import { LayoutGrid } from '@lucide/vue'
|
||||
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { formatProviderLabel, PROVIDER_IDS, providerIcon } from '@/utils/providers'
|
||||
|
||||
defineProps<{ disabled?: boolean }>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const provider = defineModel<string>({ required: true })
|
||||
const options = [
|
||||
{ label: '全部平台', value: '', icon: LayoutGrid },
|
||||
const options = computed(() => ([
|
||||
{ label: t('common.providers.all'), value: '', icon: LayoutGrid },
|
||||
...PROVIDER_IDS.map(value => ({ label: formatProviderLabel(value), value, icon: providerIcon(value) })),
|
||||
]
|
||||
]))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -16,7 +23,7 @@ const options = [
|
||||
<div class="min-w-0 overflow-x-auto">
|
||||
<ZSegmented
|
||||
v-model="provider"
|
||||
aria-label="按平台筛选"
|
||||
:aria-label="t('common.providers.filter')"
|
||||
display="icon"
|
||||
:style="{ width: `${options.length * 40 + 4}px` }"
|
||||
:options="options"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { authenticationIcon, formatAuthenticationLabel, formatProviderLabel, providerIcon } from '@/utils/providers'
|
||||
|
||||
const props = withDefaults(
|
||||
@@ -13,6 +15,8 @@ const props = withDefaults(
|
||||
},
|
||||
)
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const normalizedProvider = computed(() => (props.provider ?? '').trim().toLowerCase())
|
||||
const providerIconComponent = computed(() => normalizedProvider.value ? providerIcon(normalizedProvider.value) : undefined)
|
||||
const authenticationIconComponent = computed(() => authenticationIcon(props.authenticationKind))
|
||||
@@ -33,7 +37,7 @@ const iconClass = computed(() => {
|
||||
return props.size === 'sm' ? 'size-3' : 'size-4'
|
||||
})
|
||||
|
||||
const providerLabel = computed(() => formatProviderLabel(props.provider, '未知平台'))
|
||||
const providerLabel = computed(() => formatProviderLabel(props.provider, t('common.providers.unknown')))
|
||||
|
||||
const authenticationLabel = computed(() => formatAuthenticationLabel(props.authenticationKind))
|
||||
</script>
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import { ZIconButton } from '@codex-proxy/ui'
|
||||
|
||||
import { LocateFixed } from '@lucide/vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
defineProps<{ loading: boolean, disabled?: boolean }>()
|
||||
|
||||
const emit = defineEmits<{ detect: [] }>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ZIconButton
|
||||
size="default"
|
||||
:aria-label="loading ? '正在解析出口位置' : '解析出口位置并填入表单'"
|
||||
:title="loading ? '正在解析出口位置' : '解析出口位置并填入表单'"
|
||||
:aria-label="loading ? t('common.location.resolving') : t('common.location.detect')"
|
||||
:title="loading ? t('common.location.resolving') : t('common.location.detect')"
|
||||
:aria-busy="loading"
|
||||
:disabled="disabled || loading"
|
||||
@click="emit('detect')"
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import type { RequestLocation } from '@/api'
|
||||
|
||||
import { ZFormItem, ZInput } from '@codex-proxy/ui'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
defineProps<{ disabled?: boolean }>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const location = defineModel<RequestLocation>({ required: true })
|
||||
|
||||
function update(field: keyof RequestLocation, value: string) {
|
||||
@@ -12,17 +17,17 @@ function update(field: keyof RequestLocation, value: string) {
|
||||
|
||||
<template>
|
||||
<div class="grid gap-4 sm:grid-cols-2">
|
||||
<ZFormItem label="国家代码" required>
|
||||
<ZInput :model-value="location.country" :disabled="disabled" aria-label="国家代码" placeholder="请输入两位国家代码" maxlength="2" @update:model-value="update('country', $event)" />
|
||||
<ZFormItem :label="t('common.location.countryCode')" required>
|
||||
<ZInput :model-value="location.country" :disabled="disabled" :aria-label="t('common.location.countryCode')" :placeholder="t('common.location.countryCodePlaceholder')" maxlength="2" @update:model-value="update('country', $event)" />
|
||||
</ZFormItem>
|
||||
<ZFormItem label="地区" required>
|
||||
<ZInput :model-value="location.region" :disabled="disabled" aria-label="地区" placeholder="请输入地区" maxlength="128" @update:model-value="update('region', $event)" />
|
||||
<ZFormItem :label="t('common.location.region')" required>
|
||||
<ZInput :model-value="location.region" :disabled="disabled" :aria-label="t('common.location.region')" :placeholder="t('common.location.regionPlaceholder')" maxlength="128" @update:model-value="update('region', $event)" />
|
||||
</ZFormItem>
|
||||
<ZFormItem label="城市" required>
|
||||
<ZInput :model-value="location.city" :disabled="disabled" aria-label="城市" placeholder="请输入城市" maxlength="128" @update:model-value="update('city', $event)" />
|
||||
<ZFormItem :label="t('common.location.city')" required>
|
||||
<ZInput :model-value="location.city" :disabled="disabled" :aria-label="t('common.location.city')" :placeholder="t('common.location.cityPlaceholder')" maxlength="128" @update:model-value="update('city', $event)" />
|
||||
</ZFormItem>
|
||||
<ZFormItem label="IANA 时区" required>
|
||||
<ZInput :model-value="location.timezone" :disabled="disabled" aria-label="IANA 时区" placeholder="请输入 IANA 时区" @update:model-value="update('timezone', $event)" />
|
||||
<ZFormItem :label="t('common.location.timeZone')" required>
|
||||
<ZInput :model-value="location.timezone" :disabled="disabled" :aria-label="t('common.location.timeZone')" :placeholder="t('common.location.timeZonePlaceholder')" @update:model-value="update('timezone', $event)" />
|
||||
</ZFormItem>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import type { AccountQuotaWindow } from '@/api/index'
|
||||
|
||||
import type { AccountUsageWindowVariant } from '@/components/account/account-usage-window/presenter'
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import AccountRequestTimeline from '@/components/account/account-usage-window/AccountRequestTimeline.vue'
|
||||
import { resolveAccountUsageWindowPresentation } from '@/components/account/account-usage-window/presenter'
|
||||
|
||||
@@ -21,6 +23,8 @@ const props = withDefaults(
|
||||
},
|
||||
)
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const view = computed(() => resolveAccountUsageWindowPresentation({
|
||||
window: props.window,
|
||||
variant: props.variant,
|
||||
@@ -37,7 +41,7 @@ const view = computed(() => resolveAccountUsageWindowPresentation({
|
||||
:class="view.classes.label"
|
||||
:title="showNativeTooltip ? view.labelTooltip : undefined"
|
||||
>
|
||||
{{ window.labelDisplay }}
|
||||
{{ view.label }}
|
||||
</span>
|
||||
<span
|
||||
v-if="view.compactValues"
|
||||
@@ -47,7 +51,7 @@ const view = computed(() => resolveAccountUsageWindowPresentation({
|
||||
v-if="view.quota.localUsageVisible"
|
||||
class="text-right text-cp-text-quaternary"
|
||||
:class="view.classes.value"
|
||||
:title="showNativeTooltip ? `窗口消耗:${view.quota.localUsageDisplay}` : undefined"
|
||||
:title="showNativeTooltip ? t('accounts.quota.usageInThisWindow', { localUsageDisplay: view.quota.localUsageDisplay }) : undefined"
|
||||
>
|
||||
{{ view.quota.localUsageDisplay }}
|
||||
</span>
|
||||
@@ -55,7 +59,7 @@ const view = computed(() => resolveAccountUsageWindowPresentation({
|
||||
v-if="showPercentage && view.quota.valueVisible"
|
||||
class="text-right"
|
||||
:class="[view.classes.value, view.quota.percentTextClass]"
|
||||
:title="showNativeTooltip ? `额度已使用:${window.usedPercentDisplay}` : undefined"
|
||||
:title="showNativeTooltip ? t('accounts.quota.quotaUsed', { rate: window.usedPercentDisplay }) : undefined"
|
||||
>
|
||||
{{ window.usedPercentDisplay }}
|
||||
</span>
|
||||
@@ -83,7 +87,7 @@ const view = computed(() => resolveAccountUsageWindowPresentation({
|
||||
class="col-span-full"
|
||||
:class="[view.classes.track, view.classes.trackOffset]"
|
||||
role="progressbar"
|
||||
:aria-label="window.labelDisplay"
|
||||
:aria-label="view.label"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
:aria-valuenow="window.usedPercent ?? undefined"
|
||||
@@ -98,7 +102,7 @@ const view = computed(() => resolveAccountUsageWindowPresentation({
|
||||
v-if="view.quota.resetVisible"
|
||||
class="mt-3 text-cp-sm font-emphasis text-cp-text-secondary"
|
||||
>
|
||||
重置时间: {{ window.resetAtDisplay }}
|
||||
{{ t('accounts.quota.resets', { resetAtDisplay: window.resetAtDisplay }) }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -125,7 +129,7 @@ const view = computed(() => resolveAccountUsageWindowPresentation({
|
||||
</template>
|
||||
|
||||
<div v-else :class="view.classes.header">
|
||||
<span class="min-w-0 text-cp-text-secondary">额度待观测</span>
|
||||
<span class="min-w-0 text-cp-text-secondary">{{ t('accounts.quota.unobserved') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { AccountQuotaWindow } from '@/api/index'
|
||||
import { clamp } from 'es-toolkit'
|
||||
import { t } from '@/i18n'
|
||||
import { isRecord } from '@/utils/data'
|
||||
import { formatInteger } from '@/utils/format'
|
||||
|
||||
@@ -125,15 +126,17 @@ export function resolveAccountUsageWindowPresentation(
|
||||
const localRequestValueVisible = input.showLocalValue
|
||||
&& typeof localUsage?.requestCount === 'number'
|
||||
&& localUsage.requestCount > 0
|
||||
const localRequestLabel = '日请求'
|
||||
const localRequestLabel = t('accounts.quota.dailyRequests')
|
||||
const quota = input.window
|
||||
? quotaWindowPresentation(input.window, definition.minimumBarWidth)
|
||||
: null
|
||||
const label = input.window ? quotaWindowLabel(input.window) : undefined
|
||||
|
||||
return {
|
||||
mode,
|
||||
compactValues: definition.compactValues,
|
||||
labelTooltip: definition.labelTooltip ? input.window?.labelDisplay : undefined,
|
||||
label,
|
||||
labelTooltip: definition.labelTooltip ? label : undefined,
|
||||
classes: {
|
||||
root: definition.rootClass,
|
||||
header: definition.headerClass,
|
||||
@@ -159,7 +162,7 @@ export function resolveAccountUsageWindowPresentation(
|
||||
label: localRequestLabel,
|
||||
requestDisplay: localRequestDisplay,
|
||||
requestValueVisible: localRequestValueVisible,
|
||||
timelineTitle: `${localRequestLabel} ${localRequestDisplay} 次`,
|
||||
timelineTitle: t('accounts.quota.requests', { localRequestLabel, localRequestDisplay }),
|
||||
requestBars: requestTimeline(localUsage?.requestBuckets ?? []),
|
||||
durationDisplay: rollingWindowDurationDisplay(input.window?.windowSeconds),
|
||||
},
|
||||
@@ -237,6 +240,41 @@ export function quotaWindowLocalUsageDisplay(window: AccountQuotaWindow) {
|
||||
return localTokenDisplay(localUsage) || null
|
||||
}
|
||||
|
||||
const quotaWindowPeriods = [
|
||||
{ seconds: 18_000, label: () => t('accounts.quota.windows.fiveHour') },
|
||||
{ seconds: 86_400, label: () => t('accounts.quota.windows.daily') },
|
||||
{ seconds: 604_800, label: () => t('accounts.quota.windows.weekly') },
|
||||
{ seconds: 2_592_000, label: () => t('accounts.quota.windows.monthly') },
|
||||
{ seconds: 31_536_000, label: () => t('accounts.quota.windows.annual') },
|
||||
]
|
||||
|
||||
export function quotaWindowLabel(window: AccountQuotaWindow, includeLimitName = true) {
|
||||
const seconds = window.windowSeconds
|
||||
// 沿用 Codex 官方的显示时长容差;仅决定文案,不改变后端窗口归属或额度判定。
|
||||
const period = seconds === null
|
||||
? undefined
|
||||
: quotaWindowPeriods.find(period =>
|
||||
seconds >= period.seconds * 0.95 && seconds <= period.seconds * 1.05,
|
||||
)
|
||||
let label: string
|
||||
if (period)
|
||||
label = period.label()
|
||||
else if (seconds !== null && seconds > 0)
|
||||
label = t('accounts.quota.windows.duration', { duration: rollingWindowDurationDisplay(seconds) })
|
||||
else if (window.role === 'monthly')
|
||||
label = t('accounts.quota.windows.monthly')
|
||||
else if (window.role === 'primary')
|
||||
label = t('accounts.quota.windows.usage')
|
||||
else if (window.role === 'secondary')
|
||||
label = t('accounts.quota.windows.secondary')
|
||||
else
|
||||
label = window.windowLabelDisplay
|
||||
|
||||
return includeLimitName && window.limitName && window.limitId !== 'codex'
|
||||
? `${window.limitName} · ${label}`
|
||||
: label
|
||||
}
|
||||
|
||||
function requestCountDisplay(localUsage: AccountLocalUsage | null) {
|
||||
const display = localUsage?.requestCountDisplay
|
||||
if (typeof display === 'string' && display.trim())
|
||||
@@ -252,12 +290,12 @@ function rollingWindowDurationDisplay(windowSeconds: number | null | undefined)
|
||||
const hourSeconds = 60 * 60
|
||||
const daySeconds = 24 * hourSeconds
|
||||
if (windowSeconds <= daySeconds * 2 && windowSeconds % hourSeconds === 0)
|
||||
return `${formatInteger(windowSeconds / hourSeconds)} 小时`
|
||||
return t('accounts.quota.h', { duration: formatInteger(windowSeconds / hourSeconds) })
|
||||
if (windowSeconds % daySeconds === 0)
|
||||
return `${formatInteger(windowSeconds / daySeconds)} 天`
|
||||
return t('accounts.quota.d', { duration: formatInteger(windowSeconds / daySeconds) })
|
||||
if (windowSeconds % hourSeconds === 0)
|
||||
return `${formatInteger(windowSeconds / hourSeconds)} 小时`
|
||||
return `${formatInteger(windowSeconds)} 秒`
|
||||
return t('accounts.quota.h', { duration: formatInteger(windowSeconds / hourSeconds) })
|
||||
return t('accounts.quota.s', { duration: formatInteger(windowSeconds) })
|
||||
}
|
||||
|
||||
export function quotaWindowPresentation(window: AccountQuotaWindow, minimumWidth: string) {
|
||||
|
||||
@@ -27,7 +27,7 @@ export function chartTooltipStyle(
|
||||
textStyle: {
|
||||
color: theme.textPrimary,
|
||||
fontSize: 12,
|
||||
fontFamily: options.fontFamily ?? 'Inter Variable, Inter, system-ui, sans-serif',
|
||||
fontFamily: options.fontFamily ?? (getComputedStyle(document.documentElement).fontFamily),
|
||||
fontWeight: options.fontWeight ?? 650,
|
||||
},
|
||||
extraCssText: 'border-radius: 12px; box-shadow: var(--cp-box-shadow);',
|
||||
|
||||
@@ -4,8 +4,10 @@ import type {
|
||||
ClientProfilePreview,
|
||||
ClientProfileSelection,
|
||||
} from '@/api/modules/settings/profiles'
|
||||
|
||||
import { ZButton, ZEmpty, ZSegmented } from '@codex-proxy/ui'
|
||||
import { computed, onMounted, shallowRef, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { getClientProfileOptions, previewClientProfile } from '@/api/modules/settings/profiles'
|
||||
import { errorMessage } from '@/utils/operation'
|
||||
import ClientProfilePresetFields from './ClientProfilePresetFields.vue'
|
||||
@@ -16,6 +18,9 @@ const props = withDefaults(defineProps<{ active?: boolean, disabled?: boolean, a
|
||||
disabled: false,
|
||||
allowInherit: false,
|
||||
})
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const model = defineModel<ClientProfileSelection | null>({ required: true })
|
||||
const options = shallowRef<ClientProfileOptions>()
|
||||
const preview = shallowRef<ClientProfilePreview>()
|
||||
@@ -76,7 +81,7 @@ watch([model, () => props.active], ([configuration, active], _, onCleanup) => {
|
||||
}
|
||||
catch (error) {
|
||||
if (!cancelled)
|
||||
previewError.value = errorMessage(error).replaceAll('User-Agent', '用户代理')
|
||||
previewError.value = errorMessage(error).replaceAll('User-Agent', t('settings.clientProfile.userAgent'))
|
||||
}
|
||||
finally {
|
||||
if (!cancelled)
|
||||
@@ -97,20 +102,20 @@ onMounted(() => load())
|
||||
<div v-if="allowInherit" class="flex flex-wrap items-center justify-between gap-3">
|
||||
<ZSegmented
|
||||
v-model="profileSource"
|
||||
aria-label="客户端身份来源"
|
||||
:aria-label="t('settings.clientProfile.clientIdentitySource')"
|
||||
class="shrink-0"
|
||||
:options="[
|
||||
{ label: '全局配置', value: 'global' },
|
||||
{ label: '独立配置', value: 'independent' },
|
||||
{ label: t('settings.clientProfile.globalConfiguration'), value: 'global' },
|
||||
{ label: t('settings.clientProfile.customConfiguration'), value: 'independent' },
|
||||
]"
|
||||
:disabled="disabled || loading || !options"
|
||||
/>
|
||||
<slot name="source-extra" />
|
||||
</div>
|
||||
<ZEmpty v-if="loadError" title="预设加载失败" :description="loadError" size="small" surface="none" role="alert">
|
||||
<ZEmpty v-if="loadError" :title="t('settings.clientProfile.presetLoadingFailed')" :description="loadError" size="small" surface="none" role="alert">
|
||||
<template #action>
|
||||
<ZButton size="small" :disabled="disabled || loading" @click="load()">
|
||||
重试
|
||||
{{ t('common.actions.retry') }}
|
||||
</ZButton>
|
||||
</template>
|
||||
</ZEmpty>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import type { ClientProfilePreset, ClientProfilePreview, ClientProfileSelection, CustomClientProfileSelection, PresetClientProfileSelection } from '@/api/modules/settings/profiles'
|
||||
|
||||
import { ZFormItem, ZInput, ZSelect, ZTextarea } from '@codex-proxy/ui'
|
||||
import { computed, shallowRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
presets: ClientProfilePreset[]
|
||||
@@ -13,6 +15,9 @@ const props = withDefaults(defineProps<{
|
||||
}>(), {
|
||||
maxVersionLag: 10,
|
||||
})
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const model = defineModel<ClientProfileSelection | null>({ required: true })
|
||||
const presetDraft = shallowRef<PresetClientProfileSelection>()
|
||||
const customDraft = shallowRef<CustomClientProfileSelection>()
|
||||
@@ -78,7 +83,7 @@ const versionLag = computed({
|
||||
const versionLagError = computed(() => {
|
||||
const value = preset.value?.versionLag
|
||||
return value != null && (!Number.isInteger(value) || value < 1 || value > props.maxVersionLag)
|
||||
? `请输入 1~${props.maxVersionLag} 的正整数`
|
||||
? t('settings.clientProfile.enterIntegerFromTo', { version: props.maxVersionLag })
|
||||
: ''
|
||||
})
|
||||
const terminal = computed({
|
||||
@@ -115,28 +120,28 @@ const userAgent = computed({
|
||||
<template>
|
||||
<div class="grid gap-4">
|
||||
<div class="grid gap-4" :class="preset?.client === 'cli' && !custom ? 'sm:grid-cols-3' : 'sm:grid-cols-2'">
|
||||
<ZFormItem label="客户端预设">
|
||||
<ZSelect v-model="selectedPreset" class="w-full" :options="presetOptions" :placeholder="custom ? '使用自定义用户代理' : undefined" :disabled="disabled || custom || !presets.length" />
|
||||
<ZFormItem :label="t('settings.clientProfile.clientDefault')">
|
||||
<ZSelect v-model="selectedPreset" class="w-full" :options="presetOptions" :placeholder="custom ? t('settings.clientProfile.useCustomUserAgent') : undefined" :disabled="disabled || custom || !presets.length" />
|
||||
</ZFormItem>
|
||||
<ZFormItem v-if="preset?.client === 'cli' && !custom" label="CLI 入口">
|
||||
<ZFormItem v-if="preset?.client === 'cli' && !custom" :label="t('settings.clientProfile.cliEntry')">
|
||||
<ZSelect
|
||||
v-model="cliEntry"
|
||||
class="w-full"
|
||||
:options="[
|
||||
{ label: 'Core · 默认身份', value: 'core' },
|
||||
{ label: 'TUI · 交互式终端', value: 'tui' },
|
||||
{ label: 'Exec · 非交互执行', value: 'exec' },
|
||||
{ label: t('settings.clientProfile.coreDefaultIdentity'), value: 'core' },
|
||||
{ label: t('settings.clientProfile.tuiInteractiveTerminal'), value: 'tui' },
|
||||
{ label: t('settings.clientProfile.execNonInteractiveExecution'), value: 'exec' },
|
||||
]"
|
||||
:disabled="disabled"
|
||||
/>
|
||||
</ZFormItem>
|
||||
<ZFormItem label="版本策略">
|
||||
<ZFormItem :label="t('settings.clientProfile.versionStrategy')">
|
||||
<ZSelect
|
||||
v-model="versionMode"
|
||||
class="w-full"
|
||||
:options="[
|
||||
{ label: '跟随最新版本', value: 'latest', disabled: !presets.length },
|
||||
{ label: '自定义版本', value: 'custom', disabled: !custom && (previewing || !preview) },
|
||||
{ label: t('settings.clientProfile.followLatestVersion'), value: 'latest', disabled: !presets.length },
|
||||
{ label: t('settings.clientProfile.customVersion'), value: 'custom', disabled: !custom && (previewing || !preview) },
|
||||
]"
|
||||
:disabled="disabled"
|
||||
/>
|
||||
@@ -146,37 +151,37 @@ const userAgent = computed({
|
||||
{{ currentPreset.reason }}
|
||||
</p>
|
||||
<div v-if="!custom" class="grid gap-4 sm:grid-cols-2">
|
||||
<ZFormItem label="版本滞后" :error="versionLagError">
|
||||
<ZFormItem :label="t('settings.clientProfile.versionLag')" :error="versionLagError">
|
||||
<ZInput
|
||||
v-model="versionLag"
|
||||
aria-label="版本滞后"
|
||||
:aria-label="t('settings.clientProfile.versionLag')"
|
||||
type="number"
|
||||
inputmode="numeric"
|
||||
min="1"
|
||||
:max="maxVersionLag"
|
||||
step="1"
|
||||
:placeholder="`滞后 1~${maxVersionLag} 个版本,留空不滞后`"
|
||||
:placeholder="t('settings.clientProfile.versionLagHelp', { version: maxVersionLag })"
|
||||
:disabled="disabled"
|
||||
/>
|
||||
</ZFormItem>
|
||||
<div class="grid gap-4" :class="{ 'sm:grid-cols-2': preset?.client === 'desktop' }">
|
||||
<ZFormItem label="终端标识">
|
||||
<ZFormItem :label="t('settings.clientProfile.terminalIdentification')">
|
||||
<ZInput
|
||||
v-model="terminal"
|
||||
:disabled="disabled"
|
||||
aria-label="终端标识"
|
||||
placeholder="留空使用 unknown"
|
||||
:aria-label="t('settings.clientProfile.terminalIdentification')"
|
||||
:placeholder="t('settings.clientProfile.leaveBlankToUseUnknown')"
|
||||
maxlength="128"
|
||||
spellcheck="false"
|
||||
autocomplete="off"
|
||||
class="font-mono"
|
||||
/>
|
||||
</ZFormItem>
|
||||
<ZFormItem v-if="preset?.client === 'desktop'" label="系统版本">
|
||||
<ZFormItem v-if="preset?.client === 'desktop'" :label="t('settings.clientProfile.systemVersion')">
|
||||
<ZInput
|
||||
v-model="osVersion"
|
||||
:disabled="disabled"
|
||||
aria-label="系统版本"
|
||||
:aria-label="t('settings.clientProfile.systemVersion')"
|
||||
:placeholder="currentPreset?.defaults.osVersion ?? undefined"
|
||||
maxlength="128"
|
||||
spellcheck="false"
|
||||
@@ -191,8 +196,8 @@ const userAgent = computed({
|
||||
v-model="userAgent"
|
||||
:rows="3"
|
||||
:disabled="disabled || (!model?.mode && previewing)"
|
||||
aria-label="用户代理"
|
||||
placeholder="填写完整用户代理"
|
||||
:aria-label="t('settings.clientProfile.userAgent')"
|
||||
:placeholder="t('settings.clientProfile.userAgentPlaceholder')"
|
||||
spellcheck="false"
|
||||
autocomplete="off"
|
||||
class="font-mono"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import type { ClientProfilePreview } from '@/api/modules/settings/profiles'
|
||||
|
||||
import { ZEmpty, ZSkeleton } from '@codex-proxy/ui'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
defineProps<{
|
||||
preview?: Pick<ClientProfilePreview, 'userAgent' | 'versionSource' | 'checkedAtDisplay' | 'error'> & { versionLag?: number | null }
|
||||
@@ -8,13 +10,15 @@ defineProps<{
|
||||
needsVersionInput: boolean
|
||||
error: string
|
||||
}>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p v-if="needsVersionInput" role="status" class="m-0 text-cp-sm text-cp-text-tertiary">
|
||||
填写版本后预览
|
||||
{{ t('settings.clientProfile.previewAfterFillingInVersion') }}
|
||||
</p>
|
||||
<ZEmpty v-else-if="error && !previewing" title="预览暂不可用" :description="error" size="small" surface="none" role="alert" />
|
||||
<ZEmpty v-else-if="error && !previewing" :title="t('settings.clientProfile.previewIsNotAvailableYet')" :description="error" size="small" surface="none" role="alert" />
|
||||
<div
|
||||
v-else-if="previewing || preview"
|
||||
class="grid min-h-20 min-w-0 content-center gap-2 rounded-cp bg-cp-fill-quaternary p-4"
|
||||
@@ -22,7 +26,7 @@ defineProps<{
|
||||
:aria-busy="previewing"
|
||||
>
|
||||
<template v-if="previewing">
|
||||
<div class="flex h-lh items-center text-cp-sm" role="status" aria-label="正在解析客户端身份">
|
||||
<div class="flex h-lh items-center text-cp-sm" role="status" :aria-label="t('settings.clientProfile.resolvingClientIdentity')">
|
||||
<ZSkeleton shape="text" class="w-4/5" aria-hidden="true" />
|
||||
</div>
|
||||
<div class="flex h-lh items-center text-cp-xs" aria-hidden="true">
|
||||
@@ -32,16 +36,16 @@ defineProps<{
|
||||
<template v-else-if="preview">
|
||||
<code class="break-all text-cp-sm text-cp-text">{{ preview.userAgent }}</code>
|
||||
<p class="m-0 text-cp-xs text-cp-text-tertiary">
|
||||
{{ preview.versionSource === 'custom' ? '固定身份' : '自动更新' }}
|
||||
{{ preview.versionSource === 'custom' ? t('settings.clientProfile.fixedIdentity') : t('settings.clientProfile.automaticUpdates') }}
|
||||
<template v-if="preview.versionSource === 'official'">
|
||||
<template v-if="preview.versionLag">
|
||||
· 滞后 {{ preview.versionLag }} 版
|
||||
{{ t('settings.clientProfile.versionsBehind', { version: preview.versionLag }) }}
|
||||
</template>
|
||||
· {{ preview.checkedAtDisplay ? `检查于 ${preview.checkedAtDisplay}` : '待检查' }}
|
||||
· {{ preview.checkedAtDisplay ? t('settings.clientProfile.checked', { checkedAtDisplay: preview.checkedAtDisplay }) : t('settings.clientProfile.toBeChecked') }}
|
||||
</template>
|
||||
</p>
|
||||
<p v-if="preview.error && preview.versionSource !== 'custom'" :title="preview.error" class="m-0 text-cp-sm text-cp-warning">
|
||||
更新失败 · 沿用上次版本
|
||||
{{ t('settings.clientProfile.updateFailedUseLastVersion') }}
|
||||
</p>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import type { ClientProfileSelection, ProviderRequestProfile, ProviderRequestProfiles, XaiClientProfileSelection } from '@/api/modules/settings/profiles'
|
||||
|
||||
import { ZSegmented } from '@codex-proxy/ui'
|
||||
import { computed, shallowRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { formatProviderLabel, PROVIDER_IDS, providerIcon } from '@/utils/providers'
|
||||
import ClientProfileEditor from './ClientProfileEditor.vue'
|
||||
import XaiClientProfileEditor from './XaiClientProfileEditor.vue'
|
||||
@@ -16,6 +18,8 @@ withDefaults(defineProps<{
|
||||
allowInherit: false,
|
||||
})
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const model = defineModel<ProviderRequestProfiles>({ required: true })
|
||||
const provider = shallowRef<(typeof PROVIDER_IDS)[number]>('openai')
|
||||
const providerOptions = PROVIDER_IDS.map(value => ({
|
||||
@@ -51,7 +55,7 @@ function updateProfile(providerId: string, value: ProviderRequestProfile | null)
|
||||
<ZSegmented
|
||||
v-model="provider"
|
||||
class="ml-auto max-w-full shrink-0"
|
||||
aria-label="客户端身份 Provider"
|
||||
:aria-label="t('settings.clientProfile.clientIdentityProvider')"
|
||||
:options="providerOptions"
|
||||
:disabled="disabled"
|
||||
:style="providerSelectorStyle"
|
||||
@@ -69,7 +73,7 @@ function updateProfile(providerId: string, value: ProviderRequestProfile | null)
|
||||
<ZSegmented
|
||||
v-model="provider"
|
||||
class="max-w-full shrink-0"
|
||||
aria-label="上游身份平台"
|
||||
:aria-label="t('settings.clientProfile.upstreamIdentityPlatform')"
|
||||
:options="providerOptions"
|
||||
:disabled="disabled"
|
||||
:style="providerSelectorStyle"
|
||||
@@ -88,7 +92,7 @@ function updateProfile(providerId: string, value: ProviderRequestProfile | null)
|
||||
<ZSegmented
|
||||
v-model="provider"
|
||||
class="max-w-full shrink-0"
|
||||
aria-label="上游身份平台"
|
||||
:aria-label="t('settings.clientProfile.upstreamIdentityPlatform')"
|
||||
:options="providerOptions"
|
||||
:disabled="disabled"
|
||||
:style="providerSelectorStyle"
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import type { XaiClientProfilePreview, XaiClientProfileSelection } from '@/api/modules/settings/profiles'
|
||||
|
||||
import { ZButton, ZEmpty, ZFormItem, ZInput, ZSegmented, ZSelect } from '@codex-proxy/ui'
|
||||
import { computed, onMounted, shallowRef, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { getXaiClientProfileOptions, previewXaiClientProfile } from '@/api/modules/settings/profiles'
|
||||
import { errorMessage } from '@/utils/operation'
|
||||
import ClientProfilePreviewPanel from './ClientProfilePreviewPanel.vue'
|
||||
@@ -11,6 +13,9 @@ const props = withDefaults(defineProps<{ active?: boolean, disabled?: boolean, a
|
||||
disabled: false,
|
||||
allowInherit: false,
|
||||
})
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const model = defineModel<XaiClientProfileSelection | null>({ required: true })
|
||||
const globalConfiguration = shallowRef<XaiClientProfileSelection>()
|
||||
const preview = shallowRef<XaiClientProfilePreview>()
|
||||
@@ -18,12 +23,12 @@ const loadError = shallowRef('')
|
||||
const previewError = shallowRef('')
|
||||
const previewing = shallowRef(false)
|
||||
const needsVersionInput = computed(() => model.value?.versionMode === 'fixed' && !model.value.clientVersion)
|
||||
const fields = [
|
||||
{ key: 'clientIdentifier', label: '客户端标识' },
|
||||
{ key: 'clientMode', label: '运行模式' },
|
||||
{ key: 'targetOs', label: '操作系统' },
|
||||
{ key: 'targetArch', label: 'CPU 架构' },
|
||||
] as const
|
||||
const fields = computed(() => ([
|
||||
{ key: 'clientIdentifier', label: t('settings.clientProfile.clientId') },
|
||||
{ key: 'clientMode', label: t('settings.clientProfile.operatingMode') },
|
||||
{ key: 'targetOs', label: t('settings.clientProfile.operatingSystem') },
|
||||
{ key: 'targetArch', label: t('settings.clientProfile.cpuArchitecture') },
|
||||
] as const))
|
||||
|
||||
const source = computed({
|
||||
get: () => model.value === null ? 'global' : 'independent',
|
||||
@@ -100,32 +105,32 @@ onMounted(() => props.allowInherit && void load())
|
||||
<div v-if="allowInherit" class="flex flex-wrap items-center justify-between gap-3">
|
||||
<ZSegmented
|
||||
v-model="source"
|
||||
aria-label="xAI 客户端身份来源"
|
||||
:aria-label="t('settings.clientProfile.xaiClientIdentitySource')"
|
||||
class="shrink-0"
|
||||
:options="[{ label: '全局配置', value: 'global' }, { label: '独立配置', value: 'independent' }]"
|
||||
:options="[{ label: t('settings.clientProfile.globalConfiguration'), value: 'global' }, { label: t('settings.clientProfile.customConfiguration'), value: 'independent' }]"
|
||||
:disabled="disabled || !globalConfiguration"
|
||||
/>
|
||||
<slot name="source-extra" />
|
||||
</div>
|
||||
<ZEmpty v-if="loadError" title="全局配置加载失败" :description="loadError" size="small" surface="none" role="alert">
|
||||
<ZEmpty v-if="loadError" :title="t('settings.clientProfile.loadFailed')" :description="loadError" size="small" surface="none" role="alert">
|
||||
<template #action>
|
||||
<ZButton size="small" @click="load">
|
||||
重试
|
||||
{{ t('common.actions.retry') }}
|
||||
</ZButton>
|
||||
</template>
|
||||
</ZEmpty>
|
||||
<template v-if="model">
|
||||
<div class="grid gap-4 sm:grid-cols-2">
|
||||
<ZFormItem label="客户端类型">
|
||||
<ZFormItem :label="t('settings.clientProfile.clientType')">
|
||||
<ZInput model-value="Grok CLI" readonly :disabled="disabled" />
|
||||
</ZFormItem>
|
||||
<ZFormItem label="版本策略">
|
||||
<ZSelect v-model="versionMode" class="w-full" :disabled="disabled" :options="[{ label: '跟随最新版本', value: 'latest' }, { label: '自定义版本', value: 'fixed' }]" />
|
||||
<ZFormItem :label="t('settings.clientProfile.versionStrategy')">
|
||||
<ZSelect v-model="versionMode" class="w-full" :disabled="disabled" :options="[{ label: t('settings.clientProfile.followLatestVersion'), value: 'latest' }, { label: t('settings.clientProfile.customVersion'), value: 'fixed' }]" />
|
||||
</ZFormItem>
|
||||
</div>
|
||||
<div v-if="model.versionMode === 'fixed'" class="grid gap-4 sm:grid-cols-2">
|
||||
<ZFormItem label="Grok CLI 版本" required>
|
||||
<ZInput :model-value="model.clientVersion ?? ''" :disabled="disabled" placeholder="例如:1.0.13" @update:model-value="updateField('clientVersion', $event)" />
|
||||
<ZFormItem :label="t('settings.clientProfile.grokCliVersion')" required>
|
||||
<ZInput :model-value="model.clientVersion ?? ''" :disabled="disabled" :placeholder="t('settings.clientProfile.forExample')" @update:model-value="updateField('clientVersion', $event)" />
|
||||
</ZFormItem>
|
||||
<ZFormItem v-for="field in fields" :key="field.key" :label="field.label" required>
|
||||
<ZInput :model-value="model[field.key]" :disabled="disabled" @update:model-value="updateField(field.key, $event)" />
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import type { InputField } from './schema'
|
||||
|
||||
import { ZForm, ZFormItem, ZIconButton, ZInput, ZPopover, ZSelect, ZTextarea } from '@codex-proxy/ui'
|
||||
import { Braces, Info, List } from '@lucide/vue'
|
||||
import { computed, nextTick, shallowRef, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { parseJsonObject } from '@/utils/data'
|
||||
import { inputFields } from './schema'
|
||||
|
||||
@@ -12,6 +14,9 @@ const props = defineProps<{
|
||||
maximumBytes?: number
|
||||
fieldErrors?: Record<string, string>
|
||||
}>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const text = defineModel<string>({ required: true })
|
||||
const jsonMode = shallowRef(false)
|
||||
const root = useTemplateRef<HTMLElement>('root')
|
||||
@@ -49,8 +54,8 @@ function inputValue(key: string) {
|
||||
function fieldOptions(field: InputField) {
|
||||
const options = field.values
|
||||
? field.values.map((item, index) => ({ value: String(index), label: String(item) }))
|
||||
: [{ value: 'true', label: '是' }, { value: 'false', label: '否' }]
|
||||
return [{ value: '', label: '未填写' }, ...options]
|
||||
: [{ value: 'true', label: t('common.values.yes') }, { value: 'false', label: t('common.values.no') }]
|
||||
return [{ value: '', label: t('common.values.unspecified') }, ...options]
|
||||
}
|
||||
|
||||
function update(field: InputField, input: string) {
|
||||
@@ -95,9 +100,9 @@ defineExpose({ focusField })
|
||||
<template>
|
||||
<div v-if="!empty" ref="root" class="grid gap-3">
|
||||
<ZForm v-if="showJson">
|
||||
<ZFormItem label="输入内容" :error="error">
|
||||
<ZFormItem :label="t('common.form.inputPlaceholder')" :error="error">
|
||||
<template #extra>
|
||||
<ZIconButton v-if="fields !== null" aria-label="使用表单" size="small" variant="solid" :disabled="disabled || Boolean(error) || hasExtra || incompatibleValue" @click="jsonMode = false">
|
||||
<ZIconButton v-if="fields !== null" :aria-label="t('common.form.useForm')" size="small" variant="solid" :disabled="disabled || Boolean(error) || hasExtra || incompatibleValue" @click="jsonMode = false">
|
||||
<List class="size-4" />
|
||||
</ZIconButton>
|
||||
</template>
|
||||
@@ -115,7 +120,7 @@ defineExpose({ focusField })
|
||||
<template v-if="field.description" #label-extra>
|
||||
<ZPopover trigger="hover-click" placement="top-start">
|
||||
<template #reference>
|
||||
<ZIconButton :aria-label="`${field.label}说明`" class="size-3.5!" :title="undefined">
|
||||
<ZIconButton :aria-label="t('common.form.fieldHelp', { label: field.label })" class="size-3.5!" :title="undefined">
|
||||
<Info class="size-3.5" />
|
||||
</ZIconButton>
|
||||
</template>
|
||||
@@ -125,7 +130,7 @@ defineExpose({ focusField })
|
||||
</ZPopover>
|
||||
</template>
|
||||
<template v-if="index === 0" #extra>
|
||||
<ZIconButton aria-label="编辑 JSON" size="small" variant="solid" :disabled="disabled" @click="jsonMode = true">
|
||||
<ZIconButton :aria-label="t('common.form.editJson')" size="small" variant="solid" :disabled="disabled" @click="jsonMode = true">
|
||||
<Braces class="size-4" />
|
||||
</ZIconButton>
|
||||
</template>
|
||||
|
||||
@@ -2,37 +2,41 @@
|
||||
import type { DashboardHealthTimelinePoint } from '@/api'
|
||||
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { formatHealthCount, healthEligibleRequestCount, healthObservedRequestCount, healthServiceFailureCount, healthStatusMeta } from '@/components/usage/shared/health'
|
||||
|
||||
const props = defineProps<{
|
||||
point: DashboardHealthTimelinePoint
|
||||
}>()
|
||||
|
||||
const status = computed(() => healthStatusMeta[props.point.status])
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const status = computed(() => healthStatusMeta.value[props.point.status])
|
||||
const eligibleRequests = computed(() => healthEligibleRequestCount(props.point))
|
||||
const observedRequests = computed(() => healthObservedRequestCount(props.point))
|
||||
// 结果标签、取值与配色集中维护,分段条与明细行都由此派生
|
||||
const outcomeMeta = computed(() => [
|
||||
{
|
||||
label: '成功',
|
||||
label: t('common.status.success'),
|
||||
value: props.point.successRequests,
|
||||
dotClass: 'bg-cp-success',
|
||||
valueClass: 'text-cp-success-text',
|
||||
},
|
||||
{
|
||||
label: '服务失败',
|
||||
label: t('usage.health.point.serviceFailed'),
|
||||
value: healthServiceFailureCount(props.point),
|
||||
dotClass: 'bg-cp-error',
|
||||
valueClass: 'text-cp-error-text',
|
||||
},
|
||||
{
|
||||
label: '客户端取消',
|
||||
label: t('usage.health.point.clientCancel'),
|
||||
value: props.point.cancelledRequests,
|
||||
dotClass: 'bg-cp-orange-solid',
|
||||
valueClass: 'text-cp-orange-text',
|
||||
},
|
||||
{
|
||||
label: '调用方错误',
|
||||
label: t('usage.health.point.callerError'),
|
||||
value: props.point.callerErrorRequests,
|
||||
dotClass: 'bg-cp-info',
|
||||
valueClass: 'text-cp-info-text',
|
||||
@@ -57,7 +61,7 @@ const metricItems = outcomeMeta
|
||||
<template>
|
||||
<section
|
||||
role="dialog"
|
||||
:aria-label="`${point.time} 请求健康详情`"
|
||||
:aria-label="t('usage.health.point.requestHealthDetailsFor', { time: point.time })"
|
||||
class="overflow-hidden rounded-cp-lg bg-cp-bg-elevated"
|
||||
>
|
||||
<header class="flex items-center justify-between gap-3 bg-cp-popover-header-bg px-3.5 py-3">
|
||||
@@ -73,14 +77,14 @@ const metricItems = outcomeMeta
|
||||
{{ status.label }}
|
||||
</span>
|
||||
</div>
|
||||
<span class="shrink-0 text-[10px] leading-none font-emphasis text-cp-text-quaternary"> 15 分钟 </span>
|
||||
<span class="shrink-0 text-[10px] leading-none font-emphasis text-cp-text-quaternary"> {{ t('usage.health.point.minutes') }} </span>
|
||||
</header>
|
||||
|
||||
<div class="grid gap-3.5 px-3.5 py-3.5">
|
||||
<div class="flex items-end justify-between gap-4">
|
||||
<div>
|
||||
<p class="m-0 text-cp-xs leading-none font-emphasis text-cp-text-quaternary">
|
||||
有效请求可用性
|
||||
{{ t('usage.health.point.validRequestAvailability') }}
|
||||
</p>
|
||||
<strong
|
||||
class="mt-2 block font-mono text-[25px] leading-none font-heavy tabular-nums"
|
||||
@@ -90,7 +94,7 @@ const metricItems = outcomeMeta
|
||||
</strong>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<span class="block text-[10px] leading-none font-emphasis text-cp-text-quaternary"> 有效请求 </span>
|
||||
<span class="block text-[10px] leading-none font-emphasis text-cp-text-quaternary"> {{ t('usage.health.point.validRequest') }} </span>
|
||||
<strong class="mt-2 block font-mono text-cp-xl leading-none font-heavy tabular-nums text-cp-text">
|
||||
{{ formatHealthCount(eligibleRequests) }}
|
||||
</strong>
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import type { DashboardHealthTimeline, DashboardHealthTimelinePoint } from '@/api'
|
||||
import { ZButton, ZCard, ZPopover } from '@codex-proxy/ui'
|
||||
|
||||
import { ZButton, ZCard, ZPopover } from '@codex-proxy/ui'
|
||||
import { usePreferredReducedMotion, useResizeObserver } from '@vueuse/core'
|
||||
|
||||
import { gsap } from 'gsap'
|
||||
import { computed, onBeforeUnmount, shallowRef, useTemplateRef, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import HealthTimelinePointPopover from '@/components/usage/HealthTimelinePointPopover.vue'
|
||||
import { formatHealthCount, healthEligibleRequestCount, healthLegend, healthObservedRequestCount, healthStatusMeta } from '@/components/usage/shared/health'
|
||||
|
||||
@@ -12,6 +14,8 @@ const props = defineProps<{
|
||||
timeline: DashboardHealthTimeline
|
||||
}>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const healthPopoverArrowSurfaceClasses = {
|
||||
top: 'bg-cp-popover-header-bg',
|
||||
bottom: 'bg-cp-bg-elevated',
|
||||
@@ -193,7 +197,7 @@ function releasePointWave() {
|
||||
|
||||
function pointAccessibilityLabel(point: DashboardHealthTimelinePoint) {
|
||||
const eligibleRequests = healthEligibleRequestCount(point)
|
||||
return `${point.time},${healthStatusMeta[point.status].label},有效请求 ${formatHealthCount(eligibleRequests)},可用性 ${point.reliabilityDisplay}`
|
||||
return t('usage.health.validRequestsAvailability', { time: point.time, label: healthStatusMeta.value[point.status].label, count: formatHealthCount(eligibleRequests), reliabilityDisplay: point.reliabilityDisplay })
|
||||
}
|
||||
|
||||
watch(popoverOpen, (open) => {
|
||||
@@ -222,7 +226,7 @@ onBeforeUnmount(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ZCard as="article" :title="timeline.title" :description="timeline.description" class="w-full">
|
||||
<ZCard as="article" :title="t('dashboard.health.title')" :description="t('dashboard.health.description')" class="w-full">
|
||||
<template #actions>
|
||||
<div class="flex w-full flex-wrap items-center justify-between gap-x-4 gap-y-2">
|
||||
<div
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
import type { UsageListRecord } from '@/api'
|
||||
|
||||
import { Zap } from '@lucide/vue'
|
||||
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import UsageDetailPopover from '@/components/usage/UsageDetailPopover.vue'
|
||||
import { usageBillingText } from './shared/presenter'
|
||||
|
||||
@@ -10,6 +12,8 @@ const props = defineProps<{
|
||||
record: Pick<UsageListRecord, 'billing'>
|
||||
}>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const billing = computed(() => props.record.billing)
|
||||
const billingItems = computed(() => {
|
||||
const value = billing.value
|
||||
@@ -17,10 +21,10 @@ const billingItems = computed(() => {
|
||||
return []
|
||||
|
||||
return [
|
||||
{ label: '服务档位', value: value.serviceTierDisplay, tone: 'info' },
|
||||
{ label: '倍率', value: value.multiplierDisplay, tone: 'info' },
|
||||
{ label: '总费用', value: value.totalAmountDisplay, tone: 'success' },
|
||||
{ label: '标准费用', value: value.standardAmountDisplay, tone: 'default' },
|
||||
{ label: t('usage.billing.serviceLevel'), value: value.serviceTierDisplay, tone: 'info' },
|
||||
{ label: t('settings.pricing.multiplier'), value: value.multiplierDisplay, tone: 'info' },
|
||||
{ label: t('usage.billing.totalCost'), value: value.totalAmountDisplay, tone: 'success' },
|
||||
{ label: t('usage.billing.standardFee'), value: value.standardAmountDisplay, tone: 'default' },
|
||||
]
|
||||
})
|
||||
|
||||
@@ -30,21 +34,21 @@ const amountItems = computed(() => {
|
||||
return []
|
||||
|
||||
return [
|
||||
{ label: value.image ? '文本输入费用' : '输入费用', value: value.inputAmountDisplay, accent: false },
|
||||
{ label: value.image ? t('usage.billing.textInputCost') : t('usage.billing.inputCost'), value: value.inputAmountDisplay, accent: false },
|
||||
...(value.image
|
||||
? [
|
||||
{ label: '图像输入费用', value: value.image.inputAmountDisplay, accent: false },
|
||||
{ label: '图像缓存费用', value: value.image.cacheReadAmountDisplay, accent: false },
|
||||
{ label: '图像输入单价', value: value.image.inputPriceDisplay, accent: true },
|
||||
{ label: '图像缓存单价', value: value.image.cacheReadPriceDisplay, accent: true },
|
||||
{ label: t('usage.billing.imageInputFee'), value: value.image.inputAmountDisplay, accent: false },
|
||||
{ label: t('usage.billing.imageCachingCharges'), value: value.image.cacheReadAmountDisplay, accent: false },
|
||||
{ label: t('usage.billing.imageInputUnitPrice'), value: value.image.inputPriceDisplay, accent: true },
|
||||
{ label: t('usage.billing.imageCacheUnitPrice'), value: value.image.cacheReadPriceDisplay, accent: true },
|
||||
]
|
||||
: []),
|
||||
{ label: value.image ? '图像输出费用' : '输出费用', value: value.outputAmountDisplay, accent: false },
|
||||
{ label: value.image ? '文本输入单价' : '输入单价', value: value.inputPriceDisplay, accent: true },
|
||||
{ label: value.image ? '图像输出单价' : '输出单价', value: value.outputPriceDisplay, accent: true },
|
||||
{ label: value.image ? '文本缓存读取费用' : '缓存读取费用', value: value.cacheReadAmountDisplay, accent: false },
|
||||
{ label: '缓存写入费用', value: value.cacheWriteAmountDisplay, accent: false },
|
||||
{ label: '缓存写入单价', value: value.cacheWritePriceDisplay, accent: true },
|
||||
{ label: value.image ? t('usage.billing.imageOutputFee') : t('usage.billing.outputFee'), value: value.outputAmountDisplay, accent: false },
|
||||
{ label: value.image ? t('usage.billing.textInputUnitPrice') : t('usage.billing.inputUnitPrice'), value: value.inputPriceDisplay, accent: true },
|
||||
{ label: value.image ? t('usage.billing.imageOutputUnitPrice') : t('usage.billing.outputUnitPrice'), value: value.outputPriceDisplay, accent: true },
|
||||
{ label: value.image ? t('usage.billing.textCacheReadCost') : t('usage.billing.cacheReadCost'), value: value.cacheReadAmountDisplay, accent: false },
|
||||
{ label: t('usage.billing.cacheWriteCost'), value: value.cacheWriteAmountDisplay, accent: false },
|
||||
{ label: t('usage.billing.cacheWriteUnitPrice'), value: value.cacheWritePriceDisplay, accent: true },
|
||||
]
|
||||
})
|
||||
|
||||
@@ -67,15 +71,15 @@ function itemValueClass(tone?: string, accent?: boolean) {
|
||||
<span
|
||||
v-if="billing.serviceTierDisplay === 'Fast'"
|
||||
class="inline-flex size-4 items-center justify-center rounded-full bg-cp-warning-container text-cp-warning-on-container"
|
||||
title="Fast 模式"
|
||||
:title="t('usage.billing.fastMode')"
|
||||
role="img"
|
||||
aria-label="Fast 模式"
|
||||
:aria-label="t('usage.billing.fastMode')"
|
||||
>
|
||||
<Zap class="size-3" stroke-width="2.2" aria-hidden="true" />
|
||||
</span>
|
||||
<UsageDetailPopover
|
||||
:title="billing.longContextBillingApplied ? '长上下文计费明细' : '计费明细'"
|
||||
:trigger-label="billing.longContextBillingApplied ? '查看长上下文计费明细' : '查看费用明细'"
|
||||
:title="billing.longContextBillingApplied ? t('usage.billing.longContextBillingDetails') : t('usage.billing.billingDetails')"
|
||||
:trigger-label="billing.longContextBillingApplied ? t('usage.billing.viewLongContextBillingDetails') : t('usage.billing.viewCostDetails')"
|
||||
:tone="billing.longContextBillingApplied ? 'warning' : 'primary'"
|
||||
>
|
||||
<div class="grid gap-1.5 text-cp-text-secondary">
|
||||
|
||||
@@ -29,7 +29,7 @@ defineProps<{
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<div class="grid w-60 gap-2 p-3 text-cp-sm leading-none">
|
||||
<div class="grid w-max min-w-60 max-w-[calc(100vw-2rem)] gap-2 p-3 text-cp-sm leading-none">
|
||||
<p v-if="title" class="m-0 font-heavy text-cp-text">
|
||||
{{ title }}
|
||||
</p>
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import type { UsageListRecord } from '@/api'
|
||||
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import UsageDetailPopover from '@/components/usage/UsageDetailPopover.vue'
|
||||
import { usageLatencyDetails } from './shared/presenter'
|
||||
|
||||
@@ -9,6 +11,8 @@ const props = defineProps<{
|
||||
record: Pick<UsageListRecord, 'latencyDetails' | 'firstTokenLatencyMs' | 'latencyMs'>
|
||||
}>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const latencyDetails = computed(() => usageLatencyDetails(props.record))
|
||||
|
||||
const latencyTones = {
|
||||
@@ -25,17 +29,17 @@ const latencyTones = {
|
||||
<div
|
||||
class="grid grid-cols-[auto_auto] items-center justify-end gap-x-2 gap-y-1.5 whitespace-nowrap font-mono text-cp-sm leading-none font-heavy tabular-nums"
|
||||
>
|
||||
<span class="text-cp-xs text-cp-text-quaternary">首字</span>
|
||||
<span class="text-cp-xs text-cp-text-quaternary">{{ t('usage.ttft') }}</span>
|
||||
<span :class="latencyDetails.firstOutputSeverity === null ? 'text-cp-text-quaternary' : latencyTones[latencyDetails.firstOutputSeverity]">
|
||||
{{ latencyDetails.firstOutputDisplay }}
|
||||
</span>
|
||||
<span class="text-cp-xs text-cp-text-quaternary">总耗时</span>
|
||||
<span class="text-cp-xs text-cp-text-quaternary">{{ t('usage.latency.total') }}</span>
|
||||
<span :class="latencyDetails.totalSeverity === null ? 'text-cp-text-quaternary' : latencyTones[latencyDetails.totalSeverity]">
|
||||
{{ latencyDetails.totalDisplay }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<UsageDetailPopover trigger-label="查看延迟明细">
|
||||
<UsageDetailPopover :trigger-label="t('usage.latency.viewLatencyDetails')">
|
||||
<section
|
||||
v-for="(section, index) in latencyDetails.sections"
|
||||
:key="section.title"
|
||||
@@ -50,7 +54,7 @@ const latencyTones = {
|
||||
? 'bg-cp-primary-container text-cp-primary-on-container'
|
||||
: 'bg-cp-fill-tertiary text-cp-text-tertiary'"
|
||||
>
|
||||
{{ section.source === 'official' ? '官方' : '本地' }}
|
||||
{{ section.source === 'official' ? t('usage.latency.official') : t('usage.latency.local') }}
|
||||
</span>
|
||||
</p>
|
||||
<div
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { UsageModelRecord } from './shared/presenter'
|
||||
import { CornerDownRight } from '@lucide/vue'
|
||||
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { usageModelDisplay } from './shared/presenter'
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -11,13 +12,14 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
const modelDisplay = computed(() => usageModelDisplay(props.record))
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="inline-grid max-w-full gap-1">
|
||||
<code
|
||||
class="block max-w-full truncate font-mono text-cp-sm leading-none font-heavy text-cp-text"
|
||||
:title="`请求模型:${modelDisplay.primary}`"
|
||||
:title="t('usage.status.requestedModel', { model: modelDisplay.primary })"
|
||||
>
|
||||
{{ modelDisplay.primary }}
|
||||
</code>
|
||||
|
||||
@@ -2,12 +2,16 @@
|
||||
import type { UsagePerformanceRecord } from './shared/presenter'
|
||||
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { usagePerformanceDetails } from './shared/presenter'
|
||||
|
||||
const props = defineProps<{
|
||||
record: UsagePerformanceRecord
|
||||
}>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const performance = computed(() => usagePerformanceDetails(props.record))
|
||||
</script>
|
||||
|
||||
@@ -15,7 +19,7 @@ const performance = computed(() => usagePerformanceDetails(props.record))
|
||||
<div class="grid justify-items-end gap-y-1.5 whitespace-nowrap font-mono text-cp-sm leading-none font-heavy tabular-nums">
|
||||
<span class="text-cp-text">{{ performance.throughputDisplay }}</span>
|
||||
<span class="text-cp-xs text-cp-text-secondary">
|
||||
<span title="首字时间" class="text-cp-text-quaternary">TTFT</span>
|
||||
<span :title="t('usage.performance.ttftHelp')" class="text-cp-text-quaternary">TTFT</span>
|
||||
{{ performance.firstTokenDisplay }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -2,11 +2,15 @@
|
||||
import type { UsageReasoningRecord } from './shared/presenter'
|
||||
|
||||
import { Bot, SquareDashedBottomCode } from '@lucide/vue'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { usageReasoningEffort } from './shared/presenter'
|
||||
|
||||
defineProps<{
|
||||
record: UsageReasoningRecord
|
||||
}>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -17,16 +21,16 @@ defineProps<{
|
||||
<span
|
||||
v-if="record.subagentKind"
|
||||
class="inline-flex shrink-0 text-cp-purple-text"
|
||||
title="子代理请求"
|
||||
aria-label="子代理请求"
|
||||
:title="t('usage.reasoning.subagentRequest')"
|
||||
:aria-label="t('usage.reasoning.subagentRequest')"
|
||||
>
|
||||
<Bot class="size-3.5" stroke-width="2.2" />
|
||||
</span>
|
||||
<span
|
||||
v-if="record.subagentKind === 'review'"
|
||||
class="inline-flex shrink-0 text-cp-purple-text"
|
||||
title="Review 子代理请求"
|
||||
aria-label="Review 子代理请求"
|
||||
:title="t('usage.reasoning.reviewSubagentRequest')"
|
||||
:aria-label="t('usage.reasoning.reviewSubagentRequest')"
|
||||
>
|
||||
<SquareDashedBottomCode class="size-3.25" stroke-width="2.2" />
|
||||
</span>
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import type { UsageRecordStatus } from '@/api/modules/usage'
|
||||
|
||||
import { ZSegmented } from '@codex-proxy/ui'
|
||||
|
||||
import { CloudRain, List, Sun } from '@lucide/vue'
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const model = defineModel<UsageRecordStatus>({ required: true })
|
||||
const options = [
|
||||
{ label: '成功', value: 'success', icon: Sun },
|
||||
{ label: '错误', value: 'error', icon: CloudRain },
|
||||
{ label: '全部', value: 'all', icon: List },
|
||||
]
|
||||
const options = computed(() => ([
|
||||
{ label: t('common.status.success'), value: 'success', icon: Sun },
|
||||
{ label: t('usage.filters.error'), value: 'error', icon: CloudRain },
|
||||
{ label: t('common.values.all'), value: 'all', icon: List },
|
||||
]))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ZSegmented v-model="model" aria-label="请求明细类型" :options="options" display="icon" class="w-30 shrink-0" />
|
||||
<ZSegmented v-model="model" :aria-label="t('usage.filters.requestDetailType')" :options="options" display="icon" class="w-30 shrink-0" />
|
||||
</template>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import type { TableColumn } from '@codex-proxy/ui'
|
||||
import type { UsageListRecord } from '@/api'
|
||||
|
||||
import type { UsageListRecord } from '@/api'
|
||||
import { ZTable } from '@codex-proxy/ui'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import AccountPlanBadge from '@/components/account/AccountPlanBadge.vue'
|
||||
import ProviderIconGroup from '@/components/ProviderIconGroup.vue'
|
||||
import UsageBillingCell from '@/components/usage/UsageBillingCell.vue'
|
||||
@@ -30,9 +32,10 @@ withDefaults(
|
||||
}>(),
|
||||
{
|
||||
loading: false,
|
||||
emptyText: '暂无使用记录',
|
||||
},
|
||||
)
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -40,7 +43,7 @@ withDefaults(
|
||||
:columns="columns"
|
||||
:data="rows"
|
||||
:loading="loading"
|
||||
:empty-text="emptyText"
|
||||
:empty-text="emptyText ?? t('usage.noUsageRecords')"
|
||||
>
|
||||
<template #clientApiKeyName="{ displayValue }">
|
||||
<span
|
||||
@@ -113,7 +116,7 @@ withDefaults(
|
||||
<template #errorMessage="{ row }">
|
||||
<div class="min-w-0 py-0.5" :title="row.errorMessage || row.errorCode || undefined">
|
||||
<code class="block truncate font-mono text-cp-sm font-bold text-cp-error-text">
|
||||
{{ row.errorCode || (row.logicalOutcome === 'incomplete' ? '响应未完成' : '请求失败') }}
|
||||
{{ row.errorCode || (row.logicalOutcome === 'incomplete' ? t('usage.error.responseIsNotComplete') : t('usage.error.requestFailed')) }}
|
||||
</code>
|
||||
<p v-if="row.errorMessage" class="mt-1 mb-0 truncate text-cp-xs leading-[1.45] font-emphasis text-cp-text-secondary">
|
||||
{{ row.errorMessage }}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { Minimize2 } from '@lucide/vue'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
defineProps<{ record: { route: string | null, compact?: boolean } }>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -10,8 +14,8 @@ defineProps<{ record: { route: string | null, compact?: boolean } }>()
|
||||
<span
|
||||
v-if="record.compact"
|
||||
class="inline-flex shrink-0 text-cp-orange-text"
|
||||
title="压缩请求"
|
||||
aria-label="压缩请求"
|
||||
:title="t('usage.route.compressionRequest')"
|
||||
:aria-label="t('usage.route.compressionRequest')"
|
||||
>
|
||||
<Minimize2 class="size-3.5" stroke-width="2.4" />
|
||||
</span>
|
||||
|
||||
@@ -4,6 +4,8 @@ import type { UsageListRecord } from '@/api'
|
||||
import { Archive, ArrowDown, ArrowUp } from '@lucide/vue'
|
||||
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { usageTokenDetails } from '@/components/usage/shared/presenter'
|
||||
import UsageDetailPopover from '@/components/usage/UsageDetailPopover.vue'
|
||||
|
||||
@@ -11,13 +13,15 @@ const props = defineProps<{
|
||||
record: Pick<UsageListRecord, 'tokenDetails'>
|
||||
}>()
|
||||
|
||||
const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const tokenDetails = computed(() => usageTokenDetails(props.record.tokenDetails))
|
||||
const tokenItems = computed(() => [
|
||||
{ label: '输入 Token', value: tokenDetails.value.inputTokensDisplay },
|
||||
{ label: '输出 Token', value: tokenDetails.value.outputTokensDisplay },
|
||||
{ label: '缓存读取 Token', value: tokenDetails.value.cachedInputTokensDisplay },
|
||||
{ label: '缓存写入 Token', value: tokenDetails.value.cacheWriteInputTokensDisplay },
|
||||
{ label: '推理 Token', value: tokenDetails.value.reasoningOutputTokensDisplay },
|
||||
{ label: t('usage.tokens.enterToken'), value: tokenDetails.value.inputTokensDisplay },
|
||||
{ label: t('usage.tokens.outputToken'), value: tokenDetails.value.outputTokensDisplay },
|
||||
{ label: t('usage.tokens.cacheReadTokens'), value: tokenDetails.value.cachedInputTokensDisplay },
|
||||
{ label: t('usage.tokens.cacheWriteTokens'), value: tokenDetails.value.cacheWriteInputTokensDisplay },
|
||||
{ label: t('usage.tokens.reasoningToken'), value: tokenDetails.value.reasoningOutputTokensDisplay },
|
||||
])
|
||||
</script>
|
||||
|
||||
@@ -40,7 +44,7 @@ const tokenItems = computed(() => [
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<UsageDetailPopover title="Token 明细" trigger-label="查看 Token 明细">
|
||||
<UsageDetailPopover :title="t('usage.tokens.tokenDetails')" :trigger-label="t('usage.tokens.viewTokenDetails')">
|
||||
<div class="grid gap-1.5 text-cp-text-secondary">
|
||||
<div v-for="item in tokenItems" :key="item.label" class="flex justify-between gap-4">
|
||||
<span class="whitespace-nowrap">{{ item.label }}</span>
|
||||
@@ -50,7 +54,7 @@ const tokenItems = computed(() => [
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-1 flex justify-between border-t border-cp-split pt-2">
|
||||
<span class="whitespace-nowrap text-cp-text-secondary">总 Token</span>
|
||||
<span class="whitespace-nowrap text-cp-text-secondary">{{ t('usage.tokens.totalTokens') }}</span>
|
||||
<span class="whitespace-nowrap font-mono font-heavy text-cp-info-text">
|
||||
{{ tokenDetails.totalTokensDisplay }}
|
||||
</span>
|
||||
|
||||
@@ -1,41 +1,43 @@
|
||||
import type { TableColumn } from '@codex-proxy/ui'
|
||||
import type { UsageListRecord } from '@/api'
|
||||
import { defineTableColumns } from '@codex-proxy/ui'
|
||||
import { computed } from 'vue'
|
||||
import { t } from '@/i18n'
|
||||
import { formatProviderLabel } from '@/utils/providers'
|
||||
|
||||
export const usageDataColumns = [
|
||||
{ key: 'model', label: '模型', kind: 'custom', size: 'xl' },
|
||||
{ key: 'reasoningEffort', label: '推理强度', kind: 'status', size: 'md', align: 'left' },
|
||||
{ key: 'route', label: '端点', kind: 'mono' },
|
||||
{ key: 'upstreamTransport', label: '上游', kind: 'status', size: 'md' },
|
||||
{ key: 'clientTransport', label: '接入', kind: 'status', size: 'md' },
|
||||
export const usageDataColumns = computed(() => ([
|
||||
{ key: 'model', label: t('usage.fields.model'), kind: 'custom', size: 'xl' },
|
||||
{ key: 'reasoningEffort', label: t('usage.fields.reasoningEffort'), kind: 'status', size: 'md', align: 'left' },
|
||||
{ key: 'route', label: t('usage.fields.endpoint'), kind: 'mono' },
|
||||
{ key: 'upstreamTransport', label: t('usage.fields.upstream'), kind: 'status', size: 'md' },
|
||||
{ key: 'clientTransport', label: t('usage.fields.access'), kind: 'status', size: 'md' },
|
||||
{ key: 'tokenDetails', label: 'TOKEN', kind: 'numeric', size: 'xl' },
|
||||
{ key: 'billing', label: '费用', kind: 'numeric', size: 'xl' },
|
||||
{ key: 'latency', label: '延迟', kind: 'numeric', size: 'xl' },
|
||||
{ key: 'performance', label: '速率', kind: 'numeric', size: 'lg' },
|
||||
{ key: 'createdAtDisplay', label: '时间', kind: 'datetime' },
|
||||
{ key: 'billing', label: t('usage.fields.cost'), kind: 'numeric', size: 'xl' },
|
||||
{ key: 'latency', label: t('usage.fields.latency'), kind: 'numeric', size: 'xl' },
|
||||
{ key: 'performance', label: t('usage.outputThroughput'), kind: 'numeric', size: 'lg' },
|
||||
{ key: 'createdAtDisplay', label: t('usage.fields.time'), kind: 'datetime' },
|
||||
{ key: 'clientIp', label: 'IP', kind: 'custom', size: '3xl' },
|
||||
{ key: 'userAgent', label: 'User-Agent', kind: 'custom', size: '4xl' },
|
||||
] satisfies TableColumn[]
|
||||
] satisfies TableColumn[]))
|
||||
|
||||
export const usageRecordColumns = defineTableColumns<UsageListRecord>([
|
||||
{ key: 'clientApiKeyName', label: '密钥名称', kind: 'identity', size: 'xl' },
|
||||
export const usageRecordColumns = computed(() => (defineTableColumns<UsageListRecord>([
|
||||
{ key: 'clientApiKeyName', label: t('usage.fields.keyName'), kind: 'identity', size: 'xl' },
|
||||
{
|
||||
key: 'accountEmail',
|
||||
hideable: false,
|
||||
label: '账号',
|
||||
label: t('accounts.account'),
|
||||
kind: 'identity',
|
||||
size: '3xl',
|
||||
},
|
||||
{ key: 'accountPlanType', label: '订阅', kind: 'status', size: 'sm', fixedWidth: true },
|
||||
{ key: 'accountPlanType', label: t('usage.fields.subscription'), kind: 'status', size: 'sm', fixedWidth: true },
|
||||
{
|
||||
key: 'provider',
|
||||
label: '平台/类型',
|
||||
label: t('usage.fields.platformType'),
|
||||
kind: 'status',
|
||||
size: 'md',
|
||||
fixedWidth: true,
|
||||
formatter: (value: unknown) => formatProviderLabel(typeof value === 'string' ? value : null),
|
||||
},
|
||||
...usageDataColumns,
|
||||
{ key: 'actions', label: '操作', kind: 'actions', size: 'sm', hideable: false },
|
||||
])
|
||||
...usageDataColumns.value,
|
||||
{ key: 'actions', label: t('common.fields.actions'), kind: 'actions', size: 'sm', hideable: false },
|
||||
])))
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { DashboardHealthStatus, DashboardHealthTimelinePoint } from '@/api'
|
||||
import { computed } from 'vue'
|
||||
import { t } from '@/i18n'
|
||||
import { formatInteger } from '@/utils/format'
|
||||
|
||||
interface DashboardHealthStatusMeta {
|
||||
@@ -8,52 +10,52 @@ interface DashboardHealthStatusMeta {
|
||||
valueClass: string
|
||||
}
|
||||
|
||||
export const healthLegend = [
|
||||
{ status: 'no_data', label: '无有效样本' },
|
||||
{ status: 'unavailable', label: '不可达' },
|
||||
{ status: 'unstable', label: '不稳定' },
|
||||
{ status: 'low_sample', label: '低样本' },
|
||||
{ status: 'stable', label: '稳定' },
|
||||
] satisfies { status: DashboardHealthStatus, label: string }[]
|
||||
export const healthLegend = computed(() => ([
|
||||
{ status: 'no_data', label: t('usage.noValidSample') },
|
||||
{ status: 'unavailable', label: t('usage.notReachable') },
|
||||
{ status: 'unstable', label: t('usage.unstable') },
|
||||
{ status: 'low_sample', label: t('usage.lowSample') },
|
||||
{ status: 'stable', label: t('usage.stable') },
|
||||
] satisfies { status: DashboardHealthStatus, label: string }[]))
|
||||
|
||||
export const healthStatusMeta: Record<DashboardHealthStatus, DashboardHealthStatusMeta> = {
|
||||
export const healthStatusMeta = computed<Record<DashboardHealthStatus, DashboardHealthStatusMeta>>(() => ({
|
||||
future: {
|
||||
label: '未来',
|
||||
label: t('usage.future'),
|
||||
cellClass: 'bg-cp-bg-container-disabled opacity-60',
|
||||
badgeClass: 'bg-cp-fill-tertiary text-cp-text-quaternary',
|
||||
valueClass: 'text-cp-text-quaternary',
|
||||
},
|
||||
no_data: {
|
||||
label: '无有效样本',
|
||||
label: t('usage.noValidSample'),
|
||||
cellClass: 'bg-cp-border',
|
||||
badgeClass: 'bg-cp-fill-tertiary text-cp-text-secondary',
|
||||
valueClass: 'text-cp-text-quaternary',
|
||||
},
|
||||
unavailable: {
|
||||
label: '不可达',
|
||||
label: t('usage.notReachable'),
|
||||
cellClass: 'bg-cp-error',
|
||||
badgeClass: 'bg-cp-error-container text-cp-error-on-container',
|
||||
valueClass: 'text-cp-error-text',
|
||||
},
|
||||
unstable: {
|
||||
label: '不稳定',
|
||||
label: t('usage.unstable'),
|
||||
cellClass: 'bg-cp-warning',
|
||||
badgeClass: 'bg-cp-warning-container text-cp-warning-on-container',
|
||||
valueClass: 'text-cp-warning-text',
|
||||
},
|
||||
low_sample: {
|
||||
label: '低样本',
|
||||
label: t('usage.lowSample'),
|
||||
cellClass: 'bg-cp-cyan-solid',
|
||||
badgeClass: 'bg-cp-cyan-container text-cp-cyan-on-container',
|
||||
valueClass: 'text-cp-cyan-text',
|
||||
},
|
||||
stable: {
|
||||
label: '稳定',
|
||||
label: t('usage.stable'),
|
||||
cellClass: 'bg-cp-success',
|
||||
badgeClass: 'bg-cp-success-container text-cp-success-on-container',
|
||||
valueClass: 'text-cp-success-text',
|
||||
},
|
||||
}
|
||||
}))
|
||||
|
||||
export function healthServiceFailureCount(point: Pick<DashboardHealthTimelinePoint, 'failedRequests' | 'incompleteRequests'>) {
|
||||
return point.failedRequests + point.incompleteRequests
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { UsageListRecord, UsageRecordDetail, UsageTokenDetails } from '@/api'
|
||||
import { t } from '@/i18n'
|
||||
import { formatCompactNumber, formatDuration, formatInteger } from '@/utils/format'
|
||||
|
||||
// 列表与详情使用独立读模型,展示函数只依赖两者的公共字段。
|
||||
@@ -99,7 +100,7 @@ export function usageModelDisplay(record: UsageModelRecord) {
|
||||
routes.push({
|
||||
model: secondary,
|
||||
kind: 'mapped' as const,
|
||||
description: `网关映射后发送给上游的模型:${secondary}`,
|
||||
description: t('usage.status.mappedModel', { secondary }),
|
||||
})
|
||||
}
|
||||
if (returned) {
|
||||
@@ -107,8 +108,8 @@ export function usageModelDisplay(record: UsageModelRecord) {
|
||||
model: returned,
|
||||
kind: 'returned' as const,
|
||||
description: returned === secondary
|
||||
? `上游返回模型:${returned}(与网关映射后发送的模型一致)`
|
||||
: `上游返回模型:${returned}`,
|
||||
? t('usage.status.returnedModel', { returned })
|
||||
: t('usage.status.returnedModelHelp', { returned }),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -140,38 +141,38 @@ export function usageLatencyDetails(record: UsageLatencyRecord) {
|
||||
const requestItems: UsageTimingItem[] = []
|
||||
|
||||
if (firstTokenMs !== null && totalMs !== null && firstTokenMs <= totalMs) {
|
||||
requestItems.push({ label: '首个输出等待', value: formatDuration(firstTokenMs) })
|
||||
requestItems.push({ label: t('usage.status.firstOutputWaiting'), value: formatDuration(firstTokenMs) })
|
||||
|
||||
if (firstTextMs !== null && firstTextMs >= firstTokenMs && firstTextMs <= totalMs) {
|
||||
const beforeTextMs = firstTextMs - firstTokenMs
|
||||
if (beforeTextMs > 0) {
|
||||
requestItems.push({
|
||||
label: firstReasoningMs === firstTokenMs ? '推理到正文' : '首个输出到正文',
|
||||
label: firstReasoningMs === firstTokenMs ? t('usage.status.reasoningToText') : t('usage.status.firstOneIsOutputToText'),
|
||||
value: formatDuration(beforeTextMs),
|
||||
})
|
||||
}
|
||||
requestItems.push({ label: '正文到完成', value: formatDuration(totalMs - firstTextMs) })
|
||||
requestItems.push({ label: t('usage.status.textToCompletion'), value: formatDuration(totalMs - firstTextMs) })
|
||||
}
|
||||
else {
|
||||
requestItems.push({
|
||||
label: '首个输出后完成',
|
||||
label: t('usage.status.completedAfterFirstOutput'),
|
||||
value: formatDuration(totalMs - firstTokenMs),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
requestItems.push({ label: '总耗时', value: formatDuration(totalMs), emphasized: true })
|
||||
requestItems.push({ label: t('usage.latency.totalLatency'), value: formatDuration(totalMs), emphasized: true })
|
||||
|
||||
const transportItems: UsageTimingItem[] = [
|
||||
{ label: '准入判定', value: durationValue(latencyDetails?.admissionDecisionMs) },
|
||||
{ label: '账号选择等待', value: durationValue(latencyDetails?.accountSelectionWaitMs) },
|
||||
{ label: t('usage.status.admissionDecision'), value: durationValue(latencyDetails?.admissionDecisionMs) },
|
||||
{ label: t('usage.status.accountSelectionWaiting'), value: durationValue(latencyDetails?.accountSelectionWaitMs) },
|
||||
{
|
||||
label: '传输决策等待',
|
||||
label: t('usage.status.transferDecisionWaiting'),
|
||||
value: durationValue(latencyDetails?.transportDecisionWaitMs),
|
||||
},
|
||||
{ label: 'WebSocket 连接', value: durationValue(latencyDetails?.wsConnectMs) },
|
||||
{ label: '上游响应头', value: durationValue(latencyDetails?.upstreamHeadersMs) },
|
||||
{ label: '首个上游事件', value: durationValue(latencyDetails?.firstEventMs) },
|
||||
{ label: t('usage.status.websocketConnection'), value: durationValue(latencyDetails?.wsConnectMs) },
|
||||
{ label: t('usage.status.upstreamResponseHeader'), value: durationValue(latencyDetails?.upstreamHeadersMs) },
|
||||
{ label: t('usage.status.firstUpstreamEvent'), value: durationValue(latencyDetails?.firstEventMs) },
|
||||
]
|
||||
.filter(item => item.value !== null)
|
||||
.map(item => ({ ...item, value: formatDuration(item.value) }))
|
||||
@@ -181,7 +182,7 @@ export function usageLatencyDetails(record: UsageLatencyRecord) {
|
||||
&& latencyDetails.capacityTotalSlots != null
|
||||
) {
|
||||
transportItems.push({
|
||||
label: '账号槽位快照',
|
||||
label: t('usage.status.accountSlotSnapshot'),
|
||||
value: `${latencyDetails.capacityUsedSlots} / ${latencyDetails.capacityTotalSlots}`,
|
||||
})
|
||||
}
|
||||
@@ -189,14 +190,14 @@ export function usageLatencyDetails(record: UsageLatencyRecord) {
|
||||
const upstreamDisplay = formatDuration(upstreamMs)
|
||||
const upstreamItems: UsageTimingItem[] = []
|
||||
if (upstreamMs !== null)
|
||||
upstreamItems.push({ label: '响应耗时', value: upstreamDisplay })
|
||||
upstreamItems.push({ label: t('accounts.connectionTest.duration'), value: upstreamDisplay })
|
||||
const processingMs = durationValue(latencyDetails?.openaiProcessingMs)
|
||||
if (processingMs !== null)
|
||||
upstreamItems.push({ label: '处理耗时', value: formatDuration(processingMs) })
|
||||
upstreamItems.push({ label: t('usage.status.processingTime'), value: formatDuration(processingMs) })
|
||||
|
||||
const performanceItems = [
|
||||
{ label: 'API 开销', value: durationValue(latencyDetails?.upstreamApiOverheadMs) },
|
||||
{ label: '引擎耗时', value: durationValue(latencyDetails?.upstreamEngineMs) },
|
||||
{ label: t('usage.status.apiOverhead'), value: durationValue(latencyDetails?.upstreamApiOverheadMs) },
|
||||
{ label: t('usage.status.engineTime'), value: durationValue(latencyDetails?.upstreamEngineMs) },
|
||||
]
|
||||
for (const item of performanceItems) {
|
||||
if (item.value !== null)
|
||||
@@ -206,15 +207,15 @@ export function usageLatencyDetails(record: UsageLatencyRecord) {
|
||||
const sections: UsageTimingSection[] = []
|
||||
if (upstreamItems.length) {
|
||||
sections.push({
|
||||
title: '上游性能',
|
||||
title: t('usage.status.upstreamPerformance'),
|
||||
source: 'official',
|
||||
items: upstreamItems,
|
||||
})
|
||||
}
|
||||
sections.push({ title: '请求观测', source: 'local', items: requestItems })
|
||||
sections.push({ title: t('usage.status.requestObservation'), source: 'local', items: requestItems })
|
||||
if (transportItems.length) {
|
||||
sections.push({
|
||||
title: '传输观测',
|
||||
title: t('usage.status.transport'),
|
||||
source: 'local',
|
||||
items: transportItems,
|
||||
})
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { ZNotification } from '@codex-proxy/ui'
|
||||
|
||||
import { shallowRef } from 'vue'
|
||||
import { ApiError } from '@/api/request'
|
||||
|
||||
import { t } from '@/i18n'
|
||||
import { notification as ZNotification } from '@/utils/notification'
|
||||
import { errorMessage, withMinimumDuration } from '@/utils/operation'
|
||||
|
||||
type MaybePromise<T> = T | Promise<T>
|
||||
@@ -18,7 +19,7 @@ function resolveErrorText(error: unknown, errorText: string | false | undefined)
|
||||
return ''
|
||||
}
|
||||
|
||||
return errorMessage(error, errorText || '操作失败')
|
||||
return errorMessage(error, errorText || t('common.errors.operation'))
|
||||
}
|
||||
|
||||
export function useAsyncAction(defaults: AsyncActionRunOptions = {}) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ZNotification } from '@codex-proxy/ui'
|
||||
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
import { notification as ZNotification } from '@/utils/notification'
|
||||
import { errorMessage } from '@/utils/operation'
|
||||
|
||||
interface CopyTextOptions {
|
||||
@@ -27,7 +28,7 @@ export function useCopyText() {
|
||||
ZNotification.success({ message: options.successText })
|
||||
}
|
||||
catch (error: unknown) {
|
||||
ZNotification.error({ message: options.errorFromException ? errorMessage(error, '复制失败') : '复制失败' })
|
||||
ZNotification.error({ message: options.errorFromException ? errorMessage(error, t('common.errors.copy')) : t('common.errors.copy') })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { isLocale, localeOptions } from '@/i18n/locale'
|
||||
|
||||
export function useLocale() {
|
||||
const { locale } = useI18n({ useScope: 'global' })
|
||||
|
||||
function setLocale(value: unknown) {
|
||||
if (isLocale(value))
|
||||
locale.value = value
|
||||
}
|
||||
|
||||
return { locale, localeOptions, setLocale }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createI18n } from 'vue-i18n'
|
||||
import { readInitialLocale } from './locale'
|
||||
import messages from './messages'
|
||||
|
||||
export const i18n = createI18n({
|
||||
legacy: false,
|
||||
locale: readInitialLocale(),
|
||||
fallbackLocale: 'en',
|
||||
messages,
|
||||
})
|
||||
|
||||
// 非组件入口与 Vue 组件共享同一 Composer,调用时读取当前语言
|
||||
export const t: typeof i18n.global.t = i18n.global.t
|
||||
export const { locale } = i18n.global
|
||||
@@ -0,0 +1,52 @@
|
||||
export type Locale = 'en' | 'zh-Hans' | 'zh-Hant'
|
||||
|
||||
export const localeOptions = [
|
||||
{ label: '简体中文', value: 'zh-Hans' },
|
||||
{ label: '繁體中文', value: 'zh-Hant' },
|
||||
{ label: 'English', value: 'en' },
|
||||
] satisfies { label: string, value: Locale }[]
|
||||
|
||||
const storageKey = 'codex-proxy-rs-locale'
|
||||
|
||||
export function isLocale(value: unknown): value is Locale {
|
||||
return localeOptions.some(option => option.value === value)
|
||||
}
|
||||
|
||||
export function normalizeLocale(language: string): Locale {
|
||||
try {
|
||||
const { language: base, script, region } = new Intl.Locale(language)
|
||||
if (base === 'zh') {
|
||||
if (script === 'Hant')
|
||||
return 'zh-Hant'
|
||||
if (script === 'Hans')
|
||||
return 'zh-Hans'
|
||||
return region && ['TW', 'HK', 'MO'].includes(region) ? 'zh-Hant' : 'zh-Hans'
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// 无效的浏览器语言使用应用默认语言
|
||||
}
|
||||
return 'en'
|
||||
}
|
||||
|
||||
export function readInitialLocale(): Locale {
|
||||
try {
|
||||
const saved = localStorage.getItem(storageKey)
|
||||
if (isLocale(saved))
|
||||
return saved
|
||||
}
|
||||
catch {
|
||||
// 存储不可用时继续使用浏览器语言
|
||||
}
|
||||
return normalizeLocale(navigator.language)
|
||||
}
|
||||
|
||||
export function applyLocale(value: string): void {
|
||||
document.documentElement.lang = value
|
||||
try {
|
||||
localStorage.setItem(storageKey, value)
|
||||
}
|
||||
catch {
|
||||
// 存储不可用不影响当前会话的语言切换
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,620 @@
|
||||
{
|
||||
"accounts": {
|
||||
"quota": {
|
||||
"usageInThisWindow": "Usage in this window: {localUsageDisplay}",
|
||||
"quotaUsed": "Quota used: {rate}",
|
||||
"resets": "Resets: {resetAtDisplay}",
|
||||
"unobserved": "Awaiting quota data",
|
||||
"dailyRequests": "Daily requests",
|
||||
"requests": "{localRequestLabel}: {localRequestDisplay} requests",
|
||||
"h": "{duration} h",
|
||||
"d": "{duration} d",
|
||||
"s": "{duration} s",
|
||||
"unlimited": "Unlimited",
|
||||
"noPointsAvailableYet": "No credits available",
|
||||
"quotaPoints": "Credits",
|
||||
"point": "credits",
|
||||
"requestsInThisWindow": "Requests in this window: {requestDisplay}",
|
||||
"requestCount": "Requests: {requestDisplay}",
|
||||
"statisticalRange": "Statistical range",
|
||||
"rolling": "Rolling {duration}",
|
||||
"awaitingData": "Awaiting data",
|
||||
"remaining": "{remaining}% remaining",
|
||||
"usageLimit": "Usage limit",
|
||||
"reset": "Reset:",
|
||||
"remainingQuota": "Remaining {label} quota",
|
||||
"accountLimit": "Account limit",
|
||||
"quota": "{provider} quota",
|
||||
"lastRefreshed": "Last refreshed: {refreshedAtDisplay}",
|
||||
"viewPersonalInformation": "View personal information",
|
||||
"forecastWeeklyMonthlyQuota": "Forecast weekly/monthly quota",
|
||||
"queryUnsupported": "Upstream quota queries are not supported",
|
||||
"quotaDetails": "Quota details",
|
||||
"viewDetails": "View {detailTitle} details",
|
||||
"details": "{detailTitle} details",
|
||||
"statisticalMethod": "Statistical method",
|
||||
"rollingWindow": "Rolling window",
|
||||
"windowConsumption": "Window consumption",
|
||||
"resetTime": "Reset time",
|
||||
"localTokens": "Locally accumulated tokens",
|
||||
"unavailableHelp": "Upstream quota is unavailable, the green bar does not represent remaining quota",
|
||||
"totalTokensFor": "Total tokens for {windowLabelDisplay}",
|
||||
"usageRateHelp": "Current usage percentage for the most recently used quota",
|
||||
"usageRate": "Usage rate",
|
||||
"moreGroups": "{count} more quota groups, expand the account to view them",
|
||||
"windows": {
|
||||
"fiveHour": "5h limit",
|
||||
"daily": "Daily limit",
|
||||
"weekly": "Weekly limit",
|
||||
"monthly": "Monthly limit",
|
||||
"annual": "Annual limit",
|
||||
"usage": "Usage limit",
|
||||
"secondary": "Secondary usage limit",
|
||||
"duration": "{duration} limit"
|
||||
}
|
||||
},
|
||||
"account": "Account",
|
||||
"connectionTest": {
|
||||
"duration": "Response time",
|
||||
"title": "Test connection",
|
||||
"description": "Verify account credentials, identity binding, and upstream model access",
|
||||
"model": "Test model",
|
||||
"refreshModels": "Refresh upstream models",
|
||||
"loadingModels": "Loading models…",
|
||||
"modelPlaceholder": "Select an upstream model",
|
||||
"noModels": "The upstream service returned no models",
|
||||
"running": "Testing…",
|
||||
"completedAt": "Completed",
|
||||
"events": {
|
||||
"title": "Event timeline",
|
||||
"request": "Request sent",
|
||||
"response": "Receiving response",
|
||||
"completed": "Response complete"
|
||||
},
|
||||
"diagnostics": "Raw diagnostics",
|
||||
"retry": "Test again",
|
||||
"start": "Start test",
|
||||
"errors": {
|
||||
"invalidRequest": "Invalid test request",
|
||||
"unsupported": "The current provider does not support connection testing",
|
||||
"credentials": "Invalid account credentials",
|
||||
"policyRejected": "Test request rejected by gateway policy",
|
||||
"modelNotFound": "Test model not found",
|
||||
"accountUnavailable": "This account is unavailable for connection testing",
|
||||
"capacityUnavailable": "This account has no available capacity",
|
||||
"infrastructureUnavailable": "The provider's local infrastructure is temporarily unavailable",
|
||||
"rateLimited": "Upstream rate limit exceeded",
|
||||
"upstreamUnavailable": "Upstream service temporarily unavailable",
|
||||
"timeout": "Upstream request timed out",
|
||||
"canceled": "Test canceled",
|
||||
"internal": "Internal gateway error",
|
||||
"unknown": "Unknown error",
|
||||
"failed": "Connection test failed",
|
||||
"modelRequired": "Select a model to test",
|
||||
"browserUnsupported": "The current browser does not support connection testing",
|
||||
"missingCompletion": "The connection test did not return a completion event",
|
||||
"invalidResponse": "Could not parse the test response",
|
||||
"disconnected": "Connection lost during the test"
|
||||
},
|
||||
"stages": {
|
||||
"gateway": "Gateway validation",
|
||||
"provider": "Provider setup",
|
||||
"upstream": "Upstream response"
|
||||
},
|
||||
"failed": "Test failed",
|
||||
"testing": "Testing",
|
||||
"runningDescription": "Sending a request to the selected model and receiving its streaming response",
|
||||
"successTitle": "Connection successful",
|
||||
"completedDescription": "Request complete, view the model, response time, and event timeline below",
|
||||
"failedDescription": "Request incomplete, view the failure source and raw diagnostics below",
|
||||
"readyTitle": "Ready to test",
|
||||
"readyDescription": "Select a model and choose Start test to send a real request",
|
||||
"starting": "Starting a connection test for {value}",
|
||||
"emptyResponse": "The upstream service completed without returning text",
|
||||
"testCompleted": "Test completed",
|
||||
"modelsRefreshed": "Refreshed {count} upstream model | Refreshed {count} upstream models",
|
||||
"noModelsAvailable": "No models available for testing"
|
||||
},
|
||||
"credentials": {
|
||||
"wsFirst": "WS first",
|
||||
"accountName": "Account name",
|
||||
"enterUpstreamName": "Enter the upstream name",
|
||||
"baseUrlHelp": "Enter the API base URL, endpoint paths are appended automatically",
|
||||
"apiPrefix": "API prefix",
|
||||
"apiKeyPlaceholder": "Leave blank to keep the current key",
|
||||
"enterUpstreamKey": "Enter the upstream key",
|
||||
"transportLabel": "Transport",
|
||||
"webSocketHelp": "WS first requires upstream support for Responses WebSocket",
|
||||
"nameRequired": "Enter an account name",
|
||||
"validation": {
|
||||
"urlLength": "Upstream API URL must not exceed 2,048 characters",
|
||||
"urlFormat": "Enter an HTTP or HTTPS URL without credentials, query parameters, or a fragment",
|
||||
"urlRequired": "Enter the full upstream API URL",
|
||||
"apiKeyFormat": "API key cannot contain spaces or control characters",
|
||||
"transportRequired": "Select a transport"
|
||||
},
|
||||
"apiKeyRequired": "Enter an API key"
|
||||
},
|
||||
"batchEdit": {
|
||||
"title": "Edit accounts",
|
||||
"selectionTitle": "Edit {count} account | Edit {count} accounts",
|
||||
"saveChanges": "Save changes",
|
||||
"proxyRequired": "Select a proxy that passed the connection test",
|
||||
"saved": "Updated {count} account | Updated {count} accounts",
|
||||
"staleAccount": "Account {accountId} is out of date, select it again"
|
||||
},
|
||||
"capacity": {
|
||||
"concurrentRequestsLimit": "Concurrent requests: {value}, limit: {value2}",
|
||||
"viewConcurrencyDetails": "{label}, view concurrency details",
|
||||
"viewDetails": "{label}, view details"
|
||||
},
|
||||
"concurrency": {
|
||||
"title": "Concurrency details",
|
||||
"description": "Requests currently being processed",
|
||||
"unavailable": "Concurrency details are temporarily unavailable",
|
||||
"empty": "No active concurrent requests",
|
||||
"key": "Key",
|
||||
"model": "Model",
|
||||
"sourceIp": "Source IP",
|
||||
"startTime": "Started",
|
||||
"elapsed": "Elapsed"
|
||||
},
|
||||
"editor": {
|
||||
"title": "Edit account",
|
||||
"transportLabel": "Upstream transport",
|
||||
"upstreamConnection": "Upstream connection",
|
||||
"loadError": "Could not load upstream settings",
|
||||
"notesHelp": "Up to 500 characters, leave blank to clear notes",
|
||||
"oauthUnavailable": "This account has no OAuth upstream settings",
|
||||
"apiKeyUnavailable": "This account has no upstream API key settings",
|
||||
"saved": "Account updated"
|
||||
},
|
||||
"filters": {
|
||||
"allGroups": "All",
|
||||
"ungroupedAccounts": "Ungrouped",
|
||||
"disabled": "{name} (disabled)",
|
||||
"label": "Account filters and actions",
|
||||
"searchLabel": "Search accounts",
|
||||
"statusLabel": "Filter by account status",
|
||||
"groupLabel": "Filter by account group",
|
||||
"deleteSelected": "Delete selected ({count})",
|
||||
"exportSelected": "Export selected ({count})",
|
||||
"importTasks": "Import tasks",
|
||||
"importAccount": "Import account"
|
||||
},
|
||||
"modelAccess": {
|
||||
"reserve": "Reserve",
|
||||
"allowlist": "Allowlist",
|
||||
"blocklist": "Blocklist",
|
||||
"modelLimitations": "Model limitations",
|
||||
"refreshModel": "Refresh model",
|
||||
"modelRestrictionMode": "Model restriction mode",
|
||||
"searchOrAddModels": "Search or add models",
|
||||
"searchOrEnterIdAndPressEnter": "Search or enter ID and press Enter to add",
|
||||
"selectModel": "Select model",
|
||||
"notInCurrentModelCatalog": "{id} (not in the current model catalog)",
|
||||
"loadingModel": "Loading model…",
|
||||
"noMatchingModels": "No matching models",
|
||||
"noModels": "No models",
|
||||
"modelListLoadingFailed": "Model list loading failed",
|
||||
"retryHint": "Refresh and try again",
|
||||
"selectOrAddAtLeastOneModel": "Please select or add at least one model",
|
||||
"configureUpToModels": "Configure up to 256 models",
|
||||
"invalidModelId": "Enter an exact model ID, wildcards are not supported",
|
||||
"enterValidExactModelIdUpTo": "Please enter a valid exact model ID, up to 256 bytes, no wildcards are supported"
|
||||
},
|
||||
"notes": {
|
||||
"viewAccountNotes": "View account notes",
|
||||
"title": "Account notes"
|
||||
},
|
||||
"overview": {
|
||||
"totalAccounts": "Total accounts",
|
||||
"accountPoolSize": "Account pool size",
|
||||
"availableAccounts": "Available accounts",
|
||||
"availableHelp": "Available for scheduling",
|
||||
"quotaLimited": "Quota limited",
|
||||
"waitingForQuota": "Waiting for quota reset",
|
||||
"pending": "Pending",
|
||||
"disabledError": "Disabled / error"
|
||||
},
|
||||
"proxy": {
|
||||
"keepCurrent": "Keep current",
|
||||
"keepExisting": "Keep each account's connection settings",
|
||||
"directConnection": "Direct",
|
||||
"notUsingProxy": "No proxy",
|
||||
"disabledSuffix": "(disabled)",
|
||||
"testFailed": "(test failed)",
|
||||
"notTested": "(not tested)",
|
||||
"outboundTunnel": "Outbound tunnel"
|
||||
},
|
||||
"scheduling": {
|
||||
"scheduling": "Scheduling",
|
||||
"switchAccountSchedule": "Switch account schedule",
|
||||
"concurrencyLimit": "Concurrency limit",
|
||||
"accountConcurrencyLimit": "Account concurrency limit",
|
||||
"defaultHint": "Blank uses the default",
|
||||
"weight": "Weight",
|
||||
"accountSchedulingWeight": "Account scheduling weight",
|
||||
"weightHelp": "Higher values get priority, up to 100",
|
||||
"groupLabel": "Group",
|
||||
"invalidConcurrency": "Leave the concurrency limit blank or enter an integer from 1 to {value}",
|
||||
"weightMustBeIntegerFromTo": "Weight must be an integer from 1 to 100"
|
||||
},
|
||||
"actions": {
|
||||
"deleteAccount": "Delete account",
|
||||
"moreActions": "More actions",
|
||||
"disableScheduling": "Disable",
|
||||
"enableScheduling": "Enable",
|
||||
"refreshToken": "Refresh token",
|
||||
"reauthorize": "Reauthorize",
|
||||
"downloadModelCatalog": "Download model catalog",
|
||||
"restoreState": "Reset status",
|
||||
"staleSelection": "Selected account data is out of date, select the accounts again",
|
||||
"exportUnsupported": "Some selected accounts belong to providers that do not support export",
|
||||
"deleted": "Account deleted",
|
||||
"deletedAccountDeletedAccounts": "Deleted {count} account | Deleted {count} accounts",
|
||||
"partialDeletion": "Deleted {count} accounts, the remaining accounts were not deleted: {value}",
|
||||
"batchDeletionFailed": "Batch deletion failed",
|
||||
"exportSelectionRequired": "Select at least one account to export",
|
||||
"exported": "Exported {count} account | Exported {count} accounts",
|
||||
"exportFailed": "Export failed",
|
||||
"modelCatalogDownloadedModels": "Model catalog downloaded, models: {count}",
|
||||
"tokenIsBeingRefreshed": "Token is being refreshed",
|
||||
"refreshFailed": "Refresh failed",
|
||||
"tokenRefreshed": "Token refreshed",
|
||||
"schedulingIsDisabled": "Scheduling is disabled",
|
||||
"schedulingIsEnabled": "Scheduling is enabled",
|
||||
"quotaRefreshed": "Quota refreshed",
|
||||
"refreshQuotaManually": "Refresh the quota manually",
|
||||
"resetRefreshFailed": "Quota reset succeeded, but the latest quota could not be loaded: {value}",
|
||||
"statusRestored": "Account status restored",
|
||||
"staleAccount": "Account {id} is out of date, select it again",
|
||||
"unsupportedProvider": "Unsupported provider: {provider}"
|
||||
},
|
||||
"usage": {
|
||||
"call": "Calls",
|
||||
"successRate": "Success",
|
||||
"input": "Input",
|
||||
"output": "Output",
|
||||
"cache": "Cached",
|
||||
"total": "Total",
|
||||
"billing": "Billing",
|
||||
"tokensStructure": "Token usage",
|
||||
"cacheRead": "Cache read",
|
||||
"reasoning": "Reasoning",
|
||||
"cacheWrites": "Cache writes",
|
||||
"modelUsageRanking": "Model usage",
|
||||
"totalTokens": "Total tokens",
|
||||
"totalCharge": "Total cost",
|
||||
"totalCharges": "Total cost",
|
||||
"noModelUsageYet": "No model usage yet",
|
||||
"windows": {
|
||||
"general": "Total usage",
|
||||
"weekly": "Weekly usage",
|
||||
"monthly": "Monthly usage",
|
||||
"quota": "Period usage"
|
||||
},
|
||||
"cost": "Cost"
|
||||
},
|
||||
"onboarding": {
|
||||
"fileReadingFailedTryAgain": "File reading failed, please try again",
|
||||
"uploadFiles": "Upload files",
|
||||
"authorizationExpired": "Authorization expired, start again or check whether authorization completed",
|
||||
"pollingPaused": "Polling paused, check the authorization result to continue",
|
||||
"regenerateAuthorizationLink": "Regenerate authorization link",
|
||||
"generateAuthorizationLink": "Generate authorization link",
|
||||
"authorizationLink": "Authorization link",
|
||||
"copyLink": "Copy link",
|
||||
"authorizationLinkCopied": "Authorization link copied",
|
||||
"batchImport": "Batch import",
|
||||
"selectAccountPlatform": "Select account platform",
|
||||
"accountPlatform": "Account platform",
|
||||
"maximumWordsOptional": "Maximum 500 words, optional",
|
||||
"copyAccount": "Copy account",
|
||||
"accountCopied": "Account copied",
|
||||
"howToAddAccount": "How to add an account",
|
||||
"authorize": "Authorize",
|
||||
"continueImporting": "Continue",
|
||||
"jsonDescription": "Paste or upload account JSON to import accounts or update matching credentials",
|
||||
"packageDescription": "Paste or upload a CPR account package to import accounts from multiple providers",
|
||||
"oauthDescription": "Import a {label} account through browser authorization",
|
||||
"apiKeyDescription": "Connect an upstream service compatible with the OpenAI Responses API",
|
||||
"pasteAccessTokenLineByLineIf": "Paste the Access token line by line. If the Refresh token is not included, it cannot be automatically renewed",
|
||||
"refreshTokenDescription": "Paste one refresh token per line, access tokens are obtained automatically during import",
|
||||
"accountSettings": "Account settings",
|
||||
"reauthorizeAccount": "Reauthorize account",
|
||||
"settingsDescription": "These settings apply to accounts in this import",
|
||||
"reauthorizeDescription": "Update account credentials after authorization",
|
||||
"callbackLabel": "Callback URL or authorization code",
|
||||
"callbackAddress": "Callback address",
|
||||
"callbackPlaceholder": "Callback URL, ?code=...&state=..., or authorization code",
|
||||
"callbackHelp": "Open the authorization link, authorize in your browser, then paste the callback URL or authorization code",
|
||||
"pasteOneAccessTokenPerLine": "Paste one Access token per line",
|
||||
"pasteOneRefreshTokenPerLine": "Paste one Refresh token per line",
|
||||
"batchAccountFiles": "Batch account files",
|
||||
"accountFile": "Account file",
|
||||
"packagePlaceholder": "Paste a CPR account export",
|
||||
"pasteAccountJsonContent": "Paste the account JSON content",
|
||||
"completeReauthorization": "Complete reauthorization",
|
||||
"completeImport": "Complete import",
|
||||
"invalidExpiry": "Invalid authorization expiry, generate a new link",
|
||||
"linkFailed": "Failed to generate authorization link",
|
||||
"callbackRequired": "Paste a callback URL or authorization code",
|
||||
"authorizationFailed": "Authorization failed, submit again to retry",
|
||||
"reauthorized": "Account reauthorized",
|
||||
"accountAdded": "Account added",
|
||||
"providerRequired": "Select an account provider",
|
||||
"accountPlatformIsNotSupported": "Account platform is not supported",
|
||||
"apiKeyUnsupported": "This provider does not support API key accounts",
|
||||
"apiKeyAccountAdded": "API key account added",
|
||||
"importTasksCreated": "Import tasks created: {submitted}",
|
||||
"importTaskCreated": "Import task created",
|
||||
"partialSubmission": "Some import tasks were created, retry with the same input to submit the rest",
|
||||
"accountName": "{provider} account",
|
||||
"failedToStartAuthorization": "Failed to start authorization"
|
||||
},
|
||||
"importTasks": {
|
||||
"needProcessing": "Need processing",
|
||||
"importTaskDetails": "Import task details",
|
||||
"created": "Created {createdAtDisplay}",
|
||||
"waitForCurrentEntryToEnd": "Wait for the current entry to end",
|
||||
"stopUnstartedEntries": "Stop unstarted entries",
|
||||
"viewAccount": "View account",
|
||||
"entryProgress": "Entry progress",
|
||||
"accountsImported": "Accounts imported: {importedAccounts}",
|
||||
"itemProcessingProgress": "Item processing progress",
|
||||
"itemsToBeCheckedMayHaveBeen": "The items to be checked may have been stored in the database. Please check the account first before deciding whether to re-import it",
|
||||
"filterImportDetails": "Filter import details",
|
||||
"thereAreNoItemsToBeProcessed": "There are no items to be processed yet",
|
||||
"importEntryResults": "Import entry results",
|
||||
"items": "Items: {total} · {value}",
|
||||
"description": "Imports continue after you close this page, reopen it to check progress",
|
||||
"progressUnavailable": "Progress unavailable: {value}, updates resume when the connection is restored",
|
||||
"loadingImportTasks": "Loading import tasks…",
|
||||
"noImportTasks": "No import tasks",
|
||||
"empty": "Start an account import to see results for each entry here",
|
||||
"switchImportTasks": "Switch import tasks",
|
||||
"loadingItemResults": "Loading item results…",
|
||||
"selectTask": "Select a task",
|
||||
"taskRetentionInstructions": "Task retention instructions",
|
||||
"resultsRetainedForHour": "Results retained for 1 hour",
|
||||
"retentionHelp": "Task records are cleared when the service restarts, imported accounts are kept",
|
||||
"processing": "Processing",
|
||||
"alreadyInStock": "Already in stock",
|
||||
"toBeVerified": "To be verified",
|
||||
"notExecuted": "Not executed",
|
||||
"stopping": "Stopping",
|
||||
"importing": "Importing",
|
||||
"queuing": "Queuing",
|
||||
"stopped": "Stopped",
|
||||
"endedPendingItems": "Ended · Pending items",
|
||||
"allDone": "All done",
|
||||
"savedAccountSavedAccounts": "Saved {count} account | Saved {count} accounts",
|
||||
"verifying": "Verifying and saving credentials",
|
||||
"waitingForExecution": "Waiting for execution",
|
||||
"thisArticleIsNotImplemented": "This article is not implemented",
|
||||
"entryFailed": "This entry could not be imported",
|
||||
"checkAccountList": "Check the account list to confirm whether the account was imported",
|
||||
"progressReadingFailedTryAgain": "Progress reading failed, please try again"
|
||||
},
|
||||
"profile": {
|
||||
"activity": {
|
||||
"quickMode": "Quick mode",
|
||||
"reasoningEffort": "Most used reasoning effort",
|
||||
"exploredSkills": "Explored skills",
|
||||
"totalNumberOfSkillsUsed": "Total number of skills used",
|
||||
"totalNumberOfChats": "Total number of chats",
|
||||
"activityInsights": "Activity Insights",
|
||||
"pluginsAndSkills": "Most used plugins and skills",
|
||||
"runs": "Runs: {count}",
|
||||
"noToolCalls": "No plugin or skill calls",
|
||||
"daily": "Daily",
|
||||
"weekly": "Weekly",
|
||||
"cumulative": "Cumulative",
|
||||
"tokenActivity": "Token activity",
|
||||
"tokenActivityStatisticsMethod": "Token activity statistics method",
|
||||
"noTokenActivityYet": "No token activity yet",
|
||||
"noDailyActivity": "Daily token activity was not available for this request",
|
||||
"tokenActivityHeatmap": "Token activity heatmap, {rangeLabel}",
|
||||
"weekOfTokens": "Week of {dateDisplay}: {value} tokens",
|
||||
"throughTokens": "Through {dateDisplay}: {value} tokens"
|
||||
},
|
||||
"metrics": {
|
||||
"cumulativeNumberOfTokens": "Total tokens",
|
||||
"peakNumberOfTokens": "Peak number of tokens",
|
||||
"maximumChatDuration": "Maximum chat duration",
|
||||
"currentConsecutiveDays": "Current consecutive days",
|
||||
"longestStreak": "Longest streak",
|
||||
"dayCount": "{integer} d",
|
||||
"dH": "{days} d {hours} h",
|
||||
"elapsedDays": "{days} d",
|
||||
"hMin": "{hours} h {minutes} min",
|
||||
"elapsedHours": "{hours} h",
|
||||
"min": "{totalMinutes} min",
|
||||
"durationSeconds": "{value} s",
|
||||
"cumulativeActivitySummary": "Cumulative activity summary"
|
||||
},
|
||||
"accountUser": "Account user",
|
||||
"avatarFor": "Avatar for {displayName}",
|
||||
"loadingCumulativeActivity": "Loading cumulative activity",
|
||||
"subscription": {
|
||||
"automaticRenewal": "Automatic renewal",
|
||||
"noAutomaticRenewal": "No automatic renewal",
|
||||
"byMonth": "By month",
|
||||
"byYear": "By year",
|
||||
"subscriptionStarts": "Subscription starts",
|
||||
"subscriptionEnds": "Subscription ends",
|
||||
"label": "Plan",
|
||||
"renewalMethod": "Renewal method"
|
||||
},
|
||||
"personalInformation": "Personal information",
|
||||
"subscriptionInformation": "Subscription information",
|
||||
"loadingSubscription": "Loading subscription details…",
|
||||
"loadFailed": "Failed to load profile",
|
||||
"statisticsUnavailable": "Profile statistics are temporarily unavailable",
|
||||
"statisticsEmpty": "No statistics were returned, refresh to try again",
|
||||
"refreshIncomplete": "Refresh incomplete, showing the results received so far",
|
||||
"noSubscriptionInformationYet": "No subscription information yet",
|
||||
"refreshInformation": "Refresh information"
|
||||
},
|
||||
"quotaForecast": {
|
||||
"tokenCapacity": "Token capacity",
|
||||
"equivalentFeeUsd": "Equivalent cost · USD",
|
||||
"capacityForecast": "Capacity forecast",
|
||||
"usedThisCycle": "Used this cycle",
|
||||
"preliminary": "Preliminary estimate · For reference only",
|
||||
"estimateLabel": "Estimated value · For reference only",
|
||||
"thisCycle": "This cycle",
|
||||
"usedDescription": "{rate} used this period, the remaining area is projected",
|
||||
"alreadyRecordedThisCycle": "Already recorded this cycle",
|
||||
"equivalentCapacityOverDays": "Equivalent capacity over {targetDays} days",
|
||||
"projectedTotal": "Projected total for this period",
|
||||
"loadingQuotaForecast": "Loading quota forecast",
|
||||
"weeklyQuota": "Weekly quota",
|
||||
"monthlyQuota": "Monthly quota",
|
||||
"windowExpired": "Quota window expired, refresh the account quota and try again",
|
||||
"quotaForecast": "Quota forecast",
|
||||
"periodHelp": "Estimated for this period, accumulation starts again after reset",
|
||||
"forecastPeriod": "Forecast period",
|
||||
"predictionLoadFailed": "Prediction load failed",
|
||||
"loadFailed": "Forecast unavailable, reload to try again",
|
||||
"reload": "Reload",
|
||||
"unpredictableAtMoment": "Unpredictable at the moment",
|
||||
"updated": "Updated {observedAtDisplay}",
|
||||
"forecastDescription": "Forecast description",
|
||||
"forReferenceOnly": "For reference only",
|
||||
"methodDescription": "The projected total is recorded usage plus estimated remaining usage, based on recent usage within this period",
|
||||
"limitations": "Missing usage or cost data can lower the estimate, which varies by model and usage pattern and is not an official quota commitment",
|
||||
"limitedData": "Limited data, estimates may vary substantially",
|
||||
"currentPeriod": "current period",
|
||||
"forecastCalculatedByOverDays": "Forecast calculated by {value} over {targetDays} days",
|
||||
"equivalentCostHelp": "Estimates reflect the last data update, equivalent cost is not an actual bill or account balance",
|
||||
"refreshQuota": "Refresh quota"
|
||||
},
|
||||
"quotaReset": {
|
||||
"automation": {
|
||||
"confirming": "The last automatic reset is unconfirmed, verification will continue",
|
||||
"unconfirmed": "The last automatic reset is unconfirmed",
|
||||
"expiredUnconfirmed": "The last reset could not be confirmed and the reset credit has expired",
|
||||
"queryFailed": "The last query failed, retrying on schedule",
|
||||
"aboveThreshold": "Remaining weekly quota exceeds the threshold, checking again later",
|
||||
"quotaUnavailable": "Weekly quota is unavailable, checking again later",
|
||||
"resetNotNeeded": "This quota window does not need a reset, checking again later",
|
||||
"resetIncomplete": "The upstream service did not complete the last automatic reset",
|
||||
"scheduleHelp": "Check once a day at a random time, staggered across accounts",
|
||||
"verifyHelp": "Verify reset credits before expiry, automatically skip credits already used elsewhere",
|
||||
"label": "Automatically use expiring reset credits"
|
||||
},
|
||||
"automaticallyUseResetCard": "Automatically use resets",
|
||||
"automaticallyUsed": "Auto use",
|
||||
"automaticUsageRules": "Automatic usage rules",
|
||||
"setGlobalLeadTime": "Set global lead time",
|
||||
"minutesInAdvance": "{leadMinutes} minutes in advance",
|
||||
"leadTime": "Lead time",
|
||||
"nextUse": "Next use: {nextConsumeAtDisplay}",
|
||||
"autoUsageSettingsFailedToLoad": "Auto usage settings failed to load",
|
||||
"limitReset": "Limit reset",
|
||||
"confirmLastReset": "Confirm last reset",
|
||||
"confirmResetAmount": "Confirm reset amount",
|
||||
"pendingAction": "View reset credits, an operation is awaiting confirmation",
|
||||
"queryFailedWithCount": "View reset credits, query failed, last known available: {count}",
|
||||
"queryFailedLabel": "View reset credits, query failed",
|
||||
"availableCount": "View reset credits, last known available: {count}",
|
||||
"viewCredits": "View reset credits",
|
||||
"useResetSelectedByUpstream": "Use a reset (selected by upstream)",
|
||||
"expires": "Expires {expiresAtDisplay}",
|
||||
"expiryHelp": "Expiry is determined by the upstream service",
|
||||
"querying": "Querying",
|
||||
"toBeQueried": "To be queried",
|
||||
"usesAvailable": "Uses available: {count}",
|
||||
"usageReset": "Usage reset",
|
||||
"thisTimeUse": "This time use",
|
||||
"currentQuota": "Current quota",
|
||||
"operationUnconfirmed": "The last operation is awaiting confirmation",
|
||||
"confirmPrevious": "Continue verifying the previous reset",
|
||||
"continueToConfirm": "Continue to confirm",
|
||||
"availableResetCards": "Available resets",
|
||||
"refreshCredits": "Refresh reset credits",
|
||||
"resetCardLoadingFailed": "Could not load resets",
|
||||
"refreshRequired": "Refresh and try again",
|
||||
"queryingAvailableResetTimes": "Querying available reset times…",
|
||||
"useResetCredit": "Use reset credit: {title}, {expiry}",
|
||||
"useReset": "Use reset",
|
||||
"noResetCardAvailableYet": "No resets available",
|
||||
"confirmAgain": "Confirm again",
|
||||
"confirmReset": "Confirm reset",
|
||||
"lastResetCompleted": "Last reset completed",
|
||||
"resetSuccess": "Quota reset",
|
||||
"resultUnknown": "The result is uncertain, retrying will reuse the same request ID",
|
||||
"quotaResetFailed": "Quota reset failed",
|
||||
"alreadyProcessed": "This reset was already processed, refresh the reset credit list",
|
||||
"noCredits": "No reset credits available",
|
||||
"resetNotNeeded": "This quota window does not need a reset",
|
||||
"upstreamDeclined": "The upstream service did not reset the quota: {code}"
|
||||
},
|
||||
"status": {
|
||||
"accountStatus": "Account status",
|
||||
"tryNextTime": "Try next time",
|
||||
"recommendedAction": "Recommended Action",
|
||||
"upstreamOriginalFeedback": "Upstream original feedback",
|
||||
"forTroubleshootingOnly": "For troubleshooting only",
|
||||
"retreating": "Retreating",
|
||||
"oauthRefreshBackoff": "OAuth refresh backoff",
|
||||
"refreshFailedHelp": "Refresh failed, waiting for the next automatic attempt",
|
||||
"retryScheduledHelp": "The system will retry at the scheduled time",
|
||||
"attentionHelp": "This account needs attention",
|
||||
"retestHelp": "Test the connection again to update the status",
|
||||
"rateLimitedHelp": "The upstream service rate limited this account, cooldown is in progress",
|
||||
"cooldownHelp": "Scheduling resumes automatically after cooldown",
|
||||
"credentialsHelp": "This account is excluded from scheduling, update its credentials and test the connection again",
|
||||
"reauthorizeHelp": "Reauthorize the account to resume scheduling",
|
||||
"replaceCredentialsHelp": "Update or reimport credentials, then test the connection again",
|
||||
"upstreamRestrictionHelp": "Check the upstream account and resolve its restrictions before enabling it",
|
||||
"capacityFailuresHelp": "Capacity failures reached the threshold, scheduling is paused for this account",
|
||||
"recoveryProbeHelp": "After cooldown, a successful recovery probe resumes scheduling, or you can restore the account manually",
|
||||
"recoveryHelp": "Scheduling resumes after cooldown, or you can restore the account manually",
|
||||
"nextAttempt": ", next attempt: {nextRefreshDisplay}",
|
||||
"clickOrFocusToViewDetails": "{title}, {description}{retry}, click or focus to view details",
|
||||
"resumeDetection": "Resume detection",
|
||||
"expectedToRecover": "Expected to recover"
|
||||
},
|
||||
"fields": {
|
||||
"platformType": "Provider",
|
||||
"accountGrouping": "Groups",
|
||||
"lastUsed": "Last used",
|
||||
"tokenExpires": "Token expires",
|
||||
"quotaExhausted": "Quota exhausted",
|
||||
"rateLimiting": "Rate limited",
|
||||
"deactivated": "Deactivated",
|
||||
"error": "Error",
|
||||
"identityUnconfirmed": "Account identity has not yet been confirmed",
|
||||
"accessTokenHasExpired": "Access token has expired",
|
||||
"credentialsHaveExpired": "Credentials have expired",
|
||||
"invalidCredentials": "Invalid credentials",
|
||||
"accountUnavailable": "Account is unavailable or has been banned",
|
||||
"count": "Accounts"
|
||||
},
|
||||
"page": {
|
||||
"description": "Manage the account pool and monitor availability, quota, and usage",
|
||||
"noAccountDataYet": "No account data yet",
|
||||
"collapseStatistics": "Collapse statistics",
|
||||
"expandStatistics": "Expand statistics",
|
||||
"selectAccountOnCurrentPage": "Select the account on the current page",
|
||||
"selectAccount": "Select account",
|
||||
"deleteDescription": "This account will be removed from scheduling, deletion cannot be undone",
|
||||
"batchDeleteDescription": "Delete the {count} selected account? This action cannot be undone | Delete the {count} selected accounts? This action cannot be undone",
|
||||
"thisAccount": "This account",
|
||||
"delete": "Delete {value}?"
|
||||
},
|
||||
"import": {
|
||||
"jsonFormatIsIncorrect": "JSON format is incorrect",
|
||||
"documentTooLarge": "An import document exceeds 4 MiB, split the file and try again",
|
||||
"batchImportFileMustBeCprMulti": "The batch import file must be a CPR multi-platform export file",
|
||||
"invalidProvider": "The import file contains an invalid provider document",
|
||||
"noAccounts": "The import file contains no importable account documents",
|
||||
"pasteAtLeastOne": "Paste at least one {label}",
|
||||
"missingProvider": "The import file contains no {provider} accounts",
|
||||
"importFilesMustBeJsonObjects": "Import files must be JSON objects"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
{
|
||||
"appearance": {
|
||||
"switchToLight": "Switch to light mode",
|
||||
"switchToDark": "Switch to dark mode",
|
||||
"settings": {
|
||||
"global": "Global",
|
||||
"components": "Components",
|
||||
"invalidTheme": "Invalid theme settings, check the edited values",
|
||||
"themeSavedAndApplied": "Theme saved and applied",
|
||||
"description": "Customize the admin theme in this browser",
|
||||
"pendingChanges": "Pending changes: {count}",
|
||||
"synced": "Synced",
|
||||
"themeEditingLevel": "Theme editing level",
|
||||
"undoDraft": "Undo draft",
|
||||
"restoreDefault": "Restore default",
|
||||
"saveAndApply": "Save and apply",
|
||||
"saved": "Saved",
|
||||
"themeEditor": "Theme editor",
|
||||
"themeTokenEditingPanel": "Theme token editor",
|
||||
"searchToken": "Search tokens",
|
||||
"searchPlaceholder": "Search seed, alias, or component tokens"
|
||||
},
|
||||
"color": {
|
||||
"modified": "Modified",
|
||||
"edit": "Edit {label}",
|
||||
"restoreDerivedValue": "Restore derived value"
|
||||
},
|
||||
"preview": {
|
||||
"components": {
|
||||
"relayAccount": "Relay account",
|
||||
"stickyHelp": "Keep the current account until its quota is exhausted",
|
||||
"notEditable": "Not editable",
|
||||
"allPlatforms": "All platforms",
|
||||
"restricted": "Restricted",
|
||||
"accountAvailability": "Account availability",
|
||||
"todaySQuota": "Today's quota",
|
||||
"batchImport": "Batch import",
|
||||
"platform": "Provider",
|
||||
"requestToday": "Requests today",
|
||||
"recentlyUsed": "Last used",
|
||||
"justNow": "Just now",
|
||||
"hoursAgo": "2 hours ago",
|
||||
"componentOverview": "Component overview",
|
||||
"description": "Inspect component states, data density, and overlays together",
|
||||
"currentThemeSemanticColor": "Current theme semantic color",
|
||||
"basicControlComponents": "Basic control components",
|
||||
"buttonsAndActions": "Buttons and Actions",
|
||||
"createAccount": "Create account",
|
||||
"exportData": "Export data",
|
||||
"dealWithItLater": "Deal with it later",
|
||||
"sizeAndDisabledStatus": "Size and disabled status",
|
||||
"inoperable": "Inoperable",
|
||||
"processing": "Processing",
|
||||
"notification": "Notification",
|
||||
"moreActions": "More actions",
|
||||
"deleteRecord": "Delete record",
|
||||
"formsAndInput": "Forms and input",
|
||||
"searchAccount": "Search account",
|
||||
"choosePlatform": "Choose platform",
|
||||
"accessKeyErrorExample": "Access key error example",
|
||||
"disableInputBox": "Disable input box",
|
||||
"brandColors": "Brand colors",
|
||||
"editBrandColors": "Edit brand colors",
|
||||
"schedulingNotes": "Scheduling notes",
|
||||
"controlHeight": "Control height",
|
||||
"componentExampleControlHeight": "Component example control height",
|
||||
"choiceAndFeedbackComponents": "Choice and feedback components",
|
||||
"selectAndSwitch": "Select and switch",
|
||||
"accountView": "Account view",
|
||||
"realTimeNotification": "Real time notification",
|
||||
"automaticRotation": "Automatic rotation",
|
||||
"selectCurrentPage": "Select current page",
|
||||
"partialSelection": "Partial selection",
|
||||
"equilibrium": "Equilibrium",
|
||||
"sticky": "Sticky",
|
||||
"manual": "Manual",
|
||||
"feedbackSemantics": "Feedback semantics",
|
||||
"themeSettingsSaved": "Theme settings saved",
|
||||
"quotaOfAccountsIsCloseToUpper": "The quota of 3 accounts is close to the upper limit",
|
||||
"connectionTestFailed": "Connection test failed",
|
||||
"schedulingNotice": "Scheduling rules apply to the next request",
|
||||
"statusAndProgress": "Status and progress",
|
||||
"runningNormally": "Running normally",
|
||||
"quotaLimited": "Quota limited",
|
||||
"needToBeProcessed": "Need to be processed",
|
||||
"synchronizing": "Synchronizing",
|
||||
"restoreTag": "Restore tag",
|
||||
"dataTable": "Data table",
|
||||
"tableComponents": "ZTable · ZScrollbar · ZPagination (standard row height)",
|
||||
"filterForm": "Filter form",
|
||||
"filterAccounts": "Filter accounts",
|
||||
"boundaryStateComponent": "Boundary state component",
|
||||
"emptyState": "Empty state",
|
||||
"noMatchingAccountYet": "No matching account yet",
|
||||
"emptyHelp": "Adjust the filters or add an upstream account",
|
||||
"addAccount": "Add account",
|
||||
"loadingAndSkeleton": "Loading and Skeleton",
|
||||
"synchronizingAccountStatus": "Synchronizing account status",
|
||||
"overlaysAndMenus": "Overlays and menus",
|
||||
"accountOperation": "Account operation",
|
||||
"editAccount": "Edit account",
|
||||
"deactivateAccount": "Deactivate account",
|
||||
"overlayHelp": "Overlays use their own surface and shadow tokens",
|
||||
"eyebrow": "Component preview",
|
||||
"count": "{count} base component | {count} base components",
|
||||
"buttonLabel": "Button / action",
|
||||
"feedbackTypes": "Success · Warning · Error · Info",
|
||||
"tagComponents": "ZTag · Progress tokens",
|
||||
"loadingComponents": "ZSkeleton · ZButton loading",
|
||||
"overlayComponents": "ZPopover · ZMenuItem · Elevated surface"
|
||||
},
|
||||
"dashboard": {
|
||||
"justUpdated": "Just updated",
|
||||
"demoKey": "Demo Key",
|
||||
"requestHealthTimeline": "Request a health timeline",
|
||||
"validRequestAvailability": "Valid request availability",
|
||||
"clientId": "Client ID",
|
||||
"tokenAuthentication": "Token authentication",
|
||||
"todaySToken": "Today's tokens",
|
||||
"hours": "5 hours",
|
||||
"requests": "08-23 {value}:00–{value2}:00 · Requests: {count}",
|
||||
"times": "Times",
|
||||
"dailyLimit": "Daily limit"
|
||||
},
|
||||
"homeArtboard": "Home artboard",
|
||||
"themeRealTimePreview": "Theme real-time preview",
|
||||
"livePreview": "Live preview",
|
||||
"description": "Preview real components in isolation, pan and zoom to inspect details",
|
||||
"previewType": "Preview type",
|
||||
"canvas": {
|
||||
"homeThemePreviewArtboard": "Home theme preview artboard",
|
||||
"dragBlankSpaceToPanUseScroll": "Drag the blank space to pan · Use the scroll wheel to zoom",
|
||||
"reduceArtboard": "Reduce the artboard",
|
||||
"recovery": "Recovery 100%",
|
||||
"enlargeArtboard": "Enlarge artboard",
|
||||
"adaptToArtboard": "Adapt to artboard"
|
||||
}
|
||||
},
|
||||
"componentTokens": {
|
||||
"cardsAndContainers": "Cards and Containers",
|
||||
"dataDisplay": "Data display",
|
||||
"navigation": "Navigation",
|
||||
"layoutAndScrolling": "Layout and scrolling",
|
||||
"mainButtonText": "Main button text",
|
||||
"mainButtonBackground": "Main button background",
|
||||
"mainButtonHover": "Main button Hover",
|
||||
"mainButtonActive": "Main button Active",
|
||||
"secondaryButtonBackground": "Secondary button background",
|
||||
"secondaryButtonHover": "Secondary button Hover",
|
||||
"secondaryButtonActive": "Secondary button Active",
|
||||
"secondaryIconButtonBackground": "Secondary icon button background",
|
||||
"secondaryIconButtonHover": "Secondary icon button hover",
|
||||
"secondaryIconButtonActive": "Secondary icon button active",
|
||||
"inputBoxBackground": "Input box background",
|
||||
"inputBoxHover": "Input box Hover",
|
||||
"inputBoxActive": "Input box Active",
|
||||
"inputBoxShadow": "Input box shadow",
|
||||
"inputBoxHoverShadow": "Input box Hover shadow",
|
||||
"inputBoxFocusOuterCircle": "Input box focus outer circle",
|
||||
"cardBackground": "Card background",
|
||||
"popUpBackground": "Pop-up background",
|
||||
"floatingTitleBackground": "Floating title background",
|
||||
"cardRoundedCorners": "Card rounded corners",
|
||||
"cardShadow": "Card shadow",
|
||||
"tableRowHeight": "Table row height",
|
||||
"headerBackground": "Header background",
|
||||
"lineBackground": "Line background",
|
||||
"zebraPatternBackground": "Zebra pattern background",
|
||||
"rowHover": "Row hover",
|
||||
"selectedRowBackground": "Selected row background",
|
||||
"selectRowHover": "Select row Hover",
|
||||
"progressTrack": "Progress track",
|
||||
"menuSelectionBackground": "Menu selection background",
|
||||
"sidebarBackground": "Sidebar background",
|
||||
"sidebarShadow": "Sidebar shadow",
|
||||
"scrollBarSlider": "Scroll bar slider",
|
||||
"scrollBarHover": "Scroll bar Hover",
|
||||
"componentTokenComponentFamily": "Component token family",
|
||||
"description": "Adjust component tokens for {label}, unchanged values continue to use the global seed and alias algorithms",
|
||||
"noMatchingComponentToken": "No matching component tokens",
|
||||
"kindLabel": "Component tokens"
|
||||
},
|
||||
"globalTokens": {
|
||||
"size": "Size",
|
||||
"style": "Style",
|
||||
"systemMode": "System",
|
||||
"lightColor": "Light color",
|
||||
"dark": "Dark",
|
||||
"successColor": "Success color",
|
||||
"successFeedbackAndStatus": "Success feedback and status",
|
||||
"warningColor": "Warning color",
|
||||
"limitAndRiskReminder": "Limit and risk reminder",
|
||||
"wrongColor": "Wrong color",
|
||||
"dangerHelp": "Failures and destructive actions",
|
||||
"informationColor": "Information color",
|
||||
"systemAndRequestInformation": "System and request information",
|
||||
"linkColor": "Link color",
|
||||
"linksAndJumps": "Links and jumps",
|
||||
"basicTextColor": "Basic text color",
|
||||
"textAndInformationLevels": "Text and information levels",
|
||||
"basicBackgroundColor": "Basic background color",
|
||||
"pageAndContainerBase": "Page and container base",
|
||||
"themeMode": "Theme mode",
|
||||
"globalTokenClassification": "Global token categories",
|
||||
"brandColorLabel": "Preset theme · Brand color · colorPrimary",
|
||||
"brandColor": "Brand color",
|
||||
"presetThemes": "Preset themes",
|
||||
"brandMainColor": "Brand main color",
|
||||
"paletteDescription": "Color scales and overall appearance",
|
||||
"semanticColorsTitle": "Semantic and neutral colors",
|
||||
"derivedVariablesMapAliasToken": "Derived variables: map and alias tokens",
|
||||
"sizeToken": "Size tokens",
|
||||
"basicFontSize": "Basic font size",
|
||||
"basicSpacing": "Basic spacing",
|
||||
"sizeStep": "Size step",
|
||||
"styleToken": "Style tokens",
|
||||
"surfaceDescription": "Borderless surfaces, rounded corners, and layered shadows",
|
||||
"universalFillet": "Universal fillet",
|
||||
"shadowIntensity": "Shadow intensity"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"auth": {
|
||||
"signOut": "Sign out",
|
||||
"adminSignIn": "Admin sign-in",
|
||||
"apiKeySignIn": "API key sign-in",
|
||||
"signingIn": "Signing in…",
|
||||
"signIn": "Sign in",
|
||||
"method": "Sign-in method",
|
||||
"title": "Sign in",
|
||||
"welcome": "Welcome back",
|
||||
"username": "Admin account",
|
||||
"usernamePlaceholder": "Enter your admin account",
|
||||
"passwordPlaceholder": "Enter your password",
|
||||
"apiKeyPlaceholder": "Enter your API key",
|
||||
"pageLabel": "Sign in to Codex Proxy RS",
|
||||
"password": "Password",
|
||||
"apiKey": "API key",
|
||||
"adminRealm": "Admin",
|
||||
"keyRealm": "API key"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
{
|
||||
"common": {
|
||||
"errors": {
|
||||
"canceled": "Request canceled",
|
||||
"timeout": "Request timed out, try again later",
|
||||
"network": "Connection failed, check your network and try again",
|
||||
"invalidParameters": "Invalid request parameters",
|
||||
"signInRequired": "Sign-in required",
|
||||
"forbidden": "You do not have permission to perform this action",
|
||||
"notFound": "Endpoint not found",
|
||||
"conflict": "Resource conflict, refresh and try again",
|
||||
"payloadTooLarge": "Request payload is too large",
|
||||
"unsupportedFormat": "Unsupported request format",
|
||||
"invalidContent": "Invalid request content",
|
||||
"rateLimited": "Too many requests, try again later",
|
||||
"internal": "Internal server error",
|
||||
"upstreamFailure": "Upstream service request failed",
|
||||
"unavailable": "Service temporarily unavailable, try again later",
|
||||
"upstreamTimeout": "Upstream response timed out",
|
||||
"http": "Request failed (HTTP {status})",
|
||||
"request": "Request failed",
|
||||
"responseTooLarge": "Response content exceeds size limit",
|
||||
"unsupportedResponse": "The service returned an unsupported response",
|
||||
"sessionExpired": "Your session has expired, sign in again",
|
||||
"operation": "Operation failed",
|
||||
"copy": "Failed to copy",
|
||||
"load": "Failed to load",
|
||||
"malformedJson": "The request body is not valid JSON",
|
||||
"invalidTimeRange": "Invalid time range",
|
||||
"invalidCredentials": "Invalid sign-in credentials",
|
||||
"invalidAdminApiKey": "Invalid admin API key",
|
||||
"tooManyLoginAttempts": "Too many sign-in attempts, try again later",
|
||||
"upstreamResultUnknown": "The upstream result is unknown, refresh the status before deciding whether to retry"
|
||||
},
|
||||
"status": {
|
||||
"disabled": "Disabled",
|
||||
"disabledName": "{name} (disabled)",
|
||||
"success": "Success",
|
||||
"error": "Error",
|
||||
"pending": "Pending",
|
||||
"failed": "Failed",
|
||||
"healthy": "Healthy",
|
||||
"all": "All",
|
||||
"available": "Available",
|
||||
"unavailable": "Unavailable",
|
||||
"enabled": "Enabled",
|
||||
"loading": "Loading…",
|
||||
"running": "Running",
|
||||
"completed": "Completed",
|
||||
"rateLimited": "Rate limited"
|
||||
},
|
||||
"actions": {
|
||||
"copy": "Copy",
|
||||
"close": "Close",
|
||||
"retry": "Retry",
|
||||
"cancel": "Cancel",
|
||||
"previous": "Previous",
|
||||
"reset": "Reset",
|
||||
"back": "Back",
|
||||
"delete": "Delete",
|
||||
"create": "Create",
|
||||
"enable": "Enable",
|
||||
"next": "Next",
|
||||
"confirm": "Confirm",
|
||||
"refresh": "Refresh",
|
||||
"save": "Save"
|
||||
},
|
||||
"providers": {
|
||||
"all": "All platforms",
|
||||
"filter": "Filter by platform",
|
||||
"unknown": "Unknown platform",
|
||||
"customAuth": "Custom authentication · {normalized}",
|
||||
"unknownAuth": "Unknown authentication type"
|
||||
},
|
||||
"location": {
|
||||
"resolving": "Resolving exit location…",
|
||||
"detect": "Resolve exit location and fill in the form",
|
||||
"countryCode": "Country code",
|
||||
"countryCodePlaceholder": "Enter a two-letter country code",
|
||||
"region": "Region",
|
||||
"regionPlaceholder": "Enter a region",
|
||||
"city": "City",
|
||||
"cityPlaceholder": "Enter a city",
|
||||
"timeZone": "IANA time zone",
|
||||
"timeZonePlaceholder": "Enter an IANA time zone",
|
||||
"required": "Enter a two-letter country code, region, city, and IANA time zone"
|
||||
},
|
||||
"values": {
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"unspecified": "Not specified",
|
||||
"all": "All",
|
||||
"unknown": "Unknown",
|
||||
"unlimited": "Unlimited",
|
||||
"default": "Default",
|
||||
"on": "On",
|
||||
"none": "None",
|
||||
"off": "Off"
|
||||
},
|
||||
"form": {
|
||||
"inputPlaceholder": "Enter a value",
|
||||
"useForm": "Use form",
|
||||
"fieldHelp": "About {label}",
|
||||
"editJson": "Edit JSON"
|
||||
},
|
||||
"fields": {
|
||||
"actions": "Actions",
|
||||
"notes": "Notes",
|
||||
"status": "Status",
|
||||
"color": "Color",
|
||||
"updatedAt": "Updated",
|
||||
"name": "Name",
|
||||
"createdAt": "Created",
|
||||
"baseUrl": "Base URL",
|
||||
"apiKey": "API key",
|
||||
"build": "Build"
|
||||
},
|
||||
"language": "Language",
|
||||
"validation": {
|
||||
"invalidJson": "Enter a valid JSON object",
|
||||
"jsonObject": "Input must be a JSON object",
|
||||
"sizeLimit": "Input must not exceed {value} KiB"
|
||||
},
|
||||
"feedback": {
|
||||
"deleted": "Deleted",
|
||||
"copied": "Copied"
|
||||
},
|
||||
"time": {
|
||||
"minutesAgo": "{count} minute ago | {count} minutes ago"
|
||||
},
|
||||
"units": {
|
||||
"tokens": "Tokens"
|
||||
},
|
||||
"sizes": {
|
||||
"small": "Small",
|
||||
"medium": "Medium",
|
||||
"large": "Large"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"dashboard": {
|
||||
"scheduling": {
|
||||
"defaultConcurrency": "Default concurrency",
|
||||
"totalSlots": "Total slots",
|
||||
"freeSlots": "Available slots",
|
||||
"smart": "Smart scheduling",
|
||||
"quotaReset": "Quota reset priority",
|
||||
"sticky": "Sticky",
|
||||
"title": "Account scheduling",
|
||||
"description": "Capacity, concurrency and allocation strategies",
|
||||
"occupiedSlots": "Slots in use",
|
||||
"strategy": "Allocation strategy"
|
||||
},
|
||||
"accountPool": {
|
||||
"empty": "No account pool data",
|
||||
"quotaExhausted": "Quota exhausted",
|
||||
"rateLimited": "Rate limited",
|
||||
"pending": "Pending",
|
||||
"issueCountsEmpty": "Disabled: — · Errors: —",
|
||||
"availableDescription": "Account is currently available",
|
||||
"exhaustedDescription": "Account quota has been exhausted",
|
||||
"limitedDescription": "Account requests are temporarily restricted",
|
||||
"issueCounts": "Disabled: {disabled} · Errors: {error}",
|
||||
"title": "Account status",
|
||||
"description": "Account pool health",
|
||||
"healthyRate": "Healthy accounts",
|
||||
"distribution": "State distribution",
|
||||
"unavailableCount": "Unavailable: {value}"
|
||||
},
|
||||
"activeAccounts": {
|
||||
"title": "Active account usage",
|
||||
"sortByRecent": "Sort by recent use",
|
||||
"empty": "No recent account requests",
|
||||
"recent": "Recently"
|
||||
},
|
||||
"title": "System overview",
|
||||
"today": "Today's statistics",
|
||||
"refresh": {
|
||||
"action": "Refresh overview",
|
||||
"failed": "Refresh failed, showing the last available statistics",
|
||||
"unavailable": "Statistics temporarily unavailable, try again later",
|
||||
"lastUpdated": "Refreshes every 30 s, last refreshed {updatedAt}",
|
||||
"waiting": "Refreshes every 30 s, waiting for the first update",
|
||||
"interval": "Refreshes every 30 s"
|
||||
},
|
||||
"metrics": {
|
||||
"title": "Key metrics",
|
||||
"outputTokens": "Output",
|
||||
"inputTokens": "Input",
|
||||
"cachedInputTokens": "Cached input",
|
||||
"cacheHits": "Cache hits",
|
||||
"requests": "Requests",
|
||||
"firstTokenP95Ms": "TTFT P95",
|
||||
"latencyP95Ms": "Latency P95",
|
||||
"outputThroughputP50": "Output throughput P50",
|
||||
"errors": "Errors",
|
||||
"successRate": "Success rate",
|
||||
"totalRequests": "Total requests",
|
||||
"requestCount": "Requests",
|
||||
"totalTokens": "Total tokens",
|
||||
"totalCharges": "Total cost",
|
||||
"totalCacheHits": "Total cache hits",
|
||||
"totalCache": "Total cache"
|
||||
},
|
||||
"comparedWithYesterday": "vs. yesterday",
|
||||
"trends": {
|
||||
"title": "Usage trends",
|
||||
"metric": "Trend indicator",
|
||||
"highlight": "Highlight the {label} series",
|
||||
"empty": "No trend data",
|
||||
"latency": "Latency",
|
||||
"errors": "Errors"
|
||||
},
|
||||
"recentRequests": {
|
||||
"title": "Usage records",
|
||||
"description": "Last 10 successful requests",
|
||||
"empty": "No successful requests"
|
||||
},
|
||||
"clientIdentity": {
|
||||
"notChecked": "Not checked yet",
|
||||
"versionPolicy": "Version policy",
|
||||
"customVersion": "Custom version",
|
||||
"active": "Active",
|
||||
"activeDescription": "New requests using the global settings use this identity",
|
||||
"upToDate": "Up to date",
|
||||
"upToDateDescription": "The active version matches the latest official release",
|
||||
"updateAvailable": "Update available",
|
||||
"latestRelease": "Latest official version: {releaseLabel}",
|
||||
"checkFailed": "Check failed",
|
||||
"checkFailedDescription": "Official version check failed",
|
||||
"pending": "Pending check",
|
||||
"pendingDescription": "Official releases have not been checked yet",
|
||||
"verifiedAt": "Profile verified: {verifiedAt}",
|
||||
"checkedAt": "Release checked: {checkedAt}",
|
||||
"clientId": "Client ID",
|
||||
"tokenAuth": "Token authentication",
|
||||
"title": "Default upstream identity",
|
||||
"provider": "Upstream platform",
|
||||
"empty": "No request identity available",
|
||||
"attributes": "Request identity details",
|
||||
"authProtocol": "Authentication protocol",
|
||||
"emulatedEnvironment": "Emulated environment",
|
||||
"environment": "Environment"
|
||||
},
|
||||
"health": {
|
||||
"title": "Request health",
|
||||
"description": "Valid request availability"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"groups": {
|
||||
"selector": {
|
||||
"loading": "Loading groups…",
|
||||
"empty": "No groups available, create one in Account groups"
|
||||
},
|
||||
"actions": {
|
||||
"editGroup": "Edit group",
|
||||
"disableGroup": "Disable group",
|
||||
"enableGroup": "Enable group",
|
||||
"deleteGroup": "Delete group",
|
||||
"enterGroupName": "Please enter a group name",
|
||||
"selectValidGroupingColor": "Please select a valid grouping color",
|
||||
"updated": "Group updated",
|
||||
"created": "Group created",
|
||||
"disabled": "Group disabled",
|
||||
"enabled": "Group enabled",
|
||||
"groupDeleted": "Group deleted",
|
||||
"deletedGroupDeletedGroups": "Deleted {count} group | Deleted {count} groups",
|
||||
"partialDeletion": "Deleted {count} groups, the remaining groups were not deleted: {value}",
|
||||
"batchDeletionFailed": "Batch deletion failed"
|
||||
},
|
||||
"filters": {
|
||||
"searchAccountGroup": "Search account group",
|
||||
"searchGroupName": "Search group name",
|
||||
"filterByGroupStatus": "Filter by group status",
|
||||
"deleteSelected": "Delete selected ({count})",
|
||||
"createGroup": "Create group"
|
||||
},
|
||||
"editor": {
|
||||
"editDescription": "Edit group details and request permissions",
|
||||
"createDescription": "After creating the group, add accounts to it in Accounts",
|
||||
"groupName": "Group name",
|
||||
"forExampleProductionAccount": "For example: production account",
|
||||
"groupColor": "Group color",
|
||||
"selectGroupColor": "Select group color",
|
||||
"fastMode": "Fast mode",
|
||||
"imageGeneration": "Image generation",
|
||||
"descriptionOptional": "Description (optional)",
|
||||
"groupDescription": "Group description",
|
||||
"describePurposeOfThisGroup": "Describe the purpose of this group",
|
||||
"saveGroup": "Save group"
|
||||
},
|
||||
"metrics": {
|
||||
"restricted": "Restricted",
|
||||
"total": "Total",
|
||||
"concurrency": "Concurrency",
|
||||
"today": "Today",
|
||||
"cumulative": "Cumulative"
|
||||
},
|
||||
"group": "Group",
|
||||
"fields": {
|
||||
"capacity": "Capacity"
|
||||
},
|
||||
"page": {
|
||||
"description": "Organize accounts and control which accounts each API key can use",
|
||||
"empty": "No groups yet",
|
||||
"selectCurrentPageGroup": "Select current page group",
|
||||
"selectGroup": "Select group",
|
||||
"fastModeIsOn": "Fast mode is on",
|
||||
"fastModeIsOff": "Fast mode is off",
|
||||
"imageGenerationDisabled": "Image generation disabled",
|
||||
"colorLabel": "Group color: {color}",
|
||||
"batchDeleteWarning": "These groups will stop working immediately, deletion cannot be undone",
|
||||
"batchDeleteDescription": "Delete the {count} selected group? Accounts will be kept | Delete the {count} selected groups? Accounts will be kept",
|
||||
"disableAccountGrouping": "Disable account grouping",
|
||||
"disableDescription": "API keys using this group will lose access to its accounts while the group is disabled",
|
||||
"confirmDisable": "Confirm disable",
|
||||
"disable": "Disable “{name}”?",
|
||||
"affectedApiKeys": "Affected API keys ({count}): {value}",
|
||||
"affectedKeys": "Affected API keys: {count}",
|
||||
"deleteAccountGroup": "Delete account group",
|
||||
"deleteWarning": "This group will stop working immediately, deletion cannot be undone",
|
||||
"unnamedGroup": "This group",
|
||||
"deleteAccountsWillBeKept": "Delete “{name}”? Accounts will be kept"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import accounts from './accounts.json'
|
||||
import appearance from './appearance.json'
|
||||
import auth from './auth.json'
|
||||
import common from './common.json'
|
||||
import dashboard from './dashboard.json'
|
||||
import groups from './groups.json'
|
||||
import keys from './keys.json'
|
||||
import navigation from './navigation.json'
|
||||
import plugins from './plugins.json'
|
||||
import proxies from './proxies.json'
|
||||
import settings from './settings.json'
|
||||
import systemUpdate from './systemUpdate.json'
|
||||
import usage from './usage.json'
|
||||
|
||||
export default {
|
||||
...accounts,
|
||||
...appearance,
|
||||
...auth,
|
||||
...common,
|
||||
...dashboard,
|
||||
...groups,
|
||||
...keys,
|
||||
...navigation,
|
||||
...plugins,
|
||||
...proxies,
|
||||
...settings,
|
||||
...systemUpdate,
|
||||
...usage,
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"keys": {
|
||||
"configuration": {
|
||||
"description": "Save or merge the configuration below and then restart Codex",
|
||||
"platform": "Platform",
|
||||
"toggleWebSocket": "Switch WebSocket configuration",
|
||||
"importCcSwitch": "Add to CC Switch",
|
||||
"copiedToClipboard": "Copied to clipboard",
|
||||
"fullApiKeyNotAvailable": "Full API key not available",
|
||||
"title": "Use API key"
|
||||
},
|
||||
"actions": {
|
||||
"editKey": "Edit key",
|
||||
"useKey": "Use key",
|
||||
"moreActions": "More actions",
|
||||
"resetUsedCredit": "Reset usage",
|
||||
"disableKey": "Disable",
|
||||
"enableKey": "Enable",
|
||||
"deleteKey": "Delete",
|
||||
"deletedApiKeyDeletedApiKeys": "Deleted {count} API key | Deleted {count} API keys"
|
||||
},
|
||||
"day": "Day",
|
||||
"dailyUsage": "Daily usage",
|
||||
"week": "Week",
|
||||
"weeklyUsage": "Weekly usage",
|
||||
"viewUsageAndCostsFor": "View usage and costs for {name}",
|
||||
"costDetailsTitle": "Cost details (USD)",
|
||||
"confirmNextTime": "Confirm next time",
|
||||
"budgetReset": {
|
||||
"dailyQuota": "Daily quota",
|
||||
"weeklyQuota": "Weekly quota",
|
||||
"keyQuotaReset": "Key quota reset",
|
||||
"description": "Clear spending for the selected period, the reset date is set again on the next request",
|
||||
"targetKey": "Target key",
|
||||
"resetScope": "Reset scope",
|
||||
"currentlyUsed": "Currently used",
|
||||
"afterReset": "After reset",
|
||||
"remainUnchanged": "Remain unchanged",
|
||||
"confirmReset": "Confirm reset"
|
||||
},
|
||||
"created": {
|
||||
"apiKeyCreated": "API key created",
|
||||
"description": "Copy the API key or import it into CC Switch",
|
||||
"accessNotice": "This key grants gateway access, share it only with trusted callers",
|
||||
"copyKey": "Copy key",
|
||||
"iHaveSaved": "I have saved"
|
||||
},
|
||||
"filters": {
|
||||
"apiKeyFilteringAndOperations": "API key filtering and operations",
|
||||
"searchPlaceholder": "Search by name or label",
|
||||
"searchLabel": "Search API keys by name or label",
|
||||
"deleteSelected": "Delete selected ({count})",
|
||||
"createApiKey": "Create API key"
|
||||
},
|
||||
"editor": {
|
||||
"description": "Set API key details, account groups, and usage limits",
|
||||
"namePlaceholder": "For example: Production",
|
||||
"labelOptional": "Label (optional)",
|
||||
"forExampleBackendService": "For example: backend service",
|
||||
"customKeyOptional": "Custom Key (optional)",
|
||||
"keyPlaceholder": "Leave blank to generate a key",
|
||||
"upstreamIdentity": "Upstream identity",
|
||||
"dailyLimit": "Daily limit",
|
||||
"dailyLimitUsd": "Daily limit (USD)",
|
||||
"weeklyLimit": "Weekly limit",
|
||||
"weeklyLimitUsd": "Weekly limit (USD)",
|
||||
"maximumConcurrency": "Maximum concurrency",
|
||||
"requestsPerMinuteRpm": "Requests per minute (RPM)",
|
||||
"saveChanges": "Save changes",
|
||||
"updated": "API key updated",
|
||||
"created": "API key created",
|
||||
"validation": {
|
||||
"amount": "{label} must be a non-negative amount with up to 10 decimal places",
|
||||
"integer": "{label} must be a non-negative integer"
|
||||
},
|
||||
"enterApiKeyName": "Please enter API key name",
|
||||
"invalidKey": "Use visible HTTP header characters, without spaces or line breaks",
|
||||
"requestsPerMinute": "Requests per minute"
|
||||
},
|
||||
"fields": {
|
||||
"copyFullKey": "Copy full key",
|
||||
"allAccounts": "All accounts",
|
||||
"keyPrefix": "Prefix",
|
||||
"quotaUsage": "Quota",
|
||||
"requestLimits": "Limits",
|
||||
"lastUsed": "Last used"
|
||||
},
|
||||
"page": {
|
||||
"description": "Manage API keys and account access",
|
||||
"noApiKeyYet": "No API key yet",
|
||||
"selectCurrentPageKey": "Select current page key",
|
||||
"selectKey": "Select key",
|
||||
"concurrency": "Concurrency",
|
||||
"batchDeleteWarning": "These API keys will stop working immediately, deletion cannot be undone",
|
||||
"batchDeleteDescription": "Delete the {count} selected API key? | Delete the {count} selected API keys?",
|
||||
"deleteApiKey": "Delete API key",
|
||||
"deleteWarning": "This API key will stop working immediately, deletion cannot be undone",
|
||||
"apiKey": "The API key",
|
||||
"delete": "Delete {name}?"
|
||||
},
|
||||
"scope": {
|
||||
"allAccounts": {
|
||||
"title": "Allow access to all accounts",
|
||||
"summary": "After saving, this key can access all accounts",
|
||||
"confirm": "Allow access",
|
||||
"description": "This key can access all accounts, including ungrouped and future accounts"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"navigation": {
|
||||
"overview": "Overview",
|
||||
"accounts": "Accounts",
|
||||
"proxies": "Proxies",
|
||||
"groups": "Groups",
|
||||
"apiKeys": "API keys",
|
||||
"usage": "Analytics",
|
||||
"plugins": "Plugins",
|
||||
"appearance": "Theme",
|
||||
"settings": "Settings",
|
||||
"update": {
|
||||
"available": "Update available, open System update",
|
||||
"open": "Open System update"
|
||||
},
|
||||
"switchLanguage": "Switch language ({value})",
|
||||
"mainLabel": "Main navigation",
|
||||
"pluginsLabel": "Plugin navigation",
|
||||
"pluginManagement": "Manage",
|
||||
"online": "Online",
|
||||
"sidebar": {
|
||||
"close": "Close sidebar",
|
||||
"expand": "Expand sidebar",
|
||||
"collapse": "Collapse sidebar",
|
||||
"open": "Open sidebar"
|
||||
},
|
||||
"missingEntryPoint": "No default entry point is configured for the {role} identity"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,533 @@
|
||||
{
|
||||
"plugins": {
|
||||
"assets": {
|
||||
"pluginPackage": "Plugin package: {name}",
|
||||
"selectPluginPackage": "Select a plugin package",
|
||||
"packageLabel": "Plugin package"
|
||||
},
|
||||
"bindings": {
|
||||
"observationHelpTitle": "About request observation",
|
||||
"observationHelp": "Observe requests without changing their results",
|
||||
"applyToAllRequests": "Apply to all requests",
|
||||
"scopeHelpTitle": "About request scope",
|
||||
"scopeHelp": "When disabled, select at least one scope, all conditions must match and any value within a condition may match",
|
||||
"clientKey": "Client key",
|
||||
"accountGrouping": "Account grouping",
|
||||
"modelScope": "Model scope",
|
||||
"oneModelNamePerLineExactMatch": "One model name per line, exact match",
|
||||
"providerScope": "Provider scope",
|
||||
"oneProviderIdentifierPerLine": "One Provider identifier per line",
|
||||
"executionOrder": "Execution order",
|
||||
"executionSequenceDescription": "Execution sequence description",
|
||||
"priorityHelp": "Lower values run first",
|
||||
"whenPluginFails": "When the plugin fails",
|
||||
"continueToNextHandler": "Continue to the next handler",
|
||||
"rejectRequest": "Reject request"
|
||||
},
|
||||
"capabilities": {
|
||||
"moreCapabilities": "{count} more declared capabilities"
|
||||
},
|
||||
"catalog": {
|
||||
"cardView": "Card view",
|
||||
"listView": "List view",
|
||||
"currentVersion": "Current version",
|
||||
"installedVersion": "Installed version",
|
||||
"provideFunctionality": "Features",
|
||||
"searchForInstalledPlugins": "Search for installed plugins",
|
||||
"searchPluginsPublishers": "Search plugins, publishers",
|
||||
"pluginStatus": "Plugin status",
|
||||
"pluginDisplayMode": "plugin display mode",
|
||||
"noMatchingPlugins": "No matching plugins",
|
||||
"installYourFirstPlugin": "Install your first plugin",
|
||||
"tryAnotherNameOrStatus": "Try another name or status",
|
||||
"emptyDescription": "Install a plugin above after verifying its source",
|
||||
"clearFilters": "Clear filters",
|
||||
"pluginInstalled": "Plugin installed",
|
||||
"noDescription": "The publisher provided no description",
|
||||
"versions": "Versions: {count}",
|
||||
"manage": "Manage {displayName}",
|
||||
"versionCount": "Versions"
|
||||
},
|
||||
"configuration": {
|
||||
"fillInRequiredConfiguration": "Please fill in the required configuration",
|
||||
"incompatibleSecrets": "The target version does not support some saved secrets, choose to replace or clear them",
|
||||
"requiredSecretsCannotClear": "Required secrets cannot be cleared: {labels}",
|
||||
"requiredSecretsMissing": "No saved values for required secrets: {labels}",
|
||||
"secretsRequired": "Enter the required secrets",
|
||||
"checkBasicSettings": "Please check basic settings",
|
||||
"noParameters": "No plugin parameters required",
|
||||
"sensitiveConfiguration": "Sensitive configuration",
|
||||
"secretsHelpTitle": "About secret configuration",
|
||||
"secretsHelp": "Secrets are stored separately and never displayed, Keep preserves existing values and Replace overwrites them with all values entered here",
|
||||
"settingsSaved": "Settings saved: {count}",
|
||||
"clearSecretsHelp": "Clear all secrets when saving",
|
||||
"about": "About {name}",
|
||||
"enterNewValue": "Enter new value",
|
||||
"pluginParameters": "plugin parameters",
|
||||
"advancedSettings": "Advanced settings",
|
||||
"clientAuthentication": "Client authentication",
|
||||
"applyAndSwitch": "Apply and switch",
|
||||
"saveAndEnable": "Save and enable",
|
||||
"saveSettings": "Save settings",
|
||||
"keepExistingValues": "Keep existing values",
|
||||
"replaceAllValues": "Replace all values",
|
||||
"clearAllValues": "Clear all values",
|
||||
"checkPluginParameters": "Please check plugin parameters",
|
||||
"setRequestScopeOrCheckApplyTo": "Please set the request scope, or check \"Apply to all requests\"",
|
||||
"invalidIdentityMappings": "Check the client authentication identity mappings",
|
||||
"switchTo": "Switch to {version}",
|
||||
"pluginSettings": "Plugin settings",
|
||||
"unchangedVersion": "The current version is unchanged, edit settings before applying",
|
||||
"pluginSettingsPartition": "Plugin settings partition",
|
||||
"secretsModeLabel": "Secret storage action",
|
||||
"customScope": "Custom scope",
|
||||
"applyGlobally": "Apply globally",
|
||||
"requestHandling": "Request handling: {value}",
|
||||
"description": "Provide extensions using this configuration",
|
||||
"providesTerminalCommands": "Provides terminal commands",
|
||||
"requestHandlingNotConfigured": "Request handling not configured",
|
||||
"apiKeys": "API keys: {count}",
|
||||
"groups": "Groups: {count}",
|
||||
"providers": "Providers: {count}",
|
||||
"identityMappings": "Identity mappings: {count}",
|
||||
"allRequests": "All requests",
|
||||
"noLimitOnScope": "No limit on scope",
|
||||
"featureDetails": "Feature details",
|
||||
"capabilitiesOf": "Capabilities of {name}",
|
||||
"terminalCommands": "Terminal commands",
|
||||
"legacy": {
|
||||
"multipleEnabledNotice": "Multiple configurations are enabled, disable the unused one in configuration history",
|
||||
"previousConfigurations": "Previous configurations · {count}",
|
||||
"description": "Keep existing settings and data, activating a historical configuration replaces the current one",
|
||||
"disableAction": "Disable historical configuration",
|
||||
"start": "Start",
|
||||
"deleteHistoricalConfiguration": "Delete historical configuration"
|
||||
},
|
||||
"stale": "Plugin settings changed, refresh and try again",
|
||||
"incompatible": "Adjust incompatible settings and try again"
|
||||
},
|
||||
"details": {
|
||||
"version": "Version",
|
||||
"pendingDescription": "Configuration saved and awaiting activation, status updates automatically",
|
||||
"requiredConfiguration": "Complete required settings to enable the plugin",
|
||||
"versionInUse": "The old version has active calls, wait for them to finish before deleting it",
|
||||
"pluginDetails": "Plugin details",
|
||||
"pluginDetailsSection": "Plugin details section",
|
||||
"manualInstallationVersion": "Manual installation version",
|
||||
"pluginHasNotBeenInitialized": "Plugin has not been initialized",
|
||||
"pluginIsNotInstalled": "Plugin is not installed",
|
||||
"initializePlugin": "Initialize plugin",
|
||||
"installation": "Installation",
|
||||
"versionNotAvailable": "Version not available",
|
||||
"configurationStatusOf": "Configuration status of {name}",
|
||||
"settings": "Settings",
|
||||
"restart": "Restart",
|
||||
"deactivate": "Deactivate",
|
||||
"completeSetupAndEnable": "Complete setup and enable",
|
||||
"fallbackVersion": "Fallback version",
|
||||
"uninstallPlugin": "Uninstall plugin"
|
||||
},
|
||||
"downloadAuth": {
|
||||
"accessToken": "Access token",
|
||||
"usernameAndPassword": "Username and password",
|
||||
"customRequestHeader": "Custom request header",
|
||||
"noCertificationRequired": "No certification required",
|
||||
"fillInGithubToken": "Fill in the GitHub token",
|
||||
"credentialsPlaceholder": "Enter credentials",
|
||||
"useSavedCredentials": "Use saved credentials",
|
||||
"download": "Download · {hostname}",
|
||||
"downloadCertification": "Download certification",
|
||||
"helpTitle": "About download authentication",
|
||||
"githubHelp": "Public repositories need no authentication, private repositories require a GitHub token with read access",
|
||||
"urlHelp": "Required only when the download URL needs authentication",
|
||||
"storageHelp": "Credentials are saved during lookup or resolution, used only for this source, and never shared with the plugin",
|
||||
"authenticationMethod": "Authentication method",
|
||||
"githubToken": "GitHub token",
|
||||
"downloadToken": "Download token",
|
||||
"enterToken": "Enter token",
|
||||
"username": "Username",
|
||||
"downloadUsername": "Download username",
|
||||
"password": "Password",
|
||||
"downloadPassword": "Download password",
|
||||
"requestHeaderName": "Request header name",
|
||||
"requestHeaderValue": "Request header value"
|
||||
},
|
||||
"enable": {
|
||||
"notSet": "Not set",
|
||||
"switchActiveConfiguration": "Switch active configuration",
|
||||
"enablePluginConfiguration": "Enable plugin configuration",
|
||||
"willBeEnabled": "Will be enabled",
|
||||
"configurationsToDisable": "Configurations to disable: {count}",
|
||||
"toggleEnablementInstructions": "Toggle enablement instructions",
|
||||
"disableDescription": "These configurations will stop receiving new requests, settings, secrets, and private data are kept",
|
||||
"willBeDeactivated": "Will be deactivated",
|
||||
"confirmSwitch": "Confirm switch",
|
||||
"confirmEnable": "Confirm enable"
|
||||
},
|
||||
"extensions": {
|
||||
"emptyTitle": "No plugin management pages",
|
||||
"emptyDescription": "Enable a plugin with a management page to open it here or from the sidebar",
|
||||
"configuration": "Configuration {value}",
|
||||
"pages": "Pages: {count}",
|
||||
"openPage": "Open page"
|
||||
},
|
||||
"frontendAuth": {
|
||||
"exclusiveCertification": "Exclusive certification",
|
||||
"fallbackApiKeyIfNoMatch": "Fallback API key if no match",
|
||||
"disabled": "(disabled)",
|
||||
"configuredUnavailable": "Configured but unavailable",
|
||||
"invalidBinding": "Client authentication requires the authentication phase and a supported unmatched-identity policy",
|
||||
"unsupportedScope": "Client authentication does not support provider, model, or group scopes, disable and reenable this binding",
|
||||
"addAtLeastOneIdentityMapping": "Please add at least one identity mapping",
|
||||
"mappingLimit": "Up to 256 identity mappings",
|
||||
"invalidIdentity": "Identity must be 1–256 UTF-8 bytes without surrounding whitespace or control characters",
|
||||
"duplicateIdentity": "Each identity can be mapped only once",
|
||||
"keyRequired": "Select a client API key for each identity",
|
||||
"repeatedCursor": "The service returned a repeated pagination cursor",
|
||||
"failedToLoadClientKey": "Failed to load client Key",
|
||||
"enableClientAuthentication": "Enable client authentication",
|
||||
"helpTitle": "About client authentication",
|
||||
"description": "The plugin identifies external callers, the host maps each identity to an existing client API key and applies its limits, account scope, and concurrency policy",
|
||||
"loginNotice": "Applies to client API requests, independently of admin sign-in",
|
||||
"unmatchedProcessing": "Unmatched processing",
|
||||
"unmatchedHandlingInstructions": "Unmatched handling instructions",
|
||||
"exclusiveHelp": "Exclusive authentication rejects requests when the plugin finds no identity",
|
||||
"fallbackToApiKeyWhenNoMatch": "Fallback to API key when no match is found: When the plugin does not recognize the identity, it will continue to use the host’s original API key for authentication",
|
||||
"rejectionHelp": "Explicit plugin rejection or a failed call always rejects the request, without fallback",
|
||||
"unmatchedLabel": "Unmatched identity policy",
|
||||
"identityMapping": "Identity mapping",
|
||||
"identityMappingDescription": "Identity mapping description",
|
||||
"identityHelp": "Match the identity returned by the plugin exactly, each identity can be mapped once",
|
||||
"keyHelp": "Select the client API key for this identity, disabled or deleted keys grant no access",
|
||||
"reloadClientKey": "Reload client Key",
|
||||
"addMapping": "Add mapping",
|
||||
"identityMark": "Identity mark",
|
||||
"identityPlaceholder": "Enter the identity returned by the plugin",
|
||||
"failedToLoadTryAgain": "Failed to load, try again",
|
||||
"selectClientApiKey": "Select a client API key",
|
||||
"noClientKeyYet": "No client Key yet",
|
||||
"removeIdentityMapping": "Remove identity mapping {value}"
|
||||
},
|
||||
"installation": {
|
||||
"uploadPackage": "Upload package",
|
||||
"enterDigitHexadecimalDigest": "Please enter a 64-digit hexadecimal digest",
|
||||
"installNewVersion": "Install new version",
|
||||
"pluginPackageCannotExceedMib": "Plugin package cannot exceed 32 MiB",
|
||||
"verificationRequired": "Verify the selected plugin package first",
|
||||
"githubRepositoryRequired": "Enter a GitHub repository URL or owner/repo",
|
||||
"prereleaseTagRequired": "Specify a tag to look up a prerelease",
|
||||
"updatePlugin": "Update plugin",
|
||||
"installPlugin": "Install plugin",
|
||||
"installDescription": "Confirm the source and version before installing",
|
||||
"switchDescription": "Check settings compatibility before switching versions",
|
||||
"sourceHelp": "Supports local packages, URLs, and GitHub",
|
||||
"installationMethod": "Installation method",
|
||||
"tarGzTgzMaxMib": "tar.gz/tgz, max 32 MiB",
|
||||
"replace": "Replace",
|
||||
"browseFiles": "Browse files",
|
||||
"downloadUrl": "Download URL",
|
||||
"downloadAddressDescription": "Download address description",
|
||||
"urlHelp": "Use HTTPS, HTTP is allowed for loopback addresses",
|
||||
"githubRepository": "GitHub repository",
|
||||
"repositoryLinkOrOwnerRepo": "Repository link or owner/repo",
|
||||
"tagLabel": "Version tag",
|
||||
"tagHelpTitle": "About version tags",
|
||||
"tagHelp": "Leave blank for the latest stable release, specify a tag for prereleases",
|
||||
"tagPlaceholder": "Leave blank for the latest stable release",
|
||||
"allowPrereleaseLabel": "Allow prerelease lookup",
|
||||
"verificationSummary": "Verification summary",
|
||||
"digestHelpTitle": "About package verification",
|
||||
"digestHelp": "Optional 64-character SHA-256 hexadecimal digest from the publisher, used to verify the download",
|
||||
"shaChecksum": "SHA-256 checksum",
|
||||
"optionalSha": "Optional, SHA-256",
|
||||
"versionFound": "Version found",
|
||||
"preRelease": "Pre-release",
|
||||
"thereIsNoTarGzOrTgz": "There is no tar.gz or tgz plugin package for this release",
|
||||
"pendingTitle": "Plugins to install",
|
||||
"parsingCompleted": "Parsing completed",
|
||||
"publisher": "Publisher",
|
||||
"applicablePlatforms": "Applicable platforms",
|
||||
"trustNotice": "Plugins can access all gateway data and settings, verify the source before installing",
|
||||
"activateAfterInstall": "Confirm switching to the new version after installation",
|
||||
"installNewVersionInstructions": "Install new version instructions",
|
||||
"configurationHelp": "Reuse settings with the new version's defaults, open settings if changes are needed, previously used versions keep their restore settings",
|
||||
"queryAgain": "Query again",
|
||||
"queryingVersion": "Querying version",
|
||||
"saveSourceAndContinue": "Save source and continue",
|
||||
"parsingPluginPackage": "Parsing plugin package",
|
||||
"pluginInstallationFailed": "Plugin installation failed",
|
||||
"noSource": "No installation source available for this plugin",
|
||||
"sourceChanged": "Installation source changed, close and reopen this dialog",
|
||||
"sourceSaveFailed": "Failed to save installation source",
|
||||
"githubReleaseQueryFailed": "GitHub Release query failed",
|
||||
"installedNeedsConfiguration": "Plugin installed, complete the required settings",
|
||||
"preparing": "Plugin installed, preparing…",
|
||||
"pluginVersionInstalled": "Plugin version installed",
|
||||
"updateSourceChanged": "Installation source changed, check for updates again",
|
||||
"pluginUpgradeFailed": "plugin upgrade failed",
|
||||
"versionRequired": "Select a plugin version to install",
|
||||
"packageMismatch": "Package does not match the current plugin, select another package",
|
||||
"verificationFailed": "Package verification failed"
|
||||
},
|
||||
"management": {
|
||||
"installed": "Installed",
|
||||
"extensions": "Extensions",
|
||||
"description": "Manage versions, configurations, and extensions",
|
||||
"tabsLabel": "Plugin management sections",
|
||||
"refresh": "Refresh plugins",
|
||||
"switchPluginVersion": "Switch plugin version",
|
||||
"switchHelp": "Check target version settings before switching, keep the current version if the check fails",
|
||||
"deletePluginVersion": "Delete plugin version",
|
||||
"deleteVersionHelp": "Versions in use cannot be deleted, deleting a version also removes its restore settings",
|
||||
"delete": "Delete {displayName} {version}?",
|
||||
"versionDeletionDetails": "Version deletion details",
|
||||
"deleteVersionInUse": "Versions referenced by configurations or active calls cannot be deleted, other configurations are not disabled automatically",
|
||||
"deleteVersionCleanupHelp": "Remove download credentials used only by this version, deleting the last version also removes source rules, shared credentials and proxies are kept",
|
||||
"deleteVersionCleanupLabel": "Remove exclusive download credentials and, for the last version, source rules",
|
||||
"deletePluginConfiguration": "Delete plugin configuration",
|
||||
"deleteConfigurationWarning": "Permanently delete this configuration, secrets, and private data",
|
||||
"deleteConfigurationHelp": "This cannot be undone, installed versions and other configurations are kept",
|
||||
"uninstallWarning": "Delete all versions, configurations, secrets, and private data",
|
||||
"confirmUninstall": "Confirm uninstall",
|
||||
"versionCount": "{displayName} · {count} versions",
|
||||
"uninstallCleanupLabel": "Also remove sources and exclusive download credentials",
|
||||
"uninstallCleanupInstructions": "Uninstall cleanup instructions",
|
||||
"uninstallCleanupHelp": "Remove credentials used by uninstalled versions only when no other version references them, shared credentials, proxies, and audit records are kept",
|
||||
"disableInsteadHelp": "Disable the configuration if you only need to stop using it temporarily",
|
||||
"permanentDeleteLabel": "Confirm permanent deletion, this cannot be undone",
|
||||
"deleteDownloadCredentials": "Delete download credentials",
|
||||
"itCannotBeDeletedWhileItIs": "It cannot be deleted while it is still in use and cannot be restored after deletion",
|
||||
"pageLoadFailed": "Failed to load plugin extension pages",
|
||||
"pluginDataLoadingFailed": "Plugin data loading failed"
|
||||
},
|
||||
"frame": {
|
||||
"pluginPageCannotBeLoaded": "Plugin page cannot be loaded",
|
||||
"versionChanged": "Plugin page version changed, refreshing…",
|
||||
"navigationBlocked": "The plugin page tried to leave its isolated document, loading stopped",
|
||||
"invalidQueryParameter": "Invalid query parameter",
|
||||
"queryParametersExceedKib": "Query parameters exceed 8 KiB",
|
||||
"invalidBody": "Request body is invalid or exceeds 1 MiB",
|
||||
"routesDoNotAcceptRequestBody": "{method} routes do not accept a request body",
|
||||
"contentTypeIsInvalid": "Content-Type is invalid",
|
||||
"unregisteredContentType": "Content-Type is not registered for this plugin route",
|
||||
"contentTypeRequired": "Requests with a body must declare Content-Type",
|
||||
"invalidRequestParameters": "Invalid request parameters",
|
||||
"unregisteredRequest": "Request is not registered in the current plugin version",
|
||||
"invalidCallbackTicket": "Invalid callback ticket parameters",
|
||||
"unregisteredCallback": "Callback path is not registered in the current plugin version",
|
||||
"invalidTicketLifetime": "Callback ticket lifetime must be 1–600 seconds",
|
||||
"invalidModelRequest": "Invalid model request parameters",
|
||||
"clientkeyidIsInvalid": "clientKeyId is invalid",
|
||||
"invalidModelBody": "Responses request body is invalid or exceeds 8 MiB",
|
||||
"invalidModelJson": "Responses request body is not valid JSON",
|
||||
"modelObjectRequired": "Responses request body must be a JSON object",
|
||||
"pageDidNotContinueToReadModel": "The page did not continue to read the model response for 30 seconds",
|
||||
"modelConcurrencyLimit": "Model request concurrency limit reached",
|
||||
"duplicateModelRequest": "Duplicate model request ID",
|
||||
"modelTimeout": "Model request exceeded 10 minutes",
|
||||
"unsupportedModelContentType": "Model endpoint returned an unsupported content type",
|
||||
"modelRequestFailed": "Model request failed",
|
||||
"invalidPullId": "Invalid model response pull ID",
|
||||
"concurrentPull": "A model response pull is already in progress",
|
||||
"stalePullId": "Model response pull ID is stale",
|
||||
"modelResponseReadFailed": "Model response read failed",
|
||||
"duplicateManagementRequest": "Duplicate plugin management request ID",
|
||||
"managementConcurrencyLimit": "Plugin management concurrency limit reached",
|
||||
"invalidEntryPoint": "Plugin page entry point is not a registered HTML resource",
|
||||
"unregisteredAsset": "Plugin page references an unregistered resource: {path}",
|
||||
"htmlSubresource": "Plugin HTML resources cannot be loaded as subresources",
|
||||
"cyclicCss": "Cyclic plugin CSS import: {path}",
|
||||
"invalidVersion": "Invalid plugin page version, refresh and try again",
|
||||
"resourceCountLimit": "Plugin page resource count exceeds the limit",
|
||||
"pageChanged": "Plugin page changed, refresh and try again",
|
||||
"pluginAssetReturnedHttp": "Plugin asset returned HTTP {status}",
|
||||
"resourceTypeMismatch": "Plugin resource type differs from its registration: {path}",
|
||||
"pluginAssetExceedsMib": "Plugin asset exceeds 1 MiB: {path}",
|
||||
"resourceSizeLimit": "Plugin page resources exceed 8 MiB in total",
|
||||
"unsupportedElement": "Plugin page uses an unsupported {'<'}{value}{'>'} element",
|
||||
"redirectForbidden": "Plugin pages cannot redirect automatically",
|
||||
"moduleScriptUnsupported": "Plugin pages currently require classic script bundles, ES modules are not supported",
|
||||
"invalidPluginScriptAssetType": "Invalid plugin script asset type: {path}",
|
||||
"unsupportedLink": "Plugin pages support stylesheet and icon links only",
|
||||
"invalidStylesheet": "Invalid plugin stylesheet resource type: {path}",
|
||||
"invalidPluginIconAssetType": "Invalid plugin icon asset type: {path}",
|
||||
"unsupportedSrc": "Plugin pages do not support src loading for {'<'}{value}{'>'}",
|
||||
"invalidPluginImageAssetType": "Invalid plugin image asset type: {path}",
|
||||
"invalidPluginPosterAssetType": "Invalid plugin poster asset type: {path}",
|
||||
"emptySrcset": "Empty resource reference in plugin srcset",
|
||||
"externalNavigation": "Plugin pages cannot navigate to external or unregistered URLs",
|
||||
"pluginPageDoesNotSupportUrls": "The plugin page does not support {name} URLs",
|
||||
"externalAttribute": "Plugin page attribute references an external resource: {name}",
|
||||
"unsupportedPluginCssSyntax": "Unsupported plugin CSS syntax: {ownerPath}",
|
||||
"invalidCss": "Unable to parse plugin CSS: {ownerPath}",
|
||||
"escapedCssIdentifier": "Plugin CSS rule and function names cannot contain escapes: {ownerPath}",
|
||||
"inlineStyleImport": "Inline style attributes cannot import stylesheets",
|
||||
"unsupportedPluginImportSyntax": "Unsupported plugin {'@'}import syntax: {ownerPath}",
|
||||
"pluginImportTargetIsNotCss": "Plugin {'@'}import target is not CSS: {path}",
|
||||
"unsupportedPluginAssetUrl": "Unsupported plugin asset URL: {rawReference}",
|
||||
"resourceQuery": "Plugin resource URLs cannot contain query parameters: {rawReference}",
|
||||
"resourceFragment": "Plugin resource URLs cannot contain fragments: {rawReference}",
|
||||
"resourceOutsideArtifact": "Plugin resource URL leaves the artifact boundary: {rawReference}",
|
||||
"invalidPluginAssetPathSegment": "Invalid plugin asset path segment: {rawReference}",
|
||||
"invalidResourcePath": "Plugin registered an invalid resource path: {path}",
|
||||
"pluginTextAssetIsNotValidUtf": "Plugin text asset is not valid UTF-8: {path}"
|
||||
},
|
||||
"pluginPage": "Plugin page",
|
||||
"page": {
|
||||
"configurationDescription": "Use plugin features with configuration “{name}”",
|
||||
"description": "Open management pages from enabled plugins",
|
||||
"unpublished": "This configuration or page is unavailable, it may have been disabled or switched to another version",
|
||||
"refreshFailed": "Failed to refresh the page directory, showing the last loaded version: {loadError}",
|
||||
"loadingPage": "Loading page"
|
||||
},
|
||||
"refreshPage": "Refresh page",
|
||||
"pluginPageIsUnavailable": "Plugin page is unavailable",
|
||||
"returnToPluginManagement": "Return to plugin management",
|
||||
"resources": {
|
||||
"unavailable": "Unavailable · {id}",
|
||||
"multipleSelectionsAllowed": "{label} (multiple selections allowed)",
|
||||
"unlimitedPlaceholder": "Unlimited, multiple selections allowed",
|
||||
"loading": "Loading…",
|
||||
"isTemporarilyUnavailable": "{label} is temporarily unavailable",
|
||||
"noMatches": "No matches",
|
||||
"no": "No {label}",
|
||||
"createOneInFirst": "Create one in {value} first"
|
||||
},
|
||||
"rollback": {
|
||||
"rollBackPluginVersion": "Roll back plugin version",
|
||||
"description": "Restore the version's settings while keeping its enabled state",
|
||||
"targetVersion": "Target version",
|
||||
"fallbackInstructions": "Fallback instructions",
|
||||
"restoreHelp": "Restore parameters and secrets from when this version was last enabled, private data must still pass compatibility checks",
|
||||
"loadingOlderVersions": "Loading older versions…",
|
||||
"selectRollbackVersion": "Select a rollback version",
|
||||
"rollBackToTargetVersion": "Roll back to target version",
|
||||
"empty": "No older version has restore settings, use Versions to switch to other versions",
|
||||
"reload": "Reload",
|
||||
"confirmRollback": "Confirm rollback",
|
||||
"completed": "Rolled back to {version} and restored its settings"
|
||||
},
|
||||
"sourceProxy": {
|
||||
"noProxyDirectConnection": "No proxy (direct connection)",
|
||||
"disabledSuffix": "(disabled)",
|
||||
"catalogUnavailable": "Selected proxy, directory unavailable",
|
||||
"label": "Download proxy"
|
||||
},
|
||||
"status": {
|
||||
"unableToStart": "Unable to start",
|
||||
"runFailed": "Run failed",
|
||||
"compatibilityReminder": "Compatibility reminder",
|
||||
"deprecatedApi": "API upgrade needed, currently compatible",
|
||||
"startupUnverified": "Startup can be attempted, runtime behavior still needs verification",
|
||||
"compatibilityWindow": "The old API remains supported for at least {remainingReleases} stable releases",
|
||||
"compatibilityEnding": "The compatibility window has ended, a future stable release will remove the old API adapter",
|
||||
"unsupportedVersionHelp": "Configuration and data are kept, install a supported plugin version",
|
||||
"restartHelp": "The enabled configuration is kept, restart it in plugin details",
|
||||
"upgradeHelp": "Update the plugin or ask its author to upgrade the API"
|
||||
},
|
||||
"updates": {
|
||||
"packageRequired": "Select a plugin package to confirm its version and compatibility",
|
||||
"currentlyUsingThisVersion": "Currently using this version",
|
||||
"verifiedUpdate": "New version found and package verified",
|
||||
"sameVersionDifferentContent": "Same version number, different package contents",
|
||||
"noHigherVersionFound": "No higher version found",
|
||||
"pluginUpdate": "Plugin update",
|
||||
"checkingDescription": "Checking the version and verifying the package…",
|
||||
"versionComparison": "Version comparison",
|
||||
"postTag": "Post tag",
|
||||
"updateInspectionInstructions": "Update inspection instructions",
|
||||
"configurationHelp": "Compare the package version and reuse current settings, incompatible settings keep the current version active and open settings",
|
||||
"trustNotice": "Plugins can access all gateway data and settings, verify the source before updating",
|
||||
"thereIsNoTarGzOrTgzPlugin": "There is no tar.gz or tgz plugin package for this release",
|
||||
"upgradeTo": "Upgrade to {version}",
|
||||
"continueInstallation": "Continue installation",
|
||||
"unsupportedSource": "This source does not support update checks, install a new version manually",
|
||||
"sourceChanged": "Installation source changed, check again",
|
||||
"checkForUpdatesFailed": "Check for updates failed"
|
||||
},
|
||||
"versionDetails": "Version details",
|
||||
"toBeInstalled": "To be installed",
|
||||
"historicalConfiguration": "Historical configuration",
|
||||
"referenceConfiguration": "Reference configuration",
|
||||
"versions": {
|
||||
"detailsLabel": "Version {version} details",
|
||||
"historicalVersion": "Historical version"
|
||||
},
|
||||
"install": "Install {version}",
|
||||
"deleteVersion": "Delete version {version}",
|
||||
"credentials": {
|
||||
"selectDownloadCredentials": "Select download credentials {name}",
|
||||
"deleteDownloadCredentials": "Delete download credentials {name}",
|
||||
"saveDownloadCredentialsFailed": "Failed to save download credentials",
|
||||
"sourceCredentialsDeleted": "Source credentials deleted",
|
||||
"deleteFailed": "Failed to delete source credentials"
|
||||
},
|
||||
"artifacts": {
|
||||
"pluginProductHasBeenDeleted": "plugin product has been deleted",
|
||||
"pluginProductDeletionFailed": "plugin product deletion failed"
|
||||
},
|
||||
"instances": {
|
||||
"saveFailed": "Failed to save plugin configuration",
|
||||
"versionMissing": "The selected version no longer exists, select another version",
|
||||
"loadFailed": "Failed to load enabled configuration",
|
||||
"configurationEnablementFailed": "Configuration enablement failed",
|
||||
"switchedCurrentConfiguration": "Switched current configuration",
|
||||
"pluginSettingsApplied": "Plugin settings applied",
|
||||
"savedDisabled": "Settings saved, plugin remains disabled",
|
||||
"pluginDisabled": "Plugin disabled",
|
||||
"pluginDeactivationFailed": "Plugin deactivation failed",
|
||||
"deleted": "Configuration, secrets, and private data permanently deleted",
|
||||
"pluginInstanceDeletionFailed": "plugin instance deletion failed"
|
||||
},
|
||||
"uninstall": {
|
||||
"newConfiguration": "A new plugin configuration appeared, close this dialog and confirm the uninstall scope again",
|
||||
"versionChanged": "“{name}” changed versions, confirm the uninstall scope again",
|
||||
"removingConfiguration": "Disabling and deleting configuration: {name}",
|
||||
"newVersion": "Confirmed items deleted, newly installed versions remain, close this dialog and confirm the remaining items",
|
||||
"completed": "Plugin uninstalled, related data and source settings removed",
|
||||
"incomplete": "Uninstall incomplete, retry the remaining steps"
|
||||
},
|
||||
"deletingVersion": "Deleting version: {version}",
|
||||
"switchedTo": "Switched to {version}",
|
||||
"versionSettingFailedToLoad": "Version setting failed to load",
|
||||
"versionSwitchingFailed": "Version switching failed",
|
||||
"fallbackVersionLoadingFailed": "Fallback version loading failed",
|
||||
"pluginVersionRollbackFailed": "plugin version rollback failed",
|
||||
"fields": {
|
||||
"requestCompletionAndUsage": "Request completion and usage",
|
||||
"upstreamWebsocketEvents": "Upstream WebSocket events",
|
||||
"requestScheduling": "Request scheduling",
|
||||
"modelRouting": "Model routing",
|
||||
"modelCatalog": "Model catalog",
|
||||
"retryStrategy": "Retry strategy",
|
||||
"requestMiddleware": "Request middleware",
|
||||
"upstreamAdapter": "Upstream adapter",
|
||||
"eventObservation": "Event observation",
|
||||
"commandLine": "Command line",
|
||||
"manageExtensions": "Manage extensions",
|
||||
"maintenanceTasks": "Maintenance tasks",
|
||||
"httpRequest": "HTTP request",
|
||||
"allHttpRequests": "All HTTP requests",
|
||||
"websocketMessages": "WebSocket messages",
|
||||
"allWebsocketMessages": "All WebSocket messages",
|
||||
"serviceCall": "Service call",
|
||||
"allServiceCalls": "All service calls",
|
||||
"requestToStart": "Request to start",
|
||||
"everyTry": "Every try",
|
||||
"upstreamCall": "Upstream call",
|
||||
"accountScheduling": "Account scheduling",
|
||||
"retryDecision": "Retry decision",
|
||||
"toBeConfigured": "To be configured",
|
||||
"deactivated": "Deactivated",
|
||||
"waitingForItToTakeEffect": "Waiting for it to take effect"
|
||||
},
|
||||
"validation": {
|
||||
"suppliedWithVersion": "Supplied with version",
|
||||
"localUpload": "Local upload",
|
||||
"fixedUrl": "Fixed URL",
|
||||
"releaseList": "Release list",
|
||||
"noRemoteUpdateSource": "No remote update source"
|
||||
},
|
||||
"onePerLine": "One item per line"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
{
|
||||
"proxies": {
|
||||
"accounts": {
|
||||
"platformType": "Provider",
|
||||
"subscription": "Plan",
|
||||
"noMatches": "No matching accounts, try another name or email address",
|
||||
"empty": "No linked accounts",
|
||||
"linkAccount": "Linked accounts",
|
||||
"searchAssociatedAccounts": "Search associated accounts",
|
||||
"searchAccountNameOrEmail": "Search account name or email",
|
||||
"removeAction": "Remove account from this proxy",
|
||||
"removeAssociatedAccount": "Remove associated account",
|
||||
"remove": "Remove",
|
||||
"removeDescription": "Removing “{name}” from “{removeProxyName}” will switch the account to a direct connection",
|
||||
"removed": "Account removed from this proxy, using a direct connection"
|
||||
},
|
||||
"actions": {
|
||||
"test": "Test proxy",
|
||||
"edit": "Edit proxy",
|
||||
"moreActionsFor": "More actions for {name}",
|
||||
"disableProxy": "Disable proxy",
|
||||
"enableProxy": "Enable proxy",
|
||||
"deleteProxy": "Delete proxy",
|
||||
"testInProgress": "A proxy test is running, wait for it to finish",
|
||||
"testFailed": "Proxy test failed",
|
||||
"connectedWithDetails": "{name}: connected, {message}",
|
||||
"timeZoneMismatch": "{name}: connected, IPv4 and IPv6 exit time zones differ",
|
||||
"connected": "{name}: connected",
|
||||
"fillInProxyConnectionAddress": "Please fill in the proxy connection address",
|
||||
"connectedInMs": "Connected in {latencyMs} ms",
|
||||
"locationFailed": "Proxy connection failed, unable to resolve its location",
|
||||
"exitLocationFilledIn": "Exit location filled in",
|
||||
"unableToObtainExitLocation": "Unable to obtain exit location",
|
||||
"fieldsRequired": "Enter a proxy name and URL",
|
||||
"invalidConnectionLimit": "Connection limit must be an integer from 0 to 4,294,967,295",
|
||||
"saved": "Proxy saved",
|
||||
"proxyEnabled": "Proxy enabled",
|
||||
"disabled": "Proxy disabled, linked accounts now use direct connections",
|
||||
"deleted": "Proxy deleted"
|
||||
},
|
||||
"batchCreate": {
|
||||
"proxyList": "Proxy list",
|
||||
"formatDescription": "Proxy list format",
|
||||
"supportedFormats": "Supported formats",
|
||||
"hostPortUsernamePassword": "host:port:username:password",
|
||||
"httpUsernamePasswordHostPort": "http://username:password{'@'}host:port",
|
||||
"protocolHelp": "Addresses without a protocol use the default below, complete URLs keep their own protocol",
|
||||
"ipv6Help": "Enclose IPv6 addresses in square brackets, for example",
|
||||
"onePerLineMaximum": "One per line · Maximum: {value}",
|
||||
"bulkProxyList": "Bulk proxy list",
|
||||
"totalReadyToAdd": "Total: {count}, ready to add: {count2}",
|
||||
"needsChanges": ", needs changes: {count}",
|
||||
"line": "Line {line}: {error}",
|
||||
"additionalIssues": "{count} more entries need attention",
|
||||
"defaultProtocol": "Default protocol",
|
||||
"defaultProtocolLabel": "Default protocol for addresses without one",
|
||||
"namePrefix": "Name prefix",
|
||||
"proxy": "Proxy",
|
||||
"conflict": "Proxy already exists or its configuration conflicts, existing records were kept",
|
||||
"stopped": "Remaining additions stopped"
|
||||
},
|
||||
"batchTest": {
|
||||
"resultsTitle": "Batch results",
|
||||
"processed": "Processed",
|
||||
"added": "Added: {created}",
|
||||
"invalidFormat": "Invalid format: {invalid}",
|
||||
"connected": "Connected: {succeeded}",
|
||||
"connectionFailed": "Connection failed: {failed}",
|
||||
"locationPending": "Location pending: {locationPending}",
|
||||
"needsAttention": "Needs attention: {attention}",
|
||||
"skipped": "Skipped: {skipped}",
|
||||
"scrollListOfProxyResults": "Scroll list of proxy results",
|
||||
"lineNumber": "Line {key}",
|
||||
"addedStatus": "Added",
|
||||
"connectionIsNormal": "The connection is normal",
|
||||
"stopped": "Remaining tests stopped",
|
||||
"proxyMissing": "The selected proxy no longer exists, refresh the list",
|
||||
"batchTestCompletedConnected": "Batch test completed, connected: {succeeded}",
|
||||
"unsuccessful": "Unsuccessful: {count}",
|
||||
"locationsPending": "Location pending: {locationPending}",
|
||||
"proxiesNoLongerAvailable": "Proxies no longer available: {missing}",
|
||||
"toBeExecuted": "To be executed",
|
||||
"requestFailed": "Request failed",
|
||||
"configurationConflict": "Configuration conflict",
|
||||
"testingIsBusy": "Testing is busy",
|
||||
"resultToBeConfirmed": "Result to be confirmed",
|
||||
"notExecuted": "Not executed",
|
||||
"invalidProxyFormat": "Invalid proxy format",
|
||||
"invalidAddress": "Invalid proxy host or port",
|
||||
"duplicateOfLine": "Duplicate of line {earlier}",
|
||||
"formatHelp": "Invalid format, check the format guide",
|
||||
"proxyListCannotExceedKib": "Proxy list cannot exceed 512 KiB",
|
||||
"addUpToProxiesAtTime": "Add up to {value} proxies at a time",
|
||||
"resultUnknown": "Result unconfirmed, refresh the list to check",
|
||||
"interrupted": "Request interrupted or service unavailable, refresh the list to check the result",
|
||||
"skippedAfterFailure": "Skipped because the previous operation failed"
|
||||
},
|
||||
"editor": {
|
||||
"single": "Single",
|
||||
"batch": "Batch",
|
||||
"timeZoneMismatch": "IPv4 and IPv6 exit time zones differ",
|
||||
"createTitle": "Add proxy",
|
||||
"connectionHelp": "Leave blank to keep the connection and credentials, include any required username and password in a new URL",
|
||||
"protocolHelp": "Supports HTTP, HTTPS, SOCKS5, and SOCKS5H, with optional credentials in the URL",
|
||||
"createDescription": "Add a proxy to route account traffic",
|
||||
"methodLabel": "Add method",
|
||||
"nameLabel": "Name",
|
||||
"namePlaceholder": "Enter a proxy name",
|
||||
"proxyAddress": "Address",
|
||||
"addressPlaceholder": "Enter proxy URL",
|
||||
"upstreamWsConnectionCap": "Upstream WS connection cap",
|
||||
"connectionLimitHelp": "Shared by accounts using this proxy",
|
||||
"noRestrictionsByDefault": "No restrictions by default",
|
||||
"customTimeZoneLocation": "Custom time zone location",
|
||||
"affectedAccounts": "The outgoing route will change for {count} linked accounts",
|
||||
"pendingResultsHelp": "Pending entries may be saved, refresh and check before adding more",
|
||||
"saveAction": "Save proxy",
|
||||
"waitForCurrentOperationToEnd": "Wait for the current operation to end",
|
||||
"stopSubsequentOperations": "Stop subsequent operations",
|
||||
"testing": "Testing",
|
||||
"adding": "Adding",
|
||||
"editItemsNotAdded": "Edit items not added",
|
||||
"testAddedProxies": "Test added proxies ({count})",
|
||||
"testAfterAdding": "Test after adding",
|
||||
"add": "Add ({count})",
|
||||
"addProxy": "Add proxy"
|
||||
},
|
||||
"region": {
|
||||
"connectionFailed": "Connection failed",
|
||||
"regionalConflict": "Regional conflict",
|
||||
"parsingFailed": "Parsing failed",
|
||||
"exitNotRecognized": "Exit not recognized",
|
||||
"ipv4AndIpv6EgressTimeZonesAre": "IPv4 and IPv6 egress time zones are inconsistent",
|
||||
"exitLocation": "Exit location: {label} · {timezone}",
|
||||
"detectHelp": "Resolve the exit location when testing proxies",
|
||||
"customLocation": "Custom location: {customLabel} · {timezone}",
|
||||
"custom": "Custom: {customLabel}"
|
||||
},
|
||||
"fields": {
|
||||
"exitIp": "Exit IP",
|
||||
"latency": "Latency",
|
||||
"testTime": "Tested"
|
||||
},
|
||||
"page": {
|
||||
"description": "Manage account proxies, test connections, and inspect exit IP addresses",
|
||||
"searchLabel": "Search proxies",
|
||||
"searchPlaceholder": "Search by proxy name",
|
||||
"batchTestAction": "Test proxies",
|
||||
"batchTest": "Batch test ({count})",
|
||||
"noMatches": "No matching proxies, try another name",
|
||||
"empty": "No proxies yet",
|
||||
"selectCurrentPageProxy": "Select current page proxy",
|
||||
"selectProxy": "Select proxy {name}",
|
||||
"credentialsSaved": "Proxy credentials saved",
|
||||
"underTest": "Under test",
|
||||
"ms": "{message} ({latencyMs} ms)",
|
||||
"notTested": "Not tested",
|
||||
"viewAccountsAssociatedWith": "View the {count} accounts associated with {name}",
|
||||
"disable": "Disable “{name}”?",
|
||||
"disableDescription": "New requests from linked accounts will use direct connections, proxy settings and bindings are kept and resume when reenabled",
|
||||
"delete": "Delete “{name}”?",
|
||||
"deleteDescription": "Linked accounts will be unlinked and new requests will use direct connections"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,648 @@
|
||||
{
|
||||
"settings": {
|
||||
"clientProfile": {
|
||||
"userAgent": "User agent",
|
||||
"clientIdentitySource": "Client identity source",
|
||||
"globalConfiguration": "Global configuration",
|
||||
"customConfiguration": "Custom configuration",
|
||||
"presetLoadingFailed": "Preset loading failed",
|
||||
"enterIntegerFromTo": "Enter an integer from 1 to {version}",
|
||||
"clientDefault": "Client default",
|
||||
"useCustomUserAgent": "Use a custom user agent",
|
||||
"cliEntry": "CLI entry",
|
||||
"coreDefaultIdentity": "Core · Default identity",
|
||||
"tuiInteractiveTerminal": "TUI · Interactive terminal",
|
||||
"execNonInteractiveExecution": "Exec · Non-interactive execution",
|
||||
"versionStrategy": "Version strategy",
|
||||
"followLatestVersion": "Follow the latest version",
|
||||
"customVersion": "Custom version",
|
||||
"versionLag": "Version lag",
|
||||
"versionLagHelp": "Stay 1–{version} versions behind, or leave blank to use the latest version",
|
||||
"terminalIdentification": "Terminal identification",
|
||||
"leaveBlankToUseUnknown": "Leave blank to use unknown",
|
||||
"systemVersion": "System version",
|
||||
"userAgentPlaceholder": "Enter the full user agent",
|
||||
"previewAfterFillingInVersion": "Preview after filling in the version",
|
||||
"previewIsNotAvailableYet": "Preview is not available yet",
|
||||
"resolvingClientIdentity": "Resolving client identity",
|
||||
"fixedIdentity": "Fixed identity",
|
||||
"automaticUpdates": "Automatic updates",
|
||||
"versionsBehind": "· {version} versions behind",
|
||||
"checked": "Checked {checkedAtDisplay}",
|
||||
"toBeChecked": "To be checked",
|
||||
"updateFailedUseLastVersion": "Update failed · Use the last version",
|
||||
"clientIdentityProvider": "Client identity provider",
|
||||
"upstreamIdentityPlatform": "Upstream identity platform",
|
||||
"clientId": "Client ID",
|
||||
"operatingMode": "Operating mode",
|
||||
"operatingSystem": "Operating system",
|
||||
"cpuArchitecture": "CPU architecture",
|
||||
"xaiClientIdentitySource": "xAI client identity source",
|
||||
"loadFailed": "Global configuration failed to load",
|
||||
"clientType": "Client type",
|
||||
"grokCliVersion": "Grok CLI version",
|
||||
"forExample": "For example: 1.0.13",
|
||||
"clientIdentity": "Client identity",
|
||||
"description": "Set the client type, version, and request headers the gateway sends upstream"
|
||||
},
|
||||
"pricing": {
|
||||
"multiplier": "Multiplier",
|
||||
"clearOverrides": "Clear overrides",
|
||||
"setMultipliers": "Set multipliers",
|
||||
"batch": {
|
||||
"description": "Only these {count} models will change, past costs will not be recalculated",
|
||||
"resetHelp": "Restore source or built-in prices, mark unconfigured when neither is available",
|
||||
"multiplierHelp": "Replace the current multiplier, 0–100 with up to four decimal places"
|
||||
},
|
||||
"targetMultiplier": "Target multiplier",
|
||||
"enterLegalMultiplier": "Please enter legal multiplier",
|
||||
"confirmClearOverride": "Confirm clear override",
|
||||
"confirmSettingMultiplier": "Confirm setting multiplier",
|
||||
"sourcePrice": "Source price",
|
||||
"textToken": "Text tokens",
|
||||
"validation": {
|
||||
"modelId": "Model ID must be 1–128 bytes without whitespace or control characters",
|
||||
"tierPrices": "Enter all four prices for this tier, 0–1,000,000 with up to four decimal places",
|
||||
"standardTier": "New models require standard tier prices"
|
||||
},
|
||||
"multiplierRangeIsWithUpToFour": "The multiplier range is 0~100, with up to four decimal places",
|
||||
"editModelPricing": "Edit model pricing",
|
||||
"addModelPricing": "Add model pricing",
|
||||
"upstreamModelId": "Upstream model ID",
|
||||
"forExampleGpt": "For example gpt-5.4",
|
||||
"customizedMultiplier": "Customized multiplier",
|
||||
"gearPrice": "Gear price",
|
||||
"priceRange": "Price range",
|
||||
"unitPriceSource": "Unit price source",
|
||||
"tier": {
|
||||
"sourceUnavailable": "No source prices for this tier"
|
||||
},
|
||||
"fillInUnitPrice": "Fill in the unit price",
|
||||
"pricingInstructions": "Pricing instructions",
|
||||
"modelIdUsesNameActuallySentTo": "Model ID uses the name actually sent to upstream, not the client alias",
|
||||
"customTierHelp": "Enter all four unit prices, up to 1,000,000 each; use 0 for free pricing and multipliers from 0 to 100, with up to four decimal places",
|
||||
"estimateHelp": "Affects local estimates and spending limits, not actual subscription charges, applies to new requests after saving and leaves past costs unchanged",
|
||||
"unitPrice": "{label} unit price",
|
||||
"source": "Source",
|
||||
"takeEffect": "Take effect",
|
||||
"sync": {
|
||||
"title": "Sync source prices",
|
||||
"description": "Sync source prices for selected models, keeping custom prices and multipliers",
|
||||
"skipped": "Skipped {count} models with incomplete prices or incompatible billing methods",
|
||||
"action": "Sync"
|
||||
},
|
||||
"selectAll": "Select all",
|
||||
"selected": "Selected: {count} / {count2}",
|
||||
"keepManualCoverage": "Keep manual coverage",
|
||||
"noChangeInSourcePrice": "No change in source price",
|
||||
"skipSynchronizedModels": "Skip synchronized models",
|
||||
"confirmSynchronization": "Confirm synchronization",
|
||||
"model": "Model",
|
||||
"input": "Input",
|
||||
"output": "Output",
|
||||
"cacheRead": "Cache read",
|
||||
"noMatchingModel": "No matching model",
|
||||
"selectModelOnThisPage": "Select model on this page",
|
||||
"select": "Select {model}",
|
||||
"image": "· Image",
|
||||
"editPrice": "Edit price",
|
||||
"deletePriceList": "Delete price list",
|
||||
"notSyncedYet": "Not synced yet",
|
||||
"searchModel": "Search model",
|
||||
"searchModelId": "Search model ID",
|
||||
"modelProvider": "Model provider",
|
||||
"priceSource": "Price source",
|
||||
"allSources": "All sources",
|
||||
"batchOperation": "Batch operation",
|
||||
"selectedCountLabel": "Selected",
|
||||
"item": "item",
|
||||
"setMultiplier": "Set multiplier",
|
||||
"clearOverwrite": "Clear overwrite",
|
||||
"deselect": "Deselect",
|
||||
"synchronizationInstructions": "Synchronization instructions",
|
||||
"sourceHelp": "Fetch community prices from models.dev, keeping custom prices and multipliers",
|
||||
"lastSynced": "Last synced: {syncTime}",
|
||||
"syncPriceList": "Sync price list",
|
||||
"addModel": "Add model",
|
||||
"unitHelp": "Prices in USD per million tokens, view pricing details",
|
||||
"unitPriceUnitUsdMTokens": "Unit prices in USD per million tokens",
|
||||
"priorityHelp": "Custom prices override source prices, then built-in prices, affecting local estimates and spending limits only",
|
||||
"tableHelp": "Effective standard-tier prices; image models show image token prices and struck-through values show source prices; edit a model to view other tiers",
|
||||
"priceListFailedToLoad": "Price list failed to load",
|
||||
"deleteModelPriceList": "Delete model price list",
|
||||
"deleteDescription": "Delete source and custom prices for this model, leaving past costs unchanged",
|
||||
"standard": "Standard",
|
||||
"longContextStandard": "Long context · standard",
|
||||
"longContextPriority": "Long context · Fast",
|
||||
"longContextUltrafast": "Long context · Ultrafast",
|
||||
"longContextFlex": "Long context · Flex",
|
||||
"imageToken": "Image tokens",
|
||||
"cacheWrites": "Cache writes",
|
||||
"builtInPriceList": "Built-in price list",
|
||||
"manualCoverage": "Manual coverage",
|
||||
"notConfigured": "Not configured",
|
||||
"unableToLoadPriceList": "Unable to load price list",
|
||||
"deleted": "Model price deleted",
|
||||
"manualOverrideCleared": "Manual override cleared",
|
||||
"modelPricingSaved": "Model pricing saved",
|
||||
"synced": "Source prices synced, custom prices kept",
|
||||
"unitLabel": "USD / 1M tokens"
|
||||
},
|
||||
"scheduling": {
|
||||
"roundRobin": "Round robin",
|
||||
"autoReviewSlotsHelp": "Applies to OpenAI accounts only: with a regular concurrency limit of 10 and 3 auto review slots, up to 10 regular requests and 3 auto review requests can run independently",
|
||||
"autoReviewQueueHelp": "With dedicated slots, auto review uses a separate queue that may exceed account queue capacity, while total queue capacity, queue timeout, and API key limits still apply",
|
||||
"weights": {
|
||||
"load": "Load weight",
|
||||
"loadHelp": "Higher values favor accounts with lower concurrency utilization",
|
||||
"quota": "Remaining quota weight",
|
||||
"quotaHelp": "Higher values favor accounts with more remaining quota",
|
||||
"health": "Health weight",
|
||||
"healthHelp": "Higher values favor accounts with fewer recent failures",
|
||||
"latency": "Latency weight",
|
||||
"latencyHelp": "Higher values favor accounts with faster first useful output",
|
||||
"reset": "Quota reset weight",
|
||||
"resetHelp": "Higher values favor accounts whose quota resets soon, unknown or past reset times receive no bonus",
|
||||
"queue": "Queue weight",
|
||||
"queueHelp": "When queuing is needed, higher values favor accounts with fewer waiting requests, set to 0 to use the shortest queue"
|
||||
},
|
||||
"enterValueFromToUpToOne": "Please enter a value from 0 to 10, up to one decimal place",
|
||||
"description": "Adjust account selection preferences",
|
||||
"enabledHelp": "Applies when smart scheduling is enabled",
|
||||
"about": "About {label}",
|
||||
"zeroWeightHelp": "Set to 0 to exclude a factor from scoring",
|
||||
"weightsRequired": "At least one weight must be greater than 0"
|
||||
},
|
||||
"affinity": {
|
||||
"modes": {
|
||||
"relaxed": "Relaxed",
|
||||
"preferred": "Preferred",
|
||||
"strict": "Strict",
|
||||
"relaxedHelp": "Relaxed: use the scheduling policy without preferring the session's primary account",
|
||||
"preferredHelp": "Preferred: reuse the primary account, route elsewhere temporarily if busy or unavailable, and keep the session binding",
|
||||
"strictHelp": "Strict: use one account per session, child threads wait and follow the parent thread's account switches"
|
||||
},
|
||||
"title": "Session affinity",
|
||||
"mode": "Mode",
|
||||
"description": "Account binding within a session",
|
||||
"accountAffinityInstructions": "Account affinity instructions",
|
||||
"policyHelp": "Reselection follows the current scheduling policy",
|
||||
"duration": "Binding duration",
|
||||
"durationHelp": "Renewed on successful scheduling",
|
||||
"durationHours": "Binding duration (hours)",
|
||||
"hours": "hours",
|
||||
"maxAccountSwitches": "Max account switches",
|
||||
"switchLimitHelp": "Per request, 0 disables switching"
|
||||
},
|
||||
"autoDisable": {
|
||||
"overloadProtection": "Overload protection",
|
||||
"description": "Pause scheduling and start cooldown when upstream capacity failures reach the threshold",
|
||||
"enableOverloadProtection": "Enable overload protection",
|
||||
"failureCountThreshold": "Failure threshold",
|
||||
"thresholdHelp": "Capacity failures in the counting window",
|
||||
"times": "times",
|
||||
"statisticsWindow": "Counting window",
|
||||
"windowHelp": "Extended after each failure",
|
||||
"statisticsWindowSeconds": "Counting window (seconds)",
|
||||
"seconds": "seconds",
|
||||
"cooldownTime": "Cooldown",
|
||||
"cooldownHelp": "Delay recovery if the probe fails",
|
||||
"cooldownTimeInSeconds": "Cooldown (seconds)",
|
||||
"recoveryProbeModel": "Recovery probe model",
|
||||
"probeModelHelp": "Blank uses the first available model",
|
||||
"requireSuccessfulProbe": "Require successful probe",
|
||||
"modelPlaceholder": "Auto-select model",
|
||||
"concurrencyReduction": {
|
||||
"label": "Adaptive concurrency reduction",
|
||||
"helpTitle": "About adaptive concurrency reduction",
|
||||
"description": "Lower the account's concurrency limit, recovery does not raise it automatically"
|
||||
}
|
||||
},
|
||||
"warmup": {
|
||||
"title": "Account warmup",
|
||||
"description": "Try to start quota windows for idle Codex OAuth accounts",
|
||||
"enableDailyWarmup": "Enable daily warmup",
|
||||
"executionTime": "Execution time",
|
||||
"timesPlaceholder": "HH:MM, separate times with commas",
|
||||
"scheduleLabel": "Daily warmup times",
|
||||
"modelLabel": "Warmup model",
|
||||
"modelHelp": "Required when enabled, use an available model",
|
||||
"modelPlaceholder": "Enter model name",
|
||||
"helpTitle": "About account warmup",
|
||||
"help": "Send one request to each idle Codex OAuth account at the scheduled times, starting a quota window is not guaranteed"
|
||||
},
|
||||
"adminApiKey": {
|
||||
"adminApiKey": "Admin API key",
|
||||
"description": "For external integrations with administrator access",
|
||||
"regenerate": "Regenerate",
|
||||
"generate": "Generate",
|
||||
"notGenerated": "Not generated",
|
||||
"enabledDescription": "Admin API access is enabled, the full key is shown only when generated",
|
||||
"disabledDescription": "External systems cannot currently access the admin API with an API key",
|
||||
"generatedNotice": "The full key is shown once, save it now",
|
||||
"adminApiKeyUpdated": "Admin API key updated",
|
||||
"generated": "Admin API key generated",
|
||||
"adminApiKeyDeleted": "Admin API key deleted"
|
||||
},
|
||||
"password": {
|
||||
"administratorPassword": "Administrator password",
|
||||
"description": "Used to sign in to the admin console",
|
||||
"changePassword": "Change password",
|
||||
"verifyCurrentPassword": "Verify current password",
|
||||
"sessionNotice": "All administrators must sign in again after a password change",
|
||||
"validation": {
|
||||
"minLength": "The new password must have at least 12 characters",
|
||||
"unchanged": "The new password must differ from the current password",
|
||||
"mismatch": "The new passwords do not match"
|
||||
},
|
||||
"newPasswordCannotExceedBytes": "New password cannot exceed 1024 bytes",
|
||||
"changed": "Password changed, sign in again with the new password",
|
||||
"changeAdministratorPassword": "Change administrator password",
|
||||
"changeDescription": "Verify your current password to set a new one",
|
||||
"currentPassword": "Current password",
|
||||
"enterCurrentPassword": "Enter current password",
|
||||
"newPassword": "New password",
|
||||
"passwordHelp": "At least 12 characters, a mix of letters, numbers, and symbols is recommended",
|
||||
"setNewPassword": "Set new password",
|
||||
"confirmNewPassword": "Confirm new password",
|
||||
"enterNewPasswordAgain": "Enter new password again",
|
||||
"saveAndLogInAgain": "Save and log in again"
|
||||
},
|
||||
"concurrency": {
|
||||
"title": "Concurrency",
|
||||
"accountLimit": {
|
||||
"label": "Default account concurrency",
|
||||
"help": "Used unless overridden, 0 means unlimited"
|
||||
},
|
||||
"keyQueueCapacity": "API key queue capacity",
|
||||
"keyQueueHelp": "Per API key, 0 disables queuing",
|
||||
"accountQueueCapacity": "Account queue capacity",
|
||||
"accountQueueHelp": "Per account, 0 disables queuing",
|
||||
"queueTimeoutLabel": "Queue timeout (s)",
|
||||
"queueTimeoutHelp": "Shared by both queues, 1–120 s",
|
||||
"autoReview": {
|
||||
"label": "Reserved auto review slots",
|
||||
"description": "Extra slots per OpenAI account, 0 shares regular concurrency",
|
||||
"helpTitle": "About auto review concurrency"
|
||||
},
|
||||
"queueTimeoutHelpTitle": "About queue timeout",
|
||||
"queueTimeoutDetails": "The API key and account queues share this timeout, measured from the first queue entry"
|
||||
},
|
||||
"modelMapping": "Model mapping",
|
||||
"routing": {
|
||||
"modelMapHelp": "Map client model names to the upstream models used"
|
||||
},
|
||||
"addMapping": "Add mapping",
|
||||
"loadingModelMapping": "Loading model mapping…",
|
||||
"requestModel": "Request model",
|
||||
"upstreamModel": "Upstream model",
|
||||
"upstreamModelName": "Upstream model name",
|
||||
"deleteMapping": "Delete mapping",
|
||||
"history": {
|
||||
"title": "History retention",
|
||||
"retentionHelp": "Auto-delete expired request records and statistics",
|
||||
"retentionConstraints": "Minimum 1 day, deletion is permanent",
|
||||
"retentionDaysLabel": "History retention (days)"
|
||||
},
|
||||
"retentionDays": "Retention days",
|
||||
"enterDays": "Please enter 1–31 days",
|
||||
"day": "days",
|
||||
"location": {
|
||||
"requestLocationOverride": "Request location override",
|
||||
"description": "Override time zone and location fields in Codex requests, custom locations on account proxies take precedence",
|
||||
"enableLocationOverlay": "Enable location overlay"
|
||||
},
|
||||
"quotaReset": {
|
||||
"title": "Quota reset credits",
|
||||
"enableHelp": "Enable automatic use in the account's Quota reset panel",
|
||||
"description": "Global settings for accounts with automatic use enabled",
|
||||
"thresholdHelp": "Skip automatic use when the remaining quota exceeds this threshold, leave blank for no limit",
|
||||
"weeklyQuotaLimit": "Reset credit remaining weekly quota threshold"
|
||||
},
|
||||
"advanceUsageTimeMinutes": "Advance usage time (minutes)",
|
||||
"resetCardAdvanceTime": "Reset card advance time",
|
||||
"remainingWeeklyQuotaLimit": "Remaining weekly quota limit (%)",
|
||||
"responseLimit": {
|
||||
"requestBodyLimit": "Request body limit",
|
||||
"description": "Limit decompressed request bodies for the Responses API",
|
||||
"maximumSizeAfterDecompression": "Maximum size after decompression",
|
||||
"sizeHelp": "Higher limits allow larger images and conversation history, increasing memory use",
|
||||
"maxSizeLabel": "Maximum decompressed request body size"
|
||||
},
|
||||
"rotation": {
|
||||
"title": "Scheduling",
|
||||
"customized": "Custom",
|
||||
"smartSchedulingSettings": "Smart scheduling settings",
|
||||
"smartLabel": "Smart",
|
||||
"smartDescription": "Adjustable weights for load, remaining quota, health, and latency",
|
||||
"quotaResetLabel": "Soonest reset",
|
||||
"quotaResetDescription": "Use remaining quota on accounts closest to reset",
|
||||
"roundRobinLabel": "Round robin",
|
||||
"roundRobinDescription": "Cycle through available accounts in order",
|
||||
"stickyLabel": "Sticky",
|
||||
"stickyDescription": "Reuse the most recent account until unavailable"
|
||||
},
|
||||
"access": {
|
||||
"accessRestrictions": "Access restrictions",
|
||||
"deleteAdminApiKey": "Delete Admin API key",
|
||||
"deleteKeyDescription": "External systems will lose admin API access through this key",
|
||||
"areYouSureYouWantToDelete": "Are you sure you want to delete the current administrator API key? This operation will take effect immediately"
|
||||
},
|
||||
"tokenRefresh": {
|
||||
"title": "Credential refresh",
|
||||
"leadTimeLabel": "Refresh lead time (s)",
|
||||
"leadTimeHelp": "Refresh access tokens before they expire",
|
||||
"concurrencyLabel": "Refresh concurrency limit",
|
||||
"concurrencyHelp": "Concurrent refresh limit, lower to reduce rate limiting"
|
||||
},
|
||||
"backup": {
|
||||
"fileName": "Filename",
|
||||
"size": "Size",
|
||||
"expirationTime": "Expires",
|
||||
"triggerMode": "Trigger",
|
||||
"startTime": "Started",
|
||||
"manual": "Manual",
|
||||
"plan": "Plan",
|
||||
"exclusions": "Excludes request details and logs",
|
||||
"backupRecords": "Backup records",
|
||||
"backupScopeDescription": "Backup scope description",
|
||||
"contents": "Includes accounts, API keys, settings, plugins, and consumed quota",
|
||||
"usageRetentionHourSummary": "Usage retention hour summary",
|
||||
"creating": "Creating…",
|
||||
"createBackup": "Create backup",
|
||||
"noBackupRecordYet": "No backup record yet",
|
||||
"downloadBackup": "Download backup",
|
||||
"deleteBackup": "Delete backup",
|
||||
"deleteWarning": "The remote object and backup record will be deleted, this cannot be undone",
|
||||
"deleteConfirmation": "Delete this backup?",
|
||||
"message": "?",
|
||||
"schedule": {
|
||||
"backupPlan": "Backup plan",
|
||||
"description": "Set automatic backup times and retention limits",
|
||||
"saving": "Saving…",
|
||||
"enableScheduledBackup": "Enable scheduled backup",
|
||||
"cronExpression": "Cron expression",
|
||||
"cronHelp": "Five-field cron expression, for example 0 2 * * * runs daily at 02:00",
|
||||
"retentionDaysHelp": "Delete older backups, 0 disables age limits, count limits still apply",
|
||||
"retentionDaysLabel": "Retention (days)",
|
||||
"maxBackupsLabel": "Max backups",
|
||||
"retentionCountHelp": "Delete excess backups, 0 disables count limits, age limits still apply"
|
||||
},
|
||||
"status": {
|
||||
"queuing": "Queuing",
|
||||
"exporting": "Exporting",
|
||||
"uploading": "Uploading",
|
||||
"deleting": "Deleting"
|
||||
},
|
||||
"storage": {
|
||||
"s3StorageConfiguration": "S3 storage configuration",
|
||||
"connectionTestPassed": "Connection test passed",
|
||||
"connectionTestHasNotPassed": "Connection test has not passed",
|
||||
"testing": "Testing…",
|
||||
"endpointAddress": "Endpoint address",
|
||||
"endpointHelp": "HTTPS endpoint for the S3-compatible service",
|
||||
"region": "Region",
|
||||
"regionHelp": "Use auto for R2, otherwise use the provider's region",
|
||||
"bucket": "Bucket",
|
||||
"privateBucketName": "Private bucket name",
|
||||
"objectKeyPrefix": "Object key prefix",
|
||||
"prefixHelp": "Storage path prefix for new backup objects, existing backups are unchanged",
|
||||
"credentialsLabel": "Object storage credentials",
|
||||
"objectStorageSpecificSecret": "Object storage-specific Secret",
|
||||
"forcePathStyle": "Force path-style access",
|
||||
"accessKeyId": "Access key ID",
|
||||
"secretAccessKey": "Secret access key",
|
||||
"description": "Configure S3-compatible storage, including {service}"
|
||||
},
|
||||
"r2": {
|
||||
"cloudflareR2OnboardingGuide": "Cloudflare R2 Onboarding Guide",
|
||||
"createBucket": "1. Create a bucket",
|
||||
"createApiToken": "2. Create an API token",
|
||||
"fillInConnectionParameters": "3. Fill in the connection parameters",
|
||||
"credentialsHelp": "Access key ID / Secret access key: credentials generated in the previous step",
|
||||
"forcePathStyleOff": "Force Path Style: Off",
|
||||
"completeConnectionTest": "4. Complete the connection test",
|
||||
"testDescription": "Save the configuration, then select Test connection to verify read and write permissions using a probe object, a successful test is required before enabling scheduled or manual backups, credentials are stored only on the server",
|
||||
"gotIt": "Got it",
|
||||
"bucketDescription": "In Cloudflare Dashboard, open R2 and create a private bucket such as {bucket}, keep public read access disabled",
|
||||
"tokenDescription": "In Manage API Tokens, create an object storage token with read, write, list, and delete access to the target bucket only",
|
||||
"endpointLabel": "Endpoint:",
|
||||
"regionDescription": "Region: {region} (required by R2)"
|
||||
},
|
||||
"backupTaskCreated": "Backup task created",
|
||||
"failedToDownloadBackup": "Failed to download backup",
|
||||
"backupDeletionRequested": "Backup deletion requested",
|
||||
"storageSaved": "Storage settings saved and scheduled backups paused, test the connection before reenabling them",
|
||||
"storageConfigurationSaved": "Storage configuration saved",
|
||||
"connectionVerified": "Connection test passed",
|
||||
"backupPlanSaved": "Backup plan saved"
|
||||
},
|
||||
"clientVersion": {
|
||||
"macosLinuxOfficialInstaller": "macOS/Linux · Official installer",
|
||||
"windowsInstaller": "Windows PowerShell · Official installer",
|
||||
"homebrewFirstTimeInstallation": "Homebrew · First time installation",
|
||||
"homebrewUpgrade": "Homebrew · Upgrade",
|
||||
"installOrUpgradeCodexCli": "Install or upgrade Codex CLI",
|
||||
"cliInstallHelp": "Use the command for your installation source, the official installer selects your platform architecture automatically",
|
||||
"selectInstallationSource": "Select installation source",
|
||||
"cliUpgradeHelp": "Run the same command again to upgrade to the current release",
|
||||
"viewOfficialDocumentation": "View official documentation",
|
||||
"ubuntuDebianUpgrade": "Ubuntu/Debian · Upgrade",
|
||||
"fedoraRhelUpgrade": "Fedora/RHEL · Upgrade",
|
||||
"onlineInstallationAndUpgrade": "Online installation and upgrade",
|
||||
"desktopUpgradeHelp": "Desktop apps usually update automatically, or you can reinstall from official sources",
|
||||
"officialDownloadPage": "Official download page",
|
||||
"openAiPackageHelp": "Official OpenAI installer, choose your device's architecture",
|
||||
"storePackageHelp": "Offline Microsoft Store package, choose your device's architecture",
|
||||
"msixInstallHelp": "After downloading, install or upgrade with PowerShell",
|
||||
"sizeUnknown": "Size unknown",
|
||||
"windowsOfflineInstallation": "Windows offline installation",
|
||||
"cached": "Cached",
|
||||
"refreshingDownloads": "Refreshing offline download links…",
|
||||
"refreshOfflineDownloadLinks": "Refresh offline download links",
|
||||
"loadingPackages": "Loading offline packages…",
|
||||
"packagesFailed": "Failed to load offline packages",
|
||||
"stableChannel": "Stable channel",
|
||||
"linkExpired": "Link expired: {value}",
|
||||
"downloadMsix": "Download {value} MSIX",
|
||||
"downloadPackage": "Download MSIX",
|
||||
"commandCopied": "Command copied",
|
||||
"copyCommand": "Copy command",
|
||||
"codexClientUpgrade": "Codex client upgrade",
|
||||
"guideDescription": "Select a client to view its installation and upgrade instructions",
|
||||
"clientVersionRestrictions": "Client version restrictions",
|
||||
"openGuide": "View installation and upgrade instructions",
|
||||
"codexDesktopMinimumVersion": "Codex Desktop minimum version",
|
||||
"onlyCheckDesktopVersionEG": "Only check the desktop version, e.g. 26.825.51511",
|
||||
"codexCliMinimumVersion": "Codex CLI minimum version",
|
||||
"minimumVersionHelp": "Checks standalone CLI versions only, for example 0.152.0"
|
||||
},
|
||||
"privacy": {
|
||||
"preview": {
|
||||
"enterValidRequestSampleJson": "Please enter a valid request sample JSON",
|
||||
"testRules": "Test rules",
|
||||
"description": "Run enabled draft rules in order, the sample is used only for this test",
|
||||
"requestSample": "Request sample",
|
||||
"requestPlaceholder": "Paste request JSON containing body, headers, and turnMetadata",
|
||||
"finalResult": "Final result",
|
||||
"ruleExecutionResults": "Rule execution results",
|
||||
"notEnabled": "Not enabled",
|
||||
"skipped": "Skipped"
|
||||
},
|
||||
"skipCurrentRule": "Skip current rule",
|
||||
"blockRequestFromBeingSent": "Block request from being sent",
|
||||
"privacyPolicy": "Privacy policy",
|
||||
"description": "Normalize or remove private information in Codex requests using rules",
|
||||
"enableRequestRules": "Enable request rules",
|
||||
"addRule": "Add rule",
|
||||
"addFromPreset": "Add from preset",
|
||||
"runsInListOrderRulesSteps": "Runs in list order · Rules: {count} · Steps: {count2} / 32",
|
||||
"executionFailed": "Execution failed",
|
||||
"ruleExecutionFailed": "Rule execution failed",
|
||||
"ruleExecutionInstructions": "Rule execution instructions",
|
||||
"skipHelp": "Skipping rolls back all changes from this rule and continues, this rule's redaction is not applied",
|
||||
"overrideHelp": "Allow changes to selected fields, review their effects on authentication, sessions, and tools",
|
||||
"rules": {
|
||||
"fillInRuleName": "Please fill in the rule name",
|
||||
"stepLimit": "Up to 32 steps across all rules",
|
||||
"enterFieldPathForStep": "Enter a field path for step {value}",
|
||||
"fixedValueForStepMustBeJson": "The fixed value for step {value} must be JSON, such as \"alias\", false, or 123",
|
||||
"invalidSampleFormat": "Invalid sample format",
|
||||
"ruleFormatIsInvalid": "Rule format is invalid",
|
||||
"editRule": "Edit rule",
|
||||
"description": "Configure field processing and preview privacy transformations",
|
||||
"ruleName": "Rule name",
|
||||
"namePlaceholder": "For example: Normalize workspace details",
|
||||
"currentStepSettings": "Current step settings",
|
||||
"testPreview": "Test preview",
|
||||
"previewOfEntireRule": "Preview of the entire rule",
|
||||
"ruleSkipped": "Rule skipped",
|
||||
"matches": "Matches: {matches}",
|
||||
"testThisRule": "Test this rule",
|
||||
"test": "Test",
|
||||
"testSample": "Test sample",
|
||||
"samplePlaceholder": "Paste a request sample containing body, headers, and turnMetadata",
|
||||
"afterProcessing": "After processing",
|
||||
"applyToDraft": "Apply to draft",
|
||||
"movedToPosition": "{name} moved to position {value}",
|
||||
"ruleField": "Rule",
|
||||
"scope": "Scope",
|
||||
"processingMethod": "Action",
|
||||
"reorderHelp": "Drag to reorder rules, or focus the handle and use the up and down arrow keys",
|
||||
"noRulesYetAddOneOrStart": "No rules yet, add one or start from default",
|
||||
"enableRule": "Enable rule: {name}",
|
||||
"edit": "Edit {name}",
|
||||
"delete": "Delete {name}",
|
||||
"dragToReorder": "Drag to reorder {name}"
|
||||
},
|
||||
"steps": {
|
||||
"pathPlaceholder": "For example: $.workspaces.*.associated_remote_urls.*",
|
||||
"forExampleRemotesFetchurl": "For example: $.remotes[*].fetchUrl",
|
||||
"environmentPathHelp": "Use $ to match the entire environment text",
|
||||
"forExampleMetadataWorkspace": "For example: $.metadata.workspace",
|
||||
"forExampleXClientName": "For example: x-client-name",
|
||||
"requestHeaderName": "Request header name",
|
||||
"fieldPath": "Field path",
|
||||
"fieldPathSyntax": "Field path syntax",
|
||||
"jsonPathHelp": "Supports object members, quoted keys, array indexes, and * wildcards, for example $[\"workspaces\"][\"/home/alex/demo\"]",
|
||||
"targetHelp": "Use $ for environment text and a header name for request headers",
|
||||
"commonFields": "Common fields",
|
||||
"deleteMatchHelp": "Remove only fields or array items whose values match the regular expression",
|
||||
"matchExpression": "Match expression",
|
||||
"forExampleHome": "For example: ^/home/[^/]+/",
|
||||
"forExamplePrivateOrg": "For example: private-org",
|
||||
"replaceContent": "Replace content",
|
||||
"regularSyntaxDescription": "Regular syntax description",
|
||||
"useOrForCaptureGroupsAndFor": "Use ${'{'}1{'}'} or ${'{'}name{'}'} for capture groups, and $$ for a literal $",
|
||||
"usesRustRegexSyntaxAndDoesNot": "Uses Rust regex syntax and does not support backreferences in lookahead and pattern patterns",
|
||||
"forExampleHomeUser": "For example: /home/user/",
|
||||
"forExampleTeamOrLeaveBlankTo": "For example: team, or leave blank to clear matching content",
|
||||
"fixedValueJson": "Fixed value (JSON)",
|
||||
"forExampleAnonymousNullOr": "For example: \"anonymous\", null, or {'{'}{'}'}",
|
||||
"fixedJsonLabel": "Fixed JSON value",
|
||||
"replaceAllMatches": "Replace all matches",
|
||||
"ignoreCase": "Ignore case",
|
||||
"matchMultipleLines": "Match multiple lines",
|
||||
"entireEnvironmentText": "Entire environment text",
|
||||
"fullContent": "Full content",
|
||||
"noFieldsSelected": "No fields selected",
|
||||
"deleteHelp": "Remove matching fields or array items",
|
||||
"noExpressionEntered": "No expression entered",
|
||||
"deleteAfterMatching": "Delete after matching: {value}",
|
||||
"clearMatchingContent": "Clear matching content",
|
||||
"stepMovedToPosition": "Step moved to position {value}",
|
||||
"processingSteps": "Processing steps",
|
||||
"helpTitle": "About processing steps",
|
||||
"executionOrderHelp": "Drag to reorder execution, or focus the handle and use the up and down arrow keys",
|
||||
"eachStepCanSetScopeFieldsAnd": "Each step can set the scope, fields and processing methods separately, and the next step will be processed based on the results of the previous step",
|
||||
"failureHelp": "Steps share the rule's enabled state, any failure rolls back the rule's changes before the failure policy skips or blocks the request",
|
||||
"addSteps": "Add steps",
|
||||
"reorderHelp": "Drag to reorder steps, or focus the handle and use the up and down arrow keys",
|
||||
"dragStep": "Drag step {value}: {field}",
|
||||
"step": "Step {value}: {field}, {scope}, {action}, {effect}",
|
||||
"deleteStep": "Delete step {value}: {field}"
|
||||
},
|
||||
"presets": {
|
||||
"workspaceMetadata": "Additional workspace information",
|
||||
"desktopGitInformation": "Desktop Git information",
|
||||
"automaticEnvironmentContext": "Automatic environment context",
|
||||
"specifyRequestFields": "Specify request fields",
|
||||
"specifyRequestHeader": "Specify request header",
|
||||
"regularReplacement": "Regular replacement",
|
||||
"fixedValue": "Fixed value",
|
||||
"fieldNameReplacement": "Field name replacement",
|
||||
"deleteFieldArrayItem": "Delete field/array item",
|
||||
"customFieldPath": "Custom field path",
|
||||
"gitRemoteAddress": "Git remote address",
|
||||
"workspacePathKey": "Workspace path key",
|
||||
"gitCommitId": "Git commit ID",
|
||||
"gitRemoteCollection": "Git remote collection",
|
||||
"workspaceFingerprint": "Workspace fingerprint",
|
||||
"unifyWorkspaceInformation": "Unify workspace information"
|
||||
},
|
||||
"testPlaceholder": "Run a test to see results"
|
||||
},
|
||||
"form": {
|
||||
"enterStandardSemverForExample": "Please enter a standard SemVer, for example 0.152.0",
|
||||
"exitLocationFilledIn": "Exit location filled in",
|
||||
"ipv4AndIpv6ExportTimeZonesAre": "IPv4 and IPv6 export time zones are inconsistent, please fill in manually",
|
||||
"unableToObtainExitLocation": "Unable to obtain exit location",
|
||||
"fillInModelMappingCompletely": "Please fill in the model mapping completely",
|
||||
"duplicateClientModel": "Duplicate client model: {requested}",
|
||||
"requiredSettings": "Complete concurrency, queue, credential refresh, and scheduling settings",
|
||||
"invalidAffinityDuration": "Affinity duration must be an integer from 1 to 720 hours",
|
||||
"invalidSwitchLimit": "Maximum account switches must be an integer from 0 to 31, set to 0 to disable switching",
|
||||
"invalidConcurrency": "Default account concurrency must be an integer from 0 to 4,294,967,295, set to 0 for unlimited",
|
||||
"invalidReviewConcurrency": "Auto review concurrency must be an integer from 0 to 4,294,967,295, set to 0 to share regular concurrency",
|
||||
"invalidBodyLimit": "Responses decompression limit must be a positive integer in MiB",
|
||||
"invalidQuotaThreshold": "Remaining weekly quota threshold must be an integer from 0 to 100, leave blank for no limit",
|
||||
"invalidResetLeadTime": "Reset credit lead time must be an integer from 1 to 1,440 minutes",
|
||||
"invalidRetention": "History retention must be an integer from 1 to 31 days",
|
||||
"invalidQueueSettings": "Queue capacity must be an integer from 0 to 1,000 and timeout from 1 to 120 seconds",
|
||||
"invalidClientVersion": "Enter a valid minimum client version",
|
||||
"overloadSettingsRequired": "Complete the overload protection settings",
|
||||
"invalidOverloadSettings": "Use a failure threshold of 2–1,000, a counting window of 60–3,600 seconds, and a cooldown of 300–604,800 seconds",
|
||||
"invalidProbeModel": "Probe model name must not exceed 128 characters",
|
||||
"invalidWarmupTimes": "Use HH:MM for warmup times, for example 08:00 or 08:00,13:00",
|
||||
"warmupModelRequired": "Select a model to enable warmup",
|
||||
"invalidWarmupModel": "Warmup model name must not exceed 128 characters",
|
||||
"settingsSaved": "Settings saved"
|
||||
},
|
||||
"page": {
|
||||
"tabs": {
|
||||
"runtime": "Runtime",
|
||||
"upstream": "Upstream",
|
||||
"pricing": "Pricing",
|
||||
"access": "Security",
|
||||
"backups": "Backups"
|
||||
},
|
||||
"description": "Manage scheduling, upstreams, pricing, security, history retention, and backups",
|
||||
"sectionsLabel": "Settings sections",
|
||||
"undoAllBasicSettingsChanges": "Undo all basic settings changes",
|
||||
"saveChanges": "Save changes",
|
||||
"settingsLoadingFailed": "Settings loading failed",
|
||||
"reload": "Reload",
|
||||
"basicSettings": "Basic settings"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"systemUpdate": {
|
||||
"channels": {
|
||||
"stable": {
|
||||
"label": "Stable",
|
||||
"description": "Stable releases only"
|
||||
},
|
||||
"rc": {
|
||||
"label": "RC",
|
||||
"description": "RC and stable releases"
|
||||
},
|
||||
"beta": {
|
||||
"label": "Beta",
|
||||
"description": "Beta, RC, and stable releases"
|
||||
},
|
||||
"alpha": {
|
||||
"label": "Alpha",
|
||||
"description": "All regular prereleases and stable releases"
|
||||
},
|
||||
"experimental": {
|
||||
"label": "Experimental",
|
||||
"description": "Current experimental release line only"
|
||||
},
|
||||
"loading": "Loading the current release channel…",
|
||||
"label": "Update channel",
|
||||
"help": "About update channels",
|
||||
"description": "This selection applies to the current check only, reopening uses the installed version's channel and does not install or downgrade automatically"
|
||||
},
|
||||
"feedback": {
|
||||
"available": "Update available",
|
||||
"noUpdates": "No updates available",
|
||||
"started": "Update has started"
|
||||
},
|
||||
"errors": {
|
||||
"remoteTargetMissing": "No remote target version was returned",
|
||||
"infoPending": "Wait for update information to finish loading",
|
||||
"preRestartCheck": "Pre-restart check failed",
|
||||
"restart": "Restart failed, please check again",
|
||||
"unconfirmed": "Update task has not been confirmed, check its status and try again",
|
||||
"updateFailed": "Update failed",
|
||||
"startTimeout": "Service v{version} did not start within the expected time",
|
||||
"activationTargetMissing": "No target version is pending activation"
|
||||
},
|
||||
"title": "System update",
|
||||
"description": "Check versions, read release notes, and install updates",
|
||||
"application": "Application updates",
|
||||
"releasePage": "Release page",
|
||||
"status": {
|
||||
"checkingVersion": "Checking for updates…",
|
||||
"lastFailed": "Last operation failed",
|
||||
"updating": "Updating…",
|
||||
"restarting": "Restarting",
|
||||
"checking": "Checking…",
|
||||
"restartRequired": "Restart required",
|
||||
"available": "Update available",
|
||||
"upToDate": "No updates available",
|
||||
"notChecked": "Not checked",
|
||||
"retrying": "Update status is temporarily unavailable, retrying…",
|
||||
"confirmingStart": "Checking whether the update has started…"
|
||||
},
|
||||
"targetVersion": "Target version v{version}",
|
||||
"releaseNotes": "Release notes",
|
||||
"progress": "Update progress",
|
||||
"actions": {
|
||||
"check": "Check for updates",
|
||||
"install": "Download and update",
|
||||
"continueRestart": "Continue restart",
|
||||
"restart": "Restart now"
|
||||
},
|
||||
"plugins": {
|
||||
"title": "Plugin compatibility notice",
|
||||
"description": "Keep enabled configurations and try starting each plugin after restarting",
|
||||
"incompatible": "Incompatible plugins"
|
||||
},
|
||||
"versionAfterRestart": "Version after restart",
|
||||
"confirmation": {
|
||||
"newerVersion": "A newer update is available",
|
||||
"channelChanged": "The latest version of the selected channel has changed",
|
||||
"title": "Confirm update",
|
||||
"description": "Confirm to close this dialog and update to the latest remote target version"
|
||||
},
|
||||
"logs": {
|
||||
"live": "Live",
|
||||
"disconnectedState": "Disconnected",
|
||||
"waiting": "Waiting to connect",
|
||||
"disconnected": "Update log connection lost",
|
||||
"parseFailed": "Failed to parse update logs",
|
||||
"unsupported": "This browser does not support live update logs",
|
||||
"timeout": "Update log connection timed out"
|
||||
},
|
||||
"currentVersion": "Current version",
|
||||
"latestVersion": "Latest in channel",
|
||||
"build": "Build",
|
||||
"deployment": "Deployment",
|
||||
"displayedTarget": "Displayed target",
|
||||
"remoteTarget": "Latest remote target",
|
||||
"buildTypes": {
|
||||
"release": "Release build",
|
||||
"source": "Source build",
|
||||
"dev": "Development build",
|
||||
"experimental": "Experimental build"
|
||||
},
|
||||
"deploymentModes": {
|
||||
"docker": "Docker",
|
||||
"binary": "Binary",
|
||||
"source": "From source"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
{
|
||||
"usage": {
|
||||
"health": {
|
||||
"point": {
|
||||
"serviceFailed": "Failed",
|
||||
"clientCancel": "Client cancel",
|
||||
"callerError": "Caller error",
|
||||
"requestHealthDetailsFor": "Request health details for {time}",
|
||||
"minutes": "15 min",
|
||||
"validRequestAvailability": "Valid request availability",
|
||||
"validRequest": "Valid request"
|
||||
},
|
||||
"validRequestsAvailability": "{time}, {label}, valid requests: {count}, availability: {reliabilityDisplay}",
|
||||
"hours": "hours",
|
||||
"day": "day",
|
||||
"serviceSuccessRate": "Service success",
|
||||
"notCompleted": "Incomplete",
|
||||
"requestVolume": "Requests",
|
||||
"noServiceResult": "No service result",
|
||||
"title": "Health",
|
||||
"description": "Request outcomes · {granularityText}",
|
||||
"completionRate": "Completion",
|
||||
"abnormalEnd": "Abnormal",
|
||||
"loading": "Loading requests…",
|
||||
"empty": "No requests in this range"
|
||||
},
|
||||
"billing": {
|
||||
"serviceLevel": "Service tier",
|
||||
"totalCost": "Total cost",
|
||||
"standardFee": "Standard cost",
|
||||
"textInputCost": "Text input cost",
|
||||
"inputCost": "Input cost",
|
||||
"imageInputFee": "Image input cost",
|
||||
"imageCachingCharges": "Image cache cost",
|
||||
"imageInputUnitPrice": "Image input unit price",
|
||||
"imageCacheUnitPrice": "Image cache unit price",
|
||||
"imageOutputFee": "Image output cost",
|
||||
"outputFee": "Output cost",
|
||||
"textInputUnitPrice": "Text input unit price",
|
||||
"inputUnitPrice": "Input unit price",
|
||||
"imageOutputUnitPrice": "Image output unit price",
|
||||
"outputUnitPrice": "Output unit price",
|
||||
"textCacheReadCost": "Text cache read cost",
|
||||
"cacheReadCost": "Cache read cost",
|
||||
"cacheWriteCost": "Cache write cost",
|
||||
"cacheWriteUnitPrice": "Cache write unit price",
|
||||
"fastMode": "Fast mode",
|
||||
"longContextBillingDetails": "Long-context cost details",
|
||||
"billingDetails": "Cost details",
|
||||
"viewLongContextBillingDetails": "View long-context cost details",
|
||||
"viewCostDetails": "View cost details"
|
||||
},
|
||||
"ttft": "TTFT",
|
||||
"latency": {
|
||||
"totalLatency": "Total latency",
|
||||
"viewLatencyDetails": "View latency details",
|
||||
"official": "Official",
|
||||
"local": "Local",
|
||||
"total": "Total"
|
||||
},
|
||||
"performance": {
|
||||
"ttftHelp": "TTFT: time to first token",
|
||||
"scheduling": "Scheduling",
|
||||
"admissionP95": "Admission P95",
|
||||
"accountSelectionP95": "Selection P95",
|
||||
"capacityP95": "Capacity P95",
|
||||
"decisionCoverage": "Decision coverage",
|
||||
"accountSelectionCoverage": "Selection coverage",
|
||||
"capacityCoverage": "Capacity coverage",
|
||||
"title": "Performance",
|
||||
"description": "Latency, throughput, scheduling",
|
||||
"performanceIndicators": "Performance indicators",
|
||||
"loading": "Loading performance…",
|
||||
"noTtftSamples": "No TTFT samples in this range",
|
||||
"noThroughput": "No throughput samples in this range",
|
||||
"noScheduling": "No scheduling or capacity samples in this range",
|
||||
"noLatency": "No latency samples in this range"
|
||||
},
|
||||
"reasoning": {
|
||||
"subagentRequest": "Subagent request",
|
||||
"reviewSubagentRequest": "Review subagent request"
|
||||
},
|
||||
"filters": {
|
||||
"error": "Error",
|
||||
"requestDetailType": "Request detail type",
|
||||
"label": "Usage record filters and actions",
|
||||
"refreshUsageHistory": "Refresh usage history",
|
||||
"keyName": "Key name",
|
||||
"account": "Account",
|
||||
"fieldLabel": "Request detail filter field",
|
||||
"enterFilterValue": "Enter filter value",
|
||||
"valueLabel": "Request detail filter value"
|
||||
},
|
||||
"route": {
|
||||
"compressionRequest": "Compression request"
|
||||
},
|
||||
"tokens": {
|
||||
"enterToken": "Uncached input tokens",
|
||||
"outputToken": "Output tokens",
|
||||
"cacheReadTokens": "Cache read tokens",
|
||||
"cacheWriteTokens": "Cache write tokens",
|
||||
"reasoningToken": "Reasoning tokens",
|
||||
"tokenDetails": "Token details",
|
||||
"viewTokenDetails": "View token details",
|
||||
"totalTokens": "Total tokens"
|
||||
},
|
||||
"fields": {
|
||||
"model": "Model",
|
||||
"reasoningEffort": "Effort",
|
||||
"endpoint": "Endpoint",
|
||||
"upstream": "Upstream",
|
||||
"access": "Access",
|
||||
"cost": "Cost",
|
||||
"latency": "Latency",
|
||||
"time": "Time",
|
||||
"keyName": "Key",
|
||||
"subscription": "Plan",
|
||||
"platformType": "Provider"
|
||||
},
|
||||
"outputThroughput": "Rate",
|
||||
"noValidSample": "No valid sample",
|
||||
"notReachable": "Not reachable",
|
||||
"unstable": "Unstable",
|
||||
"lowSample": "Low sample",
|
||||
"stable": "Stable",
|
||||
"future": "Future",
|
||||
"status": {
|
||||
"mappedModel": "Model sent upstream after gateway mapping: {secondary}",
|
||||
"returnedModel": "Upstream response model: {returned} (matches the mapped request model)",
|
||||
"returnedModelHelp": "Model returned by upstream: {returned}",
|
||||
"firstOutputWaiting": "First output waiting",
|
||||
"reasoningToText": "Reasoning to the text",
|
||||
"firstOneIsOutputToText": "The first one is output to the text",
|
||||
"textToCompletion": "Text to completion",
|
||||
"completedAfterFirstOutput": "Completed after first output",
|
||||
"admissionDecision": "Admission decision",
|
||||
"accountSelectionWaiting": "Account selection waiting",
|
||||
"transferDecisionWaiting": "Transfer decision wait",
|
||||
"websocketConnection": "WebSocket connection",
|
||||
"upstreamResponseHeader": "Upstream response header",
|
||||
"firstUpstreamEvent": "First upstream event",
|
||||
"accountSlotSnapshot": "Account slot snapshot",
|
||||
"processingTime": "Processing time",
|
||||
"apiOverhead": "API overhead",
|
||||
"engineTime": "Engine time",
|
||||
"upstreamPerformance": "Upstream performance",
|
||||
"requestObservation": "Request observation",
|
||||
"transport": "Transport",
|
||||
"cancelled": "Cancelled",
|
||||
"requestedModel": "Requested model: {model}"
|
||||
},
|
||||
"balanceUnavailable": "Balance unavailable",
|
||||
"quota": "Quota",
|
||||
"usage": "Usage",
|
||||
"averageTtft": "Average TTFT",
|
||||
"budget": {
|
||||
"todaySQuota": "Daily quota",
|
||||
"weeklyQuota": "Weekly quota",
|
||||
"quotaOverview": "Quota",
|
||||
"noLimit": "No limit",
|
||||
"remaining": "Remaining / {value}",
|
||||
"used": "{rate}% used",
|
||||
"usedAmount": "Used: {value}",
|
||||
"resetTime": "Resets",
|
||||
"timingStartsAfterFirstUse": "Timing starts after first use",
|
||||
"concurrencyLimit": "Concurrency",
|
||||
"requestsPerMinute": "RPM"
|
||||
},
|
||||
"header": {
|
||||
"currentKey": "Current key",
|
||||
"keyPrefix": "Key prefix",
|
||||
"keyConfiguration": "Key configuration",
|
||||
"statisticsTimeRange": "Statistics time range",
|
||||
"today": "Today",
|
||||
"lastDays": "Last 7 days",
|
||||
"lastThirtyDays": "Last 30 days",
|
||||
"automaticRefreshFrequency": "Automatic refresh frequency",
|
||||
"refreshEveryS": "Every 30 s",
|
||||
"refreshInterval": "Every 60 s",
|
||||
"pauseRefresh": "Paused",
|
||||
"refreshUsage": "Refresh usage",
|
||||
"switchTheme": "Switch theme"
|
||||
},
|
||||
"records": {
|
||||
"requestLog": "Request log",
|
||||
"currentRequestRecord": "Current request record",
|
||||
"refreshFailed": "Failed to refresh request logs, showing the last available results",
|
||||
"loadFailed": "Failed to load request logs, use the refresh button above to try again",
|
||||
"noRecordsMatchTheseFilters": "No records match these filters"
|
||||
},
|
||||
"page": {
|
||||
"cacheHitRate": "Token hit rate",
|
||||
"loadingUsage": "Loading usage",
|
||||
"usageSummaryLoading": "Usage summary loading",
|
||||
"usageTrends": "Trends",
|
||||
"changesInUsageOverTime": "Changes in usage over time",
|
||||
"requestHealthTimeline": "Request health",
|
||||
"updated": "Updated {asOfDisplay}",
|
||||
"temporarilyRetainLastResult": ", temporarily retain the last result",
|
||||
"clickRefreshAtTopToTryAgain": ", please click refresh at the top to try again",
|
||||
"description": "View usage, performance trends, and request errors",
|
||||
"dateRangeLabel": "Statistics date range, limited to the last 31 days",
|
||||
"requestDetails": "Request details",
|
||||
"recordsDescription": "Successful and failed request details",
|
||||
"failedToLoad": "Failed to load: {error}",
|
||||
"noRequestsMatchTheseFilters": "No requests match these filters",
|
||||
"viewErrorDetails": "View error details",
|
||||
"viewUsageRecordDetails": "View usage record details"
|
||||
},
|
||||
"summary": {
|
||||
"usageSummary": "Usage summary",
|
||||
"consumeTokens": "Tokens used",
|
||||
"totalRequests": "Requests",
|
||||
"totalCost": "Cost",
|
||||
"usageDetails": "Usage details"
|
||||
},
|
||||
"trends": {
|
||||
"cost": "Cost",
|
||||
"cacheHit": "Cache hit",
|
||||
"empty": "No requests in the selected range"
|
||||
},
|
||||
"configuration": {
|
||||
"copiedToClipboard": "Copied to clipboard"
|
||||
},
|
||||
"metrics": {
|
||||
"notPriced": "Not priced",
|
||||
"newInput": "Uncached input",
|
||||
"output": "Output",
|
||||
"cacheCreation": "Cache write",
|
||||
"reasoning": "Reasoning"
|
||||
},
|
||||
"firstTokenLatency": "TTFT",
|
||||
"diagnostics": {
|
||||
"downloadDiagnosticPackage": "Download diagnostic package",
|
||||
"key": "Key",
|
||||
"transport": "Transport",
|
||||
"dimensions": "Dimensions",
|
||||
"request": "Requests",
|
||||
"performance": "Performance",
|
||||
"title": "Diagnostics",
|
||||
"groupBy": "By {resultDimensionLabel}",
|
||||
"diagnosticDimension": "Diagnostic dimension",
|
||||
"noDiagnosticDataYet": "No diagnostic data yet",
|
||||
"successful": "Successful: {count}",
|
||||
"failed": "Failed: {count}",
|
||||
"failureRate": "Failure rate: {rate}",
|
||||
"retryRate": "Retry rate: {rate}",
|
||||
"retries": "Retries: {count}",
|
||||
"loading": "Loading diagnostics…",
|
||||
"empty": "No diagnostics in this range"
|
||||
},
|
||||
"cost": {
|
||||
"savings": "Savings",
|
||||
"cache": "Cache",
|
||||
"cacheSavings": "Cache savings",
|
||||
"cacheTokenProportion": "Cached tokens",
|
||||
"hitRequestRate": "Request hit rate",
|
||||
"actualCost": "Cost",
|
||||
"withoutCacheEstimate": "Without cache",
|
||||
"costEfficiency": "Costs",
|
||||
"description": "Costs, cache savings, tier premiums",
|
||||
"costView": "Cost view",
|
||||
"tierPremium": "Tier premium",
|
||||
"perSuccessfulRequest": "Cost/success",
|
||||
"costCoverage": "Cost coverage",
|
||||
"loading": "Loading costs…",
|
||||
"empty": "No cost or cache savings data in this range"
|
||||
},
|
||||
"error": {
|
||||
"noDetails": "No detailed error message was recorded",
|
||||
"platform": "Provider",
|
||||
"requestModel": "Request model",
|
||||
"upstreamModel": "Upstream model",
|
||||
"clientTransfer": "Client transfer",
|
||||
"upstreamTransport": "Upstream transport",
|
||||
"clientStatusCode": "Client status code",
|
||||
"upstreamStatusCode": "Upstream status code",
|
||||
"requestId": "Request ID",
|
||||
"upstreamRequestId": "Upstream request ID",
|
||||
"responseId": "Response ID",
|
||||
"clientKeyId": "Client key ID",
|
||||
"errorCode": "Error code",
|
||||
"failureClassification": "Failure classification",
|
||||
"duration": "Duration",
|
||||
"triggerMode": "Trigger mode",
|
||||
"sendStatus": "Send status",
|
||||
"errorDetails": "Error details",
|
||||
"description": "Failure reason and request context",
|
||||
"responseIsNotComplete": "Response is not complete",
|
||||
"requestFailed": "Request failed",
|
||||
"requestContext": "Request context",
|
||||
"errorLocation": "Error location",
|
||||
"attempts": "Attempt history",
|
||||
"attemptRecordMayBeIncomplete": "Attempt record may be incomplete",
|
||||
"attempt": "Attempt {index}",
|
||||
"diagnosticData": "Diagnostic data",
|
||||
"responseContent": "Response content",
|
||||
"metadata": "Metadata"
|
||||
},
|
||||
"insights": {
|
||||
"useStatisticalObservations": "Use statistical observations"
|
||||
},
|
||||
"request": {
|
||||
"statusCode": "Status code",
|
||||
"message": "Message",
|
||||
"upstreamTimeConsumption": "Upstream time consumption",
|
||||
"storageModel": "Storage model",
|
||||
"upstreamReturnModel": "Upstream return model",
|
||||
"clientIp": "Client IP",
|
||||
"eventType": "Event type",
|
||||
"trySerialNumber": "Try serial number",
|
||||
"accountId": "Account ID",
|
||||
"serialNumber": "Attempt",
|
||||
"result": "Result",
|
||||
"textInput": "Text input",
|
||||
"input": "Input",
|
||||
"imageOutput": "Image output",
|
||||
"textCacheRead": "Text cache read",
|
||||
"cacheRead": "Cache read",
|
||||
"cacheWrites": "Cache writes",
|
||||
"textCacheUnitPrice": "Text cache unit price",
|
||||
"cacheUnitPrice": "Cache unit price",
|
||||
"nonInferentialOutput": "Non-reasoning output",
|
||||
"totalOutput": "Total output",
|
||||
"noneYet": "None yet",
|
||||
"usageRecordDetails": "Usage record details",
|
||||
"description": "End-to-end details for a single request",
|
||||
"requestInformation": "Request information",
|
||||
"transportAndUsage": "Transport and usage",
|
||||
"modelsAndRouting": "Models and routing",
|
||||
"clientAndUpstream": "Client and upstream",
|
||||
"requestId": "Request ID",
|
||||
"incompleteDetails": "Incomplete details",
|
||||
"total": "Total",
|
||||
"requestContent": "Request content",
|
||||
"inProgress": "In progress"
|
||||
},
|
||||
"successfulRequest": "Successful requests",
|
||||
"withinFilterRange": "Within filter range",
|
||||
"inputOutput": "Input: {inputTokens} / Output: {outputTokens}",
|
||||
"cachedTokens": "Cached tokens",
|
||||
"cacheReadHit": "Cache read hit",
|
||||
"averageTimeTaken": "Average latency",
|
||||
"successfulRequestAverage": "Successful requests only",
|
||||
"usageOverview": "Usage overview",
|
||||
"noUsageRecords": "No usage records"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,620 @@
|
||||
{
|
||||
"accounts": {
|
||||
"quota": {
|
||||
"usageInThisWindow": "窗口消耗:{localUsageDisplay}",
|
||||
"quotaUsed": "额度已使用:{rate}",
|
||||
"resets": "重置时间: {resetAtDisplay}",
|
||||
"unobserved": "额度待观测",
|
||||
"dailyRequests": "日请求",
|
||||
"requests": "{localRequestLabel} {localRequestDisplay} 次",
|
||||
"h": "{duration} 小时",
|
||||
"d": "{duration} 天",
|
||||
"s": "{duration} 秒",
|
||||
"unlimited": "无限",
|
||||
"noPointsAvailableYet": "暂无可用点数",
|
||||
"quotaPoints": "额度点数",
|
||||
"point": "点",
|
||||
"requestsInThisWindow": "窗口请求:{requestDisplay} 次",
|
||||
"requestCount": "{requestDisplay} 次",
|
||||
"statisticalRange": "统计范围",
|
||||
"rolling": "滚动 {duration}",
|
||||
"awaitingData": "待观测",
|
||||
"remaining": "剩余 {remaining}%",
|
||||
"usageLimit": "使用限额",
|
||||
"reset": "重置:",
|
||||
"remainingQuota": "{label}剩余额度",
|
||||
"accountLimit": "账号额度",
|
||||
"quota": "{provider} 额度",
|
||||
"lastRefreshed": "最近刷新: {refreshedAtDisplay}",
|
||||
"viewPersonalInformation": "查看个人信息",
|
||||
"forecastWeeklyMonthlyQuota": "预测周/月额度",
|
||||
"queryUnsupported": "暂不支持查询上游额度",
|
||||
"quotaDetails": "额度详情",
|
||||
"viewDetails": "查看{detailTitle}详情",
|
||||
"details": "{detailTitle}详情",
|
||||
"statisticalMethod": "统计方式",
|
||||
"rollingWindow": "滚动窗口",
|
||||
"windowConsumption": "窗口消耗",
|
||||
"resetTime": "重置时间",
|
||||
"localTokens": "本地累计总 Token",
|
||||
"unavailableHelp": "上游额度未提供,绿色条不表示剩余额度",
|
||||
"totalTokensFor": "{windowLabelDisplay}总 Token",
|
||||
"usageRateHelp": "最近使用额度的当前已用比例",
|
||||
"usageRate": "使用率",
|
||||
"moreGroups": "另有 {count} 个额度组,可展开账号查看",
|
||||
"windows": {
|
||||
"fiveHour": "5h 额度",
|
||||
"daily": "日额度",
|
||||
"weekly": "周额度",
|
||||
"monthly": "月额度",
|
||||
"annual": "年额度",
|
||||
"usage": "用量上限",
|
||||
"secondary": "次级用量上限",
|
||||
"duration": "{duration}额度"
|
||||
}
|
||||
},
|
||||
"account": "账号",
|
||||
"connectionTest": {
|
||||
"duration": "响应耗时",
|
||||
"title": "测试连接",
|
||||
"description": "验证账号凭据、身份绑定与上游模型端点是否可用",
|
||||
"model": "测试模型",
|
||||
"refreshModels": "刷新上游模型",
|
||||
"loadingModels": "加载模型中",
|
||||
"modelPlaceholder": "选择上游模型",
|
||||
"noModels": "上游没有返回模型",
|
||||
"running": "检测中",
|
||||
"completedAt": "完成时间",
|
||||
"events": {
|
||||
"title": "事件轨迹",
|
||||
"request": "发起请求",
|
||||
"response": "接收响应内容",
|
||||
"completed": "响应完成"
|
||||
},
|
||||
"diagnostics": "原始诊断",
|
||||
"retry": "重新测试",
|
||||
"start": "开始测试",
|
||||
"errors": {
|
||||
"invalidRequest": "测试请求不合法",
|
||||
"unsupported": "当前 Provider 不支持连接测试",
|
||||
"credentials": "账号凭据无效",
|
||||
"policyRejected": "测试请求被网关策略拒绝",
|
||||
"modelNotFound": "测试模型不存在",
|
||||
"accountUnavailable": "指定账号当前不可用于连接测试",
|
||||
"capacityUnavailable": "指定账号当前没有可用容量",
|
||||
"infrastructureUnavailable": "Provider 本地基础设施暂不可用",
|
||||
"rateLimited": "上游请求过于频繁",
|
||||
"upstreamUnavailable": "上游服务暂不可用",
|
||||
"timeout": "上游请求超时",
|
||||
"canceled": "测试请求已取消",
|
||||
"internal": "网关内部错误",
|
||||
"unknown": "未分类错误",
|
||||
"failed": "测试连接失败",
|
||||
"modelRequired": "未选择模型",
|
||||
"browserUnsupported": "当前浏览器不支持连接测试",
|
||||
"missingCompletion": "测试连接未返回完成事件",
|
||||
"invalidResponse": "测试响应解析失败",
|
||||
"disconnected": "测试连接已断开"
|
||||
},
|
||||
"stages": {
|
||||
"gateway": "网关校验",
|
||||
"provider": "Provider 本地准备",
|
||||
"upstream": "上游响应"
|
||||
},
|
||||
"failed": "测试失败",
|
||||
"testing": "正在测试",
|
||||
"runningDescription": "正在向所选模型发送请求并接收流式响应",
|
||||
"successTitle": "连接正常",
|
||||
"completedDescription": "请求已完成,可在下方查看模型、耗时和事件轨迹",
|
||||
"failedDescription": "请求未完成,请在下方查看失败来源与原始诊断",
|
||||
"readyTitle": "准备测试",
|
||||
"readyDescription": "选择模型后,点击“开始测试”发送真实请求",
|
||||
"starting": "开始测试 {value}",
|
||||
"emptyResponse": "上游已完成,没有返回文本内容",
|
||||
"testCompleted": "测试完成",
|
||||
"modelsRefreshed": "已刷新 {count} 个上游模型",
|
||||
"noModelsAvailable": "没有可测试模型"
|
||||
},
|
||||
"credentials": {
|
||||
"wsFirst": "WS 优先",
|
||||
"accountName": "账号名称",
|
||||
"enterUpstreamName": "输入上游名称",
|
||||
"baseUrlHelp": "填写 API 前缀,接口路径会自动追加",
|
||||
"apiPrefix": "API 前缀",
|
||||
"apiKeyPlaceholder": "留空保留当前密钥",
|
||||
"enterUpstreamKey": "输入上游密钥",
|
||||
"transportLabel": "传输方式",
|
||||
"webSocketHelp": "WS 优先需要上游支持 Responses WebSocket",
|
||||
"nameRequired": "请输入账号名称",
|
||||
"validation": {
|
||||
"urlLength": "上游 API 地址不能超过 2048 个字符",
|
||||
"urlFormat": "请输入不含认证、查询参数或片段的 HTTP 或 HTTPS 地址",
|
||||
"urlRequired": "请输入完整的上游 API 地址",
|
||||
"apiKeyFormat": "API Key 不能包含空格或控制字符",
|
||||
"transportRequired": "请选择传输方式"
|
||||
},
|
||||
"apiKeyRequired": "请输入 API Key"
|
||||
},
|
||||
"batchEdit": {
|
||||
"title": "批量编辑账号",
|
||||
"selectionTitle": "编辑 {count} 个账号",
|
||||
"saveChanges": "保存更改",
|
||||
"proxyRequired": "请选择已通过测试的代理",
|
||||
"saved": "已更新 {count} 个账号",
|
||||
"staleAccount": "账号 {accountId} 的页面数据已失效,请重新选择"
|
||||
},
|
||||
"capacity": {
|
||||
"concurrentRequestsLimit": "账号并发占用 {value},上限 {value2}",
|
||||
"viewConcurrencyDetails": "{label},查看并发明细",
|
||||
"viewDetails": "{label},查看明细"
|
||||
},
|
||||
"concurrency": {
|
||||
"title": "并发明细",
|
||||
"description": "当前正在处理的请求",
|
||||
"unavailable": "暂时无法读取并发明细",
|
||||
"empty": "当前没有并发占用",
|
||||
"key": "密钥",
|
||||
"model": "模型",
|
||||
"sourceIp": "来源 IP",
|
||||
"startTime": "开始时间",
|
||||
"elapsed": "占用时长"
|
||||
},
|
||||
"editor": {
|
||||
"title": "编辑账号",
|
||||
"transportLabel": "上游传输方式",
|
||||
"upstreamConnection": "上游连接",
|
||||
"loadError": "上游设置读取失败",
|
||||
"notesHelp": "最多 500 字,留空可清除备注",
|
||||
"oauthUnavailable": "该账号没有 OAuth 上游设置",
|
||||
"apiKeyUnavailable": "该账号没有 API Key 上游设置",
|
||||
"saved": "账号已更新"
|
||||
},
|
||||
"filters": {
|
||||
"allGroups": "全部分组",
|
||||
"ungroupedAccounts": "未分组账号",
|
||||
"disabled": "{name}(已禁用)",
|
||||
"label": "账号筛选与操作",
|
||||
"searchLabel": "搜索账号",
|
||||
"statusLabel": "按账号状态筛选",
|
||||
"groupLabel": "按账号分组筛选",
|
||||
"deleteSelected": "删除选中 ({count})",
|
||||
"exportSelected": "导出选中 ({count})",
|
||||
"importTasks": "导入任务",
|
||||
"importAccount": "导入账号"
|
||||
},
|
||||
"modelAccess": {
|
||||
"reserve": "保留",
|
||||
"allowlist": "白名单",
|
||||
"blocklist": "黑名单",
|
||||
"modelLimitations": "模型限制",
|
||||
"refreshModel": "刷新模型",
|
||||
"modelRestrictionMode": "模型限制模式",
|
||||
"searchOrAddModels": "搜索或添加模型",
|
||||
"searchOrEnterIdAndPressEnter": "搜索或输入 ID,回车添加",
|
||||
"selectModel": "选择模型",
|
||||
"notInCurrentModelCatalog": "{id}(当前目录未返回)",
|
||||
"loadingModel": "加载模型中…",
|
||||
"noMatchingModels": "无匹配模型",
|
||||
"noModels": "暂无模型",
|
||||
"modelListLoadingFailed": "模型列表加载失败",
|
||||
"retryHint": "请刷新后重试",
|
||||
"selectOrAddAtLeastOneModel": "请至少选择或添加一个模型",
|
||||
"configureUpToModels": "最多配置 256 个模型",
|
||||
"invalidModelId": "请使用有效的精确模型 ID,不支持通配符",
|
||||
"enterValidExactModelIdUpTo": "请输入有效的精确模型 ID,最多 256 字节,不支持通配符"
|
||||
},
|
||||
"notes": {
|
||||
"viewAccountNotes": "查看账号备注",
|
||||
"title": "账号备注"
|
||||
},
|
||||
"overview": {
|
||||
"totalAccounts": "总账号",
|
||||
"accountPoolSize": "账号池规模",
|
||||
"availableAccounts": "可用账号",
|
||||
"availableHelp": "可参与调度",
|
||||
"quotaLimited": "额度受限",
|
||||
"waitingForQuota": "等待额度恢复",
|
||||
"pending": "待处理",
|
||||
"disabledError": "已停用 / 错误"
|
||||
},
|
||||
"proxy": {
|
||||
"keepCurrent": "保持当前",
|
||||
"keepExisting": "保留各账号的连接设置",
|
||||
"directConnection": "直连",
|
||||
"notUsingProxy": "不使用代理",
|
||||
"disabledSuffix": "(已禁用)",
|
||||
"testFailed": "(测试失败)",
|
||||
"notTested": "(未测试)",
|
||||
"outboundTunnel": "出站隧道"
|
||||
},
|
||||
"scheduling": {
|
||||
"scheduling": "调度",
|
||||
"switchAccountSchedule": "切换账号调度",
|
||||
"concurrencyLimit": "并发限制",
|
||||
"accountConcurrencyLimit": "账号并发限制",
|
||||
"defaultHint": "留空使用默认值",
|
||||
"weight": "权重",
|
||||
"accountSchedulingWeight": "账号调度权重",
|
||||
"weightHelp": "数值越高越优先,最高 100",
|
||||
"groupLabel": "所属分组",
|
||||
"invalidConcurrency": "并发限制必须留空,或为 1 到 {value} 的整数",
|
||||
"weightMustBeIntegerFromTo": "权重必须是 1 到 100 的整数"
|
||||
},
|
||||
"actions": {
|
||||
"deleteAccount": "删除账号",
|
||||
"moreActions": "更多操作",
|
||||
"disableScheduling": "停用",
|
||||
"enableScheduling": "启用",
|
||||
"refreshToken": "刷新令牌",
|
||||
"reauthorize": "重新授权",
|
||||
"downloadModelCatalog": "下载模型目录",
|
||||
"restoreState": "重置状态",
|
||||
"staleSelection": "所选账号数据已失效,请重新选择",
|
||||
"exportUnsupported": "所选账号包含不支持导出的平台",
|
||||
"deleted": "账号已删除",
|
||||
"deletedAccountDeletedAccounts": "已删除 {count} 个账号",
|
||||
"partialDeletion": "已删除 {count} 个账号,其余未删除:{value}",
|
||||
"batchDeletionFailed": "批量删除失败",
|
||||
"exportSelectionRequired": "请选择要导出的账号",
|
||||
"exported": "已导出 {count} 个账号",
|
||||
"exportFailed": "导出失败",
|
||||
"modelCatalogDownloadedModels": "已下载模型目录,共 {count} 个模型",
|
||||
"tokenIsBeingRefreshed": "Token 正在刷新中",
|
||||
"refreshFailed": "刷新失败",
|
||||
"tokenRefreshed": "Token 已刷新",
|
||||
"schedulingIsDisabled": "调度已停用",
|
||||
"schedulingIsEnabled": "调度已启用",
|
||||
"quotaRefreshed": "额度已刷新",
|
||||
"refreshQuotaManually": "请手动刷新额度",
|
||||
"resetRefreshFailed": "额度已重置,但最新额度加载失败:{value}",
|
||||
"statusRestored": "账号状态已恢复",
|
||||
"staleAccount": "账号 {id} 的页面数据已失效,请重新选择",
|
||||
"unsupportedProvider": "不支持的 Provider:{provider}"
|
||||
},
|
||||
"usage": {
|
||||
"call": "调用",
|
||||
"successRate": "成功率",
|
||||
"input": "输入",
|
||||
"output": "输出",
|
||||
"cache": "缓存",
|
||||
"total": "总计",
|
||||
"billing": "计费",
|
||||
"tokensStructure": "Token 用量",
|
||||
"cacheRead": "缓存读取",
|
||||
"reasoning": "推理",
|
||||
"cacheWrites": "缓存写入",
|
||||
"modelUsageRanking": "模型用量",
|
||||
"totalTokens": "总 Token",
|
||||
"totalCharge": "总计费",
|
||||
"totalCharges": "总计费:",
|
||||
"noModelUsageYet": "暂无模型用量",
|
||||
"windows": {
|
||||
"general": "累计用量",
|
||||
"weekly": "周用量",
|
||||
"monthly": "月用量",
|
||||
"quota": "周期用量"
|
||||
},
|
||||
"cost": "费用"
|
||||
},
|
||||
"onboarding": {
|
||||
"fileReadingFailedTryAgain": "文件读取失败,请重新选择",
|
||||
"uploadFiles": "上传文件",
|
||||
"authorizationExpired": "授权已过期,可重新开始或检查已完成的授权结果",
|
||||
"pollingPaused": "查询已暂停,可检查授权结果后继续",
|
||||
"regenerateAuthorizationLink": "重新生成授权链接",
|
||||
"generateAuthorizationLink": "生成授权链接",
|
||||
"authorizationLink": "授权链接",
|
||||
"copyLink": "复制链接",
|
||||
"authorizationLinkCopied": "授权链接已复制",
|
||||
"batchImport": "批量导入",
|
||||
"selectAccountPlatform": "选择账号平台",
|
||||
"accountPlatform": "账号平台",
|
||||
"maximumWordsOptional": "最多 500 字,可不填",
|
||||
"copyAccount": "复制账号",
|
||||
"accountCopied": "账号已复制",
|
||||
"howToAddAccount": "账号添加方式",
|
||||
"authorize": "授权",
|
||||
"continueImporting": "继续",
|
||||
"jsonDescription": "粘贴或上传账号 JSON,匹配已有账号时更新凭据",
|
||||
"packageDescription": "粘贴或上传 CPR 账号包,一次导入多个平台账号",
|
||||
"oauthDescription": "通过浏览器授权导入 {label} 账号",
|
||||
"apiKeyDescription": "接入 OpenAI Responses 兼容上游",
|
||||
"pasteAccessTokenLineByLineIf": "逐行粘贴 Access Token,未包含 Refresh Token 时无法自动续期",
|
||||
"refreshTokenDescription": "逐行粘贴 Refresh Token,导入时将自动换取 Access Token",
|
||||
"accountSettings": "账号设置",
|
||||
"reauthorizeAccount": "重新授权账号",
|
||||
"settingsDescription": "设置将应用于本次导入的账号",
|
||||
"reauthorizeDescription": "完成授权后更新账号凭据",
|
||||
"callbackLabel": "回调地址或授权码",
|
||||
"callbackAddress": "回调地址",
|
||||
"callbackPlaceholder": "回调地址、?code=...&state=... 或授权码",
|
||||
"callbackHelp": "打开授权链接,完成浏览器授权后粘贴回调地址或授权码",
|
||||
"pasteOneAccessTokenPerLine": "每行粘贴一个 Access Token",
|
||||
"pasteOneRefreshTokenPerLine": "每行粘贴一个 Refresh Token",
|
||||
"batchAccountFiles": "批量账号文件",
|
||||
"accountFile": "账号文件",
|
||||
"packagePlaceholder": "粘贴 CPR 多平台导出文件内容",
|
||||
"pasteAccountJsonContent": "粘贴账号 JSON 内容",
|
||||
"completeReauthorization": "完成重新授权",
|
||||
"completeImport": "完成导入",
|
||||
"invalidExpiry": "授权有效期无效,请重新生成链接",
|
||||
"linkFailed": "生成授权链接失败",
|
||||
"callbackRequired": "请粘贴回调地址或授权码",
|
||||
"authorizationFailed": "完成授权失败,可重试提交",
|
||||
"reauthorized": "账号重新授权成功",
|
||||
"accountAdded": "账号已添加",
|
||||
"providerRequired": "请选择账号平台",
|
||||
"accountPlatformIsNotSupported": "账号平台不受支持",
|
||||
"apiKeyUnsupported": "当前平台不支持 API Key 账号",
|
||||
"apiKeyAccountAdded": "API Key 账号已添加",
|
||||
"importTasksCreated": "已创建 {submitted} 个导入任务",
|
||||
"importTaskCreated": "导入任务已创建",
|
||||
"partialSubmission": "部分导入任务已创建,保持输入不变重试可继续提交",
|
||||
"accountName": "{provider} 账号",
|
||||
"failedToStartAuthorization": "启动授权失败"
|
||||
},
|
||||
"importTasks": {
|
||||
"needProcessing": "需处理",
|
||||
"importTaskDetails": "导入任务详情",
|
||||
"created": "{createdAtDisplay} 创建",
|
||||
"waitForCurrentEntryToEnd": "等待当前条目结束",
|
||||
"stopUnstartedEntries": "停止未开始条目",
|
||||
"viewAccount": "查看账号",
|
||||
"entryProgress": "条目进度",
|
||||
"accountsImported": "已入库 {importedAccounts} 个账号",
|
||||
"itemProcessingProgress": "条目处理进度",
|
||||
"itemsToBeCheckedMayHaveBeen": "待核对条目可能已入库,请先查看账号,再决定是否重新导入",
|
||||
"filterImportDetails": "筛选导入明细",
|
||||
"thereAreNoItemsToBeProcessed": "暂无需要处理的条目",
|
||||
"importEntryResults": "导入条目结果",
|
||||
"items": "{total} 个条目 · {value}",
|
||||
"description": "关闭页面后继续导入,再次打开即可查看进度",
|
||||
"progressUnavailable": "进度暂未更新:{value},恢复连接后将自动刷新",
|
||||
"loadingImportTasks": "正在读取导入任务",
|
||||
"noImportTasks": "暂无导入任务",
|
||||
"empty": "新建一次账号导入,即可在这里查看逐条入库结果",
|
||||
"switchImportTasks": "切换导入任务",
|
||||
"loadingItemResults": "正在读取条目结果",
|
||||
"selectTask": "请选择一个任务",
|
||||
"taskRetentionInstructions": "任务保留说明",
|
||||
"resultsRetainedForHour": "结果保留 1 小时",
|
||||
"retentionHelp": "服务重启后任务记录消失,已入库账号保留",
|
||||
"processing": "处理中",
|
||||
"alreadyInStock": "已入库",
|
||||
"toBeVerified": "待核对",
|
||||
"notExecuted": "未执行",
|
||||
"stopping": "正在停止",
|
||||
"importing": "导入中",
|
||||
"queuing": "排队中",
|
||||
"stopped": "已停止",
|
||||
"endedPendingItems": "已结束 · 有待处理项",
|
||||
"allDone": "全部完成",
|
||||
"savedAccountSavedAccounts": "已保存 {count} 个账号",
|
||||
"verifying": "正在校验凭据并入库",
|
||||
"waitingForExecution": "等待执行",
|
||||
"thisArticleIsNotImplemented": "本条未执行",
|
||||
"entryFailed": "本条导入未成功",
|
||||
"checkAccountList": "请检查账号列表,确认是否已入库",
|
||||
"progressReadingFailedTryAgain": "进度读取失败,请重试"
|
||||
},
|
||||
"profile": {
|
||||
"activity": {
|
||||
"quickMode": "快速模式",
|
||||
"reasoningEffort": "最常用的推理强度",
|
||||
"exploredSkills": "已探索的技能",
|
||||
"totalNumberOfSkillsUsed": "使用的技能总数",
|
||||
"totalNumberOfChats": "聊天总数",
|
||||
"activityInsights": "活动洞察",
|
||||
"pluginsAndSkills": "最常用的插件与技能",
|
||||
"runs": "{count} 次运行",
|
||||
"noToolCalls": "暂无插件或技能调用记录",
|
||||
"daily": "每日",
|
||||
"weekly": "每周",
|
||||
"cumulative": "累计",
|
||||
"tokenActivity": "Token 活动",
|
||||
"tokenActivityStatisticsMethod": "Token 活动统计方式",
|
||||
"noTokenActivityYet": "暂无 Token 活动",
|
||||
"noDailyActivity": "本次未获取到每日 Token 活动",
|
||||
"tokenActivityHeatmap": "Token 活动热力图,{rangeLabel}",
|
||||
"weekOfTokens": "{dateDisplay}所在周:{value} Tokens",
|
||||
"throughTokens": "截至{dateDisplay}:{value} Tokens"
|
||||
},
|
||||
"metrics": {
|
||||
"cumulativeNumberOfTokens": "累计 Token 数",
|
||||
"peakNumberOfTokens": "峰值 Token 数",
|
||||
"maximumChatDuration": "最长聊天时长",
|
||||
"currentConsecutiveDays": "当前连续天数",
|
||||
"longestStreak": "最长连续天数",
|
||||
"dayCount": "{integer} 天",
|
||||
"dH": "{days} 天 {hours} 小时",
|
||||
"elapsedDays": "{days} 天",
|
||||
"hMin": "{hours} 小时 {minutes} 分",
|
||||
"elapsedHours": "{hours} 小时",
|
||||
"min": "{totalMinutes} 分",
|
||||
"durationSeconds": "{value} 秒",
|
||||
"cumulativeActivitySummary": "累计活动摘要"
|
||||
},
|
||||
"accountUser": "账号用户",
|
||||
"avatarFor": "{displayName} 的头像",
|
||||
"loadingCumulativeActivity": "正在加载累计活动",
|
||||
"subscription": {
|
||||
"automaticRenewal": "自动续费",
|
||||
"noAutomaticRenewal": "不自动续费",
|
||||
"byMonth": "按月",
|
||||
"byYear": "按年",
|
||||
"subscriptionStarts": "订阅开始",
|
||||
"subscriptionEnds": "订阅结束",
|
||||
"label": "订阅",
|
||||
"renewalMethod": "续费方式"
|
||||
},
|
||||
"personalInformation": "个人信息",
|
||||
"subscriptionInformation": "订阅信息",
|
||||
"loadingSubscription": "正在加载订阅信息",
|
||||
"loadFailed": "个人信息加载失败",
|
||||
"statisticsUnavailable": "个人统计暂不可用",
|
||||
"statisticsEmpty": "本次未获取到统计数据,可以点击刷新信息重试",
|
||||
"refreshIncomplete": "本次信息刷新未完成,保留已获取的结果",
|
||||
"noSubscriptionInformationYet": "暂无订阅信息",
|
||||
"refreshInformation": "刷新信息"
|
||||
},
|
||||
"quotaForecast": {
|
||||
"tokenCapacity": "Token 容量",
|
||||
"equivalentFeeUsd": "等价费用 · USD",
|
||||
"capacityForecast": "容量预测",
|
||||
"usedThisCycle": "本周期已用",
|
||||
"preliminary": "初步估算 · 仅供参考",
|
||||
"estimateLabel": "估算值 · 仅供参考",
|
||||
"thisCycle": "本周期",
|
||||
"usedDescription": "本周期已用 {rate},其余为推算区域",
|
||||
"alreadyRecordedThisCycle": "本周期已记录",
|
||||
"equivalentCapacityOverDays": "{targetDays}天折算容量",
|
||||
"projectedTotal": "本周期预计总量",
|
||||
"loadingQuotaForecast": "正在加载额度预测",
|
||||
"weeklyQuota": "周额度",
|
||||
"monthlyQuota": "月额度",
|
||||
"windowExpired": "额度窗口已过期,请刷新账号额度后重试",
|
||||
"quotaForecast": "额度预测",
|
||||
"periodHelp": "按本周期估算,重置后重新累计",
|
||||
"forecastPeriod": "预测周期",
|
||||
"predictionLoadFailed": "预测加载失败",
|
||||
"loadFailed": "暂时无法取得预测数据,请重新加载",
|
||||
"reload": "重新加载",
|
||||
"unpredictableAtMoment": "暂时无法预测",
|
||||
"updated": "更新于 {observedAtDisplay}",
|
||||
"forecastDescription": "预测说明",
|
||||
"forReferenceOnly": "仅供参考",
|
||||
"methodDescription": "本周期预计总量为已记录用量加预计剩余,剩余量按本周期内近期用量估算",
|
||||
"limitations": "缺失的用量或费用可能使结果偏低,结果会随使用的模型和方式变化,并非官方承诺额度",
|
||||
"limitedData": "目前数据还较少,结果可能有较大波动",
|
||||
"currentPeriod": "当前周期",
|
||||
"forecastCalculatedByOverDays": "本页预测由{value}按 {targetDays} 天折算",
|
||||
"equivalentCostHelp": "预测以数据更新时间为准,等价费用不是实际账单或账户余额",
|
||||
"refreshQuota": "刷新额度"
|
||||
},
|
||||
"quotaReset": {
|
||||
"automation": {
|
||||
"confirming": "上次自动重置结果待确认,将继续核对",
|
||||
"unconfirmed": "上次自动重置结果待确认",
|
||||
"expiredUnconfirmed": "上次重置结果未能确认,卡片已到期",
|
||||
"queryFailed": "最近查询失败,将按计划重试",
|
||||
"aboveThreshold": "剩余周额度高于上限,稍后检查",
|
||||
"quotaUnavailable": "暂时无法确认周额度,稍后检查",
|
||||
"resetNotNeeded": "当前额度窗口不需要重置,稍后检查",
|
||||
"resetIncomplete": "上游未完成最近一次自动重置",
|
||||
"scheduleHelp": "每天随机查询一次,各账号错开时间",
|
||||
"verifyHelp": "临期使用前核对卡片,已在其他地方使用的会自动跳过",
|
||||
"label": "自动使用临期重置卡"
|
||||
},
|
||||
"automaticallyUseResetCard": "自动使用重置卡",
|
||||
"automaticallyUsed": "自动使用",
|
||||
"automaticUsageRules": "自动使用规则",
|
||||
"setGlobalLeadTime": "设置全局提前时间",
|
||||
"minutesInAdvance": "提前 {leadMinutes} 分钟",
|
||||
"leadTime": "提前时间",
|
||||
"nextUse": "下次使用 {nextConsumeAtDisplay}",
|
||||
"autoUsageSettingsFailedToLoad": "自动使用设置加载失败",
|
||||
"limitReset": "额度重置",
|
||||
"confirmLastReset": "确认上次重置",
|
||||
"confirmResetAmount": "确认重置额度",
|
||||
"pendingAction": "查看主动重置卡,有一项操作待确认",
|
||||
"queryFailedWithCount": "查看主动重置卡,查询失败,最近查询 {count} 张可用",
|
||||
"queryFailedLabel": "查看主动重置卡,查询失败",
|
||||
"availableCount": "查看主动重置卡,最近查询 {count} 张可用",
|
||||
"viewCredits": "查看主动重置卡",
|
||||
"useResetSelectedByUpstream": "使用一次重置(由上游选择)",
|
||||
"expires": "将于 {expiresAtDisplay} 到期",
|
||||
"expiryHelp": "有效期由上游决定",
|
||||
"querying": "查询中",
|
||||
"toBeQueried": "待查询",
|
||||
"usesAvailable": "可用 {count} 次",
|
||||
"usageReset": "用量重置",
|
||||
"thisTimeUse": "本次使用",
|
||||
"currentQuota": "当前额度",
|
||||
"operationUnconfirmed": "上次操作结果待确认",
|
||||
"confirmPrevious": "请继续确认上次重置结果",
|
||||
"continueToConfirm": "继续确认",
|
||||
"availableResetCards": "可用重置卡",
|
||||
"refreshCredits": "刷新主动重置卡",
|
||||
"resetCardLoadingFailed": "重置卡加载失败",
|
||||
"refreshRequired": "请刷新重试",
|
||||
"queryingAvailableResetTimes": "正在查询可用重置次数…",
|
||||
"useResetCredit": "使用重置:{title},{expiry}",
|
||||
"useReset": "使用重置",
|
||||
"noResetCardAvailableYet": "暂无可用重置卡",
|
||||
"confirmAgain": "再次确认",
|
||||
"confirmReset": "确认重置",
|
||||
"lastResetCompleted": "上次重置已完成",
|
||||
"resetSuccess": "额度已重置",
|
||||
"resultUnknown": "消费结果暂不确定,重试会复用同一个请求标识",
|
||||
"quotaResetFailed": "额度重置失败",
|
||||
"alreadyProcessed": "该重置操作已被处理,请先刷新重置卡列表",
|
||||
"noCredits": "当前没有可用的主动重置卡",
|
||||
"resetNotNeeded": "当前额度窗口不需要重置",
|
||||
"upstreamDeclined": "上游未执行额度重置:{code}"
|
||||
},
|
||||
"status": {
|
||||
"accountStatus": "账号状态",
|
||||
"tryNextTime": "下次尝试",
|
||||
"recommendedAction": "建议操作",
|
||||
"upstreamOriginalFeedback": "上游原始反馈",
|
||||
"forTroubleshootingOnly": "仅供排查",
|
||||
"retreating": "退避中",
|
||||
"oauthRefreshBackoff": "OAuth 刷新退避",
|
||||
"refreshFailedHelp": "刷新失败,系统正在等待下一次自动尝试",
|
||||
"retryScheduledHelp": "系统会在计划时间自动重试",
|
||||
"attentionHelp": "该账号当前状态需要关注",
|
||||
"retestHelp": "重新测试连接以获取最新状态",
|
||||
"rateLimitedHelp": "上游暂时限制了请求频率,系统正在冷却该账号",
|
||||
"cooldownHelp": "冷却结束后,系统会自动恢复调度",
|
||||
"credentialsHelp": "该账号暂不参与调度,处理凭据后可重新测试连接",
|
||||
"reauthorizeHelp": "重新授权后,账号会重新参与调度",
|
||||
"replaceCredentialsHelp": "请更新或重新导入凭据,再次测试连接",
|
||||
"upstreamRestrictionHelp": "请确认上游账号状态,解除限制后再启用",
|
||||
"capacityFailuresHelp": "容量类请求失败累计达到阈值,系统已暂停该账号的调度",
|
||||
"recoveryProbeHelp": "冷却结束后进行恢复探测,成功后恢复调度,也可手动恢复账号",
|
||||
"recoveryHelp": "冷却结束后自动恢复调度,也可手动恢复账号",
|
||||
"nextAttempt": ",下次尝试:{nextRefreshDisplay}",
|
||||
"clickOrFocusToViewDetails": "{title},{description}{retry},点击或聚焦查看详情",
|
||||
"resumeDetection": "恢复探测",
|
||||
"expectedToRecover": "预计恢复"
|
||||
},
|
||||
"fields": {
|
||||
"platformType": "平台",
|
||||
"accountGrouping": "分组",
|
||||
"lastUsed": "最后使用",
|
||||
"tokenExpires": "令牌过期",
|
||||
"quotaExhausted": "配额耗尽",
|
||||
"rateLimiting": "限流中",
|
||||
"deactivated": "已停用",
|
||||
"error": "错误",
|
||||
"identityUnconfirmed": "账号身份尚未确认",
|
||||
"accessTokenHasExpired": "Access Token 已过期",
|
||||
"credentialsHaveExpired": "凭据已过期",
|
||||
"invalidCredentials": "凭据无效",
|
||||
"accountUnavailable": "账号不可用或已被封禁",
|
||||
"count": "账号数"
|
||||
},
|
||||
"page": {
|
||||
"description": "维护账号池,查看可用性、配额与使用状态",
|
||||
"noAccountDataYet": "暂无账号数据",
|
||||
"collapseStatistics": "收起统计",
|
||||
"expandStatistics": "展开统计",
|
||||
"selectAccountOnCurrentPage": "选择当前页账号",
|
||||
"selectAccount": "选择账号",
|
||||
"deleteDescription": "删除后该账号将不再参与调度,此操作不可撤销",
|
||||
"batchDeleteDescription": "确定要删除选中的 {count} 个账号吗?此操作不可撤销",
|
||||
"thisAccount": "该账号",
|
||||
"delete": "确定要删除 {value} 吗?"
|
||||
},
|
||||
"import": {
|
||||
"jsonFormatIsIncorrect": "JSON 格式不正确",
|
||||
"documentTooLarge": "单条导入文档超过 4 MiB,请拆分文件后重试",
|
||||
"batchImportFileMustBeCprMulti": "批量导入文件必须是 CPR 多平台导出文件",
|
||||
"invalidProvider": "批量导入文件包含无效的 Provider 文档",
|
||||
"noAccounts": "批量文件没有可导入的账号文档",
|
||||
"pasteAtLeastOne": "请至少粘贴一个 {label}",
|
||||
"missingProvider": "批量导入文件不包含 {provider} 账号文档",
|
||||
"importFilesMustBeJsonObjects": "导入文件必须是 JSON 对象"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
{
|
||||
"appearance": {
|
||||
"switchToLight": "切换浅色模式",
|
||||
"switchToDark": "切换暗黑模式",
|
||||
"settings": {
|
||||
"global": "全局",
|
||||
"components": "组件",
|
||||
"invalidTheme": "主题设置无效,请检查编辑值",
|
||||
"themeSavedAndApplied": "主题已保存并应用",
|
||||
"description": "自定义当前浏览器中的管理端主题",
|
||||
"pendingChanges": "{count} 处修改待应用",
|
||||
"synced": "已同步",
|
||||
"themeEditingLevel": "主题编辑层级",
|
||||
"undoDraft": "撤销草稿",
|
||||
"restoreDefault": "恢复默认",
|
||||
"saveAndApply": "保存并应用",
|
||||
"saved": "已保存",
|
||||
"themeEditor": "主题编辑器",
|
||||
"themeTokenEditingPanel": "主题 Token 编辑面板",
|
||||
"searchToken": "搜索 Token",
|
||||
"searchPlaceholder": "搜索 Seed、Alias 或 Component Token"
|
||||
},
|
||||
"color": {
|
||||
"modified": "已修改",
|
||||
"edit": "编辑 {label}",
|
||||
"restoreDerivedValue": "恢复派生值"
|
||||
},
|
||||
"preview": {
|
||||
"components": {
|
||||
"relayAccount": "中继账号",
|
||||
"stickyHelp": "优先保持当前账号,额度耗尽后再切换",
|
||||
"notEditable": "不可编辑",
|
||||
"allPlatforms": "全部平台",
|
||||
"restricted": "受限",
|
||||
"accountAvailability": "账号可用率",
|
||||
"todaySQuota": "今日额度",
|
||||
"batchImport": "批量导入",
|
||||
"platform": "平台",
|
||||
"requestToday": "今日请求",
|
||||
"recentlyUsed": "最近使用",
|
||||
"justNow": "刚刚",
|
||||
"hoursAgo": "2 小时前",
|
||||
"componentOverview": "组件概览",
|
||||
"description": "在同一张校样板中检查控制态、数据密度与浮层关系",
|
||||
"currentThemeSemanticColor": "当前主题语义色",
|
||||
"basicControlComponents": "基础控制组件",
|
||||
"buttonsAndActions": "按钮与动作",
|
||||
"createAccount": "创建账号",
|
||||
"exportData": "导出数据",
|
||||
"dealWithItLater": "稍后处理",
|
||||
"sizeAndDisabledStatus": "尺寸与禁用状态",
|
||||
"inoperable": "不可操作",
|
||||
"processing": "处理中",
|
||||
"notification": "通知",
|
||||
"moreActions": "更多操作",
|
||||
"deleteRecord": "删除记录",
|
||||
"formsAndInput": "表单与输入",
|
||||
"searchAccount": "搜索账号",
|
||||
"choosePlatform": "选择平台",
|
||||
"accessKeyErrorExample": "访问密钥错误示例",
|
||||
"disableInputBox": "禁用输入框",
|
||||
"brandColors": "品牌颜色",
|
||||
"editBrandColors": "编辑品牌颜色",
|
||||
"schedulingNotes": "调度备注",
|
||||
"controlHeight": "控件高度",
|
||||
"componentExampleControlHeight": "组件示例控件高度",
|
||||
"choiceAndFeedbackComponents": "选择与反馈组件",
|
||||
"selectAndSwitch": "选择与切换",
|
||||
"accountView": "账号视图",
|
||||
"realTimeNotification": "实时通知",
|
||||
"automaticRotation": "自动轮换",
|
||||
"selectCurrentPage": "选择当前页",
|
||||
"partialSelection": "部分选择",
|
||||
"equilibrium": "均衡",
|
||||
"sticky": "粘性",
|
||||
"manual": "手动",
|
||||
"feedbackSemantics": "反馈语义",
|
||||
"themeSettingsSaved": "主题设置已保存",
|
||||
"quotaOfAccountsIsCloseToUpper": "3 个账号额度接近上限",
|
||||
"connectionTestFailed": "连接测试未通过",
|
||||
"schedulingNotice": "调度规则将在下次请求生效",
|
||||
"statusAndProgress": "状态与进度",
|
||||
"runningNormally": "运行正常",
|
||||
"quotaLimited": "额度受限",
|
||||
"needToBeProcessed": "需要处理",
|
||||
"synchronizing": "同步中",
|
||||
"restoreTag": "恢复标签",
|
||||
"dataTable": "数据表格",
|
||||
"tableComponents": "ZTable · ZScrollbar · ZPagination(标准行高)",
|
||||
"filterForm": "筛选表格",
|
||||
"filterAccounts": "筛选账号",
|
||||
"boundaryStateComponent": "边界状态组件",
|
||||
"emptyState": "空状态",
|
||||
"noMatchingAccountYet": "暂无匹配账号",
|
||||
"emptyHelp": "调整筛选条件,或添加一个新的上游账号",
|
||||
"addAccount": "添加账号",
|
||||
"loadingAndSkeleton": "加载与骨架",
|
||||
"synchronizingAccountStatus": "正在同步账号状态",
|
||||
"overlaysAndMenus": "浮层与菜单",
|
||||
"accountOperation": "账号操作",
|
||||
"editAccount": "编辑账号",
|
||||
"deactivateAccount": "停用账号",
|
||||
"overlayHelp": "浮层始终使用独立 Surface 与 Shadow Token",
|
||||
"eyebrow": "组件预览",
|
||||
"count": "{count} 个基础组件",
|
||||
"buttonLabel": "按钮 / 操作",
|
||||
"feedbackTypes": "成功 · 警告 · 错误 · 信息",
|
||||
"tagComponents": "ZTag · 进度 Token",
|
||||
"loadingComponents": "ZSkeleton · ZButton 加载态",
|
||||
"overlayComponents": "ZPopover · ZMenuItem · 浮层表面"
|
||||
},
|
||||
"dashboard": {
|
||||
"justUpdated": "刚刚更新",
|
||||
"demoKey": "演示 Key",
|
||||
"requestHealthTimeline": "请求健康时间线",
|
||||
"validRequestAvailability": "有效请求可用性",
|
||||
"clientId": "客户端 ID",
|
||||
"tokenAuthentication": "Token 认证",
|
||||
"todaySToken": "今日 Token",
|
||||
"hours": "5 小时",
|
||||
"requests": "08-23 {value}:00–{value2}:00 · {count} 次请求",
|
||||
"times": "次数",
|
||||
"dailyLimit": "日限额"
|
||||
},
|
||||
"homeArtboard": "首页画板",
|
||||
"themeRealTimePreview": "主题实时预览",
|
||||
"livePreview": "实时预览",
|
||||
"description": "真实组件在影子环境隔离渲染,拖动画板并缩放检查细节",
|
||||
"previewType": "预览类型",
|
||||
"canvas": {
|
||||
"homeThemePreviewArtboard": "首页主题预览画板",
|
||||
"dragBlankSpaceToPanUseScroll": "拖动空白处平移 · 滚轮缩放",
|
||||
"reduceArtboard": "缩小画板",
|
||||
"recovery": "恢复 100%",
|
||||
"enlargeArtboard": "放大画板",
|
||||
"adaptToArtboard": "适应画板"
|
||||
}
|
||||
},
|
||||
"componentTokens": {
|
||||
"cardsAndContainers": "卡片与容器",
|
||||
"dataDisplay": "数据展示",
|
||||
"navigation": "导航",
|
||||
"layoutAndScrolling": "布局与滚动",
|
||||
"mainButtonText": "主按钮文字",
|
||||
"mainButtonBackground": "主按钮背景",
|
||||
"mainButtonHover": "主按钮 Hover",
|
||||
"mainButtonActive": "主按钮 Active",
|
||||
"secondaryButtonBackground": "次要按钮背景",
|
||||
"secondaryButtonHover": "次要按钮 Hover",
|
||||
"secondaryButtonActive": "次要按钮 Active",
|
||||
"secondaryIconButtonBackground": "次要图标按钮背景",
|
||||
"secondaryIconButtonHover": "次要图标按钮 Hover",
|
||||
"secondaryIconButtonActive": "次要图标按钮 Active",
|
||||
"inputBoxBackground": "输入框背景",
|
||||
"inputBoxHover": "输入框 Hover",
|
||||
"inputBoxActive": "输入框 Active",
|
||||
"inputBoxShadow": "输入框阴影",
|
||||
"inputBoxHoverShadow": "输入框 Hover 阴影",
|
||||
"inputBoxFocusOuterCircle": "输入框焦点外圈",
|
||||
"cardBackground": "卡片背景",
|
||||
"popUpBackground": "弹窗背景",
|
||||
"floatingTitleBackground": "浮层标题背景",
|
||||
"cardRoundedCorners": "卡片圆角",
|
||||
"cardShadow": "卡片阴影",
|
||||
"tableRowHeight": "表格行高",
|
||||
"headerBackground": "表头背景",
|
||||
"lineBackground": "行背景",
|
||||
"zebraPatternBackground": "斑马纹背景",
|
||||
"rowHover": "行 Hover",
|
||||
"selectedRowBackground": "选中行背景",
|
||||
"selectRowHover": "选中行 Hover",
|
||||
"progressTrack": "进度轨道",
|
||||
"menuSelectionBackground": "菜单选中背景",
|
||||
"sidebarBackground": "侧栏背景",
|
||||
"sidebarShadow": "侧栏阴影",
|
||||
"scrollBarSlider": "滚动条滑块",
|
||||
"scrollBarHover": "滚动条 Hover",
|
||||
"componentTokenComponentFamily": "Component Token 组件族",
|
||||
"description": "调整 {label} 的 Component Token,未修改的值继续由全局 Seed / Alias 算法生成",
|
||||
"noMatchingComponentToken": "没有匹配的 Component Token",
|
||||
"kindLabel": "组件 Token"
|
||||
},
|
||||
"globalTokens": {
|
||||
"size": "尺寸",
|
||||
"style": "风格",
|
||||
"systemMode": "跟随系统",
|
||||
"lightColor": "浅色",
|
||||
"dark": "深色",
|
||||
"successColor": "成功色",
|
||||
"successFeedbackAndStatus": "成功反馈与状态",
|
||||
"warningColor": "警告色",
|
||||
"limitAndRiskReminder": "额度与风险提醒",
|
||||
"wrongColor": "错误色",
|
||||
"dangerHelp": "失败与破坏性操作",
|
||||
"informationColor": "信息色",
|
||||
"systemAndRequestInformation": "系统与请求信息",
|
||||
"linkColor": "链接色",
|
||||
"linksAndJumps": "链接与跳转",
|
||||
"basicTextColor": "基础文本色",
|
||||
"textAndInformationLevels": "正文与信息层级",
|
||||
"basicBackgroundColor": "基础背景色",
|
||||
"pageAndContainerBase": "页面与容器基底",
|
||||
"themeMode": "主题模式",
|
||||
"globalTokenClassification": "全局 Token 分类",
|
||||
"brandColorLabel": "预置主题 品牌色 colorPrimary",
|
||||
"brandColor": "品牌色",
|
||||
"presetThemes": "预置主题",
|
||||
"brandMainColor": "品牌主色",
|
||||
"paletteDescription": "完整色阶与界面基调",
|
||||
"semanticColorsTitle": "功能色与中性色",
|
||||
"derivedVariablesMapAliasToken": "派生变量 Map / Alias Token",
|
||||
"sizeToken": "尺寸 Token",
|
||||
"basicFontSize": "基础字号",
|
||||
"basicSpacing": "基础间距",
|
||||
"sizeStep": "尺寸步长",
|
||||
"styleToken": "风格 Token",
|
||||
"surfaceDescription": "固定无边设计,圆角塑形,阴影分层",
|
||||
"universalFillet": "通用圆角",
|
||||
"shadowIntensity": "阴影强度"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"auth": {
|
||||
"signOut": "退出登录",
|
||||
"adminSignIn": "管理员登录",
|
||||
"apiKeySignIn": "API Key 登录",
|
||||
"signingIn": "正在登录...",
|
||||
"signIn": "登录",
|
||||
"method": "选择登录方式",
|
||||
"title": "控制台登录",
|
||||
"welcome": "「 欢迎回来,登录以开始您的数据之旅 」",
|
||||
"username": "管理员账号",
|
||||
"usernamePlaceholder": "输入会话账号",
|
||||
"passwordPlaceholder": "输入会话密钥",
|
||||
"apiKeyPlaceholder": "输入 API Key",
|
||||
"pageLabel": "Codex Proxy RS 登录",
|
||||
"password": "密码",
|
||||
"apiKey": "API 密钥",
|
||||
"adminRealm": "管理员",
|
||||
"keyRealm": "API 密钥"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
{
|
||||
"common": {
|
||||
"errors": {
|
||||
"canceled": "请求已取消",
|
||||
"timeout": "请求超时,请稍后重试",
|
||||
"network": "网络连接失败,请检查网络后重试",
|
||||
"invalidParameters": "请求参数不合法",
|
||||
"signInRequired": "需要登录",
|
||||
"forbidden": "没有权限执行此操作",
|
||||
"notFound": "请求的接口不存在",
|
||||
"conflict": "资源状态冲突,请刷新后重试",
|
||||
"payloadTooLarge": "请求内容过大",
|
||||
"unsupportedFormat": "请求格式不受支持",
|
||||
"invalidContent": "请求内容不合法",
|
||||
"rateLimited": "请求过于频繁,请稍后重试",
|
||||
"internal": "服务内部错误",
|
||||
"upstreamFailure": "上游服务请求失败",
|
||||
"unavailable": "服务暂不可用,请稍后重试",
|
||||
"upstreamTimeout": "上游服务响应超时",
|
||||
"http": "请求失败(HTTP {status})",
|
||||
"request": "请求失败",
|
||||
"responseTooLarge": "响应内容超过大小限制",
|
||||
"unsupportedResponse": "服务返回了不受支持的响应",
|
||||
"sessionExpired": "登录已失效,请重新登录",
|
||||
"operation": "操作失败",
|
||||
"copy": "复制失败",
|
||||
"load": "加载失败",
|
||||
"malformedJson": "请求体不是合法 JSON",
|
||||
"invalidTimeRange": "时间范围不合法",
|
||||
"invalidCredentials": "登录凭据错误",
|
||||
"invalidAdminApiKey": "管理 API 密钥无效",
|
||||
"tooManyLoginAttempts": "登录尝试过多,请稍后重试",
|
||||
"upstreamResultUnknown": "上游执行结果未知,请刷新状态后再决定是否重试"
|
||||
},
|
||||
"status": {
|
||||
"disabled": "已禁用",
|
||||
"disabledName": "{name}(已禁用)",
|
||||
"success": "成功",
|
||||
"error": "异常",
|
||||
"pending": "等待中",
|
||||
"failed": "失败",
|
||||
"healthy": "正常",
|
||||
"all": "全部状态",
|
||||
"available": "可用",
|
||||
"unavailable": "不可用",
|
||||
"enabled": "已启用",
|
||||
"loading": "加载中",
|
||||
"running": "执行中",
|
||||
"completed": "已完成",
|
||||
"rateLimited": "限流"
|
||||
},
|
||||
"actions": {
|
||||
"copy": "复制",
|
||||
"close": "关闭",
|
||||
"retry": "重试",
|
||||
"cancel": "取消",
|
||||
"previous": "上一步",
|
||||
"reset": "重置",
|
||||
"back": "返回",
|
||||
"delete": "确认删除",
|
||||
"create": "创建",
|
||||
"enable": "启用",
|
||||
"next": "下一步",
|
||||
"confirm": "确定",
|
||||
"refresh": "刷新",
|
||||
"save": "保存"
|
||||
},
|
||||
"providers": {
|
||||
"all": "全部平台",
|
||||
"filter": "按平台筛选",
|
||||
"unknown": "未知平台",
|
||||
"customAuth": "自定义认证 · {normalized}",
|
||||
"unknownAuth": "未知认证类型"
|
||||
},
|
||||
"location": {
|
||||
"resolving": "正在解析出口位置",
|
||||
"detect": "解析出口位置并填入表单",
|
||||
"countryCode": "国家代码",
|
||||
"countryCodePlaceholder": "请输入两位国家代码",
|
||||
"region": "地区",
|
||||
"regionPlaceholder": "请输入地区",
|
||||
"city": "城市",
|
||||
"cityPlaceholder": "请输入城市",
|
||||
"timeZone": "IANA 时区",
|
||||
"timeZonePlaceholder": "请输入 IANA 时区",
|
||||
"required": "请填写两位国家代码、地区、城市和 IANA 时区"
|
||||
},
|
||||
"values": {
|
||||
"yes": "是",
|
||||
"no": "否",
|
||||
"unspecified": "未填写",
|
||||
"all": "全部",
|
||||
"unknown": "未知",
|
||||
"unlimited": "不限",
|
||||
"default": "默认",
|
||||
"on": "开启",
|
||||
"none": "无",
|
||||
"off": "关闭"
|
||||
},
|
||||
"form": {
|
||||
"inputPlaceholder": "输入内容",
|
||||
"useForm": "使用表单",
|
||||
"fieldHelp": "{label}说明",
|
||||
"editJson": "编辑 JSON"
|
||||
},
|
||||
"fields": {
|
||||
"actions": "操作",
|
||||
"notes": "备注",
|
||||
"status": "状态",
|
||||
"color": "颜色",
|
||||
"updatedAt": "更新时间",
|
||||
"name": "名称",
|
||||
"createdAt": "创建时间",
|
||||
"baseUrl": "基础 URL",
|
||||
"apiKey": "API 密钥",
|
||||
"build": "构建"
|
||||
},
|
||||
"language": "界面语言",
|
||||
"validation": {
|
||||
"invalidJson": "请输入有效的 JSON 对象",
|
||||
"jsonObject": "输入必须是 JSON 对象",
|
||||
"sizeLimit": "输入不能超过 {value} KiB"
|
||||
},
|
||||
"feedback": {
|
||||
"deleted": "删除成功",
|
||||
"copied": "已复制"
|
||||
},
|
||||
"time": {
|
||||
"minutesAgo": "{count} 分钟前"
|
||||
},
|
||||
"units": {
|
||||
"tokens": "Token"
|
||||
},
|
||||
"sizes": {
|
||||
"small": "小",
|
||||
"medium": "中",
|
||||
"large": "大"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"dashboard": {
|
||||
"scheduling": {
|
||||
"defaultConcurrency": "默认并发",
|
||||
"totalSlots": "总槽位",
|
||||
"freeSlots": "空闲槽位",
|
||||
"smart": "智能调度",
|
||||
"quotaReset": "额度重置优先",
|
||||
"sticky": "粘滞",
|
||||
"title": "账号调度",
|
||||
"description": "容量、并发与分配策略",
|
||||
"occupiedSlots": "槽位占用",
|
||||
"strategy": "分配策略"
|
||||
},
|
||||
"accountPool": {
|
||||
"empty": "暂无账号池观测",
|
||||
"quotaExhausted": "配额耗尽",
|
||||
"rateLimited": "限流中",
|
||||
"pending": "待处理",
|
||||
"issueCountsEmpty": "停用 — · 错误 —",
|
||||
"availableDescription": "账号当前可用",
|
||||
"exhaustedDescription": "账号额度已耗尽",
|
||||
"limitedDescription": "账号请求暂时受限",
|
||||
"issueCounts": "停用 {disabled} · 错误 {error}",
|
||||
"title": "账号状态",
|
||||
"description": "账号池健康结构",
|
||||
"healthyRate": "正常率",
|
||||
"distribution": "状态分布",
|
||||
"unavailableCount": "不可用 {value}"
|
||||
},
|
||||
"activeAccounts": {
|
||||
"title": "活跃账号用量",
|
||||
"sortByRecent": "最近使用排序",
|
||||
"empty": "暂无账号请求记录",
|
||||
"recent": "最近"
|
||||
},
|
||||
"title": "系统概览",
|
||||
"today": "当日统计",
|
||||
"refresh": {
|
||||
"action": "刷新概览",
|
||||
"failed": "刷新失败,显示上次统计",
|
||||
"unavailable": "统计暂不可用,请稍后重试",
|
||||
"lastUpdated": "自动刷新 30s,最近刷新 {updatedAt}",
|
||||
"waiting": "自动刷新 30s,等待首次刷新",
|
||||
"interval": "自动刷新 30s"
|
||||
},
|
||||
"metrics": {
|
||||
"title": "核心指标",
|
||||
"outputTokens": "输出",
|
||||
"inputTokens": "输入",
|
||||
"cachedInputTokens": "缓存",
|
||||
"cacheHits": "缓存命中",
|
||||
"requests": "请求",
|
||||
"firstTokenP95Ms": "TTFT P95",
|
||||
"latencyP95Ms": "总耗时 P95",
|
||||
"outputThroughputP50": "速率 P50",
|
||||
"errors": "错误数",
|
||||
"successRate": "成功率",
|
||||
"totalRequests": "总请求",
|
||||
"requestCount": "请求次数",
|
||||
"totalTokens": "总 Token",
|
||||
"totalCharges": "总计费",
|
||||
"totalCacheHits": "总缓存命中",
|
||||
"totalCache": "总缓存"
|
||||
},
|
||||
"comparedWithYesterday": "较昨日",
|
||||
"trends": {
|
||||
"title": "使用趋势",
|
||||
"metric": "趋势指标",
|
||||
"highlight": "突出显示{label}曲线",
|
||||
"empty": "暂无趋势数据",
|
||||
"latency": "延迟",
|
||||
"errors": "错误"
|
||||
},
|
||||
"recentRequests": {
|
||||
"title": "使用记录",
|
||||
"description": "最近 10 条成功请求",
|
||||
"empty": "暂无成功记录"
|
||||
},
|
||||
"clientIdentity": {
|
||||
"notChecked": "尚未检查",
|
||||
"versionPolicy": "版本策略",
|
||||
"customVersion": "固定自定义",
|
||||
"active": "当前生效",
|
||||
"activeDescription": "跟随通用设置的新请求使用此身份",
|
||||
"upToDate": "制品一致",
|
||||
"upToDateDescription": "当前生效版本与官方最新发布一致",
|
||||
"updateAvailable": "发现新版",
|
||||
"latestRelease": "官方最新版本 {releaseLabel}",
|
||||
"checkFailed": "检查失败",
|
||||
"checkFailedDescription": "官方版本检查失败",
|
||||
"pending": "待检查",
|
||||
"pendingDescription": "尚未检查官方发布渠道",
|
||||
"verifiedAt": "画像核验 {verifiedAt}",
|
||||
"checkedAt": "发布检查 {checkedAt}",
|
||||
"clientId": "客户端 ID",
|
||||
"tokenAuth": "Token 认证",
|
||||
"title": "通用上游身份",
|
||||
"provider": "上游平台",
|
||||
"empty": "暂无请求身份",
|
||||
"attributes": "请求身份组成",
|
||||
"authProtocol": "认证协议",
|
||||
"emulatedEnvironment": "模拟运行环境",
|
||||
"environment": "运行环境"
|
||||
},
|
||||
"health": {
|
||||
"title": "请求健康时间线",
|
||||
"description": "有效请求可用性"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"groups": {
|
||||
"selector": {
|
||||
"loading": "正在加载分组...",
|
||||
"empty": "暂无分组,请先在分组管理中创建"
|
||||
},
|
||||
"actions": {
|
||||
"editGroup": "编辑分组",
|
||||
"disableGroup": "禁用分组",
|
||||
"enableGroup": "启用分组",
|
||||
"deleteGroup": "删除分组",
|
||||
"enterGroupName": "请输入分组名称",
|
||||
"selectValidGroupingColor": "请选择有效的分组颜色",
|
||||
"updated": "分组已更新",
|
||||
"created": "分组已创建",
|
||||
"disabled": "分组已禁用",
|
||||
"enabled": "分组已启用",
|
||||
"groupDeleted": "分组已删除",
|
||||
"deletedGroupDeletedGroups": "已删除 {count} 个分组",
|
||||
"partialDeletion": "已删除 {count} 个分组,其余未删除:{value}",
|
||||
"batchDeletionFailed": "批量删除失败"
|
||||
},
|
||||
"filters": {
|
||||
"searchAccountGroup": "搜索账号分组",
|
||||
"searchGroupName": "搜索分组名称",
|
||||
"filterByGroupStatus": "按分组状态筛选",
|
||||
"deleteSelected": "删除选中 ({count})",
|
||||
"createGroup": "创建分组"
|
||||
},
|
||||
"editor": {
|
||||
"editDescription": "修改分组信息和请求权限",
|
||||
"createDescription": "创建后,可在账号管理中将账号加入这个分组",
|
||||
"groupName": "分组名称",
|
||||
"forExampleProductionAccount": "例如:生产账号",
|
||||
"groupColor": "分组颜色",
|
||||
"selectGroupColor": "选择分组颜色",
|
||||
"fastMode": "快速模式",
|
||||
"imageGeneration": "图像生成",
|
||||
"descriptionOptional": "描述(可选)",
|
||||
"groupDescription": "分组描述",
|
||||
"describePurposeOfThisGroup": "说明这个分组的用途",
|
||||
"saveGroup": "保存分组"
|
||||
},
|
||||
"metrics": {
|
||||
"restricted": "受限",
|
||||
"total": "总数",
|
||||
"concurrency": "并发",
|
||||
"today": "今日",
|
||||
"cumulative": "累计"
|
||||
},
|
||||
"group": "分组",
|
||||
"fields": {
|
||||
"capacity": "容量"
|
||||
},
|
||||
"page": {
|
||||
"description": "将账号归类管理,并为每个 API 密钥指定可使用的账号",
|
||||
"empty": "暂无分组",
|
||||
"selectCurrentPageGroup": "选择当前页分组",
|
||||
"selectGroup": "选择分组",
|
||||
"fastModeIsOn": "Fast 已开启",
|
||||
"fastModeIsOff": "Fast 已关闭",
|
||||
"imageGenerationDisabled": "生图已关闭",
|
||||
"colorLabel": "分组颜色 {color}",
|
||||
"batchDeleteWarning": "删除后这些分组将立即失效,此操作不可撤销",
|
||||
"batchDeleteDescription": "确定删除选中的 {count} 个分组吗?账号本身不会被删除",
|
||||
"disableAccountGrouping": "禁用账号分组",
|
||||
"disableDescription": "禁用后,使用该分组的 API 密钥将无法再使用其中的账号",
|
||||
"confirmDisable": "确认禁用",
|
||||
"disable": "确定禁用“{name}”吗?",
|
||||
"affectedApiKeys": "将影响 {count} 个 API 密钥:{value}",
|
||||
"affectedKeys": "将影响 {count} 个 API 密钥",
|
||||
"deleteAccountGroup": "删除账号分组",
|
||||
"deleteWarning": "删除后该分组将立即失效,此操作不可撤销",
|
||||
"unnamedGroup": "该分组",
|
||||
"deleteAccountsWillBeKept": "确定删除“{name}”吗?账号本身不会被删除"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import accounts from './accounts.json'
|
||||
import appearance from './appearance.json'
|
||||
import auth from './auth.json'
|
||||
import common from './common.json'
|
||||
import dashboard from './dashboard.json'
|
||||
import groups from './groups.json'
|
||||
import keys from './keys.json'
|
||||
import navigation from './navigation.json'
|
||||
import plugins from './plugins.json'
|
||||
import proxies from './proxies.json'
|
||||
import settings from './settings.json'
|
||||
import systemUpdate from './systemUpdate.json'
|
||||
import usage from './usage.json'
|
||||
|
||||
export default {
|
||||
...accounts,
|
||||
...appearance,
|
||||
...auth,
|
||||
...common,
|
||||
...dashboard,
|
||||
...groups,
|
||||
...keys,
|
||||
...navigation,
|
||||
...plugins,
|
||||
...proxies,
|
||||
...settings,
|
||||
...systemUpdate,
|
||||
...usage,
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"keys": {
|
||||
"configuration": {
|
||||
"description": "保存或合并下方配置后重启 Codex",
|
||||
"platform": "配置平台",
|
||||
"toggleWebSocket": "切换 WebSocket 配置",
|
||||
"importCcSwitch": "添加到 CC Switch",
|
||||
"copiedToClipboard": "已复制到剪贴板",
|
||||
"fullApiKeyNotAvailable": "完整 API Key 不可用",
|
||||
"title": "使用密钥"
|
||||
},
|
||||
"actions": {
|
||||
"editKey": "编辑密钥",
|
||||
"useKey": "使用密钥",
|
||||
"moreActions": "更多操作",
|
||||
"resetUsedCredit": "重置用量",
|
||||
"disableKey": "停用",
|
||||
"enableKey": "启用",
|
||||
"deleteKey": "删除",
|
||||
"deletedApiKeyDeletedApiKeys": "已删除 {count} 个 API Key"
|
||||
},
|
||||
"day": "日",
|
||||
"dailyUsage": "日用量",
|
||||
"week": "周",
|
||||
"weeklyUsage": "周用量",
|
||||
"viewUsageAndCostsFor": "查看 {name} 的费用用量",
|
||||
"costDetailsTitle": "费用详情(USD)",
|
||||
"confirmNextTime": "下次使用时确定",
|
||||
"budgetReset": {
|
||||
"dailyQuota": "日额度",
|
||||
"weeklyQuota": "周额度",
|
||||
"keyQuotaReset": "已重置密钥额度",
|
||||
"description": "清零所选周期的已用金额,下次使用时重新确定重置日期",
|
||||
"targetKey": "目标密钥",
|
||||
"resetScope": "重置范围",
|
||||
"currentlyUsed": "当前已用",
|
||||
"afterReset": "重置后",
|
||||
"remainUnchanged": "保持不变",
|
||||
"confirmReset": "确认重置"
|
||||
},
|
||||
"created": {
|
||||
"apiKeyCreated": "API Key 已创建",
|
||||
"description": "复制密钥,或直接导入 CCSwitch",
|
||||
"accessNotice": "该密钥具有网关访问权限,请仅发送给可信调用方",
|
||||
"copyKey": "复制密钥",
|
||||
"iHaveSaved": "我已保存"
|
||||
},
|
||||
"filters": {
|
||||
"apiKeyFilteringAndOperations": "API Key 筛选与操作",
|
||||
"searchPlaceholder": "搜索名称或标签",
|
||||
"searchLabel": "搜索 API Key 名称或标签",
|
||||
"deleteSelected": "删除选中 ({count})",
|
||||
"createApiKey": "创建 API Key"
|
||||
},
|
||||
"editor": {
|
||||
"description": "配置密钥信息、分组与使用限制",
|
||||
"namePlaceholder": "例如:生产环境",
|
||||
"labelOptional": "标签(可选)",
|
||||
"forExampleBackendService": "例如:后端服务",
|
||||
"customKeyOptional": "自定义 Key(可选)",
|
||||
"keyPlaceholder": "留空自动生成",
|
||||
"upstreamIdentity": "上游身份",
|
||||
"dailyLimit": "日限额",
|
||||
"dailyLimitUsd": "日限额(USD)",
|
||||
"weeklyLimit": "周限额",
|
||||
"weeklyLimitUsd": "周限额(USD)",
|
||||
"maximumConcurrency": "最大并发",
|
||||
"requestsPerMinuteRpm": "每分钟请求数(RPM)",
|
||||
"saveChanges": "保存更改",
|
||||
"updated": "API Key 已更新",
|
||||
"created": "API Key 已创建",
|
||||
"validation": {
|
||||
"amount": "{label}必须是非负金额,最多 10 位小数",
|
||||
"integer": "{label}必须是非负整数"
|
||||
},
|
||||
"enterApiKeyName": "请输入 API Key 名称",
|
||||
"invalidKey": "自定义 Key 只能包含 HTTP 可传输的可见字符,不能包含空格或换行",
|
||||
"requestsPerMinute": "每分钟请求数"
|
||||
},
|
||||
"fields": {
|
||||
"copyFullKey": "复制完整密钥",
|
||||
"allAccounts": "全部账号",
|
||||
"keyPrefix": "密钥前缀",
|
||||
"quotaUsage": "额度使用",
|
||||
"requestLimits": "请求限制",
|
||||
"lastUsed": "最后使用"
|
||||
},
|
||||
"page": {
|
||||
"description": "管理 API 密钥及账号访问范围",
|
||||
"noApiKeyYet": "暂无 API Key",
|
||||
"selectCurrentPageKey": "选择当前页密钥",
|
||||
"selectKey": "选择密钥",
|
||||
"concurrency": "并发",
|
||||
"batchDeleteWarning": "删除后这些 API Key 将立即失效,此操作不可撤销",
|
||||
"batchDeleteDescription": "确定删除选中的 {count} 个 API Key 吗?",
|
||||
"deleteApiKey": "删除 API Key",
|
||||
"deleteWarning": "删除后该 API Key 将立即失效,此操作不可撤销",
|
||||
"apiKey": "该 API Key",
|
||||
"delete": "确定删除 {name} 吗?"
|
||||
},
|
||||
"scope": {
|
||||
"allAccounts": {
|
||||
"title": "允许访问全部账号",
|
||||
"summary": "保存后,此密钥可访问全部账号",
|
||||
"confirm": "允许访问",
|
||||
"description": "此密钥可访问全部账号,包括未分组和以后新增的账号"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"navigation": {
|
||||
"overview": "概览",
|
||||
"accounts": "账号管理",
|
||||
"proxies": "代理管理",
|
||||
"groups": "分组管理",
|
||||
"apiKeys": "API 密钥",
|
||||
"usage": "分析统计",
|
||||
"plugins": "插件",
|
||||
"appearance": "主题设置",
|
||||
"settings": "系统设置",
|
||||
"update": {
|
||||
"available": "发现新版本,打开系统更新",
|
||||
"open": "打开系统更新"
|
||||
},
|
||||
"switchLanguage": "切换语言({value})",
|
||||
"mainLabel": "主导航",
|
||||
"pluginsLabel": "插件导航",
|
||||
"pluginManagement": "插件管理",
|
||||
"online": "在线",
|
||||
"sidebar": {
|
||||
"close": "关闭侧边栏",
|
||||
"expand": "展开侧边栏",
|
||||
"collapse": "收缩侧边栏",
|
||||
"open": "打开侧边栏"
|
||||
},
|
||||
"missingEntryPoint": "未配置 {role} 身份的默认入口"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,533 @@
|
||||
{
|
||||
"plugins": {
|
||||
"assets": {
|
||||
"pluginPackage": "插件包:{name}",
|
||||
"selectPluginPackage": "选择插件包",
|
||||
"packageLabel": "插件包"
|
||||
},
|
||||
"bindings": {
|
||||
"observationHelpTitle": "请求观察说明",
|
||||
"observationHelp": "仅观察请求,不改变请求结果",
|
||||
"applyToAllRequests": "应用于所有请求",
|
||||
"scopeHelpTitle": "生效请求范围说明",
|
||||
"scopeHelp": "关闭后至少选择一项范围,不同条件同时满足才生效,同一条件内任意一项匹配即可",
|
||||
"clientKey": "客户端 Key",
|
||||
"accountGrouping": "账号分组",
|
||||
"modelScope": "模型范围",
|
||||
"oneModelNamePerLineExactMatch": "每行一个模型名称,精确匹配",
|
||||
"providerScope": "Provider 范围",
|
||||
"oneProviderIdentifierPerLine": "每行一个 Provider 标识",
|
||||
"executionOrder": "执行顺序",
|
||||
"executionSequenceDescription": "执行顺序说明",
|
||||
"priorityHelp": "数值较小的先执行",
|
||||
"whenPluginFails": "插件失败时",
|
||||
"continueToNextHandler": "交给后续处理",
|
||||
"rejectRequest": "拒绝请求"
|
||||
},
|
||||
"capabilities": {
|
||||
"moreCapabilities": "另有 {count} 项声明能力"
|
||||
},
|
||||
"catalog": {
|
||||
"cardView": "卡片视图",
|
||||
"listView": "列表视图",
|
||||
"currentVersion": "当前版本",
|
||||
"installedVersion": "已安装版本",
|
||||
"provideFunctionality": "功能",
|
||||
"searchForInstalledPlugins": "搜索已安装插件",
|
||||
"searchPluginsPublishers": "搜索插件、发布者",
|
||||
"pluginStatus": "插件状态",
|
||||
"pluginDisplayMode": "插件显示方式",
|
||||
"noMatchingPlugins": "没有匹配的插件",
|
||||
"installYourFirstPlugin": "安装第一个插件",
|
||||
"tryAnotherNameOrStatus": "试试其他名称或状态",
|
||||
"emptyDescription": "从上方安装插件,请先确认来源可信",
|
||||
"clearFilters": "清除筛选",
|
||||
"pluginInstalled": "已安装插件",
|
||||
"noDescription": "发布者未提供说明",
|
||||
"versions": "{count} 个版本",
|
||||
"manage": "管理 {displayName}",
|
||||
"versionCount": "版本数"
|
||||
},
|
||||
"configuration": {
|
||||
"fillInRequiredConfiguration": "请填写必填配置",
|
||||
"incompatibleSecrets": "目标版本不支持部分已保存的敏感配置,请选择替换或清除",
|
||||
"requiredSecretsCannotClear": "必填敏感配置不能清除:{labels}",
|
||||
"requiredSecretsMissing": "没有可保留的必填敏感配置:{labels}",
|
||||
"secretsRequired": "请填写必填敏感配置",
|
||||
"checkBasicSettings": "请检查基本设置",
|
||||
"noParameters": "无需填写插件参数",
|
||||
"sensitiveConfiguration": "敏感配置",
|
||||
"secretsHelpTitle": "敏感配置说明",
|
||||
"secretsHelp": "敏感配置单独保存,不回显已有值,选择保留时不会更改,选择替换时以本次填写的全部值覆盖",
|
||||
"settingsSaved": "已保存 {count} 项",
|
||||
"clearSecretsHelp": "保存时清除全部敏感配置",
|
||||
"about": "{name}说明",
|
||||
"enterNewValue": "输入新值",
|
||||
"pluginParameters": "插件参数",
|
||||
"advancedSettings": "高级设置",
|
||||
"clientAuthentication": "客户端认证",
|
||||
"applyAndSwitch": "应用并切换",
|
||||
"saveAndEnable": "保存并启用",
|
||||
"saveSettings": "保存设置",
|
||||
"keepExistingValues": "保留已有值",
|
||||
"replaceAllValues": "替换全部值",
|
||||
"clearAllValues": "清除全部值",
|
||||
"checkPluginParameters": "请检查插件参数",
|
||||
"setRequestScopeOrCheckApplyTo": "请设置请求范围,或勾选“应用于所有请求”",
|
||||
"invalidIdentityMappings": "请检查客户端认证身份映射",
|
||||
"switchTo": "切换至 {version}",
|
||||
"pluginSettings": "插件设置",
|
||||
"unchangedVersion": "当前版本保持不变,修改后再应用",
|
||||
"pluginSettingsPartition": "插件设置分区",
|
||||
"secretsModeLabel": "敏感配置保存方式",
|
||||
"customScope": "自定义范围",
|
||||
"applyGlobally": "全局生效",
|
||||
"requestHandling": "请求处理:{value}",
|
||||
"description": "按配置提供扩展功能",
|
||||
"providesTerminalCommands": "提供终端命令",
|
||||
"requestHandlingNotConfigured": "未配置请求处理",
|
||||
"apiKeys": "{count} 个 Key",
|
||||
"groups": "{count} 个分组",
|
||||
"providers": "{count} 个 Provider",
|
||||
"identityMappings": "{count} 组身份映射",
|
||||
"allRequests": "所有请求",
|
||||
"noLimitOnScope": "不限制范围",
|
||||
"featureDetails": "功能详情",
|
||||
"capabilitiesOf": "{name} 的功能详情",
|
||||
"terminalCommands": "终端命令",
|
||||
"legacy": {
|
||||
"multipleEnabledNotice": "检测到多套启用配置,请在历史配置中停用不再使用的一套",
|
||||
"previousConfigurations": "历史配置 · {count}",
|
||||
"description": "保留已有设置和数据,使用历史配置会替换当前启用配置",
|
||||
"disableAction": "停用历史配置",
|
||||
"start": "启动",
|
||||
"deleteHistoricalConfiguration": "删除历史配置"
|
||||
},
|
||||
"stale": "插件设置已变更,请刷新后重试",
|
||||
"incompatible": "请调整不兼容的设置后重试"
|
||||
},
|
||||
"details": {
|
||||
"version": "版本",
|
||||
"pendingDescription": "配置已保存,等待生效,状态会自动刷新",
|
||||
"requiredConfiguration": "补充必填配置后即可启用",
|
||||
"versionInUse": "旧版本仍有进行中的调用,完成前暂不能删除",
|
||||
"pluginDetails": "插件详情",
|
||||
"pluginDetailsSection": "插件详情分区",
|
||||
"manualInstallationVersion": "手动安装版本",
|
||||
"pluginHasNotBeenInitialized": "插件尚未初始化",
|
||||
"pluginIsNotInstalled": "插件待安装",
|
||||
"initializePlugin": "初始化插件",
|
||||
"installation": "安装",
|
||||
"versionNotAvailable": "版本不可用",
|
||||
"configurationStatusOf": "{name}配置状态说明",
|
||||
"settings": "设置",
|
||||
"restart": "重新启动",
|
||||
"deactivate": "停用",
|
||||
"completeSetupAndEnable": "完成设置并启用",
|
||||
"fallbackVersion": "回退版本",
|
||||
"uninstallPlugin": "卸载插件"
|
||||
},
|
||||
"downloadAuth": {
|
||||
"accessToken": "访问令牌",
|
||||
"usernameAndPassword": "用户名与密码",
|
||||
"customRequestHeader": "自定义请求头",
|
||||
"noCertificationRequired": "无需认证",
|
||||
"fillInGithubToken": "填写 GitHub 令牌",
|
||||
"credentialsPlaceholder": "填写认证信息",
|
||||
"useSavedCredentials": "使用已保存凭据",
|
||||
"download": "下载 · {hostname}",
|
||||
"downloadCertification": "下载认证",
|
||||
"helpTitle": "下载认证说明",
|
||||
"githubHelp": "公开仓库无需认证,私有仓库需要有读取权限的 GitHub 令牌",
|
||||
"urlHelp": "仅在下载地址要求认证时填写",
|
||||
"storageHelp": "认证信息在查询或解析时保存,仅用于当前来源,不会提供给插件",
|
||||
"authenticationMethod": "认证方式",
|
||||
"githubToken": "GitHub 令牌",
|
||||
"downloadToken": "下载令牌",
|
||||
"enterToken": "输入令牌",
|
||||
"username": "用户名",
|
||||
"downloadUsername": "下载用户名",
|
||||
"password": "密码",
|
||||
"downloadPassword": "下载密码",
|
||||
"requestHeaderName": "请求头名称",
|
||||
"requestHeaderValue": "请求头值"
|
||||
},
|
||||
"enable": {
|
||||
"notSet": "未设置",
|
||||
"switchActiveConfiguration": "切换启用配置",
|
||||
"enablePluginConfiguration": "启用插件配置",
|
||||
"willBeEnabled": "将启用",
|
||||
"configurationsToDisable": "将停用 {count} 项",
|
||||
"toggleEnablementInstructions": "切换启用说明",
|
||||
"disableDescription": "以下配置将停止处理新请求,设置、密钥与私有数据保留",
|
||||
"willBeDeactivated": "将停用",
|
||||
"confirmSwitch": "确认切换",
|
||||
"confirmEnable": "确认启用"
|
||||
},
|
||||
"extensions": {
|
||||
"emptyTitle": "暂无插件管理页面",
|
||||
"emptyDescription": "启用带有管理页面的插件后,可从此处或侧栏进入",
|
||||
"configuration": "配置 {value}",
|
||||
"pages": "{count} 页",
|
||||
"openPage": "打开页面"
|
||||
},
|
||||
"frontendAuth": {
|
||||
"exclusiveCertification": "独占认证",
|
||||
"fallbackApiKeyIfNoMatch": "未匹配时回退 API Key",
|
||||
"disabled": "(已停用)",
|
||||
"configuredUnavailable": "已配置但当前不可用",
|
||||
"invalidBinding": "客户端认证绑定必须使用认证阶段和受支持的未匹配处理",
|
||||
"unsupportedScope": "客户端认证不支持 Provider、模型或分组范围,请关闭后重新启用该绑定",
|
||||
"addAtLeastOneIdentityMapping": "请添加至少一条身份映射",
|
||||
"mappingLimit": "身份映射不能超过 256 条",
|
||||
"invalidIdentity": "身份标识必须是 1–256 个 UTF-8 字节,且不能含首尾空白或控制字符",
|
||||
"duplicateIdentity": "同一身份标识只能配置一次",
|
||||
"keyRequired": "请为每个身份标识选择客户端 Key",
|
||||
"repeatedCursor": "服务返回了重复的分页位置",
|
||||
"failedToLoadClientKey": "加载客户端 Key 失败",
|
||||
"enableClientAuthentication": "启用客户端认证",
|
||||
"helpTitle": "客户端认证说明",
|
||||
"description": "插件识别请求中的外部身份,宿主再将该身份映射到已有 Client Key,沿用这个 Key 的限额、账号范围与并发策略",
|
||||
"loginNotice": "此功能用于客户端 API 请求,不替代管理端登录",
|
||||
"unmatchedProcessing": "未匹配处理",
|
||||
"unmatchedHandlingInstructions": "未匹配处理说明",
|
||||
"exclusiveHelp": "独占认证:插件未识别到身份时拒绝请求",
|
||||
"fallbackToApiKeyWhenNoMatch": "未匹配时回退 API Key:插件未识别到身份时,继续使用宿主原有的 API Key 认证",
|
||||
"rejectionHelp": "插件明确拒绝或调用失败时始终拒绝请求,不会回退",
|
||||
"unmatchedLabel": "客户端认证未匹配处理",
|
||||
"identityMapping": "身份映射",
|
||||
"identityMappingDescription": "身份映射说明",
|
||||
"identityHelp": "身份标识必须与插件返回的值完全一致,同一身份只能映射一次",
|
||||
"keyHelp": "选择该身份使用的 Client Key,已停用或删除的 Key 不会获得执行权限",
|
||||
"reloadClientKey": "重新加载客户端 Key",
|
||||
"addMapping": "添加映射",
|
||||
"identityMark": "身份标识",
|
||||
"identityPlaceholder": "填写插件返回的身份标识",
|
||||
"failedToLoadTryAgain": "加载失败,请重试",
|
||||
"selectClientApiKey": "选择客户端 Key",
|
||||
"noClientKeyYet": "暂无客户端 Key",
|
||||
"removeIdentityMapping": "移除第 {value} 条身份映射"
|
||||
},
|
||||
"installation": {
|
||||
"uploadPackage": "上传包",
|
||||
"enterDigitHexadecimalDigest": "请输入 64 位十六进制摘要",
|
||||
"installNewVersion": "安装新版本",
|
||||
"pluginPackageCannotExceedMib": "插件包不能超过 32 MiB",
|
||||
"verificationRequired": "请先校验当前选择的插件包",
|
||||
"githubRepositoryRequired": "请输入 GitHub 仓库链接或 owner/repo",
|
||||
"prereleaseTagRequired": "查询预发行版需要明确填写 tag",
|
||||
"updatePlugin": "更新插件",
|
||||
"installPlugin": "安装插件",
|
||||
"installDescription": "确认来源与版本后安装",
|
||||
"switchDescription": "检查设置兼容性后切换版本",
|
||||
"sourceHelp": "支持本地插件包、URL 与 GitHub",
|
||||
"installationMethod": "安装方式",
|
||||
"tarGzTgzMaxMib": "tar.gz / tgz,最大 32 MiB",
|
||||
"replace": "更换",
|
||||
"browseFiles": "浏览文件",
|
||||
"downloadUrl": "下载 URL",
|
||||
"downloadAddressDescription": "下载地址说明",
|
||||
"urlHelp": "仅支持 HTTPS,本机回环地址可使用 HTTP",
|
||||
"githubRepository": "GitHub 仓库",
|
||||
"repositoryLinkOrOwnerRepo": "仓库链接或 owner/repo",
|
||||
"tagLabel": "版本标签",
|
||||
"tagHelpTitle": "版本标签说明",
|
||||
"tagHelp": "留空查询最新稳定版,查询预发行版时必须指定标签",
|
||||
"tagPlaceholder": "留空查最新稳定版",
|
||||
"allowPrereleaseLabel": "允许查询预发行版",
|
||||
"verificationSummary": "校验摘要",
|
||||
"digestHelpTitle": "校验摘要说明",
|
||||
"digestHelp": "可选,填写发布者提供的 64 位 SHA-256 十六进制摘要,用于核对下载内容",
|
||||
"shaChecksum": "SHA-256 校验摘要",
|
||||
"optionalSha": "可选,SHA-256",
|
||||
"versionFound": "已找到版本",
|
||||
"preRelease": "预发行版",
|
||||
"thereIsNoTarGzOrTgz": "此版本没有 tar.gz 或 tgz 插件包",
|
||||
"pendingTitle": "待安装插件",
|
||||
"parsingCompleted": "解析完成",
|
||||
"publisher": "发布者",
|
||||
"applicablePlatforms": "适用平台",
|
||||
"trustNotice": "插件可访问全部网关数据与配置,安装前请确认来源可信",
|
||||
"activateAfterInstall": "安装后确认切换到新版本",
|
||||
"installNewVersionInstructions": "安装新版本说明",
|
||||
"configurationHelp": "沿用设置并补充新版本默认值,需要调整时会打开设置,已使用版本保留恢复设置",
|
||||
"queryAgain": "重新查询",
|
||||
"queryingVersion": "正在查询版本",
|
||||
"saveSourceAndContinue": "保存来源并继续",
|
||||
"parsingPluginPackage": "正在解析插件包",
|
||||
"pluginInstallationFailed": "插件安装失败",
|
||||
"noSource": "此插件没有可用的安装来源",
|
||||
"sourceChanged": "安装来源已变更,请关闭后重新打开",
|
||||
"sourceSaveFailed": "安装来源保存失败",
|
||||
"githubReleaseQueryFailed": "GitHub Release 查询失败",
|
||||
"installedNeedsConfiguration": "插件已安装,请补充必要配置",
|
||||
"preparing": "插件已安装,正在准备",
|
||||
"pluginVersionInstalled": "插件版本已安装",
|
||||
"updateSourceChanged": "安装来源已变更,请重新检查更新",
|
||||
"pluginUpgradeFailed": "插件升级失败",
|
||||
"versionRequired": "请选择待安装的插件版本",
|
||||
"packageMismatch": "插件包与当前插件不符,请重新选择",
|
||||
"verificationFailed": "插件包校验失败"
|
||||
},
|
||||
"management": {
|
||||
"installed": "已安装",
|
||||
"extensions": "扩展页",
|
||||
"description": "管理版本、配置与扩展页",
|
||||
"tabsLabel": "插件管理分区",
|
||||
"refresh": "刷新插件",
|
||||
"switchPluginVersion": "切换插件版本",
|
||||
"switchHelp": "切换前会检查目标版本设置,失败时保留当前版本",
|
||||
"deletePluginVersion": "删除插件版本",
|
||||
"deleteVersionHelp": "使用中的版本不可删除,删除版本也会清除对应的恢复设置",
|
||||
"delete": "删除 {displayName} {version}?",
|
||||
"versionDeletionDetails": "版本删除详情",
|
||||
"deleteVersionInUse": "被配置或运行中的调用引用时不能删除,不会自动停用其他配置",
|
||||
"deleteVersionCleanupHelp": "只清理此版本独用的下载认证,删除最后一个版本时同时清理来源规则,共享认证与代理不受影响",
|
||||
"deleteVersionCleanupLabel": "同时清理独用下载认证,最后一版还会清理来源",
|
||||
"deletePluginConfiguration": "删除插件配置",
|
||||
"deleteConfigurationWarning": "配置、密钥与私有数据将永久删除",
|
||||
"deleteConfigurationHelp": "无法恢复,已安装版本与其他配置不受影响",
|
||||
"uninstallWarning": "删除全部版本、配置、密钥与私有数据",
|
||||
"confirmUninstall": "确认卸载",
|
||||
"versionCount": "{displayName} · {count} 个版本",
|
||||
"uninstallCleanupLabel": "同时清理来源与独用下载认证",
|
||||
"uninstallCleanupInstructions": "卸载清理说明",
|
||||
"uninstallCleanupHelp": "只清理被卸载版本使用且不再被其他版本引用的下载认证,不删除共享认证、代理或审计记录",
|
||||
"disableInsteadHelp": "暂时不用可停用配置,无需卸载",
|
||||
"permanentDeleteLabel": "确认永久删除,无法恢复",
|
||||
"deleteDownloadCredentials": "删除下载认证",
|
||||
"itCannotBeDeletedWhileItIs": "仍被使用时不可删除,删除后无法恢复",
|
||||
"pageLoadFailed": "插件扩展页加载失败",
|
||||
"pluginDataLoadingFailed": "插件数据加载失败"
|
||||
},
|
||||
"frame": {
|
||||
"pluginPageCannotBeLoaded": "插件页面无法加载",
|
||||
"versionChanged": "插件页面版本已变更,正在刷新",
|
||||
"navigationBlocked": "插件页面尝试离开已隔离的管理文档,已停止加载",
|
||||
"invalidQueryParameter": "查询参数无效",
|
||||
"queryParametersExceedKib": "查询参数超过 8 KiB",
|
||||
"invalidBody": "请求正文无效或超过 1 MiB",
|
||||
"routesDoNotAcceptRequestBody": "{method} 路由不接受请求正文",
|
||||
"contentTypeIsInvalid": "Content-Type 无效",
|
||||
"unregisteredContentType": "Content-Type 未在插件路由中注册",
|
||||
"contentTypeRequired": "包含正文的请求必须声明 Content-Type",
|
||||
"invalidRequestParameters": "请求参数无效",
|
||||
"unregisteredRequest": "请求未在当前插件版本中注册",
|
||||
"invalidCallbackTicket": "回调票据参数无效",
|
||||
"unregisteredCallback": "回调路径未在当前插件版本中注册",
|
||||
"invalidTicketLifetime": "回调票据有效期必须为 1 到 600 秒",
|
||||
"invalidModelRequest": "模型请求参数无效",
|
||||
"clientkeyidIsInvalid": "clientKeyId 无效",
|
||||
"invalidModelBody": "Responses 请求正文无效或超过 8 MiB",
|
||||
"invalidModelJson": "Responses 请求正文不是有效 JSON",
|
||||
"modelObjectRequired": "Responses 请求正文必须是 JSON 对象",
|
||||
"pageDidNotContinueToReadModel": "页面 30 秒未继续读取模型响应",
|
||||
"modelConcurrencyLimit": "模型请求已达并发上限",
|
||||
"duplicateModelRequest": "模型请求序号重复",
|
||||
"modelTimeout": "模型请求超过 10 分钟",
|
||||
"unsupportedModelContentType": "模型接口返回了不受支持的内容类型",
|
||||
"modelRequestFailed": "模型请求失败",
|
||||
"invalidPullId": "模型响应拉取序号无效",
|
||||
"concurrentPull": "模型响应拉取发生重入",
|
||||
"stalePullId": "模型响应拉取序号已失效",
|
||||
"modelResponseReadFailed": "模型响应读取失败",
|
||||
"duplicateManagementRequest": "插件管理请求序号重复",
|
||||
"managementConcurrencyLimit": "插件管理请求已达并发上限",
|
||||
"invalidEntryPoint": "插件页面入口不是已注册的 HTML 资源",
|
||||
"unregisteredAsset": "插件页面引用了未注册资源:{path}",
|
||||
"htmlSubresource": "插件 HTML 资源不能作为子资源加载",
|
||||
"cyclicCss": "插件 CSS 资源存在循环引用:{path}",
|
||||
"invalidVersion": "插件页面版本无效,请刷新后重试",
|
||||
"resourceCountLimit": "插件页面资源数量超过限制",
|
||||
"pageChanged": "插件页面已变更,请刷新后重试",
|
||||
"pluginAssetReturnedHttp": "插件资源返回 HTTP {status}",
|
||||
"resourceTypeMismatch": "插件资源类型与注册值不一致:{path}",
|
||||
"pluginAssetExceedsMib": "插件资源超过 1 MiB:{path}",
|
||||
"resourceSizeLimit": "插件页面资源总量超过 8 MiB",
|
||||
"unsupportedElement": "插件页面使用了不受支持的 {'<'}{value}{'>'} 元素",
|
||||
"redirectForbidden": "插件页面不能使用自动跳转",
|
||||
"moduleScriptUnsupported": "插件页面暂不支持 ES Module 脚本,请使用经典脚本包",
|
||||
"invalidPluginScriptAssetType": "插件脚本资源类型无效:{path}",
|
||||
"unsupportedLink": "插件页面只支持 stylesheet 和 icon 链接资源",
|
||||
"invalidStylesheet": "插件样式资源类型无效:{path}",
|
||||
"invalidPluginIconAssetType": "插件图标资源类型无效:{path}",
|
||||
"unsupportedSrc": "插件页面不支持 {'<'}{value}{'>'} 的 src 加载",
|
||||
"invalidPluginImageAssetType": "插件图像资源类型无效:{path}",
|
||||
"invalidPluginPosterAssetType": "插件 poster 资源类型无效:{path}",
|
||||
"emptySrcset": "插件 srcset 资源引用为空",
|
||||
"externalNavigation": "插件页面不能导航到外部或未注册地址",
|
||||
"pluginPageDoesNotSupportUrls": "插件页面不支持 {name} 地址",
|
||||
"externalAttribute": "插件页面属性不能引用外部资源:{name}",
|
||||
"unsupportedPluginCssSyntax": "插件 CSS 语法不受支持:{ownerPath}",
|
||||
"invalidCss": "插件 CSS 包含无法解析的内容:{ownerPath}",
|
||||
"escapedCssIdentifier": "插件 CSS 规则或函数名不能使用转义:{ownerPath}",
|
||||
"inlineStyleImport": "内联 style 属性不能导入样式表",
|
||||
"unsupportedPluginImportSyntax": "插件 {'@'}import 语法不受支持:{ownerPath}",
|
||||
"pluginImportTargetIsNotCss": "插件 {'@'}import 目标不是 CSS:{path}",
|
||||
"unsupportedPluginAssetUrl": "插件资源地址不受支持:{rawReference}",
|
||||
"resourceQuery": "插件资源地址不支持查询参数:{rawReference}",
|
||||
"resourceFragment": "插件资源地址不支持片段标识:{rawReference}",
|
||||
"resourceOutsideArtifact": "插件资源地址越过制品边界:{rawReference}",
|
||||
"invalidPluginAssetPathSegment": "插件资源路径片段无效:{rawReference}",
|
||||
"invalidResourcePath": "插件注册了无效资源路径:{path}",
|
||||
"pluginTextAssetIsNotValidUtf": "插件文本资源不是有效 UTF-8:{path}"
|
||||
},
|
||||
"pluginPage": "插件页面",
|
||||
"page": {
|
||||
"configurationDescription": "使用插件提供的功能,当前配置为「{name}」",
|
||||
"description": "加载已启用插件的管理页面",
|
||||
"unpublished": "该配置或页面未发布,可能已停用或切换版本",
|
||||
"refreshFailed": "页面目录刷新失败,当前显示上次成功加载的版本:{loadError}",
|
||||
"loadingPage": "正在加载页面"
|
||||
},
|
||||
"refreshPage": "刷新页面",
|
||||
"pluginPageIsUnavailable": "插件页面不可用",
|
||||
"returnToPluginManagement": "返回插件管理",
|
||||
"resources": {
|
||||
"unavailable": "不可用 · {id}",
|
||||
"multipleSelectionsAllowed": "{label}(可多选)",
|
||||
"unlimitedPlaceholder": "不限(可多选)",
|
||||
"loading": "正在加载…",
|
||||
"isTemporarilyUnavailable": "暂时无法获取{label}",
|
||||
"noMatches": "没有匹配项",
|
||||
"no": "暂无{label}",
|
||||
"createOneInFirst": "请先在{value}中创建"
|
||||
},
|
||||
"rollback": {
|
||||
"rollBackPluginVersion": "回退插件版本",
|
||||
"description": "恢复对应版本的设置,保持当前启停状态",
|
||||
"targetVersion": "目标版本",
|
||||
"fallbackInstructions": "回退说明",
|
||||
"restoreHelp": "恢复目标版本上次启用时的参数和密钥,私有数据仍须通过兼容检查",
|
||||
"loadingOlderVersions": "正在加载旧版",
|
||||
"selectRollbackVersion": "请选择回退目标",
|
||||
"rollBackToTargetVersion": "回退目标版本",
|
||||
"empty": "没有保留恢复设置的旧版,其他版本可在“版本”中切换",
|
||||
"reload": "重新加载",
|
||||
"confirmRollback": "确认回退",
|
||||
"completed": "已回退至 {version},并恢复对应设置"
|
||||
},
|
||||
"sourceProxy": {
|
||||
"noProxyDirectConnection": "不使用代理(直连)",
|
||||
"disabledSuffix": "(已禁用)",
|
||||
"catalogUnavailable": "已选代理(目录暂不可用)",
|
||||
"label": "下载代理"
|
||||
},
|
||||
"status": {
|
||||
"unableToStart": "无法启动",
|
||||
"runFailed": "运行失败",
|
||||
"compatibilityReminder": "兼容性提醒",
|
||||
"deprecatedApi": "接口待升级,当前仍兼容",
|
||||
"startupUnverified": "可以尝试启动,运行结果仍需验证",
|
||||
"compatibilityWindow": "旧接口还将兼容至少 {remainingReleases} 个正式版本",
|
||||
"compatibilityEnding": "兼容窗口已满,后续正式版本将移除旧接口转换",
|
||||
"unsupportedVersionHelp": "配置与数据保留,请安装可加载的插件版本",
|
||||
"restartHelp": "启用配置保留,可在插件详情中重新启动",
|
||||
"upgradeHelp": "请更新插件,或联系作者升级接口"
|
||||
},
|
||||
"updates": {
|
||||
"packageRequired": "请选择插件包以确认版本与兼容性",
|
||||
"currentlyUsingThisVersion": "当前已使用此版本",
|
||||
"verifiedUpdate": "发现新版本,插件包已校验",
|
||||
"sameVersionDifferentContent": "版本号相同,插件包内容不同",
|
||||
"noHigherVersionFound": "未发现更高版本",
|
||||
"pluginUpdate": "插件更新",
|
||||
"checkingDescription": "正在检查版本并校验插件包",
|
||||
"versionComparison": "版本对比",
|
||||
"postTag": "发布标签",
|
||||
"updateInspectionInstructions": "更新检查说明",
|
||||
"configurationHelp": "按插件包内版本判断升级,沿用当前设置,配置不兼容时保留当前版本并打开设置",
|
||||
"trustNotice": "插件可访问全部网关数据与配置,更新前请确认来源可信",
|
||||
"thereIsNoTarGzOrTgzPlugin": "此发布没有 tar.gz 或 tgz 插件包",
|
||||
"upgradeTo": "升级到 {version}",
|
||||
"continueInstallation": "继续安装",
|
||||
"unsupportedSource": "此来源不支持检查更新,请安装新版本",
|
||||
"sourceChanged": "安装来源已变更,请重新检查",
|
||||
"checkForUpdatesFailed": "检查更新失败"
|
||||
},
|
||||
"versionDetails": "版本详情",
|
||||
"toBeInstalled": "待安装",
|
||||
"historicalConfiguration": "历史配置",
|
||||
"referenceConfiguration": "引用配置",
|
||||
"versions": {
|
||||
"detailsLabel": "{version} 版本详情",
|
||||
"historicalVersion": "历史版本"
|
||||
},
|
||||
"install": "安装 {version}",
|
||||
"deleteVersion": "删除版本 {version}",
|
||||
"credentials": {
|
||||
"selectDownloadCredentials": "选择下载认证 {name}",
|
||||
"deleteDownloadCredentials": "删除下载认证 {name}",
|
||||
"saveDownloadCredentialsFailed": "下载认证保存失败",
|
||||
"sourceCredentialsDeleted": "来源凭据已删除",
|
||||
"deleteFailed": "来源凭据删除失败"
|
||||
},
|
||||
"artifacts": {
|
||||
"pluginProductHasBeenDeleted": "插件制品已删除",
|
||||
"pluginProductDeletionFailed": "插件制品删除失败"
|
||||
},
|
||||
"instances": {
|
||||
"saveFailed": "插件配置保存失败",
|
||||
"versionMissing": "所选版本已不存在,请重新选择",
|
||||
"loadFailed": "启用配置加载失败",
|
||||
"configurationEnablementFailed": "配置启用失败",
|
||||
"switchedCurrentConfiguration": "已切换当前配置",
|
||||
"pluginSettingsApplied": "插件设置已应用",
|
||||
"savedDisabled": "设置已保存,插件保持停用",
|
||||
"pluginDisabled": "插件已停用",
|
||||
"pluginDeactivationFailed": "插件停用失败",
|
||||
"deleted": "配置、密钥与私有数据已删除,无法恢复",
|
||||
"pluginInstanceDeletionFailed": "插件实例删除失败"
|
||||
},
|
||||
"uninstall": {
|
||||
"newConfiguration": "出现了新的插件配置,请关闭并重新确认卸载范围",
|
||||
"versionChanged": "“{name}”已切换版本,请重新确认卸载范围",
|
||||
"removingConfiguration": "正在停用并删除配置:{name}",
|
||||
"newVersion": "已删除确认范围,但还有新安装的版本,请关闭并重新确认剩余内容",
|
||||
"completed": "插件已卸载,相关数据与来源设置已清理",
|
||||
"incomplete": "卸载尚未完成,可重试剩余步骤"
|
||||
},
|
||||
"deletingVersion": "正在删除版本:{version}",
|
||||
"switchedTo": "已切换至 {version}",
|
||||
"versionSettingFailedToLoad": "版本设置加载失败",
|
||||
"versionSwitchingFailed": "版本切换失败",
|
||||
"fallbackVersionLoadingFailed": "回退版本加载失败",
|
||||
"pluginVersionRollbackFailed": "插件版本回退失败",
|
||||
"fields": {
|
||||
"requestCompletionAndUsage": "请求完成与用量",
|
||||
"upstreamWebsocketEvents": "上游 WebSocket 事件",
|
||||
"requestScheduling": "请求调度",
|
||||
"modelRouting": "模型路由",
|
||||
"modelCatalog": "模型目录",
|
||||
"retryStrategy": "重试策略",
|
||||
"requestMiddleware": "请求中间件",
|
||||
"upstreamAdapter": "上游适配器",
|
||||
"eventObservation": "事件观察",
|
||||
"commandLine": "命令行",
|
||||
"manageExtensions": "管理扩展",
|
||||
"maintenanceTasks": "维护任务",
|
||||
"httpRequest": "HTTP 请求",
|
||||
"allHttpRequests": "所有 HTTP 请求",
|
||||
"websocketMessages": "WebSocket 消息",
|
||||
"allWebsocketMessages": "所有 WebSocket 消息",
|
||||
"serviceCall": "服务调用",
|
||||
"allServiceCalls": "所有服务调用",
|
||||
"requestToStart": "请求开始",
|
||||
"everyTry": "每次尝试",
|
||||
"upstreamCall": "上游调用",
|
||||
"accountScheduling": "账号调度",
|
||||
"retryDecision": "重试决策",
|
||||
"toBeConfigured": "待配置",
|
||||
"deactivated": "已停用",
|
||||
"waitingForItToTakeEffect": "等待生效"
|
||||
},
|
||||
"validation": {
|
||||
"suppliedWithVersion": "随版本提供",
|
||||
"localUpload": "本地上传",
|
||||
"fixedUrl": "固定 URL",
|
||||
"releaseList": "发行清单",
|
||||
"noRemoteUpdateSource": "无远程更新来源"
|
||||
},
|
||||
"onePerLine": "每行一项"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
{
|
||||
"proxies": {
|
||||
"accounts": {
|
||||
"platformType": "平台",
|
||||
"subscription": "订阅",
|
||||
"noMatches": "没有找到匹配的账号,请尝试其他名称或邮箱",
|
||||
"empty": "暂无关联账号",
|
||||
"linkAccount": "关联账号",
|
||||
"searchAssociatedAccounts": "搜索关联账号",
|
||||
"searchAccountNameOrEmail": "搜索账号名称或邮箱",
|
||||
"removeAction": "从当前代理移除账号",
|
||||
"removeAssociatedAccount": "移除关联账号",
|
||||
"remove": "移除",
|
||||
"removeDescription": "将“{name}”从“{removeProxyName}”移除后,该账号将改为直连",
|
||||
"removed": "账号已移出当前代理,改为直连"
|
||||
},
|
||||
"actions": {
|
||||
"test": "测试代理",
|
||||
"edit": "编辑代理",
|
||||
"moreActionsFor": "{name} 的更多操作",
|
||||
"disableProxy": "禁用代理",
|
||||
"enableProxy": "启用代理",
|
||||
"deleteProxy": "删除代理",
|
||||
"testInProgress": "代理正在测试,请等待当前测试结束",
|
||||
"testFailed": "代理测试失败",
|
||||
"connectedWithDetails": "{name}:连接成功,{message}",
|
||||
"timeZoneMismatch": "{name}:连接成功,IPv4 与 IPv6 出口时区不一致",
|
||||
"connected": "{name}:连接成功",
|
||||
"fillInProxyConnectionAddress": "请填写代理连接地址",
|
||||
"connectedInMs": "连接成功,耗时 {latencyMs} ms",
|
||||
"locationFailed": "代理连接失败,未能解析位置",
|
||||
"exitLocationFilledIn": "已填入出口位置",
|
||||
"unableToObtainExitLocation": "未获取到出口位置",
|
||||
"fieldsRequired": "请填写代理名称和连接地址",
|
||||
"invalidConnectionLimit": "连接上限须为 0 到 4294967295 之间的整数",
|
||||
"saved": "代理已保存",
|
||||
"proxyEnabled": "代理已启用",
|
||||
"disabled": "代理已禁用,关联账号已改为直连",
|
||||
"deleted": "代理已删除"
|
||||
},
|
||||
"batchCreate": {
|
||||
"proxyList": "代理列表",
|
||||
"formatDescription": "代理列表格式说明",
|
||||
"supportedFormats": "支持以下格式",
|
||||
"hostPortUsernamePassword": "host:port:用户名:密码",
|
||||
"httpUsernamePasswordHostPort": "http://用户名:密码{'@'}host:port",
|
||||
"protocolHelp": "未写协议时使用下方默认协议,完整 URL 保留各自协议",
|
||||
"ipv6Help": "IPv6 地址需加方括号,例如",
|
||||
"onePerLineMaximum": "每行一条 · 最多 {value} 条",
|
||||
"bulkProxyList": "批量代理列表",
|
||||
"totalReadyToAdd": "共 {count} 条,{count2} 条可添加",
|
||||
"needsChanges": ",{count} 条需修改",
|
||||
"line": "第 {line} 行:{error}",
|
||||
"additionalIssues": "另有 {count} 条需处理",
|
||||
"defaultProtocol": "默认协议",
|
||||
"defaultProtocolLabel": "无协议代理的默认协议",
|
||||
"namePrefix": "名称前缀",
|
||||
"proxy": "代理",
|
||||
"conflict": "代理已存在或配置冲突,未覆盖已有记录",
|
||||
"stopped": "已停止后续添加"
|
||||
},
|
||||
"batchTest": {
|
||||
"resultsTitle": "批量添加结果",
|
||||
"processed": "已处理",
|
||||
"added": "已添加 {created}",
|
||||
"invalidFormat": "格式错误 {invalid}",
|
||||
"connected": "连接正常 {succeeded}",
|
||||
"connectionFailed": "连接失败 {failed}",
|
||||
"locationPending": "地区待处理 {locationPending}",
|
||||
"needsAttention": "需处理 {attention}",
|
||||
"skipped": "未执行 {skipped}",
|
||||
"scrollListOfProxyResults": "代理结果滚动列表",
|
||||
"lineNumber": "第 {key} 行",
|
||||
"addedStatus": "已添加",
|
||||
"connectionIsNormal": "连接正常",
|
||||
"stopped": "已停止后续测试",
|
||||
"proxyMissing": "所选代理已不存在,请刷新列表",
|
||||
"batchTestCompletedConnected": "批量测试完成,连接正常 {succeeded} 条",
|
||||
"unsuccessful": "未成功 {count} 条",
|
||||
"locationsPending": "地区待处理 {locationPending} 条",
|
||||
"proxiesNoLongerAvailable": "{missing} 条代理已不存在",
|
||||
"toBeExecuted": "待执行",
|
||||
"requestFailed": "请求失败",
|
||||
"configurationConflict": "配置冲突",
|
||||
"testingIsBusy": "测试繁忙",
|
||||
"resultToBeConfirmed": "结果待确认",
|
||||
"notExecuted": "未执行",
|
||||
"invalidProxyFormat": "代理格式不正确",
|
||||
"invalidAddress": "代理主机或端口不合法",
|
||||
"duplicateOfLine": "与第 {earlier} 行重复",
|
||||
"formatHelp": "格式不正确,请参考格式说明",
|
||||
"proxyListCannotExceedKib": "代理列表不能超过 512 KiB",
|
||||
"addUpToProxiesAtTime": "一次最多添加 {value} 条代理",
|
||||
"resultUnknown": "未取得确定结果,请刷新列表核对",
|
||||
"interrupted": "请求中断或服务异常,请刷新列表核对结果",
|
||||
"skippedAfterFailure": "前序操作异常,未执行"
|
||||
},
|
||||
"editor": {
|
||||
"single": "单条",
|
||||
"batch": "批量",
|
||||
"timeZoneMismatch": "IPv4 与 IPv6 出口时区不一致,请手动填写",
|
||||
"createTitle": "新增代理",
|
||||
"connectionHelp": "留空保留当前连接和认证信息,填写新地址时,请包含所需的用户名和密码",
|
||||
"protocolHelp": "支持 HTTP、HTTPS、SOCKS5 和 SOCKS5H,可在地址中包含用户名和密码",
|
||||
"createDescription": "添加代理,为账号配置网络出口",
|
||||
"methodLabel": "代理添加方式",
|
||||
"nameLabel": "代理名称",
|
||||
"namePlaceholder": "请输入代理名称",
|
||||
"proxyAddress": "代理地址",
|
||||
"addressPlaceholder": "输入代理地址",
|
||||
"upstreamWsConnectionCap": "上游 WS 连接上限",
|
||||
"connectionLimitHelp": "使用此代理的账号共享连接额度",
|
||||
"noRestrictionsByDefault": "默认不限制",
|
||||
"customTimeZoneLocation": "自定义时区位置",
|
||||
"affectedAccounts": "将更新 {count} 个关联账号的出口",
|
||||
"pendingResultsHelp": "待确认项可能已保存,继续添加前请刷新核对",
|
||||
"saveAction": "保存代理",
|
||||
"waitForCurrentOperationToEnd": "等待当前操作结束",
|
||||
"stopSubsequentOperations": "停止后续操作",
|
||||
"testing": "正在测试",
|
||||
"adding": "正在添加",
|
||||
"editItemsNotAdded": "修改未添加项",
|
||||
"testAddedProxies": "测试已添加的 {count} 条",
|
||||
"testAfterAdding": "添加后测试",
|
||||
"add": "添加 {count} 条",
|
||||
"addProxy": "添加代理"
|
||||
},
|
||||
"region": {
|
||||
"connectionFailed": "连接失败",
|
||||
"regionalConflict": "地区冲突",
|
||||
"parsingFailed": "解析失败",
|
||||
"exitNotRecognized": "出口未识别",
|
||||
"ipv4AndIpv6EgressTimeZonesAre": "IPv4 与 IPv6 出口时区不一致",
|
||||
"exitLocation": "出口地区:{label} · {timezone}",
|
||||
"detectHelp": "测试代理时解析出口地区",
|
||||
"customLocation": "自定义位置:{customLabel} · {timezone}",
|
||||
"custom": "自定义:{customLabel}"
|
||||
},
|
||||
"fields": {
|
||||
"exitIp": "出口 IP",
|
||||
"latency": "耗时",
|
||||
"testTime": "测试时间"
|
||||
},
|
||||
"page": {
|
||||
"description": "管理账号使用的代理,测试连接并查看出口 IP",
|
||||
"searchLabel": "搜索代理",
|
||||
"searchPlaceholder": "搜索代理名称",
|
||||
"batchTestAction": "批量测试代理",
|
||||
"batchTest": "批量测试 ({count})",
|
||||
"noMatches": "没有找到匹配的代理,请尝试其他名称",
|
||||
"empty": "暂无代理",
|
||||
"selectCurrentPageProxy": "选择当前页代理",
|
||||
"selectProxy": "选择代理 {name}",
|
||||
"credentialsSaved": "代理凭据已保存",
|
||||
"underTest": "测试中",
|
||||
"ms": "{message}(耗时 {latencyMs} ms)",
|
||||
"notTested": "未测试",
|
||||
"viewAccountsAssociatedWith": "查看 {name} 的 {count} 个关联账号",
|
||||
"disable": "确定禁用“{name}”吗?",
|
||||
"disableDescription": "关联账号的新请求将改为直连,代理配置和绑定会保留,重新启用后恢复使用",
|
||||
"delete": "确定删除“{name}”吗?",
|
||||
"deleteDescription": "将自动解除关联账号,关联账号的新请求将改为直连"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,648 @@
|
||||
{
|
||||
"settings": {
|
||||
"clientProfile": {
|
||||
"userAgent": "用户代理",
|
||||
"clientIdentitySource": "客户端身份来源",
|
||||
"globalConfiguration": "全局配置",
|
||||
"customConfiguration": "独立配置",
|
||||
"presetLoadingFailed": "预设加载失败",
|
||||
"enterIntegerFromTo": "请输入 1~{version} 的正整数",
|
||||
"clientDefault": "客户端预设",
|
||||
"useCustomUserAgent": "使用自定义用户代理",
|
||||
"cliEntry": "CLI 入口",
|
||||
"coreDefaultIdentity": "Core · 默认身份",
|
||||
"tuiInteractiveTerminal": "TUI · 交互式终端",
|
||||
"execNonInteractiveExecution": "Exec · 非交互执行",
|
||||
"versionStrategy": "版本策略",
|
||||
"followLatestVersion": "跟随最新版本",
|
||||
"customVersion": "自定义版本",
|
||||
"versionLag": "版本滞后",
|
||||
"versionLagHelp": "滞后 1~{version} 个版本,留空不滞后",
|
||||
"terminalIdentification": "终端标识",
|
||||
"leaveBlankToUseUnknown": "留空使用 unknown",
|
||||
"systemVersion": "系统版本",
|
||||
"userAgentPlaceholder": "填写完整用户代理",
|
||||
"previewAfterFillingInVersion": "填写版本后预览",
|
||||
"previewIsNotAvailableYet": "预览暂不可用",
|
||||
"resolvingClientIdentity": "正在解析客户端身份",
|
||||
"fixedIdentity": "固定身份",
|
||||
"automaticUpdates": "自动更新",
|
||||
"versionsBehind": "· 滞后 {version} 版",
|
||||
"checked": "检查于 {checkedAtDisplay}",
|
||||
"toBeChecked": "待检查",
|
||||
"updateFailedUseLastVersion": "更新失败 · 沿用上次版本",
|
||||
"clientIdentityProvider": "客户端身份 Provider",
|
||||
"upstreamIdentityPlatform": "上游身份平台",
|
||||
"clientId": "客户端 ID",
|
||||
"operatingMode": "运行模式",
|
||||
"operatingSystem": "操作系统",
|
||||
"cpuArchitecture": "CPU 架构",
|
||||
"xaiClientIdentitySource": "xAI 客户端身份来源",
|
||||
"loadFailed": "全局配置加载失败",
|
||||
"clientType": "客户端类型",
|
||||
"grokCliVersion": "Grok CLI 版本",
|
||||
"forExample": "例如:1.0.13",
|
||||
"clientIdentity": "客户端身份",
|
||||
"description": "配置网关向上游声明的客户端类型、版本与请求头"
|
||||
},
|
||||
"pricing": {
|
||||
"multiplier": "倍率",
|
||||
"clearOverrides": "清除人工覆盖",
|
||||
"setMultipliers": "批量设置倍率",
|
||||
"batch": {
|
||||
"description": "仅修改下列 {count} 个模型,不重算历史账单",
|
||||
"resetHelp": "恢复来源或内置价格,无可用价格时设为未配置",
|
||||
"multiplierHelp": "设置为此倍率,不与已有倍率相乘,0~100,最多四位小数"
|
||||
},
|
||||
"targetMultiplier": "目标倍率",
|
||||
"enterLegalMultiplier": "请输入合法倍率",
|
||||
"confirmClearOverride": "确认清除覆盖",
|
||||
"confirmSettingMultiplier": "确认设置倍率",
|
||||
"sourcePrice": "来源价",
|
||||
"textToken": "文本 Token",
|
||||
"validation": {
|
||||
"modelId": "模型 ID 必须为 1~128 字节,不含空白或控制字符",
|
||||
"tierPrices": "请完整填写该档位的四项单价:0~1000000,最多四位小数",
|
||||
"standardTier": "新模型需要配置标准档单价"
|
||||
},
|
||||
"multiplierRangeIsWithUpToFour": "倍率范围为 0~100,最多四位小数",
|
||||
"editModelPricing": "编辑模型价格",
|
||||
"addModelPricing": "添加模型价格",
|
||||
"upstreamModelId": "上游模型 ID",
|
||||
"forExampleGpt": "例如 gpt-5.4",
|
||||
"customizedMultiplier": "自定义倍率",
|
||||
"gearPrice": "档位价格",
|
||||
"priceRange": "价格档位",
|
||||
"unitPriceSource": "单价来源",
|
||||
"tier": {
|
||||
"sourceUnavailable": "此档位暂无来源价格"
|
||||
},
|
||||
"fillInUnitPrice": "填写单价",
|
||||
"pricingInstructions": "计价说明",
|
||||
"modelIdUsesNameActuallySentTo": "模型 ID 使用实际发送给上游的名称,不是客户端别名",
|
||||
"customTierHelp": "自定义档位需填写四项单价,0 表示免费,单价上限 1000000,倍率范围 0~100,最多四位小数",
|
||||
"estimateHelp": "仅调整本地估算与金额限额,不代表订阅实际扣费,保存后仅新请求生效,历史账单不变",
|
||||
"unitPrice": "{label}单价",
|
||||
"source": "来源",
|
||||
"takeEffect": "生效",
|
||||
"sync": {
|
||||
"title": "确认同步来源价目",
|
||||
"description": "仅同步所选模型的来源价格,保留自定义单价和倍率",
|
||||
"skipped": "跳过 {count} 个缺少完整价格或计价方式不匹配的模型",
|
||||
"action": "同步"
|
||||
},
|
||||
"selectAll": "全选",
|
||||
"selected": "已选 {count} / {count2}",
|
||||
"keepManualCoverage": "保留人工覆盖",
|
||||
"noChangeInSourcePrice": "来源价格没有变化",
|
||||
"skipSynchronizedModels": "跳过同步的模型",
|
||||
"confirmSynchronization": "确认同步",
|
||||
"model": "模型",
|
||||
"input": "输入",
|
||||
"output": "输出",
|
||||
"cacheRead": "缓存读取",
|
||||
"noMatchingModel": "没有匹配的模型",
|
||||
"selectModelOnThisPage": "选择本页模型",
|
||||
"select": "选择 {model}",
|
||||
"image": "· 图像",
|
||||
"editPrice": "编辑价格",
|
||||
"deletePriceList": "删除价目",
|
||||
"notSyncedYet": "尚未同步",
|
||||
"searchModel": "搜索模型",
|
||||
"searchModelId": "搜索模型 ID",
|
||||
"modelProvider": "模型提供商",
|
||||
"priceSource": "价格来源",
|
||||
"allSources": "全部来源",
|
||||
"batchOperation": "批量操作",
|
||||
"selectedCountLabel": "已选",
|
||||
"item": "项",
|
||||
"setMultiplier": "设置倍率",
|
||||
"clearOverwrite": "清除覆盖",
|
||||
"deselect": "取消选择",
|
||||
"synchronizationInstructions": "同步说明",
|
||||
"sourceHelp": "从 models.dev 获取社区价目,保留人工单价与倍率",
|
||||
"lastSynced": "最近同步:{syncTime}",
|
||||
"syncPriceList": "同步价目",
|
||||
"addModel": "添加模型",
|
||||
"unitHelp": "价格单位:USD / 百万 Token,查看定价说明",
|
||||
"unitPriceUnitUsdMTokens": "单价单位:USD / 1M Tokens",
|
||||
"priorityHelp": "人工覆盖优先于同步价目,再继承内置价格,仅影响本地估算与金额限额",
|
||||
"tableHelp": "表中为标准档生效价,图像模型显示图像 Token 价格,划线为来源价,其他档位在编辑中查看",
|
||||
"priceListFailedToLoad": "价目加载失败",
|
||||
"deleteModelPriceList": "删除模型价目",
|
||||
"deleteDescription": "删除该模型的同步与自定义价格,历史账单不变",
|
||||
"standard": "标准",
|
||||
"longContextStandard": "长上下文 · 标准",
|
||||
"longContextPriority": "长上下文 · Fast",
|
||||
"longContextUltrafast": "长上下文 · Ultrafast",
|
||||
"longContextFlex": "长上下文 · Flex",
|
||||
"imageToken": "图像 Token",
|
||||
"cacheWrites": "缓存写入",
|
||||
"builtInPriceList": "内置价目",
|
||||
"manualCoverage": "人工覆盖",
|
||||
"notConfigured": "未配置",
|
||||
"unableToLoadPriceList": "无法加载价目",
|
||||
"deleted": "模型价目已删除",
|
||||
"manualOverrideCleared": "已清除人工覆盖",
|
||||
"modelPricingSaved": "模型定价已保存",
|
||||
"synced": "来源价目已同步,人工覆盖保持不变",
|
||||
"unitLabel": "USD / 百万 Token"
|
||||
},
|
||||
"scheduling": {
|
||||
"roundRobin": "轮询",
|
||||
"autoReviewSlotsHelp": "仅对 OpenAI 账号生效,普通并发为 10、审批名额为 3 时,两类请求分别最多运行 10 个和 3 个,互不占用名额",
|
||||
"autoReviewQueueHelp": "开启独立额度后,审批请求单独排队,可超过账号队列容量,仍受总等待容量、排队超时与密钥限额约束",
|
||||
"weights": {
|
||||
"load": "负载系数",
|
||||
"loadHelp": "越大越偏向并发占用比例较低的账号",
|
||||
"quota": "剩余额度系数",
|
||||
"quotaHelp": "越大越偏向剩余额度比例较高的账号",
|
||||
"health": "健康系数",
|
||||
"healthHelp": "越大越偏向近期失败率较低的账号",
|
||||
"latency": "延迟系数",
|
||||
"latencyHelp": "越大越偏向首个有效输出较快的账号",
|
||||
"reset": "额度重置系数",
|
||||
"resetHelp": "越大越偏向即将重置额度的账号,重置时间未知或已过期时不加分",
|
||||
"queue": "排队系数",
|
||||
"queueHelp": "需要排队时,越大越偏向等待请求较少的账号,设为 0 时沿用最短队列规则"
|
||||
},
|
||||
"enterValueFromToUpToOne": "请输入 0~10 的数值,最多一位小数",
|
||||
"description": "调整账号选择偏好",
|
||||
"enabledHelp": "仅在启用智能调度后生效",
|
||||
"about": "{label}说明",
|
||||
"zeroWeightHelp": "0 表示不参与评分",
|
||||
"weightsRequired": "至少一项系数需要大于 0"
|
||||
},
|
||||
"affinity": {
|
||||
"modes": {
|
||||
"relaxed": "宽松",
|
||||
"preferred": "优先",
|
||||
"strict": "严格",
|
||||
"relaxedHelp": "宽松:会话内请求直接按调度策略选号,不优先主账号",
|
||||
"preferredHelp": "优先:会话内请求优先沿用主账号,繁忙或不可用时临时分流,不改变会话绑定",
|
||||
"strictHelp": "严格:同一会话共用账号,子线程等待当前账号,并跟随主线程换号"
|
||||
},
|
||||
"title": "亲和策略",
|
||||
"mode": "账号亲和",
|
||||
"description": "控制同一会话内的账号绑定方式",
|
||||
"accountAffinityInstructions": "账号亲和说明",
|
||||
"policyHelp": "重新选号仍遵循当前调度策略",
|
||||
"duration": "亲和时长",
|
||||
"durationHelp": "账号绑定的保留时间,成功调度后续期",
|
||||
"durationHours": "亲和时长(小时)",
|
||||
"hours": "小时",
|
||||
"maxAccountSwitches": "最大换号次数",
|
||||
"switchLimitHelp": "单请求最多换号次数,0 表示不换号"
|
||||
},
|
||||
"autoDisable": {
|
||||
"overloadProtection": "过载保护",
|
||||
"description": "上游容量类错误累计达到阈值时,暂停账号调度并进入冷却",
|
||||
"enableOverloadProtection": "启用过载保护",
|
||||
"failureCountThreshold": "失败阈值",
|
||||
"thresholdHelp": "统计窗口内累计容量类失败达到此次数后触发",
|
||||
"times": "次",
|
||||
"statisticsWindow": "统计窗口",
|
||||
"windowHelp": "每次失败后,计数有效期向后顺延",
|
||||
"statisticsWindowSeconds": "统计窗口秒数",
|
||||
"seconds": "秒",
|
||||
"cooldownTime": "冷却时长",
|
||||
"cooldownHelp": "探测失败时,按此时长延后恢复",
|
||||
"cooldownTimeInSeconds": "冷却时长秒数",
|
||||
"recoveryProbeModel": "恢复探测模型",
|
||||
"probeModelHelp": "留空选用首个可用模型",
|
||||
"requireSuccessfulProbe": "探测成功后恢复",
|
||||
"modelPlaceholder": "留空自动选择",
|
||||
"concurrencyReduction": {
|
||||
"label": "自适应并发下调",
|
||||
"helpTitle": "自适应并发下调说明",
|
||||
"description": "修改账号并发上限,恢复后不自动调高"
|
||||
}
|
||||
},
|
||||
"warmup": {
|
||||
"title": "账号预热",
|
||||
"description": "尝试启动空闲 Codex OAuth 账号的额度窗口",
|
||||
"enableDailyWarmup": "启用每日预热",
|
||||
"executionTime": "执行时间",
|
||||
"timesPlaceholder": "HH:MM,多个时间用逗号分隔",
|
||||
"scheduleLabel": "每日预热时间",
|
||||
"modelLabel": "预热模型",
|
||||
"modelHelp": "启用时必填,需为账号可用模型",
|
||||
"modelPlaceholder": "输入模型名称",
|
||||
"helpTitle": "账号预热说明",
|
||||
"help": "在设定时间向每个空闲的 Codex OAuth 账号发送一次请求,不保证额度窗口成功启动"
|
||||
},
|
||||
"adminApiKey": {
|
||||
"adminApiKey": "管理员 API Key",
|
||||
"description": "用于外部系统集成,具有管理员权限",
|
||||
"regenerate": "重新生成",
|
||||
"generate": "生成",
|
||||
"notGenerated": "未生成",
|
||||
"enabledDescription": "管理员 API 访问已启用,完整 Key 仅在生成时回显",
|
||||
"disabledDescription": "外部系统暂时无法通过 API Key 调用管理接口",
|
||||
"generatedNotice": "完整 Key 仅显示一次,请立即保存",
|
||||
"adminApiKeyUpdated": "管理员 API Key 已更新",
|
||||
"generated": "管理员 API Key 已生成",
|
||||
"adminApiKeyDeleted": "管理员 API Key 已删除"
|
||||
},
|
||||
"password": {
|
||||
"administratorPassword": "管理员密码",
|
||||
"description": "用于登录管理后台",
|
||||
"changePassword": "修改密码",
|
||||
"verifyCurrentPassword": "验证当前密码",
|
||||
"sessionNotice": "修改后,所有管理员需重新登录",
|
||||
"validation": {
|
||||
"minLength": "新密码至少需要 12 个字符",
|
||||
"unchanged": "新密码不能与当前密码相同",
|
||||
"mismatch": "两次输入的新密码不一致"
|
||||
},
|
||||
"newPasswordCannotExceedBytes": "新密码不能超过 1024 字节",
|
||||
"changed": "密码已修改,请使用新密码重新登录",
|
||||
"changeAdministratorPassword": "修改管理员密码",
|
||||
"changeDescription": "验证当前密码后,设置新的登录密码",
|
||||
"currentPassword": "当前密码",
|
||||
"enterCurrentPassword": "输入当前密码",
|
||||
"newPassword": "新密码",
|
||||
"passwordHelp": "至少 12 个字符,建议混合使用字母、数字和符号",
|
||||
"setNewPassword": "设置新密码",
|
||||
"confirmNewPassword": "确认新密码",
|
||||
"enterNewPasswordAgain": "再次输入新密码",
|
||||
"saveAndLogInAgain": "保存并重新登录"
|
||||
},
|
||||
"concurrency": {
|
||||
"title": "并发策略",
|
||||
"accountLimit": {
|
||||
"label": "默认账号并发",
|
||||
"help": "未单独设置时使用,0 不限"
|
||||
},
|
||||
"keyQueueCapacity": "密钥队列容量",
|
||||
"keyQueueHelp": "每个密钥的等待上限,0 不排队",
|
||||
"accountQueueCapacity": "账号队列容量",
|
||||
"accountQueueHelp": "每个账号的等待上限,0 不排队",
|
||||
"queueTimeoutLabel": "排队超时(秒)",
|
||||
"queueTimeoutHelp": "两个队列共用,1–120 秒",
|
||||
"autoReview": {
|
||||
"label": "自动审批独立并发",
|
||||
"description": "每个 OpenAI 账号的额外名额,0 共用普通并发",
|
||||
"helpTitle": "自动审批独立并发说明"
|
||||
},
|
||||
"queueTimeoutHelpTitle": "排队超时说明",
|
||||
"queueTimeoutDetails": "密钥与账号队列共用此时限,从首次入队起计时"
|
||||
},
|
||||
"modelMapping": "模型映射",
|
||||
"routing": {
|
||||
"modelMapHelp": "将客户端请求的模型名称映射为实际使用的上游模型"
|
||||
},
|
||||
"addMapping": "添加映射",
|
||||
"loadingModelMapping": "正在加载模型映射...",
|
||||
"requestModel": "请求模型",
|
||||
"upstreamModel": "上游模型",
|
||||
"upstreamModelName": "上游模型名称",
|
||||
"deleteMapping": "删除映射",
|
||||
"history": {
|
||||
"title": "历史保留",
|
||||
"retentionHelp": "自动删除过期请求记录及统计数据",
|
||||
"retentionConstraints": "至少 1 天,删除后不可恢复",
|
||||
"retentionDaysLabel": "历史保留天数"
|
||||
},
|
||||
"retentionDays": "保留天数",
|
||||
"enterDays": "请输入 1–31 天",
|
||||
"day": "天",
|
||||
"location": {
|
||||
"requestLocationOverride": "请求位置覆盖",
|
||||
"description": "覆盖 Codex 请求中的时区与位置字段,账号出站代理的自定义位置优先",
|
||||
"enableLocationOverlay": "启用位置覆盖"
|
||||
},
|
||||
"quotaReset": {
|
||||
"title": "主动重置卡",
|
||||
"enableHelp": "在账号的「额度重置」中开启自动使用",
|
||||
"description": "全局设置,对已开启自动使用的账号生效",
|
||||
"thresholdHelp": "高于此值时暂不自动使用,留空表示不限制",
|
||||
"weeklyQuotaLimit": "重置卡剩余周额度上限"
|
||||
},
|
||||
"advanceUsageTimeMinutes": "提前使用时间(分钟)",
|
||||
"resetCardAdvanceTime": "重置卡提前使用时间",
|
||||
"remainingWeeklyQuotaLimit": "剩余周额度上限(%)",
|
||||
"responseLimit": {
|
||||
"requestBodyLimit": "请求体限制",
|
||||
"description": "限制 Responses 请求解压后的请求体大小",
|
||||
"maximumSizeAfterDecompression": "解压后大小上限",
|
||||
"sizeHelp": "调高可接收更大的图片和历史上下文,也会增加内存占用",
|
||||
"maxSizeLabel": "解压后请求体大小上限"
|
||||
},
|
||||
"rotation": {
|
||||
"title": "调度策略",
|
||||
"customized": "自定义",
|
||||
"smartSchedulingSettings": "智能调度设置",
|
||||
"smartLabel": "智能调度",
|
||||
"smartDescription": "综合负载、剩余额度、健康和延迟评分,支持自定义评分偏好",
|
||||
"quotaResetLabel": "额度重置优先",
|
||||
"quotaResetDescription": "优先选择额度窗口更快重置的账号,适合在重置前消耗剩余额度",
|
||||
"roundRobinLabel": "轮询调度",
|
||||
"roundRobinDescription": "在可用候选账号间按顺序轮转,分配结果最可预测",
|
||||
"stickyLabel": "粘性调度",
|
||||
"stickyDescription": "优先复用最近使用的账号,直到不可用后再切换"
|
||||
},
|
||||
"access": {
|
||||
"accessRestrictions": "访问限制",
|
||||
"deleteAdminApiKey": "删除管理员 API Key",
|
||||
"deleteKeyDescription": "删除后外部系统将无法继续使用该 Key 调用管理接口",
|
||||
"areYouSureYouWantToDelete": "确定要删除当前管理员 API Key 吗?此操作会立即生效"
|
||||
},
|
||||
"tokenRefresh": {
|
||||
"title": "凭据刷新",
|
||||
"leadTimeLabel": "提前刷新(秒)",
|
||||
"leadTimeHelp": "在访问令牌到期前触发刷新",
|
||||
"concurrencyLabel": "刷新并发上限",
|
||||
"concurrencyHelp": "同时刷新的上限,调低可减少限流"
|
||||
},
|
||||
"backup": {
|
||||
"fileName": "文件名",
|
||||
"size": "大小",
|
||||
"expirationTime": "过期时间",
|
||||
"triggerMode": "触发方式",
|
||||
"startTime": "开始时间",
|
||||
"manual": "手动",
|
||||
"plan": "计划",
|
||||
"exclusions": "不包含请求明细与日志",
|
||||
"backupRecords": "备份记录",
|
||||
"backupScopeDescription": "备份范围说明",
|
||||
"contents": "保留账号、Key、设置、插件及已用额度",
|
||||
"usageRetentionHourSummary": "用量保留小时汇总",
|
||||
"creating": "创建中...",
|
||||
"createBackup": "创建备份",
|
||||
"noBackupRecordYet": "暂无备份记录",
|
||||
"downloadBackup": "下载备份",
|
||||
"deleteBackup": "删除备份",
|
||||
"deleteWarning": "将删除远端对象并移除记录,此操作不可撤销",
|
||||
"deleteConfirmation": "确定要删除备份",
|
||||
"message": "吗?",
|
||||
"schedule": {
|
||||
"backupPlan": "备份计划",
|
||||
"description": "配置自动备份的执行时间与保留策略",
|
||||
"saving": "保存中...",
|
||||
"enableScheduledBackup": "启用定时备份",
|
||||
"cronExpression": "Cron 表达式",
|
||||
"cronHelp": "5 段格式,例如 0 2 * * * 表示每天凌晨 2 点",
|
||||
"retentionDaysHelp": "超期删除,0 不限天数,仍受份数限制",
|
||||
"retentionDaysLabel": "保留天数",
|
||||
"maxBackupsLabel": "最多保留",
|
||||
"retentionCountHelp": "超额删除,0 不限份数,仍受天数限制"
|
||||
},
|
||||
"status": {
|
||||
"queuing": "排队中",
|
||||
"exporting": "导出中",
|
||||
"uploading": "上传中",
|
||||
"deleting": "删除中"
|
||||
},
|
||||
"storage": {
|
||||
"s3StorageConfiguration": "S3 存储配置",
|
||||
"connectionTestPassed": "已通过连接测试",
|
||||
"connectionTestHasNotPassed": "尚未通过连接测试",
|
||||
"testing": "测试中...",
|
||||
"endpointAddress": "端点地址",
|
||||
"endpointHelp": "S3 兼容服务的 HTTPS 地址",
|
||||
"region": "区域",
|
||||
"regionHelp": "R2 使用 auto,其他服务按提供方填写",
|
||||
"bucket": "存储桶",
|
||||
"privateBucketName": "私有存储桶名称",
|
||||
"objectKeyPrefix": "对象键前缀",
|
||||
"prefixHelp": "备份对象的存储路径前缀,不影响已有备份",
|
||||
"credentialsLabel": "对象存储专用凭据",
|
||||
"objectStorageSpecificSecret": "对象存储专用 Secret",
|
||||
"forcePathStyle": "强制路径式访问",
|
||||
"accessKeyId": "访问密钥 ID",
|
||||
"secretAccessKey": "私有访问密钥",
|
||||
"description": "配置 S3 兼容存储(支持 {service})"
|
||||
},
|
||||
"r2": {
|
||||
"cloudflareR2OnboardingGuide": "Cloudflare R2 接入指南",
|
||||
"createBucket": "1. 创建存储桶",
|
||||
"createApiToken": "2. 创建 API Token",
|
||||
"fillInConnectionParameters": "3. 填写连接参数",
|
||||
"credentialsHelp": "Access Key ID / Secret Access Key:上一步生成的 Token",
|
||||
"forcePathStyleOff": "Force Path Style:关闭",
|
||||
"completeConnectionTest": "4. 完成连接测试",
|
||||
"testDescription": "保存配置后点击「测试连接」,系统会写入一个探针对象并校验读写权限,测试通过后 才能启用自动计划或手动创建备份,凭据只保存在服务端,不会写入浏览器",
|
||||
"gotIt": "知道了",
|
||||
"bucketDescription": "在 Cloudflare Dashboard 进入 R2,创建私有存储桶(例如 {bucket}),保持关闭公共读取",
|
||||
"tokenDescription": "在「管理 API Token」创建对象存储专用 Token,仅授予目标桶的对象读取、写入、列出与删除权限",
|
||||
"endpointLabel": "Endpoint:",
|
||||
"regionDescription": "Region:{region}(R2 固定值)"
|
||||
},
|
||||
"backupTaskCreated": "备份任务已创建",
|
||||
"failedToDownloadBackup": "下载备份失败",
|
||||
"backupDeletionRequested": "已请求删除备份",
|
||||
"storageSaved": "存储配置已保存,定时备份已暂停,请测试连接后重新启用",
|
||||
"storageConfigurationSaved": "存储配置已保存",
|
||||
"connectionVerified": "连接测试通过",
|
||||
"backupPlanSaved": "备份计划已保存"
|
||||
},
|
||||
"clientVersion": {
|
||||
"macosLinuxOfficialInstaller": "macOS / Linux · 官方安装器",
|
||||
"windowsInstaller": "Windows PowerShell · 官方安装器",
|
||||
"homebrewFirstTimeInstallation": "Homebrew · 首次安装",
|
||||
"homebrewUpgrade": "Homebrew · 升级",
|
||||
"installOrUpgradeCodexCli": "安装或升级 Codex CLI",
|
||||
"cliInstallHelp": "按当前安装来源执行一种命令,官方安装器会自动选择当前平台架构",
|
||||
"selectInstallationSource": "选择安装来源",
|
||||
"cliUpgradeHelp": "重新执行对应命令即可升级到当前发布版本",
|
||||
"viewOfficialDocumentation": "查看官方文档",
|
||||
"ubuntuDebianUpgrade": "Ubuntu / Debian · 升级",
|
||||
"fedoraRhelUpgrade": "Fedora / RHEL · 升级",
|
||||
"onlineInstallationAndUpgrade": "在线安装与升级",
|
||||
"desktopUpgradeHelp": "桌面应用通常会自动更新,也可以从官方渠道重新安装",
|
||||
"officialDownloadPage": "官方下载页",
|
||||
"openAiPackageHelp": "OpenAI 官方安装包,请选择与设备一致的架构",
|
||||
"storePackageHelp": "Microsoft Store 离线安装包,请选择与设备一致的架构",
|
||||
"msixInstallHelp": "下载后使用 PowerShell 安装 / 升级",
|
||||
"sizeUnknown": "大小未知",
|
||||
"windowsOfflineInstallation": "Windows 离线安装",
|
||||
"cached": "已缓存",
|
||||
"refreshingDownloads": "正在刷新离线下载链接",
|
||||
"refreshOfflineDownloadLinks": "刷新离线下载链接",
|
||||
"loadingPackages": "正在加载离线安装包",
|
||||
"packagesFailed": "离线安装包加载失败",
|
||||
"stableChannel": "稳定通道",
|
||||
"linkExpired": "链接失效:{value}",
|
||||
"downloadMsix": "下载 {value} MSIX",
|
||||
"downloadPackage": "下载 MSIX",
|
||||
"commandCopied": "命令已复制",
|
||||
"copyCommand": "复制命令",
|
||||
"codexClientUpgrade": "Codex 客户端升级",
|
||||
"guideDescription": "先选择客户端,再查看对应的安装与升级方式",
|
||||
"clientVersionRestrictions": "客户端版本限制",
|
||||
"openGuide": "查看安装与升级说明",
|
||||
"codexDesktopMinimumVersion": "Codex Desktop 最低版本",
|
||||
"onlyCheckDesktopVersionEG": "只检查桌面端应用版本,例如 26.825.51511",
|
||||
"codexCliMinimumVersion": "Codex CLI 最低版本",
|
||||
"minimumVersionHelp": "只检查独立终端版本,例如 0.152.0"
|
||||
},
|
||||
"privacy": {
|
||||
"preview": {
|
||||
"enterValidRequestSampleJson": "请输入有效的请求样本 JSON",
|
||||
"testRules": "测试规则",
|
||||
"description": "按草稿顺序执行已启用的规则,样本仅用于本次测试",
|
||||
"requestSample": "请求样本",
|
||||
"requestPlaceholder": "粘贴包含 body、headers、turnMetadata 的请求 JSON",
|
||||
"finalResult": "最终结果",
|
||||
"ruleExecutionResults": "规则执行结果",
|
||||
"notEnabled": "未启用",
|
||||
"skipped": "已跳过"
|
||||
},
|
||||
"skipCurrentRule": "跳过当前规则",
|
||||
"blockRequestFromBeingSent": "阻止请求发送",
|
||||
"privacyPolicy": "隐私策略",
|
||||
"description": "按规则统一或移除 Codex 请求中的隐私信息",
|
||||
"enableRequestRules": "启用请求规则",
|
||||
"addRule": "添加规则",
|
||||
"addFromPreset": "从预设添加",
|
||||
"runsInListOrderRulesSteps": "按列表顺序执行 · {count} 条规则 · {count2} / 32 个步骤",
|
||||
"executionFailed": "执行失败",
|
||||
"ruleExecutionFailed": "规则执行失败",
|
||||
"ruleExecutionInstructions": "规则执行说明",
|
||||
"skipHelp": "跳过时撤销本条规则所有步骤的修改并继续执行,未完成本条脱敏",
|
||||
"overrideHelp": "允许改写选定字段,认证、会话与工具行为的影响由配置者负责",
|
||||
"rules": {
|
||||
"fillInRuleName": "请填写规则名称",
|
||||
"stepLimit": "所有规则合计最多 32 个处理步骤",
|
||||
"enterFieldPathForStep": "请填写步骤 {value} 的字段路径",
|
||||
"fixedValueForStepMustBeJson": "步骤 {value} 的固定值应为 JSON,例如 \"别名\"、false 或 123",
|
||||
"invalidSampleFormat": "样本格式无效",
|
||||
"ruleFormatIsInvalid": "规则格式无效",
|
||||
"editRule": "编辑规则",
|
||||
"description": "配置字段处理方式,预览隐私信息处理效果",
|
||||
"ruleName": "规则名称",
|
||||
"namePlaceholder": "例如:统一工作区信息",
|
||||
"currentStepSettings": "当前步骤设置",
|
||||
"testPreview": "测试预览",
|
||||
"previewOfEntireRule": "整条规则预览",
|
||||
"ruleSkipped": "规则已跳过",
|
||||
"matches": "命中 {matches} 处",
|
||||
"testThisRule": "测试本条规则",
|
||||
"test": "测试",
|
||||
"testSample": "测试样本",
|
||||
"samplePlaceholder": "粘贴包含 body、headers、turnMetadata 的请求样本",
|
||||
"afterProcessing": "处理后",
|
||||
"applyToDraft": "应用到草稿",
|
||||
"movedToPosition": "{name}已移到第 {value} 条",
|
||||
"ruleField": "规则",
|
||||
"scope": "作用范围",
|
||||
"processingMethod": "处理方式",
|
||||
"reorderHelp": "拖动手柄调整规则顺序,也可聚焦手柄后使用上下方向键移动",
|
||||
"noRulesYetAddOneOrStart": "暂无规则,添加一条或从预设开始",
|
||||
"enableRule": "启用规则:{name}",
|
||||
"edit": "编辑{name}",
|
||||
"delete": "删除{name}",
|
||||
"dragToReorder": "拖动调整{name}顺序"
|
||||
},
|
||||
"steps": {
|
||||
"pathPlaceholder": "例如:$.workspaces.*.associated_remote_urls.*",
|
||||
"forExampleRemotesFetchurl": "例如:$.remotes[*].fetchUrl",
|
||||
"environmentPathHelp": "填写 $,匹配整段环境文本",
|
||||
"forExampleMetadataWorkspace": "例如:$.metadata.workspace",
|
||||
"forExampleXClientName": "例如:x-client-name",
|
||||
"requestHeaderName": "请求头名称",
|
||||
"fieldPath": "字段路径",
|
||||
"fieldPathSyntax": "字段路径语法",
|
||||
"jsonPathHelp": "支持对象成员、双引号键名、数组索引和 * 通配,例如 $[\"workspaces\"][\"/home/alex/demo\"]",
|
||||
"targetHelp": "环境文本使用 $,请求头直接填写名称",
|
||||
"commonFields": "常用字段",
|
||||
"deleteMatchHelp": "仅删除值匹配正则的字段或数组项",
|
||||
"matchExpression": "匹配表达式",
|
||||
"forExampleHome": "例如:^/home/[^/]+/",
|
||||
"forExamplePrivateOrg": "例如:private-org",
|
||||
"replaceContent": "替换内容",
|
||||
"regularSyntaxDescription": "正则语法说明",
|
||||
"useOrForCaptureGroupsAndFor": "${'{'}1{'}'} 或 ${'{'}name{'}'} 引用捕获组,$$ 表示字面 $",
|
||||
"usesRustRegexSyntaxAndDoesNot": "使用 Rust regex 语法,不支持前后顾和模式中的反向引用",
|
||||
"forExampleHomeUser": "例如:/home/user/",
|
||||
"forExampleTeamOrLeaveBlankTo": "例如:team,留空则清除匹配内容",
|
||||
"fixedValueJson": "固定值(JSON)",
|
||||
"forExampleAnonymousNullOr": "例如:\"匿名\"、null 或 {'{'}{'}'}",
|
||||
"fixedJsonLabel": "固定值 JSON",
|
||||
"replaceAllMatches": "替换全部匹配",
|
||||
"ignoreCase": "忽略大小写",
|
||||
"matchMultipleLines": "多行匹配",
|
||||
"entireEnvironmentText": "整段环境文本",
|
||||
"fullContent": "完整内容",
|
||||
"noFieldsSelected": "未选择字段",
|
||||
"deleteHelp": "删除匹配的字段或数组项",
|
||||
"noExpressionEntered": "未填写表达式",
|
||||
"deleteAfterMatching": "匹配后删除:{value}",
|
||||
"clearMatchingContent": "清空匹配内容",
|
||||
"stepMovedToPosition": "步骤已移到第 {value} 位",
|
||||
"processingSteps": "处理步骤",
|
||||
"helpTitle": "处理步骤说明",
|
||||
"executionOrderHelp": "拖动手柄调整执行顺序,也可聚焦手柄后使用上下方向键移动",
|
||||
"eachStepCanSetScopeFieldsAnd": "每一步可分别设置作用范围、字段和处理方式,后一步基于前一步的结果处理",
|
||||
"failureHelp": "所有步骤共用规则开关,任一步骤失败会撤销本条规则的全部修改,再按失败策略跳过或阻止请求",
|
||||
"addSteps": "添加步骤",
|
||||
"reorderHelp": "拖动手柄调整步骤顺序,也可聚焦手柄后使用上下方向键移动",
|
||||
"dragStep": "拖动步骤 {value}:{field}",
|
||||
"step": "步骤 {value}:{field},{scope},{action},{effect}",
|
||||
"deleteStep": "删除步骤 {value}:{field}"
|
||||
},
|
||||
"presets": {
|
||||
"workspaceMetadata": "工作区附加信息",
|
||||
"desktopGitInformation": "Desktop Git 信息",
|
||||
"automaticEnvironmentContext": "自动环境上下文",
|
||||
"specifyRequestFields": "指定请求字段",
|
||||
"specifyRequestHeader": "指定请求头",
|
||||
"regularReplacement": "正则替换",
|
||||
"fixedValue": "固定值",
|
||||
"fieldNameReplacement": "字段名替换",
|
||||
"deleteFieldArrayItem": "删除字段 / 数组项",
|
||||
"customFieldPath": "自定义字段路径",
|
||||
"gitRemoteAddress": "Git 远端地址",
|
||||
"workspacePathKey": "工作区路径键",
|
||||
"gitCommitId": "Git 提交 ID",
|
||||
"gitRemoteCollection": "Git 远端集合",
|
||||
"workspaceFingerprint": "工作区指纹",
|
||||
"unifyWorkspaceInformation": "统一工作区信息"
|
||||
},
|
||||
"testPlaceholder": "点击测试查看结果"
|
||||
},
|
||||
"form": {
|
||||
"enterStandardSemverForExample": "请输入标准 SemVer,例如 0.152.0",
|
||||
"exitLocationFilledIn": "已填入出口位置",
|
||||
"ipv4AndIpv6ExportTimeZonesAre": "IPv4 与 IPv6 出口时区不一致,请手动填写",
|
||||
"unableToObtainExitLocation": "未获取到出口位置",
|
||||
"fillInModelMappingCompletely": "请完整填写模型映射",
|
||||
"duplicateClientModel": "存在重复的客户端模型:{requested}",
|
||||
"requiredSettings": "请完整填写并发、队列、凭据刷新参数和调度策略",
|
||||
"invalidAffinityDuration": "亲和时长应为 1~720 小时的整数",
|
||||
"invalidSwitchLimit": "最大换号次数应为 0~31 的整数,0 表示不换号",
|
||||
"invalidConcurrency": "默认账号并发上限应为 0~4294967295 的整数,0 表示不限制",
|
||||
"invalidReviewConcurrency": "自动审批独立并发应为 0~4294967295 的整数,0 表示共用普通并发",
|
||||
"invalidBodyLimit": "Responses 解压上限应为有效的正整数(MiB)",
|
||||
"invalidQuotaThreshold": "剩余周额度上限应为 0~100 的整数,留空表示不限制",
|
||||
"invalidResetLeadTime": "重置卡提前使用时间应为 1~1440 分钟的整数",
|
||||
"invalidRetention": "历史保留天数应为 1–31 的整数",
|
||||
"invalidQueueSettings": "队列容量应为 0~1000 的整数,排队超时应为 1~120 秒的整数",
|
||||
"invalidClientVersion": "请修正客户端最低版本格式",
|
||||
"overloadSettingsRequired": "请完整填写过载保护参数",
|
||||
"invalidOverloadSettings": "失败次数阈值应为 2~1000,统计窗口为 60~3600 秒,冷却时长为 300~604800 秒",
|
||||
"invalidProbeModel": "探测模型名称不能超过 128 个字符",
|
||||
"invalidWarmupTimes": "预激活时间格式无效,请输入 HH:MM 格式(如 08:00 或 08:00,13:00)",
|
||||
"warmupModelRequired": "启用预激活时请选择模型",
|
||||
"invalidWarmupModel": "预激活模型名称不能超过 128 个字符",
|
||||
"settingsSaved": "设置已保存"
|
||||
},
|
||||
"page": {
|
||||
"tabs": {
|
||||
"runtime": "运行设置",
|
||||
"upstream": "上游配置",
|
||||
"pricing": "模型定价",
|
||||
"access": "安全与访问",
|
||||
"backups": "数据备份"
|
||||
},
|
||||
"description": "配置网关调度、上游与定价,管理访问安全、历史保留与备份",
|
||||
"sectionsLabel": "设置分区",
|
||||
"undoAllBasicSettingsChanges": "撤销全部基础设置更改",
|
||||
"saveChanges": "保存基础设置",
|
||||
"settingsLoadingFailed": "设置加载失败",
|
||||
"reload": "重新加载",
|
||||
"basicSettings": "基础设置"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"systemUpdate": {
|
||||
"channels": {
|
||||
"stable": {
|
||||
"label": "Stable · 正式",
|
||||
"description": "仅正式版本"
|
||||
},
|
||||
"rc": {
|
||||
"label": "RC · 候选",
|
||||
"description": "包含 RC 和正式版本"
|
||||
},
|
||||
"beta": {
|
||||
"label": "Beta · 测试",
|
||||
"description": "包含 Beta、RC 和正式版本"
|
||||
},
|
||||
"alpha": {
|
||||
"label": "Alpha · 早期",
|
||||
"description": "包含所有常规预发布和正式版本"
|
||||
},
|
||||
"experimental": {
|
||||
"label": "Exp · 实验",
|
||||
"description": "仅当前实验线"
|
||||
},
|
||||
"loading": "正在读取运行通道",
|
||||
"label": "更新通道",
|
||||
"help": "更新通道说明",
|
||||
"description": "选择仅用于本次检查,重新打开时按运行版本选择通道,不会自动安装或降级"
|
||||
},
|
||||
"feedback": {
|
||||
"available": "发现可用更新",
|
||||
"noUpdates": "当前没有可用更新",
|
||||
"started": "更新已开始"
|
||||
},
|
||||
"errors": {
|
||||
"remoteTargetMissing": "远端目标版本为空",
|
||||
"infoPending": "请等待系统更新信息加载完成",
|
||||
"preRestartCheck": "重启前检查失败",
|
||||
"restart": "重启失败,请重新检查",
|
||||
"unconfirmed": "尚未确认更新任务,请检查状态后重试",
|
||||
"updateFailed": "更新失败",
|
||||
"startTimeout": "服务未在预期时间内启动 v{version}",
|
||||
"activationTargetMissing": "缺少待生效的目标版本"
|
||||
},
|
||||
"title": "系统更新",
|
||||
"description": "检查版本、查看发布说明并执行在线更新",
|
||||
"application": "应用包更新",
|
||||
"releasePage": "发布页",
|
||||
"status": {
|
||||
"checkingVersion": "正在检查版本",
|
||||
"lastFailed": "上次操作失败",
|
||||
"updating": "更新中",
|
||||
"restarting": "重启中",
|
||||
"checking": "检查中",
|
||||
"restartRequired": "待重启",
|
||||
"available": "有可用更新",
|
||||
"upToDate": "无可用更新",
|
||||
"notChecked": "未检查",
|
||||
"retrying": "暂时无法确认更新状态,正在重试",
|
||||
"confirmingStart": "正在确认更新是否已开始"
|
||||
},
|
||||
"targetVersion": "目标版本 v{version}",
|
||||
"releaseNotes": "发布说明",
|
||||
"progress": "更新进度",
|
||||
"actions": {
|
||||
"check": "检查更新",
|
||||
"install": "下载并更新",
|
||||
"continueRestart": "继续重启",
|
||||
"restart": "立即重启"
|
||||
},
|
||||
"plugins": {
|
||||
"title": "插件兼容性提醒",
|
||||
"description": "重启后保留启用配置,逐个尝试启动插件",
|
||||
"incompatible": "不兼容插件"
|
||||
},
|
||||
"versionAfterRestart": "重启后版本",
|
||||
"confirmation": {
|
||||
"newerVersion": "发现新的更新版本",
|
||||
"channelChanged": "所选通道的最新版本已变化",
|
||||
"title": "确认更新",
|
||||
"description": "点击确认后弹窗会关闭,并按远端最新目标版本开始更新"
|
||||
},
|
||||
"logs": {
|
||||
"live": "实时",
|
||||
"disconnectedState": "断开",
|
||||
"waiting": "待连接",
|
||||
"disconnected": "更新日志连接中断",
|
||||
"parseFailed": "更新日志解析失败",
|
||||
"unsupported": "当前浏览器不支持实时更新日志",
|
||||
"timeout": "更新日志连接超时"
|
||||
},
|
||||
"currentVersion": "当前版本",
|
||||
"latestVersion": "通道最新",
|
||||
"build": "构建",
|
||||
"deployment": "部署",
|
||||
"displayedTarget": "已显示目标",
|
||||
"remoteTarget": "远端最新目标",
|
||||
"buildTypes": {
|
||||
"release": "正式构建",
|
||||
"source": "源码构建",
|
||||
"dev": "开发构建",
|
||||
"experimental": "实验构建"
|
||||
},
|
||||
"deploymentModes": {
|
||||
"docker": "Docker",
|
||||
"binary": "二进制",
|
||||
"source": "源码运行"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
{
|
||||
"usage": {
|
||||
"health": {
|
||||
"point": {
|
||||
"serviceFailed": "服务失败",
|
||||
"clientCancel": "客户端取消",
|
||||
"callerError": "调用方错误",
|
||||
"requestHealthDetailsFor": "{time} 请求健康详情",
|
||||
"minutes": "15 分钟",
|
||||
"validRequestAvailability": "有效请求可用性",
|
||||
"validRequest": "有效请求"
|
||||
},
|
||||
"validRequestsAvailability": "{time},{label},有效请求 {count},可用性 {reliabilityDisplay}",
|
||||
"hours": "小时",
|
||||
"day": "天",
|
||||
"serviceSuccessRate": "服务成功率",
|
||||
"notCompleted": "未完成",
|
||||
"requestVolume": "请求量",
|
||||
"noServiceResult": "无服务结果",
|
||||
"title": "请求健康",
|
||||
"description": "请求状态分布 · {granularityText}",
|
||||
"completionRate": "完成率",
|
||||
"abnormalEnd": "非正常结束",
|
||||
"loading": "正在加载请求数据",
|
||||
"empty": "当前范围暂无请求"
|
||||
},
|
||||
"billing": {
|
||||
"serviceLevel": "服务档位",
|
||||
"totalCost": "总费用",
|
||||
"standardFee": "标准费用",
|
||||
"textInputCost": "文本输入费用",
|
||||
"inputCost": "输入费用",
|
||||
"imageInputFee": "图像输入费用",
|
||||
"imageCachingCharges": "图像缓存费用",
|
||||
"imageInputUnitPrice": "图像输入单价",
|
||||
"imageCacheUnitPrice": "图像缓存单价",
|
||||
"imageOutputFee": "图像输出费用",
|
||||
"outputFee": "输出费用",
|
||||
"textInputUnitPrice": "文本输入单价",
|
||||
"inputUnitPrice": "输入单价",
|
||||
"imageOutputUnitPrice": "图像输出单价",
|
||||
"outputUnitPrice": "输出单价",
|
||||
"textCacheReadCost": "文本缓存读取费用",
|
||||
"cacheReadCost": "缓存读取费用",
|
||||
"cacheWriteCost": "缓存写入费用",
|
||||
"cacheWriteUnitPrice": "缓存写入单价",
|
||||
"fastMode": "Fast 模式",
|
||||
"longContextBillingDetails": "长上下文计费明细",
|
||||
"billingDetails": "计费明细",
|
||||
"viewLongContextBillingDetails": "查看长上下文计费明细",
|
||||
"viewCostDetails": "查看费用明细"
|
||||
},
|
||||
"ttft": "TTFT",
|
||||
"latency": {
|
||||
"totalLatency": "总耗时",
|
||||
"viewLatencyDetails": "查看延迟明细",
|
||||
"official": "官方",
|
||||
"local": "本地",
|
||||
"total": "总耗时"
|
||||
},
|
||||
"performance": {
|
||||
"ttftHelp": "TTFT:首个 Token 耗时",
|
||||
"scheduling": "调度",
|
||||
"admissionP95": "准入 P95",
|
||||
"accountSelectionP95": "选号 P95",
|
||||
"capacityP95": "容量 P95",
|
||||
"decisionCoverage": "判定覆盖",
|
||||
"accountSelectionCoverage": "选号覆盖",
|
||||
"capacityCoverage": "容量覆盖",
|
||||
"title": "响应性能",
|
||||
"description": "延迟、速率与调度分位",
|
||||
"performanceIndicators": "性能指标",
|
||||
"loading": "正在加载性能数据",
|
||||
"noTtftSamples": "当前范围暂无 TTFT 样本",
|
||||
"noThroughput": "当前范围暂无速率样本",
|
||||
"noScheduling": "当前范围暂无调度或容量样本",
|
||||
"noLatency": "当前范围暂无延迟样本"
|
||||
},
|
||||
"reasoning": {
|
||||
"subagentRequest": "子代理请求",
|
||||
"reviewSubagentRequest": "Review 子代理请求"
|
||||
},
|
||||
"filters": {
|
||||
"error": "错误",
|
||||
"requestDetailType": "请求明细类型",
|
||||
"label": "使用记录筛选与操作",
|
||||
"refreshUsageHistory": "刷新使用记录",
|
||||
"keyName": "密钥名称",
|
||||
"account": "账号",
|
||||
"fieldLabel": "请求明细筛选字段",
|
||||
"enterFilterValue": "输入筛选内容",
|
||||
"valueLabel": "请求明细筛选内容"
|
||||
},
|
||||
"route": {
|
||||
"compressionRequest": "压缩请求"
|
||||
},
|
||||
"tokens": {
|
||||
"enterToken": "普通输入 Token",
|
||||
"outputToken": "输出 Token",
|
||||
"cacheReadTokens": "缓存读取 Token",
|
||||
"cacheWriteTokens": "缓存写入 Token",
|
||||
"reasoningToken": "推理 Token",
|
||||
"tokenDetails": "Token 明细",
|
||||
"viewTokenDetails": "查看 Token 明细",
|
||||
"totalTokens": "总 Token"
|
||||
},
|
||||
"fields": {
|
||||
"model": "模型",
|
||||
"reasoningEffort": "推理强度",
|
||||
"endpoint": "端点",
|
||||
"upstream": "上游",
|
||||
"access": "接入",
|
||||
"cost": "费用",
|
||||
"latency": "延迟",
|
||||
"time": "时间",
|
||||
"keyName": "密钥名称",
|
||||
"subscription": "订阅",
|
||||
"platformType": "平台"
|
||||
},
|
||||
"outputThroughput": "输出速率",
|
||||
"noValidSample": "无有效样本",
|
||||
"notReachable": "不可达",
|
||||
"unstable": "不稳定",
|
||||
"lowSample": "低样本",
|
||||
"stable": "稳定",
|
||||
"future": "未来",
|
||||
"status": {
|
||||
"mappedModel": "网关映射后发送给上游的模型:{secondary}",
|
||||
"returnedModel": "上游返回模型:{returned}(与网关映射后发送的模型一致)",
|
||||
"returnedModelHelp": "上游返回模型:{returned}",
|
||||
"firstOutputWaiting": "首个输出等待",
|
||||
"reasoningToText": "推理到正文",
|
||||
"firstOneIsOutputToText": "首个输出到正文",
|
||||
"textToCompletion": "正文到完成",
|
||||
"completedAfterFirstOutput": "首个输出后完成",
|
||||
"admissionDecision": "准入判定",
|
||||
"accountSelectionWaiting": "账号选择等待",
|
||||
"transferDecisionWaiting": "传输决策等待",
|
||||
"websocketConnection": "WebSocket 连接",
|
||||
"upstreamResponseHeader": "上游响应头",
|
||||
"firstUpstreamEvent": "首个上游事件",
|
||||
"accountSlotSnapshot": "账号槽位快照",
|
||||
"processingTime": "处理耗时",
|
||||
"apiOverhead": "API 开销",
|
||||
"engineTime": "引擎耗时",
|
||||
"upstreamPerformance": "上游性能",
|
||||
"requestObservation": "请求观测",
|
||||
"transport": "传输观测",
|
||||
"cancelled": "已取消",
|
||||
"requestedModel": "请求模型:{model}"
|
||||
},
|
||||
"balanceUnavailable": "未提供余额",
|
||||
"quota": "额度",
|
||||
"usage": "用量",
|
||||
"averageTtft": "平均 TTFT",
|
||||
"budget": {
|
||||
"todaySQuota": "今日额度",
|
||||
"weeklyQuota": "周额度",
|
||||
"quotaOverview": "额度概览",
|
||||
"noLimit": "不限额",
|
||||
"remaining": "剩余 / {value}",
|
||||
"used": "已用 {rate}%",
|
||||
"usedAmount": "已用 {value}",
|
||||
"resetTime": "重置时间",
|
||||
"timingStartsAfterFirstUse": "首次使用后开始计时",
|
||||
"concurrencyLimit": "并发上限",
|
||||
"requestsPerMinute": "RPM"
|
||||
},
|
||||
"header": {
|
||||
"currentKey": "当前密钥",
|
||||
"keyPrefix": "密钥前缀",
|
||||
"keyConfiguration": "密钥配置",
|
||||
"statisticsTimeRange": "统计时间范围",
|
||||
"today": "今天",
|
||||
"lastDays": "近 7 天",
|
||||
"lastThirtyDays": "近 30 天",
|
||||
"automaticRefreshFrequency": "自动刷新频率",
|
||||
"refreshEveryS": "30 秒刷新",
|
||||
"refreshInterval": "60 秒刷新",
|
||||
"pauseRefresh": "暂停刷新",
|
||||
"refreshUsage": "刷新用量",
|
||||
"switchTheme": "切换主题"
|
||||
},
|
||||
"records": {
|
||||
"requestLog": "请求日志",
|
||||
"currentRequestRecord": "当前请求记录",
|
||||
"refreshFailed": "请求日志刷新失败,暂时保留上次结果",
|
||||
"loadFailed": "请求日志加载失败,请点击顶部刷新重试",
|
||||
"noRecordsMatchTheseFilters": "所选条件下暂无记录"
|
||||
},
|
||||
"page": {
|
||||
"cacheHitRate": "Token 命中率",
|
||||
"loadingUsage": "正在加载用量",
|
||||
"usageSummaryLoading": "用量汇总加载中",
|
||||
"usageTrends": "使用趋势",
|
||||
"changesInUsageOverTime": "用量随时间的变化",
|
||||
"requestHealthTimeline": "请求健康时间线",
|
||||
"updated": "更新于 {asOfDisplay}",
|
||||
"temporarilyRetainLastResult": ",暂时保留上次结果",
|
||||
"clickRefreshAtTopToTryAgain": ",请点击顶部刷新重试",
|
||||
"description": "查看请求用量、性能趋势与调用错误记录",
|
||||
"dateRangeLabel": "统计日期范围,仅可选择最近 31 天",
|
||||
"requestDetails": "请求明细",
|
||||
"recordsDescription": "成功请求与失败请求明细",
|
||||
"failedToLoad": "加载失败:{error}",
|
||||
"noRequestsMatchTheseFilters": "所选条件下暂无请求记录",
|
||||
"viewErrorDetails": "查看错误详情",
|
||||
"viewUsageRecordDetails": "查看使用记录详情"
|
||||
},
|
||||
"summary": {
|
||||
"usageSummary": "用量汇总",
|
||||
"consumeTokens": "消耗 Tokens",
|
||||
"totalRequests": "总请求",
|
||||
"totalCost": "总成本",
|
||||
"usageDetails": "用量明细"
|
||||
},
|
||||
"trends": {
|
||||
"cost": "成本",
|
||||
"cacheHit": "缓存命中",
|
||||
"empty": "所选时间内暂无请求"
|
||||
},
|
||||
"configuration": {
|
||||
"copiedToClipboard": "已复制到剪贴板"
|
||||
},
|
||||
"metrics": {
|
||||
"notPriced": "未定价",
|
||||
"newInput": "普通输入",
|
||||
"output": "输出",
|
||||
"cacheCreation": "缓存创建",
|
||||
"reasoning": "推理"
|
||||
},
|
||||
"firstTokenLatency": "TTFT",
|
||||
"diagnostics": {
|
||||
"downloadDiagnosticPackage": "下载诊断包",
|
||||
"key": "密钥",
|
||||
"transport": "传输",
|
||||
"dimensions": "维度",
|
||||
"request": "请求",
|
||||
"performance": "性能",
|
||||
"title": "热点诊断",
|
||||
"groupBy": "按{resultDimensionLabel}聚合",
|
||||
"diagnosticDimension": "诊断维度",
|
||||
"noDiagnosticDataYet": "暂无诊断数据",
|
||||
"successful": "成功 {count}",
|
||||
"failed": "失败 {count} 次",
|
||||
"failureRate": "失败率 {rate}",
|
||||
"retryRate": "重试率 {rate}",
|
||||
"retries": "重试 {count}",
|
||||
"loading": "正在加载诊断数据",
|
||||
"empty": "当前范围暂无诊断数据"
|
||||
},
|
||||
"cost": {
|
||||
"savings": "节省",
|
||||
"cache": "缓存",
|
||||
"cacheSavings": "缓存节省",
|
||||
"cacheTokenProportion": "缓存 Token 占比",
|
||||
"hitRequestRate": "请求命中率",
|
||||
"actualCost": "费用",
|
||||
"withoutCacheEstimate": "无缓存估算",
|
||||
"costEfficiency": "成本效率",
|
||||
"description": "费用、缓存节省与服务层溢价",
|
||||
"costView": "成本视图",
|
||||
"tierPremium": "层级溢价",
|
||||
"perSuccessfulRequest": "每次成功请求",
|
||||
"costCoverage": "费用覆盖",
|
||||
"loading": "正在加载费用数据",
|
||||
"empty": "当前范围暂无费用或缓存节省数据"
|
||||
},
|
||||
"error": {
|
||||
"noDetails": "未记录具体错误消息",
|
||||
"platform": "平台",
|
||||
"requestModel": "请求模型",
|
||||
"upstreamModel": "上游模型",
|
||||
"clientTransfer": "客户端传输",
|
||||
"upstreamTransport": "上游传输",
|
||||
"clientStatusCode": "客户端状态码",
|
||||
"upstreamStatusCode": "上游状态码",
|
||||
"requestId": "请求 ID",
|
||||
"upstreamRequestId": "上游请求 ID",
|
||||
"responseId": "响应 ID",
|
||||
"clientKeyId": "客户端 Key ID",
|
||||
"errorCode": "错误码",
|
||||
"failureClassification": "失败分类",
|
||||
"duration": "耗时",
|
||||
"triggerMode": "触发方式",
|
||||
"sendStatus": "发送状态",
|
||||
"errorDetails": "错误详情",
|
||||
"description": "失败原因与请求上下文",
|
||||
"responseIsNotComplete": "响应未完成",
|
||||
"requestFailed": "请求失败",
|
||||
"requestContext": "请求上下文",
|
||||
"errorLocation": "错误定位",
|
||||
"attempts": "尝试记录",
|
||||
"attemptRecordMayBeIncomplete": "尝试记录可能不完整",
|
||||
"attempt": "尝试 {index}",
|
||||
"diagnosticData": "诊断数据",
|
||||
"responseContent": "响应内容",
|
||||
"metadata": "元数据"
|
||||
},
|
||||
"insights": {
|
||||
"useStatisticalObservations": "使用统计观测"
|
||||
},
|
||||
"request": {
|
||||
"statusCode": "状态码",
|
||||
"message": "消息",
|
||||
"upstreamTimeConsumption": "上游耗时",
|
||||
"storageModel": "存储模型",
|
||||
"upstreamReturnModel": "上游返回模型",
|
||||
"clientIp": "客户端 IP",
|
||||
"eventType": "事件类型",
|
||||
"trySerialNumber": "尝试序号",
|
||||
"accountId": "账号 ID",
|
||||
"serialNumber": "序号",
|
||||
"result": "结果",
|
||||
"textInput": "文本输入",
|
||||
"input": "输入",
|
||||
"imageOutput": "图像输出",
|
||||
"textCacheRead": "文本缓存读取",
|
||||
"cacheRead": "缓存读取",
|
||||
"cacheWrites": "缓存写入",
|
||||
"textCacheUnitPrice": "文本缓存单价",
|
||||
"cacheUnitPrice": "缓存单价",
|
||||
"nonInferentialOutput": "非推理输出",
|
||||
"totalOutput": "总输出",
|
||||
"noneYet": "暂无",
|
||||
"usageRecordDetails": "使用记录详情",
|
||||
"description": "单次请求的完整链路信息",
|
||||
"requestInformation": "请求信息",
|
||||
"transportAndUsage": "传输与用量",
|
||||
"modelsAndRouting": "模型与路由",
|
||||
"clientAndUpstream": "客户端与上游",
|
||||
"requestId": "请求 ID",
|
||||
"incompleteDetails": "明细不完整",
|
||||
"total": "总计",
|
||||
"requestContent": "请求内容",
|
||||
"inProgress": "进行中"
|
||||
},
|
||||
"successfulRequest": "成功请求",
|
||||
"withinFilterRange": "筛选范围内",
|
||||
"inputOutput": "输入 {inputTokens} / 输出 {outputTokens}",
|
||||
"cachedTokens": "缓存 Token",
|
||||
"cacheReadHit": "缓存读取命中",
|
||||
"averageTimeTaken": "平均耗时",
|
||||
"successfulRequestAverage": "成功请求平均值",
|
||||
"usageOverview": "使用概览",
|
||||
"noUsageRecords": "暂无使用记录"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,620 @@
|
||||
{
|
||||
"accounts": {
|
||||
"quota": {
|
||||
"usageInThisWindow": "窗口消耗:{localUsageDisplay}",
|
||||
"quotaUsed": "額度已使用:{rate}",
|
||||
"resets": "重置時間: {resetAtDisplay}",
|
||||
"unobserved": "額度待觀測",
|
||||
"dailyRequests": "日請求",
|
||||
"requests": "{localRequestLabel} {localRequestDisplay} 次",
|
||||
"h": "{duration} 小時",
|
||||
"d": "{duration} 天",
|
||||
"s": "{duration} 秒",
|
||||
"unlimited": "無限",
|
||||
"noPointsAvailableYet": "暫無可用點數",
|
||||
"quotaPoints": "額度點數",
|
||||
"point": "點",
|
||||
"requestsInThisWindow": "窗口請求:{requestDisplay} 次",
|
||||
"requestCount": "{requestDisplay} 次",
|
||||
"statisticalRange": "統計範圍",
|
||||
"rolling": "滾動 {duration}",
|
||||
"awaitingData": "待觀測",
|
||||
"remaining": "剩餘 {remaining}%",
|
||||
"usageLimit": "使用限額",
|
||||
"reset": "重置:",
|
||||
"remainingQuota": "{label}剩餘額度",
|
||||
"accountLimit": "賬號額度",
|
||||
"quota": "{provider} 額度",
|
||||
"lastRefreshed": "最近刷新: {refreshedAtDisplay}",
|
||||
"viewPersonalInformation": "查看個人信息",
|
||||
"forecastWeeklyMonthlyQuota": "預測周/月額度",
|
||||
"queryUnsupported": "暫不支持查詢上游額度",
|
||||
"quotaDetails": "額度詳情",
|
||||
"viewDetails": "查看{detailTitle}詳情",
|
||||
"details": "{detailTitle}詳情",
|
||||
"statisticalMethod": "統計方式",
|
||||
"rollingWindow": "滾動窗口",
|
||||
"windowConsumption": "窗口消耗",
|
||||
"resetTime": "重置時間",
|
||||
"localTokens": "本地累計總 Token",
|
||||
"unavailableHelp": "上游額度未提供,綠色條不表示剩餘額度",
|
||||
"totalTokensFor": "{windowLabelDisplay}總 Token",
|
||||
"usageRateHelp": "最近使用額度的當前已用比例",
|
||||
"usageRate": "使用率",
|
||||
"moreGroups": "另有 {count} 個額度組,可展開賬號查看",
|
||||
"windows": {
|
||||
"fiveHour": "5h 額度",
|
||||
"daily": "日額度",
|
||||
"weekly": "周額度",
|
||||
"monthly": "月額度",
|
||||
"annual": "年額度",
|
||||
"usage": "用量上限",
|
||||
"secondary": "次級用量上限",
|
||||
"duration": "{duration}額度"
|
||||
}
|
||||
},
|
||||
"account": "賬號",
|
||||
"connectionTest": {
|
||||
"duration": "響應耗時",
|
||||
"title": "測試連接",
|
||||
"description": "驗證賬號憑據、身份綁定與上游模型端點是否可用",
|
||||
"model": "測試模型",
|
||||
"refreshModels": "刷新上游模型",
|
||||
"loadingModels": "加載模型中",
|
||||
"modelPlaceholder": "選擇上游模型",
|
||||
"noModels": "上游沒有返回模型",
|
||||
"running": "檢測中",
|
||||
"completedAt": "完成時間",
|
||||
"events": {
|
||||
"title": "事件軌跡",
|
||||
"request": "發起請求",
|
||||
"response": "接收響應內容",
|
||||
"completed": "響應完成"
|
||||
},
|
||||
"diagnostics": "原始診斷",
|
||||
"retry": "重新測試",
|
||||
"start": "開始測試",
|
||||
"errors": {
|
||||
"invalidRequest": "測試請求不合法",
|
||||
"unsupported": "當前 Provider 不支持連接測試",
|
||||
"credentials": "賬號憑據無效",
|
||||
"policyRejected": "測試請求被網關策略拒絕",
|
||||
"modelNotFound": "測試模型不存在",
|
||||
"accountUnavailable": "指定賬號當前不可用於連接測試",
|
||||
"capacityUnavailable": "指定賬號當前沒有可用容量",
|
||||
"infrastructureUnavailable": "Provider 本地基礎設施暫不可用",
|
||||
"rateLimited": "上游請求過於頻繁",
|
||||
"upstreamUnavailable": "上游服務暫不可用",
|
||||
"timeout": "上游請求超時",
|
||||
"canceled": "測試請求已取消",
|
||||
"internal": "網關內部錯誤",
|
||||
"unknown": "未分類錯誤",
|
||||
"failed": "測試連接失敗",
|
||||
"modelRequired": "未選擇模型",
|
||||
"browserUnsupported": "當前瀏覽器不支持連接測試",
|
||||
"missingCompletion": "測試連接未返回完成事件",
|
||||
"invalidResponse": "測試響應解析失敗",
|
||||
"disconnected": "測試連接已斷開"
|
||||
},
|
||||
"stages": {
|
||||
"gateway": "網關校驗",
|
||||
"provider": "Provider 本地準備",
|
||||
"upstream": "上游響應"
|
||||
},
|
||||
"failed": "測試失敗",
|
||||
"testing": "正在測試",
|
||||
"runningDescription": "正在向所選模型發送請求並接收流式響應",
|
||||
"successTitle": "連接正常",
|
||||
"completedDescription": "請求已完成,可在下方查看模型、耗時和事件軌跡",
|
||||
"failedDescription": "請求未完成,請在下方查看失敗來源與原始診斷",
|
||||
"readyTitle": "準備測試",
|
||||
"readyDescription": "選擇模型後,點擊“開始測試”發送真實請求",
|
||||
"starting": "開始測試 {value}",
|
||||
"emptyResponse": "上游已完成,沒有返回文本內容",
|
||||
"testCompleted": "測試完成",
|
||||
"modelsRefreshed": "已刷新 {count} 個上游模型",
|
||||
"noModelsAvailable": "沒有可測試模型"
|
||||
},
|
||||
"credentials": {
|
||||
"wsFirst": "WS 優先",
|
||||
"accountName": "賬號名稱",
|
||||
"enterUpstreamName": "輸入上游名稱",
|
||||
"baseUrlHelp": "填寫 API 前綴,接口路徑會自動追加",
|
||||
"apiPrefix": "API 前綴",
|
||||
"apiKeyPlaceholder": "留空保留當前密鑰",
|
||||
"enterUpstreamKey": "輸入上游密鑰",
|
||||
"transportLabel": "傳輸方式",
|
||||
"webSocketHelp": "WS 優先需要上游支持 Responses WebSocket",
|
||||
"nameRequired": "請輸入賬號名稱",
|
||||
"validation": {
|
||||
"urlLength": "上游 API 地址不能超過 2048 個字符",
|
||||
"urlFormat": "請輸入不含認證、查詢參數或片段的 HTTP 或 HTTPS 地址",
|
||||
"urlRequired": "請輸入完整的上游 API 地址",
|
||||
"apiKeyFormat": "API Key 不能包含空格或控制字符",
|
||||
"transportRequired": "請選擇傳輸方式"
|
||||
},
|
||||
"apiKeyRequired": "請輸入 API Key"
|
||||
},
|
||||
"batchEdit": {
|
||||
"title": "批量編輯賬號",
|
||||
"selectionTitle": "編輯 {count} 個賬號",
|
||||
"saveChanges": "保存更改",
|
||||
"proxyRequired": "請選擇已通過測試的代理",
|
||||
"saved": "已更新 {count} 個賬號",
|
||||
"staleAccount": "賬號 {accountId} 的頁面數據已失效,請重新選擇"
|
||||
},
|
||||
"capacity": {
|
||||
"concurrentRequestsLimit": "賬號併發佔用 {value},上限 {value2}",
|
||||
"viewConcurrencyDetails": "{label},查看併發明細",
|
||||
"viewDetails": "{label},查看明細"
|
||||
},
|
||||
"concurrency": {
|
||||
"title": "併發明細",
|
||||
"description": "當前正在處理的請求",
|
||||
"unavailable": "暫時無法讀取併發明細",
|
||||
"empty": "當前沒有併發佔用",
|
||||
"key": "密鑰",
|
||||
"model": "模型",
|
||||
"sourceIp": "來源 IP",
|
||||
"startTime": "開始時間",
|
||||
"elapsed": "佔用時長"
|
||||
},
|
||||
"editor": {
|
||||
"title": "編輯賬號",
|
||||
"transportLabel": "上游傳輸方式",
|
||||
"upstreamConnection": "上游連接",
|
||||
"loadError": "上游設置讀取失敗",
|
||||
"notesHelp": "最多 500 字,留空可清除備註",
|
||||
"oauthUnavailable": "該賬號沒有 OAuth 上游設置",
|
||||
"apiKeyUnavailable": "該賬號沒有 API Key 上游設置",
|
||||
"saved": "賬號已更新"
|
||||
},
|
||||
"filters": {
|
||||
"allGroups": "全部分組",
|
||||
"ungroupedAccounts": "未分組賬號",
|
||||
"disabled": "{name}(已禁用)",
|
||||
"label": "賬號篩選與操作",
|
||||
"searchLabel": "搜索賬號",
|
||||
"statusLabel": "按賬號狀態篩選",
|
||||
"groupLabel": "按賬號分組篩選",
|
||||
"deleteSelected": "刪除選中 ({count})",
|
||||
"exportSelected": "導出選中 ({count})",
|
||||
"importTasks": "導入任務",
|
||||
"importAccount": "導入賬號"
|
||||
},
|
||||
"modelAccess": {
|
||||
"reserve": "保留",
|
||||
"allowlist": "白名單",
|
||||
"blocklist": "黑名單",
|
||||
"modelLimitations": "模型限制",
|
||||
"refreshModel": "刷新模型",
|
||||
"modelRestrictionMode": "模型限制模式",
|
||||
"searchOrAddModels": "搜索或添加模型",
|
||||
"searchOrEnterIdAndPressEnter": "搜索或輸入 ID,回車添加",
|
||||
"selectModel": "選擇模型",
|
||||
"notInCurrentModelCatalog": "{id}(當前目錄未返回)",
|
||||
"loadingModel": "加載模型中…",
|
||||
"noMatchingModels": "無匹配模型",
|
||||
"noModels": "暫無模型",
|
||||
"modelListLoadingFailed": "模型列表加載失敗",
|
||||
"retryHint": "請刷新後重試",
|
||||
"selectOrAddAtLeastOneModel": "請至少選擇或添加一個模型",
|
||||
"configureUpToModels": "最多配置 256 個模型",
|
||||
"invalidModelId": "請使用有效的精確模型 ID,不支持通配符",
|
||||
"enterValidExactModelIdUpTo": "請輸入有效的精確模型 ID,最多 256 字節,不支持通配符"
|
||||
},
|
||||
"notes": {
|
||||
"viewAccountNotes": "查看賬號備註",
|
||||
"title": "賬號備註"
|
||||
},
|
||||
"overview": {
|
||||
"totalAccounts": "總賬號",
|
||||
"accountPoolSize": "賬號池規模",
|
||||
"availableAccounts": "可用賬號",
|
||||
"availableHelp": "可參與調度",
|
||||
"quotaLimited": "額度受限",
|
||||
"waitingForQuota": "等待額度恢復",
|
||||
"pending": "待處理",
|
||||
"disabledError": "已停用 / 錯誤"
|
||||
},
|
||||
"proxy": {
|
||||
"keepCurrent": "保持當前",
|
||||
"keepExisting": "保留各賬號的連接設置",
|
||||
"directConnection": "直連",
|
||||
"notUsingProxy": "不使用代理",
|
||||
"disabledSuffix": "(已禁用)",
|
||||
"testFailed": "(測試失敗)",
|
||||
"notTested": "(未測試)",
|
||||
"outboundTunnel": "出站隧道"
|
||||
},
|
||||
"scheduling": {
|
||||
"scheduling": "調度",
|
||||
"switchAccountSchedule": "切換賬號調度",
|
||||
"concurrencyLimit": "併發限制",
|
||||
"accountConcurrencyLimit": "賬號併發限制",
|
||||
"defaultHint": "留空使用默認值",
|
||||
"weight": "權重",
|
||||
"accountSchedulingWeight": "賬號調度權重",
|
||||
"weightHelp": "數值越高越優先,最高 100",
|
||||
"groupLabel": "所屬分組",
|
||||
"invalidConcurrency": "併發限制必須留空,或爲 1 到 {value} 的整數",
|
||||
"weightMustBeIntegerFromTo": "權重必須是 1 到 100 的整數"
|
||||
},
|
||||
"actions": {
|
||||
"deleteAccount": "刪除賬號",
|
||||
"moreActions": "更多操作",
|
||||
"disableScheduling": "停用",
|
||||
"enableScheduling": "啓用",
|
||||
"refreshToken": "刷新令牌",
|
||||
"reauthorize": "重新授權",
|
||||
"downloadModelCatalog": "下載模型目錄",
|
||||
"restoreState": "重置狀態",
|
||||
"staleSelection": "所選賬號數據已失效,請重新選擇",
|
||||
"exportUnsupported": "所選賬號包含不支持導出的平臺",
|
||||
"deleted": "賬號已刪除",
|
||||
"deletedAccountDeletedAccounts": "已刪除 {count} 個賬號",
|
||||
"partialDeletion": "已刪除 {count} 個賬號,其餘未刪除:{value}",
|
||||
"batchDeletionFailed": "批量刪除失敗",
|
||||
"exportSelectionRequired": "請選擇要導出的賬號",
|
||||
"exported": "已導出 {count} 個賬號",
|
||||
"exportFailed": "導出失敗",
|
||||
"modelCatalogDownloadedModels": "已下載模型目錄,共 {count} 個模型",
|
||||
"tokenIsBeingRefreshed": "Token 正在刷新中",
|
||||
"refreshFailed": "刷新失敗",
|
||||
"tokenRefreshed": "Token 已刷新",
|
||||
"schedulingIsDisabled": "調度已停用",
|
||||
"schedulingIsEnabled": "調度已啓用",
|
||||
"quotaRefreshed": "額度已刷新",
|
||||
"refreshQuotaManually": "請手動刷新額度",
|
||||
"resetRefreshFailed": "額度已重置,但最新額度加載失敗:{value}",
|
||||
"statusRestored": "賬號狀態已恢復",
|
||||
"staleAccount": "賬號 {id} 的頁面數據已失效,請重新選擇",
|
||||
"unsupportedProvider": "不支持的 Provider:{provider}"
|
||||
},
|
||||
"usage": {
|
||||
"call": "調用",
|
||||
"successRate": "成功率",
|
||||
"input": "輸入",
|
||||
"output": "輸出",
|
||||
"cache": "緩存",
|
||||
"total": "總計",
|
||||
"billing": "計費",
|
||||
"tokensStructure": "Token 用量",
|
||||
"cacheRead": "緩存讀取",
|
||||
"reasoning": "推理",
|
||||
"cacheWrites": "緩存寫入",
|
||||
"modelUsageRanking": "模型用量",
|
||||
"totalTokens": "總 Token",
|
||||
"totalCharge": "總計費",
|
||||
"totalCharges": "總計費:",
|
||||
"noModelUsageYet": "暫無模型用量",
|
||||
"windows": {
|
||||
"general": "累計用量",
|
||||
"weekly": "周用量",
|
||||
"monthly": "月用量",
|
||||
"quota": "週期用量"
|
||||
},
|
||||
"cost": "費用"
|
||||
},
|
||||
"onboarding": {
|
||||
"fileReadingFailedTryAgain": "文件讀取失敗,請重新選擇",
|
||||
"uploadFiles": "上傳文件",
|
||||
"authorizationExpired": "授權已過期,可重新開始或檢查已完成的授權結果",
|
||||
"pollingPaused": "查詢已暫停,可檢查授權結果後繼續",
|
||||
"regenerateAuthorizationLink": "重新生成授權鏈接",
|
||||
"generateAuthorizationLink": "生成授權鏈接",
|
||||
"authorizationLink": "授權鏈接",
|
||||
"copyLink": "複製鏈接",
|
||||
"authorizationLinkCopied": "授權鏈接已複製",
|
||||
"batchImport": "批量導入",
|
||||
"selectAccountPlatform": "選擇賬號平臺",
|
||||
"accountPlatform": "賬號平臺",
|
||||
"maximumWordsOptional": "最多 500 字,可不填",
|
||||
"copyAccount": "複製賬號",
|
||||
"accountCopied": "賬號已複製",
|
||||
"howToAddAccount": "賬號添加方式",
|
||||
"authorize": "授權",
|
||||
"continueImporting": "繼續",
|
||||
"jsonDescription": "粘貼或上傳賬號 JSON,匹配已有賬號時更新憑據",
|
||||
"packageDescription": "粘貼或上傳 CPR 賬號包,一次導入多個平臺賬號",
|
||||
"oauthDescription": "通過瀏覽器授權導入 {label} 賬號",
|
||||
"apiKeyDescription": "接入 OpenAI Responses 兼容上游",
|
||||
"pasteAccessTokenLineByLineIf": "逐行粘貼 Access Token,未包含 Refresh Token 時無法自動續期",
|
||||
"refreshTokenDescription": "逐行粘貼 Refresh Token,導入時將自動換取 Access Token",
|
||||
"accountSettings": "賬號設置",
|
||||
"reauthorizeAccount": "重新授權賬號",
|
||||
"settingsDescription": "設置將應用於本次導入的賬號",
|
||||
"reauthorizeDescription": "完成授權後更新賬號憑據",
|
||||
"callbackLabel": "回調地址或授權碼",
|
||||
"callbackAddress": "回調地址",
|
||||
"callbackPlaceholder": "回調地址、?code=...&state=... 或授權碼",
|
||||
"callbackHelp": "打開授權鏈接,完成瀏覽器授權後粘貼回調地址或授權碼",
|
||||
"pasteOneAccessTokenPerLine": "每行粘貼一個 Access Token",
|
||||
"pasteOneRefreshTokenPerLine": "每行粘貼一個 Refresh Token",
|
||||
"batchAccountFiles": "批量賬號文件",
|
||||
"accountFile": "賬號文件",
|
||||
"packagePlaceholder": "粘貼 CPR 多平臺導出文件內容",
|
||||
"pasteAccountJsonContent": "粘貼賬號 JSON 內容",
|
||||
"completeReauthorization": "完成重新授權",
|
||||
"completeImport": "完成導入",
|
||||
"invalidExpiry": "授權有效期無效,請重新生成鏈接",
|
||||
"linkFailed": "生成授權鏈接失敗",
|
||||
"callbackRequired": "請粘貼回調地址或授權碼",
|
||||
"authorizationFailed": "完成授權失敗,可重試提交",
|
||||
"reauthorized": "賬號重新授權成功",
|
||||
"accountAdded": "賬號已添加",
|
||||
"providerRequired": "請選擇賬號平臺",
|
||||
"accountPlatformIsNotSupported": "賬號平臺不受支持",
|
||||
"apiKeyUnsupported": "當前平臺不支持 API Key 賬號",
|
||||
"apiKeyAccountAdded": "API Key 賬號已添加",
|
||||
"importTasksCreated": "已創建 {submitted} 個導入任務",
|
||||
"importTaskCreated": "導入任務已創建",
|
||||
"partialSubmission": "部分導入任務已創建,保持輸入不變重試可繼續提交",
|
||||
"accountName": "{provider} 賬號",
|
||||
"failedToStartAuthorization": "啓動授權失敗"
|
||||
},
|
||||
"importTasks": {
|
||||
"needProcessing": "需處理",
|
||||
"importTaskDetails": "導入任務詳情",
|
||||
"created": "{createdAtDisplay} 創建",
|
||||
"waitForCurrentEntryToEnd": "等待當前條目結束",
|
||||
"stopUnstartedEntries": "停止未開始條目",
|
||||
"viewAccount": "查看賬號",
|
||||
"entryProgress": "條目進度",
|
||||
"accountsImported": "已入庫 {importedAccounts} 個賬號",
|
||||
"itemProcessingProgress": "條目處理進度",
|
||||
"itemsToBeCheckedMayHaveBeen": "待覈對條目可能已入庫,請先查看賬號,再決定是否重新導入",
|
||||
"filterImportDetails": "篩選導入明細",
|
||||
"thereAreNoItemsToBeProcessed": "暫無需要處理的條目",
|
||||
"importEntryResults": "導入條目結果",
|
||||
"items": "{total} 個條目 · {value}",
|
||||
"description": "關閉頁面後繼續導入,再次打開即可查看進度",
|
||||
"progressUnavailable": "進度暫未更新:{value},恢復連接後將自動刷新",
|
||||
"loadingImportTasks": "正在讀取導入任務",
|
||||
"noImportTasks": "暫無導入任務",
|
||||
"empty": "新建一次賬號導入,即可在這裏查看逐條入庫結果",
|
||||
"switchImportTasks": "切換導入任務",
|
||||
"loadingItemResults": "正在讀取條目結果",
|
||||
"selectTask": "請選擇一個任務",
|
||||
"taskRetentionInstructions": "任務保留說明",
|
||||
"resultsRetainedForHour": "結果保留 1 小時",
|
||||
"retentionHelp": "服務重啓後任務記錄消失,已入庫賬號保留",
|
||||
"processing": "處理中",
|
||||
"alreadyInStock": "已入庫",
|
||||
"toBeVerified": "待覈對",
|
||||
"notExecuted": "未執行",
|
||||
"stopping": "正在停止",
|
||||
"importing": "導入中",
|
||||
"queuing": "排隊中",
|
||||
"stopped": "已停止",
|
||||
"endedPendingItems": "已結束 · 有待處理項",
|
||||
"allDone": "全部完成",
|
||||
"savedAccountSavedAccounts": "已保存 {count} 個賬號",
|
||||
"verifying": "正在校驗憑據併入庫",
|
||||
"waitingForExecution": "等待執行",
|
||||
"thisArticleIsNotImplemented": "本條未執行",
|
||||
"entryFailed": "本條導入未成功",
|
||||
"checkAccountList": "請檢查賬號列表,確認是否已入庫",
|
||||
"progressReadingFailedTryAgain": "進度讀取失敗,請重試"
|
||||
},
|
||||
"profile": {
|
||||
"activity": {
|
||||
"quickMode": "快速模式",
|
||||
"reasoningEffort": "最常用的推理強度",
|
||||
"exploredSkills": "已探索的技能",
|
||||
"totalNumberOfSkillsUsed": "使用的技能總數",
|
||||
"totalNumberOfChats": "聊天總數",
|
||||
"activityInsights": "活動洞察",
|
||||
"pluginsAndSkills": "最常用的插件與技能",
|
||||
"runs": "{count} 次運行",
|
||||
"noToolCalls": "暫無插件或技能調用記錄",
|
||||
"daily": "每日",
|
||||
"weekly": "每週",
|
||||
"cumulative": "累計",
|
||||
"tokenActivity": "Token 活動",
|
||||
"tokenActivityStatisticsMethod": "Token 活動統計方式",
|
||||
"noTokenActivityYet": "暫無 Token 活動",
|
||||
"noDailyActivity": "本次未獲取到每日 Token 活動",
|
||||
"tokenActivityHeatmap": "Token 活動熱力圖,{rangeLabel}",
|
||||
"weekOfTokens": "{dateDisplay}所在周:{value} Tokens",
|
||||
"throughTokens": "截至{dateDisplay}:{value} Tokens"
|
||||
},
|
||||
"metrics": {
|
||||
"cumulativeNumberOfTokens": "累計 Token 數",
|
||||
"peakNumberOfTokens": "峯值 Token 數",
|
||||
"maximumChatDuration": "最長聊天時長",
|
||||
"currentConsecutiveDays": "當前連續天數",
|
||||
"longestStreak": "最長連續天數",
|
||||
"dayCount": "{integer} 天",
|
||||
"dH": "{days} 天 {hours} 小時",
|
||||
"elapsedDays": "{days} 天",
|
||||
"hMin": "{hours} 小時 {minutes} 分",
|
||||
"elapsedHours": "{hours} 小時",
|
||||
"min": "{totalMinutes} 分",
|
||||
"durationSeconds": "{value} 秒",
|
||||
"cumulativeActivitySummary": "累計活動摘要"
|
||||
},
|
||||
"accountUser": "賬號用戶",
|
||||
"avatarFor": "{displayName} 的頭像",
|
||||
"loadingCumulativeActivity": "正在加載累計活動",
|
||||
"subscription": {
|
||||
"automaticRenewal": "自動續費",
|
||||
"noAutomaticRenewal": "不自動續費",
|
||||
"byMonth": "按月",
|
||||
"byYear": "按年",
|
||||
"subscriptionStarts": "訂閱開始",
|
||||
"subscriptionEnds": "訂閱結束",
|
||||
"label": "訂閱",
|
||||
"renewalMethod": "續費方式"
|
||||
},
|
||||
"personalInformation": "個人信息",
|
||||
"subscriptionInformation": "訂閱信息",
|
||||
"loadingSubscription": "正在加載訂閱信息",
|
||||
"loadFailed": "個人信息加載失敗",
|
||||
"statisticsUnavailable": "個人統計暫不可用",
|
||||
"statisticsEmpty": "本次未獲取到統計數據,可以點擊刷新信息重試",
|
||||
"refreshIncomplete": "本次信息刷新未完成,保留已獲取的結果",
|
||||
"noSubscriptionInformationYet": "暫無訂閱信息",
|
||||
"refreshInformation": "刷新信息"
|
||||
},
|
||||
"quotaForecast": {
|
||||
"tokenCapacity": "Token 容量",
|
||||
"equivalentFeeUsd": "等價費用 · USD",
|
||||
"capacityForecast": "容量預測",
|
||||
"usedThisCycle": "本週期已用",
|
||||
"preliminary": "初步估算 · 僅供參考",
|
||||
"estimateLabel": "估算值 · 僅供參考",
|
||||
"thisCycle": "本週期",
|
||||
"usedDescription": "本週期已用 {rate},其餘爲推算區域",
|
||||
"alreadyRecordedThisCycle": "本週期已記錄",
|
||||
"equivalentCapacityOverDays": "{targetDays}天折算容量",
|
||||
"projectedTotal": "本週期預計總量",
|
||||
"loadingQuotaForecast": "正在加載額度預測",
|
||||
"weeklyQuota": "周額度",
|
||||
"monthlyQuota": "月額度",
|
||||
"windowExpired": "額度窗口已過期,請刷新賬號額度後重試",
|
||||
"quotaForecast": "額度預測",
|
||||
"periodHelp": "按本週期估算,重置後重新累計",
|
||||
"forecastPeriod": "預測週期",
|
||||
"predictionLoadFailed": "預測加載失敗",
|
||||
"loadFailed": "暫時無法取得預測數據,請重新加載",
|
||||
"reload": "重新加載",
|
||||
"unpredictableAtMoment": "暫時無法預測",
|
||||
"updated": "更新於 {observedAtDisplay}",
|
||||
"forecastDescription": "預測說明",
|
||||
"forReferenceOnly": "僅供參考",
|
||||
"methodDescription": "本週期預計總量爲已記錄用量加預計剩餘,剩餘量按本週期內近期用量估算",
|
||||
"limitations": "缺失的用量或費用可能使結果偏低,結果會隨使用的模型和方式變化,並非官方承諾額度",
|
||||
"limitedData": "目前數據還較少,結果可能有較大波動",
|
||||
"currentPeriod": "當前週期",
|
||||
"forecastCalculatedByOverDays": "本頁預測由{value}按 {targetDays} 天折算",
|
||||
"equivalentCostHelp": "預測以數據更新時間爲準,等價費用不是實際賬單或賬戶餘額",
|
||||
"refreshQuota": "刷新額度"
|
||||
},
|
||||
"quotaReset": {
|
||||
"automation": {
|
||||
"confirming": "上次自動重置結果待確認,將繼續覈對",
|
||||
"unconfirmed": "上次自動重置結果待確認",
|
||||
"expiredUnconfirmed": "上次重置結果未能確認,卡片已到期",
|
||||
"queryFailed": "最近查詢失敗,將按計劃重試",
|
||||
"aboveThreshold": "剩餘周額度高於上限,稍後檢查",
|
||||
"quotaUnavailable": "暫時無法確認周額度,稍後檢查",
|
||||
"resetNotNeeded": "當前額度窗口不需要重置,稍後檢查",
|
||||
"resetIncomplete": "上游未完成最近一次自動重置",
|
||||
"scheduleHelp": "每天隨機查詢一次,各賬號錯開時間",
|
||||
"verifyHelp": "臨期使用前核對卡片,已在其他地方使用的會自動跳過",
|
||||
"label": "自動使用臨期重置卡"
|
||||
},
|
||||
"automaticallyUseResetCard": "自動使用重置卡",
|
||||
"automaticallyUsed": "自動使用",
|
||||
"automaticUsageRules": "自動使用規則",
|
||||
"setGlobalLeadTime": "設置全局提前時間",
|
||||
"minutesInAdvance": "提前 {leadMinutes} 分鐘",
|
||||
"leadTime": "提前時間",
|
||||
"nextUse": "下次使用 {nextConsumeAtDisplay}",
|
||||
"autoUsageSettingsFailedToLoad": "自動使用設置加載失敗",
|
||||
"limitReset": "額度重置",
|
||||
"confirmLastReset": "確認上次重置",
|
||||
"confirmResetAmount": "確認重置額度",
|
||||
"pendingAction": "查看主動重置卡,有一項操作待確認",
|
||||
"queryFailedWithCount": "查看主動重置卡,查詢失敗,最近查詢 {count} 張可用",
|
||||
"queryFailedLabel": "查看主動重置卡,查詢失敗",
|
||||
"availableCount": "查看主動重置卡,最近查詢 {count} 張可用",
|
||||
"viewCredits": "查看主動重置卡",
|
||||
"useResetSelectedByUpstream": "使用一次重置(由上游選擇)",
|
||||
"expires": "將於 {expiresAtDisplay} 到期",
|
||||
"expiryHelp": "有效期由上游決定",
|
||||
"querying": "查詢中",
|
||||
"toBeQueried": "待查詢",
|
||||
"usesAvailable": "可用 {count} 次",
|
||||
"usageReset": "用量重置",
|
||||
"thisTimeUse": "本次使用",
|
||||
"currentQuota": "當前額度",
|
||||
"operationUnconfirmed": "上次操作結果待確認",
|
||||
"confirmPrevious": "請繼續確認上次重置結果",
|
||||
"continueToConfirm": "繼續確認",
|
||||
"availableResetCards": "可用重置卡",
|
||||
"refreshCredits": "刷新主動重置卡",
|
||||
"resetCardLoadingFailed": "重置卡加載失敗",
|
||||
"refreshRequired": "請刷新重試",
|
||||
"queryingAvailableResetTimes": "正在查詢可用重置次數…",
|
||||
"useResetCredit": "使用重置:{title},{expiry}",
|
||||
"useReset": "使用重置",
|
||||
"noResetCardAvailableYet": "暫無可用重置卡",
|
||||
"confirmAgain": "再次確認",
|
||||
"confirmReset": "確認重置",
|
||||
"lastResetCompleted": "上次重置已完成",
|
||||
"resetSuccess": "額度已重置",
|
||||
"resultUnknown": "消費結果暫不確定,重試會複用同一個請求標識",
|
||||
"quotaResetFailed": "額度重置失敗",
|
||||
"alreadyProcessed": "該重置操作已被處理,請先刷新重置卡列表",
|
||||
"noCredits": "當前沒有可用的主動重置卡",
|
||||
"resetNotNeeded": "當前額度窗口不需要重置",
|
||||
"upstreamDeclined": "上游未執行額度重置:{code}"
|
||||
},
|
||||
"status": {
|
||||
"accountStatus": "賬號狀態",
|
||||
"tryNextTime": "下次嘗試",
|
||||
"recommendedAction": "建議操作",
|
||||
"upstreamOriginalFeedback": "上游原始反饋",
|
||||
"forTroubleshootingOnly": "僅供排查",
|
||||
"retreating": "退避中",
|
||||
"oauthRefreshBackoff": "OAuth 刷新退避",
|
||||
"refreshFailedHelp": "刷新失敗,系統正在等待下一次自動嘗試",
|
||||
"retryScheduledHelp": "系統會在計劃時間自動重試",
|
||||
"attentionHelp": "該賬號當前狀態需要關注",
|
||||
"retestHelp": "重新測試連接以獲取最新狀態",
|
||||
"rateLimitedHelp": "上游暫時限制了請求頻率,系統正在冷卻該賬號",
|
||||
"cooldownHelp": "冷卻結束後,系統會自動恢復調度",
|
||||
"credentialsHelp": "該賬號暫不參與調度,處理憑據後可重新測試連接",
|
||||
"reauthorizeHelp": "重新授權後,賬號會重新參與調度",
|
||||
"replaceCredentialsHelp": "請更新或重新導入憑據,再次測試連接",
|
||||
"upstreamRestrictionHelp": "請確認上游賬號狀態,解除限制後再啓用",
|
||||
"capacityFailuresHelp": "容量類請求失敗累計達到閾值,系統已暫停該賬號的調度",
|
||||
"recoveryProbeHelp": "冷卻結束後進行恢復探測,成功後恢復調度,也可手動恢復賬號",
|
||||
"recoveryHelp": "冷卻結束後自動恢復調度,也可手動恢復賬號",
|
||||
"nextAttempt": ",下次嘗試:{nextRefreshDisplay}",
|
||||
"clickOrFocusToViewDetails": "{title},{description}{retry},點擊或聚焦查看詳情",
|
||||
"resumeDetection": "恢復探測",
|
||||
"expectedToRecover": "預計恢復"
|
||||
},
|
||||
"fields": {
|
||||
"platformType": "平臺",
|
||||
"accountGrouping": "分組",
|
||||
"lastUsed": "最後使用",
|
||||
"tokenExpires": "令牌過期",
|
||||
"quotaExhausted": "配額耗盡",
|
||||
"rateLimiting": "限流中",
|
||||
"deactivated": "已停用",
|
||||
"error": "錯誤",
|
||||
"identityUnconfirmed": "賬號身份尚未確認",
|
||||
"accessTokenHasExpired": "Access Token 已過期",
|
||||
"credentialsHaveExpired": "憑據已過期",
|
||||
"invalidCredentials": "憑據無效",
|
||||
"accountUnavailable": "賬號不可用或已被封禁",
|
||||
"count": "賬號數"
|
||||
},
|
||||
"page": {
|
||||
"description": "維護賬號池,查看可用性、配額與使用狀態",
|
||||
"noAccountDataYet": "暫無賬號數據",
|
||||
"collapseStatistics": "收起統計",
|
||||
"expandStatistics": "展開統計",
|
||||
"selectAccountOnCurrentPage": "選擇當前頁賬號",
|
||||
"selectAccount": "選擇賬號",
|
||||
"deleteDescription": "刪除後該賬號將不再參與調度,此操作不可撤銷",
|
||||
"batchDeleteDescription": "確定要刪除選中的 {count} 個賬號嗎?此操作不可撤銷",
|
||||
"thisAccount": "該賬號",
|
||||
"delete": "確定要刪除 {value} 嗎?"
|
||||
},
|
||||
"import": {
|
||||
"jsonFormatIsIncorrect": "JSON 格式不正確",
|
||||
"documentTooLarge": "單條導入文檔超過 4 MiB,請拆分文件後重試",
|
||||
"batchImportFileMustBeCprMulti": "批量導入文件必須是 CPR 多平臺導出文件",
|
||||
"invalidProvider": "批量導入文件包含無效的 Provider 文檔",
|
||||
"noAccounts": "批量文件沒有可導入的賬號文檔",
|
||||
"pasteAtLeastOne": "請至少粘貼一個 {label}",
|
||||
"missingProvider": "批量導入文件不包含 {provider} 賬號文檔",
|
||||
"importFilesMustBeJsonObjects": "導入文件必須是 JSON 對象"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
{
|
||||
"appearance": {
|
||||
"switchToLight": "切換淺色模式",
|
||||
"switchToDark": "切換暗黑模式",
|
||||
"settings": {
|
||||
"global": "全局",
|
||||
"components": "組件",
|
||||
"invalidTheme": "主題設置無效,請檢查編輯值",
|
||||
"themeSavedAndApplied": "主題已保存並應用",
|
||||
"description": "自定義當前瀏覽器中的管理端主題",
|
||||
"pendingChanges": "{count} 處修改待應用",
|
||||
"synced": "已同步",
|
||||
"themeEditingLevel": "主題編輯層級",
|
||||
"undoDraft": "撤銷草稿",
|
||||
"restoreDefault": "恢復默認",
|
||||
"saveAndApply": "保存並應用",
|
||||
"saved": "已保存",
|
||||
"themeEditor": "主題編輯器",
|
||||
"themeTokenEditingPanel": "主題 Token 編輯面板",
|
||||
"searchToken": "搜索 Token",
|
||||
"searchPlaceholder": "搜索 Seed、Alias 或 Component Token"
|
||||
},
|
||||
"color": {
|
||||
"modified": "已修改",
|
||||
"edit": "編輯 {label}",
|
||||
"restoreDerivedValue": "恢復派生值"
|
||||
},
|
||||
"preview": {
|
||||
"components": {
|
||||
"relayAccount": "中繼賬號",
|
||||
"stickyHelp": "優先保持當前賬號,額度耗盡後再切換",
|
||||
"notEditable": "不可編輯",
|
||||
"allPlatforms": "全部平臺",
|
||||
"restricted": "受限",
|
||||
"accountAvailability": "賬號可用率",
|
||||
"todaySQuota": "今日額度",
|
||||
"batchImport": "批量導入",
|
||||
"platform": "平臺",
|
||||
"requestToday": "今日請求",
|
||||
"recentlyUsed": "最近使用",
|
||||
"justNow": "剛剛",
|
||||
"hoursAgo": "2 小時前",
|
||||
"componentOverview": "組件概覽",
|
||||
"description": "在同一張校樣板中檢查控制態、數據密度與浮層關係",
|
||||
"currentThemeSemanticColor": "當前主題語義色",
|
||||
"basicControlComponents": "基礎控制組件",
|
||||
"buttonsAndActions": "按鈕與動作",
|
||||
"createAccount": "創建賬號",
|
||||
"exportData": "導出數據",
|
||||
"dealWithItLater": "稍後處理",
|
||||
"sizeAndDisabledStatus": "尺寸與禁用狀態",
|
||||
"inoperable": "不可操作",
|
||||
"processing": "處理中",
|
||||
"notification": "通知",
|
||||
"moreActions": "更多操作",
|
||||
"deleteRecord": "刪除記錄",
|
||||
"formsAndInput": "表單與輸入",
|
||||
"searchAccount": "搜索賬號",
|
||||
"choosePlatform": "選擇平臺",
|
||||
"accessKeyErrorExample": "訪問密鑰錯誤示例",
|
||||
"disableInputBox": "禁用輸入框",
|
||||
"brandColors": "品牌顏色",
|
||||
"editBrandColors": "編輯品牌顏色",
|
||||
"schedulingNotes": "調度備註",
|
||||
"controlHeight": "控件高度",
|
||||
"componentExampleControlHeight": "組件示例控件高度",
|
||||
"choiceAndFeedbackComponents": "選擇與反饋組件",
|
||||
"selectAndSwitch": "選擇與切換",
|
||||
"accountView": "賬號視圖",
|
||||
"realTimeNotification": "實時通知",
|
||||
"automaticRotation": "自動輪換",
|
||||
"selectCurrentPage": "選擇當前頁",
|
||||
"partialSelection": "部分選擇",
|
||||
"equilibrium": "均衡",
|
||||
"sticky": "粘性",
|
||||
"manual": "手動",
|
||||
"feedbackSemantics": "反饋語義",
|
||||
"themeSettingsSaved": "主題設置已保存",
|
||||
"quotaOfAccountsIsCloseToUpper": "3 個賬號額度接近上限",
|
||||
"connectionTestFailed": "連接測試未通過",
|
||||
"schedulingNotice": "調度規則將在下次請求生效",
|
||||
"statusAndProgress": "狀態與進度",
|
||||
"runningNormally": "運行正常",
|
||||
"quotaLimited": "額度受限",
|
||||
"needToBeProcessed": "需要處理",
|
||||
"synchronizing": "同步中",
|
||||
"restoreTag": "恢復標籤",
|
||||
"dataTable": "數據表格",
|
||||
"tableComponents": "ZTable · ZScrollbar · ZPagination(標準行高)",
|
||||
"filterForm": "篩選表格",
|
||||
"filterAccounts": "篩選賬號",
|
||||
"boundaryStateComponent": "邊界狀態組件",
|
||||
"emptyState": "空狀態",
|
||||
"noMatchingAccountYet": "暫無匹配賬號",
|
||||
"emptyHelp": "調整篩選條件,或添加一個新的上游賬號",
|
||||
"addAccount": "添加賬號",
|
||||
"loadingAndSkeleton": "加載與骨架",
|
||||
"synchronizingAccountStatus": "正在同步賬號狀態",
|
||||
"overlaysAndMenus": "浮層與菜單",
|
||||
"accountOperation": "賬號操作",
|
||||
"editAccount": "編輯賬號",
|
||||
"deactivateAccount": "停用賬號",
|
||||
"overlayHelp": "浮層始終使用獨立 Surface 與 Shadow Token",
|
||||
"eyebrow": "組件預覽",
|
||||
"count": "{count} 個基礎組件",
|
||||
"buttonLabel": "按鈕 / 操作",
|
||||
"feedbackTypes": "成功 · 警告 · 錯誤 · 信息",
|
||||
"tagComponents": "ZTag · 進度 Token",
|
||||
"loadingComponents": "ZSkeleton · ZButton 加載態",
|
||||
"overlayComponents": "ZPopover · ZMenuItem · 浮層表面"
|
||||
},
|
||||
"dashboard": {
|
||||
"justUpdated": "剛剛更新",
|
||||
"demoKey": "演示 Key",
|
||||
"requestHealthTimeline": "請求健康時間線",
|
||||
"validRequestAvailability": "有效請求可用性",
|
||||
"clientId": "客戶端 ID",
|
||||
"tokenAuthentication": "Token 認證",
|
||||
"todaySToken": "今日 Token",
|
||||
"hours": "5 小時",
|
||||
"requests": "08-23 {value}:00–{value2}:00 · {count} 次請求",
|
||||
"times": "次數",
|
||||
"dailyLimit": "日限額"
|
||||
},
|
||||
"homeArtboard": "首頁畫板",
|
||||
"themeRealTimePreview": "主題實時預覽",
|
||||
"livePreview": "實時預覽",
|
||||
"description": "真實組件在影子環境隔離渲染,拖動畫板並縮放檢查細節",
|
||||
"previewType": "預覽類型",
|
||||
"canvas": {
|
||||
"homeThemePreviewArtboard": "首頁主題預覽畫板",
|
||||
"dragBlankSpaceToPanUseScroll": "拖動空白處平移 · 滾輪縮放",
|
||||
"reduceArtboard": "縮小畫板",
|
||||
"recovery": "恢復 100%",
|
||||
"enlargeArtboard": "放大畫板",
|
||||
"adaptToArtboard": "適應畫板"
|
||||
}
|
||||
},
|
||||
"componentTokens": {
|
||||
"cardsAndContainers": "卡片與容器",
|
||||
"dataDisplay": "數據展示",
|
||||
"navigation": "導航",
|
||||
"layoutAndScrolling": "佈局與滾動",
|
||||
"mainButtonText": "主按鈕文字",
|
||||
"mainButtonBackground": "主按鈕背景",
|
||||
"mainButtonHover": "主按鈕 Hover",
|
||||
"mainButtonActive": "主按鈕 Active",
|
||||
"secondaryButtonBackground": "次要按鈕背景",
|
||||
"secondaryButtonHover": "次要按鈕 Hover",
|
||||
"secondaryButtonActive": "次要按鈕 Active",
|
||||
"secondaryIconButtonBackground": "次要圖標按鈕背景",
|
||||
"secondaryIconButtonHover": "次要圖標按鈕 Hover",
|
||||
"secondaryIconButtonActive": "次要圖標按鈕 Active",
|
||||
"inputBoxBackground": "輸入框背景",
|
||||
"inputBoxHover": "輸入框 Hover",
|
||||
"inputBoxActive": "輸入框 Active",
|
||||
"inputBoxShadow": "輸入框陰影",
|
||||
"inputBoxHoverShadow": "輸入框 Hover 陰影",
|
||||
"inputBoxFocusOuterCircle": "輸入框焦點外圈",
|
||||
"cardBackground": "卡片背景",
|
||||
"popUpBackground": "彈窗背景",
|
||||
"floatingTitleBackground": "浮層標題背景",
|
||||
"cardRoundedCorners": "卡片圓角",
|
||||
"cardShadow": "卡片陰影",
|
||||
"tableRowHeight": "表格行高",
|
||||
"headerBackground": "表頭背景",
|
||||
"lineBackground": "行背景",
|
||||
"zebraPatternBackground": "斑馬紋背景",
|
||||
"rowHover": "行 Hover",
|
||||
"selectedRowBackground": "選中行背景",
|
||||
"selectRowHover": "選中行 Hover",
|
||||
"progressTrack": "進度軌道",
|
||||
"menuSelectionBackground": "菜單選中背景",
|
||||
"sidebarBackground": "側欄背景",
|
||||
"sidebarShadow": "側欄陰影",
|
||||
"scrollBarSlider": "滾動條滑塊",
|
||||
"scrollBarHover": "滾動條 Hover",
|
||||
"componentTokenComponentFamily": "Component Token 組件族",
|
||||
"description": "調整 {label} 的 Component Token,未修改的值繼續由全局 Seed / Alias 算法生成",
|
||||
"noMatchingComponentToken": "沒有匹配的 Component Token",
|
||||
"kindLabel": "組件 Token"
|
||||
},
|
||||
"globalTokens": {
|
||||
"size": "尺寸",
|
||||
"style": "風格",
|
||||
"systemMode": "跟隨系統",
|
||||
"lightColor": "淺色",
|
||||
"dark": "深色",
|
||||
"successColor": "成功色",
|
||||
"successFeedbackAndStatus": "成功反饋與狀態",
|
||||
"warningColor": "警告色",
|
||||
"limitAndRiskReminder": "額度與風險提醒",
|
||||
"wrongColor": "錯誤色",
|
||||
"dangerHelp": "失敗與破壞性操作",
|
||||
"informationColor": "信息色",
|
||||
"systemAndRequestInformation": "系統與請求信息",
|
||||
"linkColor": "鏈接色",
|
||||
"linksAndJumps": "鏈接與跳轉",
|
||||
"basicTextColor": "基礎文本色",
|
||||
"textAndInformationLevels": "正文與信息層級",
|
||||
"basicBackgroundColor": "基礎背景色",
|
||||
"pageAndContainerBase": "頁面與容器基底",
|
||||
"themeMode": "主題模式",
|
||||
"globalTokenClassification": "全局 Token 分類",
|
||||
"brandColorLabel": "預置主題 品牌色 colorPrimary",
|
||||
"brandColor": "品牌色",
|
||||
"presetThemes": "預置主題",
|
||||
"brandMainColor": "品牌主色",
|
||||
"paletteDescription": "完整色階與界面基調",
|
||||
"semanticColorsTitle": "功能色與中性色",
|
||||
"derivedVariablesMapAliasToken": "派生變量 Map / Alias Token",
|
||||
"sizeToken": "尺寸 Token",
|
||||
"basicFontSize": "基礎字號",
|
||||
"basicSpacing": "基礎間距",
|
||||
"sizeStep": "尺寸步長",
|
||||
"styleToken": "風格 Token",
|
||||
"surfaceDescription": "固定無邊設計,圓角塑形,陰影分層",
|
||||
"universalFillet": "通用圓角",
|
||||
"shadowIntensity": "陰影強度"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"auth": {
|
||||
"signOut": "退出登錄",
|
||||
"adminSignIn": "管理員登錄",
|
||||
"apiKeySignIn": "API Key 登錄",
|
||||
"signingIn": "正在登錄...",
|
||||
"signIn": "登錄",
|
||||
"method": "選擇登錄方式",
|
||||
"title": "控制檯登錄",
|
||||
"welcome": "「 歡迎回來,登錄以開始您的數據之旅 」",
|
||||
"username": "管理員賬號",
|
||||
"usernamePlaceholder": "輸入會話賬號",
|
||||
"passwordPlaceholder": "輸入會話密鑰",
|
||||
"apiKeyPlaceholder": "輸入 API Key",
|
||||
"pageLabel": "Codex Proxy RS 登錄",
|
||||
"password": "密碼",
|
||||
"apiKey": "API 密鑰",
|
||||
"adminRealm": "管理員",
|
||||
"keyRealm": "API 密鑰"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
{
|
||||
"common": {
|
||||
"errors": {
|
||||
"canceled": "請求已取消",
|
||||
"timeout": "請求超時,請稍後重試",
|
||||
"network": "網絡連接失敗,請檢查網絡後重試",
|
||||
"invalidParameters": "請求參數不合法",
|
||||
"signInRequired": "需要登錄",
|
||||
"forbidden": "沒有權限執行此操作",
|
||||
"notFound": "請求的接口不存在",
|
||||
"conflict": "資源狀態衝突,請刷新後重試",
|
||||
"payloadTooLarge": "請求內容過大",
|
||||
"unsupportedFormat": "請求格式不受支持",
|
||||
"invalidContent": "請求內容不合法",
|
||||
"rateLimited": "請求過於頻繁,請稍後重試",
|
||||
"internal": "服務內部錯誤",
|
||||
"upstreamFailure": "上游服務請求失敗",
|
||||
"unavailable": "服務暫不可用,請稍後重試",
|
||||
"upstreamTimeout": "上游服務響應超時",
|
||||
"http": "請求失敗(HTTP {status})",
|
||||
"request": "請求失敗",
|
||||
"responseTooLarge": "響應內容超過大小限制",
|
||||
"unsupportedResponse": "服務返回了不受支持的響應",
|
||||
"sessionExpired": "登錄已失效,請重新登錄",
|
||||
"operation": "操作失敗",
|
||||
"copy": "複製失敗",
|
||||
"load": "加載失敗",
|
||||
"malformedJson": "請求體不是合法 JSON",
|
||||
"invalidTimeRange": "時間範圍不合法",
|
||||
"invalidCredentials": "登錄憑據錯誤",
|
||||
"invalidAdminApiKey": "管理 API 密鑰無效",
|
||||
"tooManyLoginAttempts": "登錄嘗試過多,請稍後重試",
|
||||
"upstreamResultUnknown": "上游執行結果未知,請刷新狀態後再決定是否重試"
|
||||
},
|
||||
"status": {
|
||||
"disabled": "已禁用",
|
||||
"disabledName": "{name}(已禁用)",
|
||||
"success": "成功",
|
||||
"error": "異常",
|
||||
"pending": "等待中",
|
||||
"failed": "失敗",
|
||||
"healthy": "正常",
|
||||
"all": "全部狀態",
|
||||
"available": "可用",
|
||||
"unavailable": "不可用",
|
||||
"enabled": "已啓用",
|
||||
"loading": "加載中",
|
||||
"running": "執行中",
|
||||
"completed": "已完成",
|
||||
"rateLimited": "限流"
|
||||
},
|
||||
"actions": {
|
||||
"copy": "複製",
|
||||
"close": "關閉",
|
||||
"retry": "重試",
|
||||
"cancel": "取消",
|
||||
"previous": "上一步",
|
||||
"reset": "重置",
|
||||
"back": "返回",
|
||||
"delete": "確認刪除",
|
||||
"create": "創建",
|
||||
"enable": "啓用",
|
||||
"next": "下一步",
|
||||
"confirm": "確定",
|
||||
"refresh": "刷新",
|
||||
"save": "保存"
|
||||
},
|
||||
"providers": {
|
||||
"all": "全部平臺",
|
||||
"filter": "按平臺篩選",
|
||||
"unknown": "未知平臺",
|
||||
"customAuth": "自定義認證 · {normalized}",
|
||||
"unknownAuth": "未知認證類型"
|
||||
},
|
||||
"location": {
|
||||
"resolving": "正在解析出口位置",
|
||||
"detect": "解析出口位置並填入表單",
|
||||
"countryCode": "國家代碼",
|
||||
"countryCodePlaceholder": "請輸入兩位國家代碼",
|
||||
"region": "地區",
|
||||
"regionPlaceholder": "請輸入地區",
|
||||
"city": "城市",
|
||||
"cityPlaceholder": "請輸入城市",
|
||||
"timeZone": "IANA 時區",
|
||||
"timeZonePlaceholder": "請輸入 IANA 時區",
|
||||
"required": "請填寫兩位國家代碼、地區、城市和 IANA 時區"
|
||||
},
|
||||
"values": {
|
||||
"yes": "是",
|
||||
"no": "否",
|
||||
"unspecified": "未填寫",
|
||||
"all": "全部",
|
||||
"unknown": "未知",
|
||||
"unlimited": "不限",
|
||||
"default": "默認",
|
||||
"on": "開啓",
|
||||
"none": "無",
|
||||
"off": "關閉"
|
||||
},
|
||||
"form": {
|
||||
"inputPlaceholder": "輸入內容",
|
||||
"useForm": "使用表單",
|
||||
"fieldHelp": "{label}說明",
|
||||
"editJson": "編輯 JSON"
|
||||
},
|
||||
"fields": {
|
||||
"actions": "操作",
|
||||
"notes": "備註",
|
||||
"status": "狀態",
|
||||
"color": "顏色",
|
||||
"updatedAt": "更新時間",
|
||||
"name": "名稱",
|
||||
"createdAt": "創建時間",
|
||||
"baseUrl": "基礎 URL",
|
||||
"apiKey": "API 密鑰",
|
||||
"build": "構建"
|
||||
},
|
||||
"language": "界面語言",
|
||||
"validation": {
|
||||
"invalidJson": "請輸入有效的 JSON 對象",
|
||||
"jsonObject": "輸入必須是 JSON 對象",
|
||||
"sizeLimit": "輸入不能超過 {value} KiB"
|
||||
},
|
||||
"feedback": {
|
||||
"deleted": "刪除成功",
|
||||
"copied": "已複製"
|
||||
},
|
||||
"time": {
|
||||
"minutesAgo": "{count} 分鐘前"
|
||||
},
|
||||
"units": {
|
||||
"tokens": "Token"
|
||||
},
|
||||
"sizes": {
|
||||
"small": "小",
|
||||
"medium": "中",
|
||||
"large": "大"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"dashboard": {
|
||||
"scheduling": {
|
||||
"defaultConcurrency": "默認併發",
|
||||
"totalSlots": "總槽位",
|
||||
"freeSlots": "空閒槽位",
|
||||
"smart": "智能調度",
|
||||
"quotaReset": "額度重置優先",
|
||||
"sticky": "粘滯",
|
||||
"title": "賬號調度",
|
||||
"description": "容量、併發與分配策略",
|
||||
"occupiedSlots": "槽位佔用",
|
||||
"strategy": "分配策略"
|
||||
},
|
||||
"accountPool": {
|
||||
"empty": "暫無賬號池觀測",
|
||||
"quotaExhausted": "配額耗盡",
|
||||
"rateLimited": "限流中",
|
||||
"pending": "待處理",
|
||||
"issueCountsEmpty": "停用 — · 錯誤 —",
|
||||
"availableDescription": "賬號當前可用",
|
||||
"exhaustedDescription": "賬號額度已耗盡",
|
||||
"limitedDescription": "賬號請求暫時受限",
|
||||
"issueCounts": "停用 {disabled} · 錯誤 {error}",
|
||||
"title": "賬號狀態",
|
||||
"description": "賬號池健康結構",
|
||||
"healthyRate": "正常率",
|
||||
"distribution": "狀態分佈",
|
||||
"unavailableCount": "不可用 {value}"
|
||||
},
|
||||
"activeAccounts": {
|
||||
"title": "活躍賬號用量",
|
||||
"sortByRecent": "最近使用排序",
|
||||
"empty": "暫無賬號請求記錄",
|
||||
"recent": "最近"
|
||||
},
|
||||
"title": "系統概覽",
|
||||
"today": "當日統計",
|
||||
"refresh": {
|
||||
"action": "刷新概覽",
|
||||
"failed": "刷新失敗,顯示上次統計",
|
||||
"unavailable": "統計暫不可用,請稍後重試",
|
||||
"lastUpdated": "自動刷新 30s,最近刷新 {updatedAt}",
|
||||
"waiting": "自動刷新 30s,等待首次刷新",
|
||||
"interval": "自動刷新 30s"
|
||||
},
|
||||
"metrics": {
|
||||
"title": "核心指標",
|
||||
"outputTokens": "輸出",
|
||||
"inputTokens": "輸入",
|
||||
"cachedInputTokens": "緩存",
|
||||
"cacheHits": "緩存命中",
|
||||
"requests": "請求",
|
||||
"firstTokenP95Ms": "TTFT P95",
|
||||
"latencyP95Ms": "總耗時 P95",
|
||||
"outputThroughputP50": "速率 P50",
|
||||
"errors": "錯誤數",
|
||||
"successRate": "成功率",
|
||||
"totalRequests": "總請求",
|
||||
"requestCount": "請求次數",
|
||||
"totalTokens": "總 Token",
|
||||
"totalCharges": "總計費",
|
||||
"totalCacheHits": "總緩存命中",
|
||||
"totalCache": "總緩存"
|
||||
},
|
||||
"comparedWithYesterday": "較昨日",
|
||||
"trends": {
|
||||
"title": "使用趨勢",
|
||||
"metric": "趨勢指標",
|
||||
"highlight": "突出顯示{label}曲線",
|
||||
"empty": "暫無趨勢數據",
|
||||
"latency": "延遲",
|
||||
"errors": "錯誤"
|
||||
},
|
||||
"recentRequests": {
|
||||
"title": "使用記錄",
|
||||
"description": "最近 10 條成功請求",
|
||||
"empty": "暫無成功記錄"
|
||||
},
|
||||
"clientIdentity": {
|
||||
"notChecked": "尚未檢查",
|
||||
"versionPolicy": "版本策略",
|
||||
"customVersion": "固定自定義",
|
||||
"active": "當前生效",
|
||||
"activeDescription": "跟隨通用設置的新請求使用此身份",
|
||||
"upToDate": "製品一致",
|
||||
"upToDateDescription": "當前生效版本與官方最新發布一致",
|
||||
"updateAvailable": "發現新版",
|
||||
"latestRelease": "官方最新版本 {releaseLabel}",
|
||||
"checkFailed": "檢查失敗",
|
||||
"checkFailedDescription": "官方版本檢查失敗",
|
||||
"pending": "待檢查",
|
||||
"pendingDescription": "尚未檢查官方發佈渠道",
|
||||
"verifiedAt": "畫像覈驗 {verifiedAt}",
|
||||
"checkedAt": "發佈檢查 {checkedAt}",
|
||||
"clientId": "客戶端 ID",
|
||||
"tokenAuth": "Token 認證",
|
||||
"title": "通用上游身份",
|
||||
"provider": "上游平臺",
|
||||
"empty": "暫無請求身份",
|
||||
"attributes": "請求身份組成",
|
||||
"authProtocol": "認證協議",
|
||||
"emulatedEnvironment": "模擬運行環境",
|
||||
"environment": "運行環境"
|
||||
},
|
||||
"health": {
|
||||
"title": "請求健康時間線",
|
||||
"description": "有效請求可用性"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"groups": {
|
||||
"selector": {
|
||||
"loading": "正在加載分組...",
|
||||
"empty": "暫無分組,請先在分組管理中創建"
|
||||
},
|
||||
"actions": {
|
||||
"editGroup": "編輯分組",
|
||||
"disableGroup": "禁用分組",
|
||||
"enableGroup": "啓用分組",
|
||||
"deleteGroup": "刪除分組",
|
||||
"enterGroupName": "請輸入分組名稱",
|
||||
"selectValidGroupingColor": "請選擇有效的分組顏色",
|
||||
"updated": "分組已更新",
|
||||
"created": "分組已創建",
|
||||
"disabled": "分組已禁用",
|
||||
"enabled": "分組已啓用",
|
||||
"groupDeleted": "分組已刪除",
|
||||
"deletedGroupDeletedGroups": "已刪除 {count} 個分組",
|
||||
"partialDeletion": "已刪除 {count} 個分組,其餘未刪除:{value}",
|
||||
"batchDeletionFailed": "批量刪除失敗"
|
||||
},
|
||||
"filters": {
|
||||
"searchAccountGroup": "搜索賬號分組",
|
||||
"searchGroupName": "搜索分組名稱",
|
||||
"filterByGroupStatus": "按分組狀態篩選",
|
||||
"deleteSelected": "刪除選中 ({count})",
|
||||
"createGroup": "創建分組"
|
||||
},
|
||||
"editor": {
|
||||
"editDescription": "修改分組信息和請求權限",
|
||||
"createDescription": "創建後,可在賬號管理中將賬號加入這個分組",
|
||||
"groupName": "分組名稱",
|
||||
"forExampleProductionAccount": "例如:生產賬號",
|
||||
"groupColor": "分組顏色",
|
||||
"selectGroupColor": "選擇分組顏色",
|
||||
"fastMode": "快速模式",
|
||||
"imageGeneration": "圖像生成",
|
||||
"descriptionOptional": "描述(可選)",
|
||||
"groupDescription": "分組描述",
|
||||
"describePurposeOfThisGroup": "說明這個分組的用途",
|
||||
"saveGroup": "保存分組"
|
||||
},
|
||||
"metrics": {
|
||||
"restricted": "受限",
|
||||
"total": "總數",
|
||||
"concurrency": "併發",
|
||||
"today": "今日",
|
||||
"cumulative": "累計"
|
||||
},
|
||||
"group": "分組",
|
||||
"fields": {
|
||||
"capacity": "容量"
|
||||
},
|
||||
"page": {
|
||||
"description": "將賬號歸類管理,併爲每個 API 密鑰指定可使用的賬號",
|
||||
"empty": "暫無分組",
|
||||
"selectCurrentPageGroup": "選擇當前頁分組",
|
||||
"selectGroup": "選擇分組",
|
||||
"fastModeIsOn": "Fast 已開啓",
|
||||
"fastModeIsOff": "Fast 已關閉",
|
||||
"imageGenerationDisabled": "生圖已關閉",
|
||||
"colorLabel": "分組顏色 {color}",
|
||||
"batchDeleteWarning": "刪除後這些分組將立即失效,此操作不可撤銷",
|
||||
"batchDeleteDescription": "確定刪除選中的 {count} 個分組嗎?賬號本身不會被刪除",
|
||||
"disableAccountGrouping": "禁用賬號分組",
|
||||
"disableDescription": "禁用後,使用該分組的 API 密鑰將無法再使用其中的賬號",
|
||||
"confirmDisable": "確認禁用",
|
||||
"disable": "確定禁用“{name}”嗎?",
|
||||
"affectedApiKeys": "將影響 {count} 個 API 密鑰:{value}",
|
||||
"affectedKeys": "將影響 {count} 個 API 密鑰",
|
||||
"deleteAccountGroup": "刪除賬號分組",
|
||||
"deleteWarning": "刪除後該分組將立即失效,此操作不可撤銷",
|
||||
"unnamedGroup": "該分組",
|
||||
"deleteAccountsWillBeKept": "確定刪除“{name}”嗎?賬號本身不會被刪除"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import accounts from './accounts.json'
|
||||
import appearance from './appearance.json'
|
||||
import auth from './auth.json'
|
||||
import common from './common.json'
|
||||
import dashboard from './dashboard.json'
|
||||
import groups from './groups.json'
|
||||
import keys from './keys.json'
|
||||
import navigation from './navigation.json'
|
||||
import plugins from './plugins.json'
|
||||
import proxies from './proxies.json'
|
||||
import settings from './settings.json'
|
||||
import systemUpdate from './systemUpdate.json'
|
||||
import usage from './usage.json'
|
||||
|
||||
export default {
|
||||
...accounts,
|
||||
...appearance,
|
||||
...auth,
|
||||
...common,
|
||||
...dashboard,
|
||||
...groups,
|
||||
...keys,
|
||||
...navigation,
|
||||
...plugins,
|
||||
...proxies,
|
||||
...settings,
|
||||
...systemUpdate,
|
||||
...usage,
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"keys": {
|
||||
"configuration": {
|
||||
"description": "保存或合併下方配置後重啓 Codex",
|
||||
"platform": "配置平臺",
|
||||
"toggleWebSocket": "切換 WebSocket 配置",
|
||||
"importCcSwitch": "添加到 CC Switch",
|
||||
"copiedToClipboard": "已複製到剪貼板",
|
||||
"fullApiKeyNotAvailable": "完整 API Key 不可用",
|
||||
"title": "使用密鑰"
|
||||
},
|
||||
"actions": {
|
||||
"editKey": "編輯密鑰",
|
||||
"useKey": "使用密鑰",
|
||||
"moreActions": "更多操作",
|
||||
"resetUsedCredit": "重置用量",
|
||||
"disableKey": "停用",
|
||||
"enableKey": "啓用",
|
||||
"deleteKey": "刪除",
|
||||
"deletedApiKeyDeletedApiKeys": "已刪除 {count} 個 API Key"
|
||||
},
|
||||
"day": "日",
|
||||
"dailyUsage": "日用量",
|
||||
"week": "周",
|
||||
"weeklyUsage": "周用量",
|
||||
"viewUsageAndCostsFor": "查看 {name} 的費用用量",
|
||||
"costDetailsTitle": "費用詳情(USD)",
|
||||
"confirmNextTime": "下次使用時確定",
|
||||
"budgetReset": {
|
||||
"dailyQuota": "日額度",
|
||||
"weeklyQuota": "周額度",
|
||||
"keyQuotaReset": "已重置密鑰額度",
|
||||
"description": "清零所選週期的已用金額,下次使用時重新確定重置日期",
|
||||
"targetKey": "目標密鑰",
|
||||
"resetScope": "重置範圍",
|
||||
"currentlyUsed": "當前已用",
|
||||
"afterReset": "重置後",
|
||||
"remainUnchanged": "保持不變",
|
||||
"confirmReset": "確認重置"
|
||||
},
|
||||
"created": {
|
||||
"apiKeyCreated": "API Key 已創建",
|
||||
"description": "複製密鑰,或直接導入 CCSwitch",
|
||||
"accessNotice": "該密鑰具有網關訪問權限,請僅發送給可信調用方",
|
||||
"copyKey": "複製密鑰",
|
||||
"iHaveSaved": "我已保存"
|
||||
},
|
||||
"filters": {
|
||||
"apiKeyFilteringAndOperations": "API Key 篩選與操作",
|
||||
"searchPlaceholder": "搜索名稱或標籤",
|
||||
"searchLabel": "搜索 API Key 名稱或標籤",
|
||||
"deleteSelected": "刪除選中 ({count})",
|
||||
"createApiKey": "創建 API Key"
|
||||
},
|
||||
"editor": {
|
||||
"description": "配置密鑰信息、分組與使用限制",
|
||||
"namePlaceholder": "例如:生產環境",
|
||||
"labelOptional": "標籤(可選)",
|
||||
"forExampleBackendService": "例如:後端服務",
|
||||
"customKeyOptional": "自定義 Key(可選)",
|
||||
"keyPlaceholder": "留空自動生成",
|
||||
"upstreamIdentity": "上游身份",
|
||||
"dailyLimit": "日限額",
|
||||
"dailyLimitUsd": "日限額(USD)",
|
||||
"weeklyLimit": "周限額",
|
||||
"weeklyLimitUsd": "周限額(USD)",
|
||||
"maximumConcurrency": "最大併發",
|
||||
"requestsPerMinuteRpm": "每分鐘請求數(RPM)",
|
||||
"saveChanges": "保存更改",
|
||||
"updated": "API Key 已更新",
|
||||
"created": "API Key 已創建",
|
||||
"validation": {
|
||||
"amount": "{label}必須是非負金額,最多 10 位小數",
|
||||
"integer": "{label}必須是非負整數"
|
||||
},
|
||||
"enterApiKeyName": "請輸入 API Key 名稱",
|
||||
"invalidKey": "自定義 Key 只能包含 HTTP 可傳輸的可見字符,不能包含空格或換行",
|
||||
"requestsPerMinute": "每分鐘請求數"
|
||||
},
|
||||
"fields": {
|
||||
"copyFullKey": "複製完整密鑰",
|
||||
"allAccounts": "全部賬號",
|
||||
"keyPrefix": "密鑰前綴",
|
||||
"quotaUsage": "額度使用",
|
||||
"requestLimits": "請求限制",
|
||||
"lastUsed": "最後使用"
|
||||
},
|
||||
"page": {
|
||||
"description": "管理 API 密鑰及賬號訪問範圍",
|
||||
"noApiKeyYet": "暫無 API Key",
|
||||
"selectCurrentPageKey": "選擇當前頁密鑰",
|
||||
"selectKey": "選擇密鑰",
|
||||
"concurrency": "併發",
|
||||
"batchDeleteWarning": "刪除後這些 API Key 將立即失效,此操作不可撤銷",
|
||||
"batchDeleteDescription": "確定刪除選中的 {count} 個 API Key 嗎?",
|
||||
"deleteApiKey": "刪除 API Key",
|
||||
"deleteWarning": "刪除後該 API Key 將立即失效,此操作不可撤銷",
|
||||
"apiKey": "該 API Key",
|
||||
"delete": "確定刪除 {name} 嗎?"
|
||||
},
|
||||
"scope": {
|
||||
"allAccounts": {
|
||||
"title": "允許訪問全部賬號",
|
||||
"summary": "保存後,此密鑰可訪問全部賬號",
|
||||
"confirm": "允許訪問",
|
||||
"description": "此密鑰可訪問全部賬號,包括未分組和以後新增的賬號"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"navigation": {
|
||||
"overview": "概覽",
|
||||
"accounts": "賬號管理",
|
||||
"proxies": "代理管理",
|
||||
"groups": "分組管理",
|
||||
"apiKeys": "API 密鑰",
|
||||
"usage": "分析統計",
|
||||
"plugins": "插件",
|
||||
"appearance": "主題設置",
|
||||
"settings": "系統設置",
|
||||
"update": {
|
||||
"available": "發現新版本,打開系統更新",
|
||||
"open": "打開系統更新"
|
||||
},
|
||||
"switchLanguage": "切換語言({value})",
|
||||
"mainLabel": "主導航",
|
||||
"pluginsLabel": "插件導航",
|
||||
"pluginManagement": "插件管理",
|
||||
"online": "在線",
|
||||
"sidebar": {
|
||||
"close": "關閉側邊欄",
|
||||
"expand": "展開側邊欄",
|
||||
"collapse": "收縮側邊欄",
|
||||
"open": "打開側邊欄"
|
||||
},
|
||||
"missingEntryPoint": "未配置 {role} 身份的默認入口"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,533 @@
|
||||
{
|
||||
"plugins": {
|
||||
"assets": {
|
||||
"pluginPackage": "插件包:{name}",
|
||||
"selectPluginPackage": "選擇插件包",
|
||||
"packageLabel": "插件包"
|
||||
},
|
||||
"bindings": {
|
||||
"observationHelpTitle": "請求觀察說明",
|
||||
"observationHelp": "僅觀察請求,不改變請求結果",
|
||||
"applyToAllRequests": "應用於所有請求",
|
||||
"scopeHelpTitle": "生效請求範圍說明",
|
||||
"scopeHelp": "關閉後至少選擇一項範圍,不同條件同時滿足才生效,同一條件內任意一項匹配即可",
|
||||
"clientKey": "客戶端 Key",
|
||||
"accountGrouping": "賬號分組",
|
||||
"modelScope": "模型範圍",
|
||||
"oneModelNamePerLineExactMatch": "每行一個模型名稱,精確匹配",
|
||||
"providerScope": "Provider 範圍",
|
||||
"oneProviderIdentifierPerLine": "每行一個 Provider 標識",
|
||||
"executionOrder": "執行順序",
|
||||
"executionSequenceDescription": "執行順序說明",
|
||||
"priorityHelp": "數值較小的先執行",
|
||||
"whenPluginFails": "插件失敗時",
|
||||
"continueToNextHandler": "交給後續處理",
|
||||
"rejectRequest": "拒絕請求"
|
||||
},
|
||||
"capabilities": {
|
||||
"moreCapabilities": "另有 {count} 項聲明能力"
|
||||
},
|
||||
"catalog": {
|
||||
"cardView": "卡片視圖",
|
||||
"listView": "列表視圖",
|
||||
"currentVersion": "當前版本",
|
||||
"installedVersion": "已安裝版本",
|
||||
"provideFunctionality": "功能",
|
||||
"searchForInstalledPlugins": "搜索已安裝插件",
|
||||
"searchPluginsPublishers": "搜索插件、發佈者",
|
||||
"pluginStatus": "插件狀態",
|
||||
"pluginDisplayMode": "插件顯示方式",
|
||||
"noMatchingPlugins": "沒有匹配的插件",
|
||||
"installYourFirstPlugin": "安裝第一個插件",
|
||||
"tryAnotherNameOrStatus": "試試其他名稱或狀態",
|
||||
"emptyDescription": "從上方安裝插件,請先確認來源可信",
|
||||
"clearFilters": "清除篩選",
|
||||
"pluginInstalled": "已安裝插件",
|
||||
"noDescription": "發佈者未提供說明",
|
||||
"versions": "{count} 個版本",
|
||||
"manage": "管理 {displayName}",
|
||||
"versionCount": "版本數"
|
||||
},
|
||||
"configuration": {
|
||||
"fillInRequiredConfiguration": "請填寫必填配置",
|
||||
"incompatibleSecrets": "目標版本不支持部分已保存的敏感配置,請選擇替換或清除",
|
||||
"requiredSecretsCannotClear": "必填敏感配置不能清除:{labels}",
|
||||
"requiredSecretsMissing": "沒有可保留的必填敏感配置:{labels}",
|
||||
"secretsRequired": "請填寫必填敏感配置",
|
||||
"checkBasicSettings": "請檢查基本設置",
|
||||
"noParameters": "無需填寫插件參數",
|
||||
"sensitiveConfiguration": "敏感配置",
|
||||
"secretsHelpTitle": "敏感配置說明",
|
||||
"secretsHelp": "敏感配置單獨保存,不回顯已有值,選擇保留時不會更改,選擇替換時以本次填寫的全部值覆蓋",
|
||||
"settingsSaved": "已保存 {count} 項",
|
||||
"clearSecretsHelp": "保存時清除全部敏感配置",
|
||||
"about": "{name}說明",
|
||||
"enterNewValue": "輸入新值",
|
||||
"pluginParameters": "插件參數",
|
||||
"advancedSettings": "高級設置",
|
||||
"clientAuthentication": "客戶端認證",
|
||||
"applyAndSwitch": "應用並切換",
|
||||
"saveAndEnable": "保存並啓用",
|
||||
"saveSettings": "保存設置",
|
||||
"keepExistingValues": "保留已有值",
|
||||
"replaceAllValues": "替換全部值",
|
||||
"clearAllValues": "清除全部值",
|
||||
"checkPluginParameters": "請檢查插件參數",
|
||||
"setRequestScopeOrCheckApplyTo": "請設置請求範圍,或勾選“應用於所有請求”",
|
||||
"invalidIdentityMappings": "請檢查客戶端認證身份映射",
|
||||
"switchTo": "切換至 {version}",
|
||||
"pluginSettings": "插件設置",
|
||||
"unchangedVersion": "當前版本保持不變,修改後再應用",
|
||||
"pluginSettingsPartition": "插件設置分區",
|
||||
"secretsModeLabel": "敏感配置保存方式",
|
||||
"customScope": "自定義範圍",
|
||||
"applyGlobally": "全局生效",
|
||||
"requestHandling": "請求處理:{value}",
|
||||
"description": "按配置提供擴展功能",
|
||||
"providesTerminalCommands": "提供終端命令",
|
||||
"requestHandlingNotConfigured": "未配置請求處理",
|
||||
"apiKeys": "{count} 個 Key",
|
||||
"groups": "{count} 個分組",
|
||||
"providers": "{count} 個 Provider",
|
||||
"identityMappings": "{count} 組身份映射",
|
||||
"allRequests": "所有請求",
|
||||
"noLimitOnScope": "不限制範圍",
|
||||
"featureDetails": "功能詳情",
|
||||
"capabilitiesOf": "{name} 的功能詳情",
|
||||
"terminalCommands": "終端命令",
|
||||
"legacy": {
|
||||
"multipleEnabledNotice": "檢測到多套啓用配置,請在歷史配置中停用不再使用的一套",
|
||||
"previousConfigurations": "歷史配置 · {count}",
|
||||
"description": "保留已有設置和數據,使用歷史配置會替換當前啓用配置",
|
||||
"disableAction": "停用歷史配置",
|
||||
"start": "啓動",
|
||||
"deleteHistoricalConfiguration": "刪除歷史配置"
|
||||
},
|
||||
"stale": "插件設置已變更,請刷新後重試",
|
||||
"incompatible": "請調整不兼容的設置後重試"
|
||||
},
|
||||
"details": {
|
||||
"version": "版本",
|
||||
"pendingDescription": "配置已保存,等待生效,狀態會自動刷新",
|
||||
"requiredConfiguration": "補充必填配置後即可啓用",
|
||||
"versionInUse": "舊版本仍有進行中的調用,完成前暫不能刪除",
|
||||
"pluginDetails": "插件詳情",
|
||||
"pluginDetailsSection": "插件詳情分區",
|
||||
"manualInstallationVersion": "手動安裝版本",
|
||||
"pluginHasNotBeenInitialized": "插件尚未初始化",
|
||||
"pluginIsNotInstalled": "插件待安裝",
|
||||
"initializePlugin": "初始化插件",
|
||||
"installation": "安裝",
|
||||
"versionNotAvailable": "版本不可用",
|
||||
"configurationStatusOf": "{name}配置狀態說明",
|
||||
"settings": "設置",
|
||||
"restart": "重新啓動",
|
||||
"deactivate": "停用",
|
||||
"completeSetupAndEnable": "完成設置並啓用",
|
||||
"fallbackVersion": "回退版本",
|
||||
"uninstallPlugin": "卸載插件"
|
||||
},
|
||||
"downloadAuth": {
|
||||
"accessToken": "訪問令牌",
|
||||
"usernameAndPassword": "用戶名與密碼",
|
||||
"customRequestHeader": "自定義請求頭",
|
||||
"noCertificationRequired": "無需認證",
|
||||
"fillInGithubToken": "填寫 GitHub 令牌",
|
||||
"credentialsPlaceholder": "填寫認證信息",
|
||||
"useSavedCredentials": "使用已保存憑據",
|
||||
"download": "下載 · {hostname}",
|
||||
"downloadCertification": "下載認證",
|
||||
"helpTitle": "下載認證說明",
|
||||
"githubHelp": "公開倉庫無需認證,私有倉庫需要有讀取權限的 GitHub 令牌",
|
||||
"urlHelp": "僅在下載地址要求認證時填寫",
|
||||
"storageHelp": "認證信息在查詢或解析時保存,僅用於當前來源,不會提供給插件",
|
||||
"authenticationMethod": "認證方式",
|
||||
"githubToken": "GitHub 令牌",
|
||||
"downloadToken": "下載令牌",
|
||||
"enterToken": "輸入令牌",
|
||||
"username": "用戶名",
|
||||
"downloadUsername": "下載用戶名",
|
||||
"password": "密碼",
|
||||
"downloadPassword": "下載密碼",
|
||||
"requestHeaderName": "請求頭名稱",
|
||||
"requestHeaderValue": "請求頭值"
|
||||
},
|
||||
"enable": {
|
||||
"notSet": "未設置",
|
||||
"switchActiveConfiguration": "切換啓用配置",
|
||||
"enablePluginConfiguration": "啓用插件配置",
|
||||
"willBeEnabled": "將啓用",
|
||||
"configurationsToDisable": "將停用 {count} 項",
|
||||
"toggleEnablementInstructions": "切換啓用說明",
|
||||
"disableDescription": "以下配置將停止處理新請求,設置、密鑰與私有數據保留",
|
||||
"willBeDeactivated": "將停用",
|
||||
"confirmSwitch": "確認切換",
|
||||
"confirmEnable": "確認啓用"
|
||||
},
|
||||
"extensions": {
|
||||
"emptyTitle": "暫無插件管理頁面",
|
||||
"emptyDescription": "啓用帶有管理頁面的插件後,可從此處或側欄進入",
|
||||
"configuration": "配置 {value}",
|
||||
"pages": "{count} 頁",
|
||||
"openPage": "打開頁面"
|
||||
},
|
||||
"frontendAuth": {
|
||||
"exclusiveCertification": "獨佔認證",
|
||||
"fallbackApiKeyIfNoMatch": "未匹配時回退 API Key",
|
||||
"disabled": "(已停用)",
|
||||
"configuredUnavailable": "已配置但當前不可用",
|
||||
"invalidBinding": "客戶端認證綁定必須使用認證階段和受支持的未匹配處理",
|
||||
"unsupportedScope": "客戶端認證不支持 Provider、模型或分組範圍,請關閉後重新啓用該綁定",
|
||||
"addAtLeastOneIdentityMapping": "請添加至少一條身份映射",
|
||||
"mappingLimit": "身份映射不能超過 256 條",
|
||||
"invalidIdentity": "身份標識必須是 1–256 個 UTF-8 字節,且不能含首尾空白或控制字符",
|
||||
"duplicateIdentity": "同一身份標識只能配置一次",
|
||||
"keyRequired": "請爲每個身份標識選擇客戶端 Key",
|
||||
"repeatedCursor": "服務返回了重複的分頁位置",
|
||||
"failedToLoadClientKey": "加載客戶端 Key 失敗",
|
||||
"enableClientAuthentication": "啓用客戶端認證",
|
||||
"helpTitle": "客戶端認證說明",
|
||||
"description": "插件識別請求中的外部身份,宿主再將該身份映射到已有 Client Key,沿用這個 Key 的限額、賬號範圍與併發策略",
|
||||
"loginNotice": "此功能用於客戶端 API 請求,不替代管理端登錄",
|
||||
"unmatchedProcessing": "未匹配處理",
|
||||
"unmatchedHandlingInstructions": "未匹配處理說明",
|
||||
"exclusiveHelp": "獨佔認證:插件未識別到身份時拒絕請求",
|
||||
"fallbackToApiKeyWhenNoMatch": "未匹配時回退 API Key:插件未識別到身份時,繼續使用宿主原有的 API Key 認證",
|
||||
"rejectionHelp": "插件明確拒絕或調用失敗時始終拒絕請求,不會回退",
|
||||
"unmatchedLabel": "客戶端認證未匹配處理",
|
||||
"identityMapping": "身份映射",
|
||||
"identityMappingDescription": "身份映射說明",
|
||||
"identityHelp": "身份標識必須與插件返回的值完全一致,同一身份只能映射一次",
|
||||
"keyHelp": "選擇該身份使用的 Client Key,已停用或刪除的 Key 不會獲得執行權限",
|
||||
"reloadClientKey": "重新加載客戶端 Key",
|
||||
"addMapping": "添加映射",
|
||||
"identityMark": "身份標識",
|
||||
"identityPlaceholder": "填寫插件返回的身份標識",
|
||||
"failedToLoadTryAgain": "加載失敗,請重試",
|
||||
"selectClientApiKey": "選擇客戶端 Key",
|
||||
"noClientKeyYet": "暫無客戶端 Key",
|
||||
"removeIdentityMapping": "移除第 {value} 條身份映射"
|
||||
},
|
||||
"installation": {
|
||||
"uploadPackage": "上傳包",
|
||||
"enterDigitHexadecimalDigest": "請輸入 64 位十六進制摘要",
|
||||
"installNewVersion": "安裝新版本",
|
||||
"pluginPackageCannotExceedMib": "插件包不能超過 32 MiB",
|
||||
"verificationRequired": "請先校驗當前選擇的插件包",
|
||||
"githubRepositoryRequired": "請輸入 GitHub 倉庫鏈接或 owner/repo",
|
||||
"prereleaseTagRequired": "查詢預發行版需要明確填寫 tag",
|
||||
"updatePlugin": "更新插件",
|
||||
"installPlugin": "安裝插件",
|
||||
"installDescription": "確認來源與版本後安裝",
|
||||
"switchDescription": "檢查設置兼容性後切換版本",
|
||||
"sourceHelp": "支持本地插件包、URL 與 GitHub",
|
||||
"installationMethod": "安裝方式",
|
||||
"tarGzTgzMaxMib": "tar.gz / tgz,最大 32 MiB",
|
||||
"replace": "更換",
|
||||
"browseFiles": "瀏覽文件",
|
||||
"downloadUrl": "下載 URL",
|
||||
"downloadAddressDescription": "下載地址說明",
|
||||
"urlHelp": "僅支持 HTTPS,本機迴環地址可使用 HTTP",
|
||||
"githubRepository": "GitHub 倉庫",
|
||||
"repositoryLinkOrOwnerRepo": "倉庫鏈接或 owner/repo",
|
||||
"tagLabel": "版本標籤",
|
||||
"tagHelpTitle": "版本標籤說明",
|
||||
"tagHelp": "留空查詢最新穩定版,查詢預發行版時必須指定標籤",
|
||||
"tagPlaceholder": "留空查最新穩定版",
|
||||
"allowPrereleaseLabel": "允許查詢預發行版",
|
||||
"verificationSummary": "校驗摘要",
|
||||
"digestHelpTitle": "校驗摘要說明",
|
||||
"digestHelp": "可選,填寫發佈者提供的 64 位 SHA-256 十六進制摘要,用於覈對下載內容",
|
||||
"shaChecksum": "SHA-256 校驗摘要",
|
||||
"optionalSha": "可選,SHA-256",
|
||||
"versionFound": "已找到版本",
|
||||
"preRelease": "預發行版",
|
||||
"thereIsNoTarGzOrTgz": "此版本沒有 tar.gz 或 tgz 插件包",
|
||||
"pendingTitle": "待安裝插件",
|
||||
"parsingCompleted": "解析完成",
|
||||
"publisher": "發佈者",
|
||||
"applicablePlatforms": "適用平臺",
|
||||
"trustNotice": "插件可訪問全部網關數據與配置,安裝前請確認來源可信",
|
||||
"activateAfterInstall": "安裝後確認切換到新版本",
|
||||
"installNewVersionInstructions": "安裝新版本說明",
|
||||
"configurationHelp": "沿用設置並補充新版本默認值,需要調整時會打開設置,已使用版本保留恢復設置",
|
||||
"queryAgain": "重新查詢",
|
||||
"queryingVersion": "正在查詢版本",
|
||||
"saveSourceAndContinue": "保存來源並繼續",
|
||||
"parsingPluginPackage": "正在解析插件包",
|
||||
"pluginInstallationFailed": "插件安裝失敗",
|
||||
"noSource": "此插件沒有可用的安裝來源",
|
||||
"sourceChanged": "安裝來源已變更,請關閉後重新打開",
|
||||
"sourceSaveFailed": "安裝來源保存失敗",
|
||||
"githubReleaseQueryFailed": "GitHub Release 查詢失敗",
|
||||
"installedNeedsConfiguration": "插件已安裝,請補充必要配置",
|
||||
"preparing": "插件已安裝,正在準備",
|
||||
"pluginVersionInstalled": "插件版本已安裝",
|
||||
"updateSourceChanged": "安裝來源已變更,請重新檢查更新",
|
||||
"pluginUpgradeFailed": "插件升級失敗",
|
||||
"versionRequired": "請選擇待安裝的插件版本",
|
||||
"packageMismatch": "插件包與當前插件不符,請重新選擇",
|
||||
"verificationFailed": "插件包校驗失敗"
|
||||
},
|
||||
"management": {
|
||||
"installed": "已安裝",
|
||||
"extensions": "擴展頁",
|
||||
"description": "管理版本、配置與擴展頁",
|
||||
"tabsLabel": "插件管理分區",
|
||||
"refresh": "刷新插件",
|
||||
"switchPluginVersion": "切換插件版本",
|
||||
"switchHelp": "切換前會檢查目標版本設置,失敗時保留當前版本",
|
||||
"deletePluginVersion": "刪除插件版本",
|
||||
"deleteVersionHelp": "使用中的版本不可刪除,刪除版本也會清除對應的恢復設置",
|
||||
"delete": "刪除 {displayName} {version}?",
|
||||
"versionDeletionDetails": "版本刪除詳情",
|
||||
"deleteVersionInUse": "被配置或運行中的調用引用時不能刪除,不會自動停用其他配置",
|
||||
"deleteVersionCleanupHelp": "只清理此版本獨用的下載認證,刪除最後一個版本時同時清理來源規則,共享認證與代理不受影響",
|
||||
"deleteVersionCleanupLabel": "同時清理獨用下載認證,最後一版還會清理來源",
|
||||
"deletePluginConfiguration": "刪除插件配置",
|
||||
"deleteConfigurationWarning": "配置、密鑰與私有數據將永久刪除",
|
||||
"deleteConfigurationHelp": "無法恢復,已安裝版本與其他配置不受影響",
|
||||
"uninstallWarning": "刪除全部版本、配置、密鑰與私有數據",
|
||||
"confirmUninstall": "確認卸載",
|
||||
"versionCount": "{displayName} · {count} 個版本",
|
||||
"uninstallCleanupLabel": "同時清理來源與獨用下載認證",
|
||||
"uninstallCleanupInstructions": "卸載清理說明",
|
||||
"uninstallCleanupHelp": "只清理被卸載版本使用且不再被其他版本引用的下載認證,不刪除共享認證、代理或審計記錄",
|
||||
"disableInsteadHelp": "暫時不用可停用配置,無需卸載",
|
||||
"permanentDeleteLabel": "確認永久刪除,無法恢復",
|
||||
"deleteDownloadCredentials": "刪除下載認證",
|
||||
"itCannotBeDeletedWhileItIs": "仍被使用時不可刪除,刪除後無法恢復",
|
||||
"pageLoadFailed": "插件擴展頁加載失敗",
|
||||
"pluginDataLoadingFailed": "插件數據加載失敗"
|
||||
},
|
||||
"frame": {
|
||||
"pluginPageCannotBeLoaded": "插件頁面無法加載",
|
||||
"versionChanged": "插件頁面版本已變更,正在刷新",
|
||||
"navigationBlocked": "插件頁面嘗試離開已隔離的管理文檔,已停止加載",
|
||||
"invalidQueryParameter": "查詢參數無效",
|
||||
"queryParametersExceedKib": "查詢參數超過 8 KiB",
|
||||
"invalidBody": "請求正文無效或超過 1 MiB",
|
||||
"routesDoNotAcceptRequestBody": "{method} 路由不接受請求正文",
|
||||
"contentTypeIsInvalid": "Content-Type 無效",
|
||||
"unregisteredContentType": "Content-Type 未在插件路由中註冊",
|
||||
"contentTypeRequired": "包含正文的請求必須聲明 Content-Type",
|
||||
"invalidRequestParameters": "請求參數無效",
|
||||
"unregisteredRequest": "請求未在當前插件版本中註冊",
|
||||
"invalidCallbackTicket": "回調票據參數無效",
|
||||
"unregisteredCallback": "回調路徑未在當前插件版本中註冊",
|
||||
"invalidTicketLifetime": "回調票據有效期必須爲 1 到 600 秒",
|
||||
"invalidModelRequest": "模型請求參數無效",
|
||||
"clientkeyidIsInvalid": "clientKeyId 無效",
|
||||
"invalidModelBody": "Responses 請求正文無效或超過 8 MiB",
|
||||
"invalidModelJson": "Responses 請求正文不是有效 JSON",
|
||||
"modelObjectRequired": "Responses 請求正文必須是 JSON 對象",
|
||||
"pageDidNotContinueToReadModel": "頁面 30 秒未繼續讀取模型響應",
|
||||
"modelConcurrencyLimit": "模型請求已達併發上限",
|
||||
"duplicateModelRequest": "模型請求序號重複",
|
||||
"modelTimeout": "模型請求超過 10 分鐘",
|
||||
"unsupportedModelContentType": "模型接口返回了不受支持的內容類型",
|
||||
"modelRequestFailed": "模型請求失敗",
|
||||
"invalidPullId": "模型響應拉取序號無效",
|
||||
"concurrentPull": "模型響應拉取發生重入",
|
||||
"stalePullId": "模型響應拉取序號已失效",
|
||||
"modelResponseReadFailed": "模型響應讀取失敗",
|
||||
"duplicateManagementRequest": "插件管理請求序號重複",
|
||||
"managementConcurrencyLimit": "插件管理請求已達併發上限",
|
||||
"invalidEntryPoint": "插件頁面入口不是已註冊的 HTML 資源",
|
||||
"unregisteredAsset": "插件頁面引用了未註冊資源:{path}",
|
||||
"htmlSubresource": "插件 HTML 資源不能作爲子資源加載",
|
||||
"cyclicCss": "插件 CSS 資源存在循環引用:{path}",
|
||||
"invalidVersion": "插件頁面版本無效,請刷新後重試",
|
||||
"resourceCountLimit": "插件頁面資源數量超過限制",
|
||||
"pageChanged": "插件頁面已變更,請刷新後重試",
|
||||
"pluginAssetReturnedHttp": "插件資源返回 HTTP {status}",
|
||||
"resourceTypeMismatch": "插件資源類型與註冊值不一致:{path}",
|
||||
"pluginAssetExceedsMib": "插件資源超過 1 MiB:{path}",
|
||||
"resourceSizeLimit": "插件頁面資源總量超過 8 MiB",
|
||||
"unsupportedElement": "插件頁面使用了不受支持的 {'<'}{value}{'>'} 元素",
|
||||
"redirectForbidden": "插件頁面不能使用自動跳轉",
|
||||
"moduleScriptUnsupported": "插件頁面暫不支持 ES Module 腳本,請使用經典腳本包",
|
||||
"invalidPluginScriptAssetType": "插件腳本資源類型無效:{path}",
|
||||
"unsupportedLink": "插件頁面只支持 stylesheet 和 icon 鏈接資源",
|
||||
"invalidStylesheet": "插件樣式資源類型無效:{path}",
|
||||
"invalidPluginIconAssetType": "插件圖標資源類型無效:{path}",
|
||||
"unsupportedSrc": "插件頁面不支持 {'<'}{value}{'>'} 的 src 加載",
|
||||
"invalidPluginImageAssetType": "插件圖像資源類型無效:{path}",
|
||||
"invalidPluginPosterAssetType": "插件 poster 資源類型無效:{path}",
|
||||
"emptySrcset": "插件 srcset 資源引用爲空",
|
||||
"externalNavigation": "插件頁面不能導航到外部或未註冊地址",
|
||||
"pluginPageDoesNotSupportUrls": "插件頁面不支持 {name} 地址",
|
||||
"externalAttribute": "插件頁面屬性不能引用外部資源:{name}",
|
||||
"unsupportedPluginCssSyntax": "插件 CSS 語法不受支持:{ownerPath}",
|
||||
"invalidCss": "插件 CSS 包含無法解析的內容:{ownerPath}",
|
||||
"escapedCssIdentifier": "插件 CSS 規則或函數名不能使用轉義:{ownerPath}",
|
||||
"inlineStyleImport": "內聯 style 屬性不能導入樣式表",
|
||||
"unsupportedPluginImportSyntax": "插件 {'@'}import 語法不受支持:{ownerPath}",
|
||||
"pluginImportTargetIsNotCss": "插件 {'@'}import 目標不是 CSS:{path}",
|
||||
"unsupportedPluginAssetUrl": "插件資源地址不受支持:{rawReference}",
|
||||
"resourceQuery": "插件資源地址不支持查詢參數:{rawReference}",
|
||||
"resourceFragment": "插件資源地址不支持片段標識:{rawReference}",
|
||||
"resourceOutsideArtifact": "插件資源地址越過製品邊界:{rawReference}",
|
||||
"invalidPluginAssetPathSegment": "插件資源路徑片段無效:{rawReference}",
|
||||
"invalidResourcePath": "插件註冊了無效資源路徑:{path}",
|
||||
"pluginTextAssetIsNotValidUtf": "插件文本資源不是有效 UTF-8:{path}"
|
||||
},
|
||||
"pluginPage": "插件頁面",
|
||||
"page": {
|
||||
"configurationDescription": "使用插件提供的功能,當前配置爲「{name}」",
|
||||
"description": "加載已啓用插件的管理頁面",
|
||||
"unpublished": "該配置或頁面未發佈,可能已停用或切換版本",
|
||||
"refreshFailed": "頁面目錄刷新失敗,當前顯示上次成功加載的版本:{loadError}",
|
||||
"loadingPage": "正在加載頁面"
|
||||
},
|
||||
"refreshPage": "刷新頁面",
|
||||
"pluginPageIsUnavailable": "插件頁面不可用",
|
||||
"returnToPluginManagement": "返回插件管理",
|
||||
"resources": {
|
||||
"unavailable": "不可用 · {id}",
|
||||
"multipleSelectionsAllowed": "{label}(可多選)",
|
||||
"unlimitedPlaceholder": "不限(可多選)",
|
||||
"loading": "正在加載…",
|
||||
"isTemporarilyUnavailable": "暫時無法獲取{label}",
|
||||
"noMatches": "沒有匹配項",
|
||||
"no": "暫無{label}",
|
||||
"createOneInFirst": "請先在{value}中創建"
|
||||
},
|
||||
"rollback": {
|
||||
"rollBackPluginVersion": "回退插件版本",
|
||||
"description": "恢復對應版本的設置,保持當前啓停狀態",
|
||||
"targetVersion": "目標版本",
|
||||
"fallbackInstructions": "回退說明",
|
||||
"restoreHelp": "恢復目標版本上次啓用時的參數和密鑰,私有數據仍須通過兼容檢查",
|
||||
"loadingOlderVersions": "正在加載舊版",
|
||||
"selectRollbackVersion": "請選擇回退目標",
|
||||
"rollBackToTargetVersion": "回退目標版本",
|
||||
"empty": "沒有保留恢復設置的舊版,其他版本可在“版本”中切換",
|
||||
"reload": "重新加載",
|
||||
"confirmRollback": "確認回退",
|
||||
"completed": "已回退至 {version},並恢復對應設置"
|
||||
},
|
||||
"sourceProxy": {
|
||||
"noProxyDirectConnection": "不使用代理(直連)",
|
||||
"disabledSuffix": "(已禁用)",
|
||||
"catalogUnavailable": "已選代理(目錄暫不可用)",
|
||||
"label": "下載代理"
|
||||
},
|
||||
"status": {
|
||||
"unableToStart": "無法啓動",
|
||||
"runFailed": "運行失敗",
|
||||
"compatibilityReminder": "兼容性提醒",
|
||||
"deprecatedApi": "接口待升級,當前仍兼容",
|
||||
"startupUnverified": "可以嘗試啓動,運行結果仍需驗證",
|
||||
"compatibilityWindow": "舊接口還將兼容至少 {remainingReleases} 個正式版本",
|
||||
"compatibilityEnding": "兼容窗口已滿,後續正式版本將移除舊接口轉換",
|
||||
"unsupportedVersionHelp": "配置與數據保留,請安裝可加載的插件版本",
|
||||
"restartHelp": "啓用配置保留,可在插件詳情中重新啓動",
|
||||
"upgradeHelp": "請更新插件,或聯繫作者升級接口"
|
||||
},
|
||||
"updates": {
|
||||
"packageRequired": "請選擇插件包以確認版本與兼容性",
|
||||
"currentlyUsingThisVersion": "當前已使用此版本",
|
||||
"verifiedUpdate": "發現新版本,插件包已校驗",
|
||||
"sameVersionDifferentContent": "版本號相同,插件包內容不同",
|
||||
"noHigherVersionFound": "未發現更高版本",
|
||||
"pluginUpdate": "插件更新",
|
||||
"checkingDescription": "正在檢查版本並校驗插件包",
|
||||
"versionComparison": "版本對比",
|
||||
"postTag": "發佈標籤",
|
||||
"updateInspectionInstructions": "更新檢查說明",
|
||||
"configurationHelp": "按插件包內版本判斷升級,沿用當前設置,配置不兼容時保留當前版本並打開設置",
|
||||
"trustNotice": "插件可訪問全部網關數據與配置,更新前請確認來源可信",
|
||||
"thereIsNoTarGzOrTgzPlugin": "此發佈沒有 tar.gz 或 tgz 插件包",
|
||||
"upgradeTo": "升級到 {version}",
|
||||
"continueInstallation": "繼續安裝",
|
||||
"unsupportedSource": "此來源不支持檢查更新,請安裝新版本",
|
||||
"sourceChanged": "安裝來源已變更,請重新檢查",
|
||||
"checkForUpdatesFailed": "檢查更新失敗"
|
||||
},
|
||||
"versionDetails": "版本詳情",
|
||||
"toBeInstalled": "待安裝",
|
||||
"historicalConfiguration": "歷史配置",
|
||||
"referenceConfiguration": "引用配置",
|
||||
"versions": {
|
||||
"detailsLabel": "{version} 版本詳情",
|
||||
"historicalVersion": "歷史版本"
|
||||
},
|
||||
"install": "安裝 {version}",
|
||||
"deleteVersion": "刪除版本 {version}",
|
||||
"credentials": {
|
||||
"selectDownloadCredentials": "選擇下載認證 {name}",
|
||||
"deleteDownloadCredentials": "刪除下載認證 {name}",
|
||||
"saveDownloadCredentialsFailed": "下載認證保存失敗",
|
||||
"sourceCredentialsDeleted": "來源憑據已刪除",
|
||||
"deleteFailed": "來源憑據刪除失敗"
|
||||
},
|
||||
"artifacts": {
|
||||
"pluginProductHasBeenDeleted": "插件製品已刪除",
|
||||
"pluginProductDeletionFailed": "插件製品刪除失敗"
|
||||
},
|
||||
"instances": {
|
||||
"saveFailed": "插件配置保存失敗",
|
||||
"versionMissing": "所選版本已不存在,請重新選擇",
|
||||
"loadFailed": "啓用配置加載失敗",
|
||||
"configurationEnablementFailed": "配置啓用失敗",
|
||||
"switchedCurrentConfiguration": "已切換當前配置",
|
||||
"pluginSettingsApplied": "插件設置已應用",
|
||||
"savedDisabled": "設置已保存,插件保持停用",
|
||||
"pluginDisabled": "插件已停用",
|
||||
"pluginDeactivationFailed": "插件停用失敗",
|
||||
"deleted": "配置、密鑰與私有數據已刪除,無法恢復",
|
||||
"pluginInstanceDeletionFailed": "插件實例刪除失敗"
|
||||
},
|
||||
"uninstall": {
|
||||
"newConfiguration": "出現了新的插件配置,請關閉並重新確認卸載範圍",
|
||||
"versionChanged": "“{name}”已切換版本,請重新確認卸載範圍",
|
||||
"removingConfiguration": "正在停用並刪除配置:{name}",
|
||||
"newVersion": "已刪除確認範圍,但還有新安裝的版本,請關閉並重新確認剩餘內容",
|
||||
"completed": "插件已卸載,相關數據與來源設置已清理",
|
||||
"incomplete": "卸載尚未完成,可重試剩餘步驟"
|
||||
},
|
||||
"deletingVersion": "正在刪除版本:{version}",
|
||||
"switchedTo": "已切換至 {version}",
|
||||
"versionSettingFailedToLoad": "版本設置加載失敗",
|
||||
"versionSwitchingFailed": "版本切換失敗",
|
||||
"fallbackVersionLoadingFailed": "回退版本加載失敗",
|
||||
"pluginVersionRollbackFailed": "插件版本回退失敗",
|
||||
"fields": {
|
||||
"requestCompletionAndUsage": "請求完成與用量",
|
||||
"upstreamWebsocketEvents": "上游 WebSocket 事件",
|
||||
"requestScheduling": "請求調度",
|
||||
"modelRouting": "模型路由",
|
||||
"modelCatalog": "模型目錄",
|
||||
"retryStrategy": "重試策略",
|
||||
"requestMiddleware": "請求中間件",
|
||||
"upstreamAdapter": "上游適配器",
|
||||
"eventObservation": "事件觀察",
|
||||
"commandLine": "命令行",
|
||||
"manageExtensions": "管理擴展",
|
||||
"maintenanceTasks": "維護任務",
|
||||
"httpRequest": "HTTP 請求",
|
||||
"allHttpRequests": "所有 HTTP 請求",
|
||||
"websocketMessages": "WebSocket 消息",
|
||||
"allWebsocketMessages": "所有 WebSocket 消息",
|
||||
"serviceCall": "服務調用",
|
||||
"allServiceCalls": "所有服務調用",
|
||||
"requestToStart": "請求開始",
|
||||
"everyTry": "每次嘗試",
|
||||
"upstreamCall": "上游調用",
|
||||
"accountScheduling": "賬號調度",
|
||||
"retryDecision": "重試決策",
|
||||
"toBeConfigured": "待配置",
|
||||
"deactivated": "已停用",
|
||||
"waitingForItToTakeEffect": "等待生效"
|
||||
},
|
||||
"validation": {
|
||||
"suppliedWithVersion": "隨版本提供",
|
||||
"localUpload": "本地上傳",
|
||||
"fixedUrl": "固定 URL",
|
||||
"releaseList": "發行清單",
|
||||
"noRemoteUpdateSource": "無遠程更新來源"
|
||||
},
|
||||
"onePerLine": "每行一項"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
{
|
||||
"proxies": {
|
||||
"accounts": {
|
||||
"platformType": "平臺",
|
||||
"subscription": "訂閱",
|
||||
"noMatches": "沒有找到匹配的賬號,請嘗試其他名稱或郵箱",
|
||||
"empty": "暫無關聯賬號",
|
||||
"linkAccount": "關聯賬號",
|
||||
"searchAssociatedAccounts": "搜索關聯賬號",
|
||||
"searchAccountNameOrEmail": "搜索賬號名稱或郵箱",
|
||||
"removeAction": "從當前代理移除賬號",
|
||||
"removeAssociatedAccount": "移除關聯賬號",
|
||||
"remove": "移除",
|
||||
"removeDescription": "將“{name}”從“{removeProxyName}”移除後,該賬號將改爲直連",
|
||||
"removed": "賬號已移出當前代理,改爲直連"
|
||||
},
|
||||
"actions": {
|
||||
"test": "測試代理",
|
||||
"edit": "編輯代理",
|
||||
"moreActionsFor": "{name} 的更多操作",
|
||||
"disableProxy": "禁用代理",
|
||||
"enableProxy": "啓用代理",
|
||||
"deleteProxy": "刪除代理",
|
||||
"testInProgress": "代理正在測試,請等待當前測試結束",
|
||||
"testFailed": "代理測試失敗",
|
||||
"connectedWithDetails": "{name}:連接成功,{message}",
|
||||
"timeZoneMismatch": "{name}:連接成功,IPv4 與 IPv6 出口時區不一致",
|
||||
"connected": "{name}:連接成功",
|
||||
"fillInProxyConnectionAddress": "請填寫代理連接地址",
|
||||
"connectedInMs": "連接成功,耗時 {latencyMs} ms",
|
||||
"locationFailed": "代理連接失敗,未能解析位置",
|
||||
"exitLocationFilledIn": "已填入出口位置",
|
||||
"unableToObtainExitLocation": "未獲取到出口位置",
|
||||
"fieldsRequired": "請填寫代理名稱和連接地址",
|
||||
"invalidConnectionLimit": "連接上限須爲 0 到 4294967295 之間的整數",
|
||||
"saved": "代理已保存",
|
||||
"proxyEnabled": "代理已啓用",
|
||||
"disabled": "代理已禁用,關聯賬號已改爲直連",
|
||||
"deleted": "代理已刪除"
|
||||
},
|
||||
"batchCreate": {
|
||||
"proxyList": "代理列表",
|
||||
"formatDescription": "代理列表格式說明",
|
||||
"supportedFormats": "支持以下格式",
|
||||
"hostPortUsernamePassword": "host:port:用戶名:密碼",
|
||||
"httpUsernamePasswordHostPort": "http://用戶名:密碼{'@'}host:port",
|
||||
"protocolHelp": "未寫協議時使用下方默認協議,完整 URL 保留各自協議",
|
||||
"ipv6Help": "IPv6 地址需加方括號,例如",
|
||||
"onePerLineMaximum": "每行一條 · 最多 {value} 條",
|
||||
"bulkProxyList": "批量代理列表",
|
||||
"totalReadyToAdd": "共 {count} 條,{count2} 條可添加",
|
||||
"needsChanges": ",{count} 條需修改",
|
||||
"line": "第 {line} 行:{error}",
|
||||
"additionalIssues": "另有 {count} 條需處理",
|
||||
"defaultProtocol": "默認協議",
|
||||
"defaultProtocolLabel": "無協議代理的默認協議",
|
||||
"namePrefix": "名稱前綴",
|
||||
"proxy": "代理",
|
||||
"conflict": "代理已存在或配置衝突,未覆蓋已有記錄",
|
||||
"stopped": "已停止後續添加"
|
||||
},
|
||||
"batchTest": {
|
||||
"resultsTitle": "批量添加結果",
|
||||
"processed": "已處理",
|
||||
"added": "已添加 {created}",
|
||||
"invalidFormat": "格式錯誤 {invalid}",
|
||||
"connected": "連接正常 {succeeded}",
|
||||
"connectionFailed": "連接失敗 {failed}",
|
||||
"locationPending": "地區待處理 {locationPending}",
|
||||
"needsAttention": "需處理 {attention}",
|
||||
"skipped": "未執行 {skipped}",
|
||||
"scrollListOfProxyResults": "代理結果滾動列表",
|
||||
"lineNumber": "第 {key} 行",
|
||||
"addedStatus": "已添加",
|
||||
"connectionIsNormal": "連接正常",
|
||||
"stopped": "已停止後續測試",
|
||||
"proxyMissing": "所選代理已不存在,請刷新列表",
|
||||
"batchTestCompletedConnected": "批量測試完成,連接正常 {succeeded} 條",
|
||||
"unsuccessful": "未成功 {count} 條",
|
||||
"locationsPending": "地區待處理 {locationPending} 條",
|
||||
"proxiesNoLongerAvailable": "{missing} 條代理已不存在",
|
||||
"toBeExecuted": "待執行",
|
||||
"requestFailed": "請求失敗",
|
||||
"configurationConflict": "配置衝突",
|
||||
"testingIsBusy": "測試繁忙",
|
||||
"resultToBeConfirmed": "結果待確認",
|
||||
"notExecuted": "未執行",
|
||||
"invalidProxyFormat": "代理格式不正確",
|
||||
"invalidAddress": "代理主機或端口不合法",
|
||||
"duplicateOfLine": "與第 {earlier} 行重複",
|
||||
"formatHelp": "格式不正確,請參考格式說明",
|
||||
"proxyListCannotExceedKib": "代理列表不能超過 512 KiB",
|
||||
"addUpToProxiesAtTime": "一次最多添加 {value} 條代理",
|
||||
"resultUnknown": "未取得確定結果,請刷新列表覈對",
|
||||
"interrupted": "請求中斷或服務異常,請刷新列表覈對結果",
|
||||
"skippedAfterFailure": "前序操作異常,未執行"
|
||||
},
|
||||
"editor": {
|
||||
"single": "單條",
|
||||
"batch": "批量",
|
||||
"timeZoneMismatch": "IPv4 與 IPv6 出口時區不一致,請手動填寫",
|
||||
"createTitle": "新增代理",
|
||||
"connectionHelp": "留空保留當前連接和認證信息,填寫新地址時,請包含所需的用戶名和密碼",
|
||||
"protocolHelp": "支持 HTTP、HTTPS、SOCKS5 和 SOCKS5H,可在地址中包含用戶名和密碼",
|
||||
"createDescription": "添加代理,爲賬號配置網絡出口",
|
||||
"methodLabel": "代理添加方式",
|
||||
"nameLabel": "代理名稱",
|
||||
"namePlaceholder": "請輸入代理名稱",
|
||||
"proxyAddress": "代理地址",
|
||||
"addressPlaceholder": "輸入代理地址",
|
||||
"upstreamWsConnectionCap": "上游 WS 連接上限",
|
||||
"connectionLimitHelp": "使用此代理的賬號共享連接額度",
|
||||
"noRestrictionsByDefault": "默認不限制",
|
||||
"customTimeZoneLocation": "自定義時區位置",
|
||||
"affectedAccounts": "將更新 {count} 個關聯賬號的出口",
|
||||
"pendingResultsHelp": "待確認項可能已保存,繼續添加前請刷新覈對",
|
||||
"saveAction": "保存代理",
|
||||
"waitForCurrentOperationToEnd": "等待當前操作結束",
|
||||
"stopSubsequentOperations": "停止後續操作",
|
||||
"testing": "正在測試",
|
||||
"adding": "正在添加",
|
||||
"editItemsNotAdded": "修改未添加項",
|
||||
"testAddedProxies": "測試已添加的 {count} 條",
|
||||
"testAfterAdding": "添加後測試",
|
||||
"add": "添加 {count} 條",
|
||||
"addProxy": "添加代理"
|
||||
},
|
||||
"region": {
|
||||
"connectionFailed": "連接失敗",
|
||||
"regionalConflict": "地區衝突",
|
||||
"parsingFailed": "解析失敗",
|
||||
"exitNotRecognized": "出口未識別",
|
||||
"ipv4AndIpv6EgressTimeZonesAre": "IPv4 與 IPv6 出口時區不一致",
|
||||
"exitLocation": "出口地區:{label} · {timezone}",
|
||||
"detectHelp": "測試代理時解析出口地區",
|
||||
"customLocation": "自定義位置:{customLabel} · {timezone}",
|
||||
"custom": "自定義:{customLabel}"
|
||||
},
|
||||
"fields": {
|
||||
"exitIp": "出口 IP",
|
||||
"latency": "耗時",
|
||||
"testTime": "測試時間"
|
||||
},
|
||||
"page": {
|
||||
"description": "管理賬號使用的代理,測試連接並查看出口 IP",
|
||||
"searchLabel": "搜索代理",
|
||||
"searchPlaceholder": "搜索代理名稱",
|
||||
"batchTestAction": "批量測試代理",
|
||||
"batchTest": "批量測試 ({count})",
|
||||
"noMatches": "沒有找到匹配的代理,請嘗試其他名稱",
|
||||
"empty": "暫無代理",
|
||||
"selectCurrentPageProxy": "選擇當前頁代理",
|
||||
"selectProxy": "選擇代理 {name}",
|
||||
"credentialsSaved": "代理憑據已保存",
|
||||
"underTest": "測試中",
|
||||
"ms": "{message}(耗時 {latencyMs} ms)",
|
||||
"notTested": "未測試",
|
||||
"viewAccountsAssociatedWith": "查看 {name} 的 {count} 個關聯賬號",
|
||||
"disable": "確定禁用“{name}”嗎?",
|
||||
"disableDescription": "關聯賬號的新請求將改爲直連,代理配置和綁定會保留,重新啓用後恢復使用",
|
||||
"delete": "確定刪除“{name}”嗎?",
|
||||
"deleteDescription": "將自動解除關聯賬號,關聯賬號的新請求將改爲直連"
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user