diff --git a/src/components/config/VisualConfigEditor.tsx b/src/components/config/VisualConfigEditor.tsx
index a4e76d5..7541b29 100644
--- a/src/components/config/VisualConfigEditor.tsx
+++ b/src/components/config/VisualConfigEditor.tsx
@@ -1,4 +1,5 @@
import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react';
+import { useTranslation } from 'react-i18next';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
import { Modal } from '@/components/ui/Modal';
@@ -198,6 +199,7 @@ function ApiKeysCardEditor({
disabled?: boolean;
onChange: (nextValue: string) => void;
}) {
+ const { t } = useTranslation();
const apiKeys = useMemo(
() =>
value
@@ -244,11 +246,11 @@ function ApiKeysCardEditor({
const handleSave = () => {
const trimmed = inputValue.trim();
if (!trimmed) {
- setFormError('请输入 API 密钥');
+ setFormError(t('config_management.visual.api_keys.error_empty'));
return;
}
if (!isValidApiKeyCharset(trimmed)) {
- setFormError('API 密钥包含无效字符');
+ setFormError(t('config_management.visual.api_keys.error_invalid'));
return;
}
@@ -263,9 +265,9 @@ function ApiKeysCardEditor({
return (
-
+
@@ -279,7 +281,7 @@ function ApiKeysCardEditor({
textAlign: 'center',
}}
>
- 暂无 API 密钥
+ {t('config_management.visual.api_keys.empty')}
) : (
@@ -292,10 +294,10 @@ function ApiKeysCardEditor({
@@ -303,31 +305,31 @@ function ApiKeysCardEditor({
)}
- 每个条目代表一个 API 密钥(与 “API 密钥管理” 页面样式一致)
+ {t('config_management.visual.api_keys.hint')}
>
}
>
setInputValue(e.target.value)}
disabled={disabled}
error={formError || undefined}
- hint="此处仅修改本地配置文件内容,不会自动同步到 API 密钥管理接口"
+ hint={t('config_management.visual.api_keys.input_hint')}
/>
@@ -345,6 +347,7 @@ function StringListEditor({
placeholder?: string;
onChange: (next: string[]) => void;
}) {
+ const { t } = useTranslation();
const items = value.length ? value : [];
const updateItem = (index: number, nextValue: string) =>
@@ -365,13 +368,13 @@ function StringListEditor({
style={{ flex: 1 }}
/>
))}
@@ -389,6 +392,7 @@ function PayloadRulesEditor({
protocolFirst?: boolean;
onChange: (next: PayloadRule[]) => void;
}) {
+ const { t } = useTranslation();
const rules = value.length ? value : [];
const addRule = () => onChange([...rules, { id: makeClientId(), models: [], params: [] }]);
@@ -441,15 +445,15 @@ function PayloadRulesEditor({
const getValuePlaceholder = (valueType: PayloadParamValueType) => {
switch (valueType) {
case 'string':
- return '字符串值';
+ return t('config_management.visual.payload_rules.value_string');
case 'number':
- return '数字值 (如 0.7)';
+ return t('config_management.visual.payload_rules.value_number');
case 'boolean':
- return 'true 或 false';
+ return t('config_management.visual.payload_rules.value_boolean');
case 'json':
- return 'JSON 值';
+ return t('config_management.visual.payload_rules.value_json');
default:
- return '值';
+ return t('config_management.visual.payload_rules.value_default');
}
};
@@ -468,14 +472,14 @@ function PayloadRulesEditor({
}}
>
-
规则 {ruleIndex + 1}
+
{t('config_management.visual.payload_rules.rule')} {ruleIndex + 1}
-
适用模型
+
{t('config_management.visual.payload_rules.models')}
{(rule.models.length ? rule.models : []).map((model, modelIndex) => (
updateModel(ruleIndex, modelIndex, {
protocol: (nextValue || undefined) as PayloadModelEntry['protocol'],
@@ -500,7 +504,7 @@ function PayloadRulesEditor({
/>
updateModel(ruleIndex, modelIndex, { name: e.target.value })}
disabled={disabled}
@@ -510,7 +514,7 @@ function PayloadRulesEditor({
<>
updateModel(ruleIndex, modelIndex, { name: e.target.value })}
disabled={disabled}
@@ -519,7 +523,7 @@ function PayloadRulesEditor({
value={model.protocol ?? ''}
options={VISUAL_CONFIG_PROTOCOL_OPTIONS}
disabled={disabled}
- ariaLabel="供应商类型"
+ ariaLabel={t('config_management.visual.payload_rules.provider_type')}
onChange={(nextValue) =>
updateModel(ruleIndex, modelIndex, {
protocol: (nextValue || undefined) as PayloadModelEntry['protocol'],
@@ -529,24 +533,24 @@ function PayloadRulesEditor({
>
)}
))}
-
参数设置
+
{t('config_management.visual.payload_rules.params')}
{(rule.params.length ? rule.params : []).map((param, paramIndex) => (
updateParam(ruleIndex, paramIndex, { path: e.target.value })}
disabled={disabled}
@@ -555,7 +559,7 @@ function PayloadRulesEditor({
value={param.valueType}
options={VISUAL_CONFIG_PAYLOAD_VALUE_TYPE_OPTIONS}
disabled={disabled}
- ariaLabel="参数类型"
+ ariaLabel={t('config_management.visual.payload_rules.param_type')}
onChange={(nextValue) =>
updateParam(ruleIndex, paramIndex, { valueType: nextValue as PayloadParamValueType })
}
@@ -568,13 +572,13 @@ function PayloadRulesEditor({
disabled={disabled}
/>
))}
@@ -591,13 +595,13 @@ function PayloadRulesEditor({
textAlign: 'center',
}}
>
- 暂无规则
+ {t('config_management.visual.payload_rules.no_rules')}
)}
@@ -613,6 +617,7 @@ function PayloadFilterRulesEditor({
disabled?: boolean;
onChange: (next: PayloadFilterRule[]) => void;
}) {
+ const { t } = useTranslation();
const rules = value.length ? value : [];
const addRule = () => onChange([...rules, { id: makeClientId(), models: [], params: [] }]);
@@ -654,19 +659,19 @@ function PayloadFilterRulesEditor({
}}
>
-
规则 {ruleIndex + 1}
+
{t('config_management.visual.payload_rules.rule')} {ruleIndex + 1}
-
适用模型
+
{t('config_management.visual.payload_rules.models')}
{rule.models.map((model, modelIndex) => (
updateModel(ruleIndex, modelIndex, { name: e.target.value })}
disabled={disabled}
@@ -675,7 +680,7 @@ function PayloadFilterRulesEditor({
value={model.protocol ?? ''}
options={VISUAL_CONFIG_PROTOCOL_OPTIONS}
disabled={disabled}
- ariaLabel="供应商类型"
+ ariaLabel={t('config_management.visual.payload_rules.provider_type')}
onChange={(nextValue) =>
updateModel(ruleIndex, modelIndex, {
protocol: (nextValue || undefined) as PayloadModelEntry['protocol'],
@@ -683,23 +688,23 @@ function PayloadFilterRulesEditor({
}
/>
))}
-
移除参数
+
{t('config_management.visual.payload_rules.remove_params')}
updateRule(ruleIndex, { params })}
/>
@@ -708,7 +713,7 @@ function PayloadFilterRulesEditor({
@@ -716,23 +721,24 @@ function PayloadFilterRulesEditor({
}
export function VisualConfigEditor({ values, disabled = false, onChange }: VisualConfigEditorProps) {
+ const { t } = useTranslation();
const isKeepaliveDisabled = values.streaming.keepaliveSeconds === '' || values.streaming.keepaliveSeconds === '0';
const isNonstreamKeepaliveDisabled =
values.streaming.nonstreamKeepaliveInterval === '' || values.streaming.nonstreamKeepaliveInterval === '0';
return (
-
+
onChange({ host: e.target.value })}
disabled={disabled}
/>
-
+
-
+
onChange({ rmAllowRemote })}
/>
onChange({ rmDisableControlPanel })}
/>
onChange({ rmSecretKey: e.target.value })}
disabled={disabled}
/>
onChange({ rmPanelRepo: e.target.value })}
@@ -811,15 +817,15 @@ export function VisualConfigEditor({ values, disabled = false, onChange }: Visua
-
+
onChange({ authDir: e.target.value })}
disabled={disabled}
- hint="存放认证文件的目录路径(支持 ~)"
+ hint={t('config_management.visual.sections.auth.auth_dir_hint')}
/>
-
+
onChange({ debug })}
/>
onChange({ commercialMode })}
/>
onChange({ loggingToFile })}
/>
onChange({ usageStatisticsEnabled })}
@@ -864,7 +870,7 @@ export function VisualConfigEditor({ values, disabled = false, onChange }: Visua
onChange({ usageRecordsRetentionDays: e.target.value })}
disabled={disabled}
- hint="0 为无限制(不清理)"
+ hint={t('config_management.visual.sections.system.usage_retention_hint')}
/>
-
+
-
+
onChange({ quotaSwitchProject })}
/>
onChange({ quotaSwitchPreviewModel })}
@@ -964,11 +970,11 @@ export function VisualConfigEditor({ values, disabled = false, onChange }: Visua
-
+
-
+
- 已禁用
+ {t('config_management.visual.sections.streaming.disabled')}
)}
-
设置为 0 或留空表示禁用 keepalive
+
{t('config_management.visual.sections.streaming.keepalive_hint')}
onChange({ streaming: { ...values.streaming, bootstrapRetries: e.target.value } })}
disabled={disabled}
- hint="流式传输启动时(首包前)的重试次数"
+ hint={t('config_management.visual.sections.streaming.bootstrap_hint')}
/>
-
+
- 已禁用
+ {t('config_management.visual.sections.streaming.disabled')}
)}
- 非流式响应时每隔 N 秒发送空行以防止空闲超时,设置为 0 或留空表示禁用
+ {t('config_management.visual.sections.streaming.nonstream_keepalive_hint')}
-
+
-
默认规则
+
{t('config_management.visual.sections.payload.default_rules')}
- 当请求中未指定参数时,使用这些默认值
+ {t('config_management.visual.sections.payload.default_rules_desc')}
-
覆盖规则
+
{t('config_management.visual.sections.payload.override_rules')}
- 强制覆盖请求中的参数值
+ {t('config_management.visual.sections.payload.override_rules_desc')}
-
过滤规则
+
{t('config_management.visual.sections.payload.filter_rules')}
- 通过 JSON Path 预过滤上游请求体,自动剔除不合规/冗余参数(Request Sanitization)
+ {t('config_management.visual.sections.payload.filter_rules_desc')}