feat: Integrate i18n support and enhance UI text localization

- Added internationalization (i18n) support across various components, enabling dynamic language switching and improved user experience.
- Updated multiple components to utilize translation functions for labels, buttons, and messages, ensuring consistent language display.
- Enhanced the user interface by refining text elements in the ChannelsTable, LogsTable, and various settings pages, improving clarity and accessibility.
- Adjusted CSS styles for better responsiveness and layout consistency across different screen sizes.
This commit is contained in:
CalciumIon
2024-12-13 19:03:14 +08:00
parent cd21aa1c56
commit 221d7b5c99
42 changed files with 3192 additions and 1828 deletions

View File

@@ -9,8 +9,10 @@ import {
verifyJSON,
verifyJSONPromise
} from '../../../helpers';
import { useTranslation } from 'react-i18next';
export default function SettingsChats(props) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [inputs, setInputs] = useState({
Chats: "[]",
@@ -24,7 +26,7 @@ export default function SettingsChats(props) {
await refForm.current.validate().then(() => {
console.log('Validation passed');
const updateArray = compareObjects(inputs, inputsRow);
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
const requestQueue = updateArray.map((item) => {
let value = '';
if (typeof inputs[item.key] === 'boolean') {
@@ -44,23 +46,23 @@ export default function SettingsChats(props) {
if (res.includes(undefined)) return;
} else if (requestQueue.length > 1) {
if (res.includes(undefined))
return showError('部分保存失败,请重试');
return showError(t('部分保存失败,请重试'));
}
showSuccess('保存成功');
showSuccess(t('保存成功'));
props.refresh();
})
.catch(() => {
showError('保存失败,请重试');
showError(t('保存失败,请重试'));
})
.finally(() => {
setLoading(false);
});
}).catch((error) => {
console.error('Validation failed:', error);
showError('请检查输入');
showError(t('请检查输入'));
});
} catch (error) {
showError('请检查输入');
showError(t('请检查输入'));
console.error(error);
}
}
@@ -104,19 +106,19 @@ export default function SettingsChats(props) {
getFormApi={(formAPI) => (refForm.current = formAPI)}
style={{ marginBottom: 15 }}
>
<Form.Section text={'令牌聊天设置'}>
<Form.Section text={t('令牌聊天设置')}>
<Banner
type='warning'
description={'必须将上方聊天链接全部设置为空,才能使用下方聊天设置功能'}
description={t('必须将上方聊天链接全部设置为空,才能使用下方聊天设置功能')}
/>
<Banner
type='info'
description={'链接中的{key}将自动替换为sk-xxxx{address}将自动替换为系统设置的服务器地址,末尾不带/和/v1'}
description={t('链接中的{key}将自动替换为sk-xxxx{address}将自动替换为系统设置的服务器地址,末尾不带/和/v1')}
/>
<Form.TextArea
label={'聊天配置'}
label={t('聊天配置')}
extraText={''}
placeholder={'为一个 JSON 文本'}
placeholder={t('为一个 JSON 文本')}
field={'Chats'}
autosize={{ minRows: 6, maxRows: 12 }}
trigger='blur'
@@ -126,7 +128,7 @@ export default function SettingsChats(props) {
validator: (rule, value) => {
return verifyJSON(value);
},
message: '不是合法的 JSON 字符串'
message: t('不是合法的 JSON 字符串')
}
]}
onChange={(value) =>
@@ -140,7 +142,7 @@ export default function SettingsChats(props) {
</Form>
<Space>
<Button onClick={onSubmit}>
保存聊天设置
{t('保存聊天设置')}
</Button>
</Space>
</Spin>

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState, useRef } from 'react';
import { Button, Col, Form, Row, Spin } from '@douyinfe/semi-ui';
import { useTranslation } from 'react-i18next';
import {
compareObjects,
API,
@@ -9,6 +10,7 @@ import {
} from '../../../helpers';
export default function SettingsCreditLimit(props) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [inputs, setInputs] = useState({
QuotaForNewUser: '',
@@ -21,7 +23,7 @@ export default function SettingsCreditLimit(props) {
function onSubmit() {
const updateArray = compareObjects(inputs, inputsRow);
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
const requestQueue = updateArray.map((item) => {
let value = '';
if (typeof inputs[item.key] === 'boolean') {
@@ -40,13 +42,13 @@ export default function SettingsCreditLimit(props) {
if (requestQueue.length === 1) {
if (res.includes(undefined)) return;
} else if (requestQueue.length > 1) {
if (res.includes(undefined)) return showError('部分保存失败,请重试');
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
}
showSuccess('保存成功');
showSuccess(t('保存成功'));
props.refresh();
})
.catch(() => {
showError('保存失败,请重试');
showError(t('保存失败,请重试'));
})
.finally(() => {
setLoading(false);
@@ -72,11 +74,11 @@ export default function SettingsCreditLimit(props) {
getFormApi={(formAPI) => (refForm.current = formAPI)}
style={{ marginBottom: 15 }}
>
<Form.Section text={'额度设置'}>
<Form.Section text={t('额度设置')}>
<Row gutter={16}>
<Col span={6}>
<Form.InputNumber
label={'新用户初始额度'}
label={t('新用户初始额度')}
field={'QuotaForNewUser'}
step={1}
min={0}
@@ -92,12 +94,12 @@ export default function SettingsCreditLimit(props) {
</Col>
<Col span={6}>
<Form.InputNumber
label={'请求预扣费额度'}
label={t('请求预扣费额度')}
field={'PreConsumedQuota'}
step={1}
min={0}
suffix={'Token'}
extraText={'请求结束后多退少补'}
extraText={t('请求结束后多退少补')}
placeholder={''}
onChange={(value) =>
setInputs({
@@ -109,13 +111,13 @@ export default function SettingsCreditLimit(props) {
</Col>
<Col span={6}>
<Form.InputNumber
label={'邀请新用户奖励额度'}
label={t('邀请新用户奖励额度')}
field={'QuotaForInviter'}
step={1}
min={0}
suffix={'Token'}
extraText={''}
placeholder={'例如2000'}
placeholder={t('例如2000')}
onChange={(value) =>
setInputs({
...inputs,
@@ -126,13 +128,13 @@ export default function SettingsCreditLimit(props) {
</Col>
<Col span={6}>
<Form.InputNumber
label={'新用户使用邀请码奖励额度'}
label={t('新用户使用邀请码奖励额度')}
field={'QuotaForInvitee'}
step={1}
min={0}
suffix={'Token'}
extraText={''}
placeholder={'例如1000'}
placeholder={t('例如1000')}
onChange={(value) =>
setInputs({
...inputs,
@@ -145,7 +147,7 @@ export default function SettingsCreditLimit(props) {
<Row>
<Button size='default' onClick={onSubmit}>
保存额度设置
{t('保存额度设置')}
</Button>
</Row>
</Form.Section>

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useState, useRef } from 'react';
import { Button, Col, Form, Row, Spin, Tag } from '@douyinfe/semi-ui';
import { Button, Col, Form, Row, Spin } from '@douyinfe/semi-ui';
import {
compareObjects,
API,
@@ -7,12 +7,15 @@ import {
showSuccess,
showWarning,
} from '../../../helpers';
import { useTranslation } from 'react-i18next';
export default function DataDashboard(props) {
const { t } = useTranslation();
const optionsDataExportDefaultTime = [
{ key: 'hour', label: '小时', value: 'hour' },
{ key: 'day', label: '天', value: 'day' },
{ key: 'week', label: '周', value: 'week' },
{ key: 'hour', label: t('小时'), value: 'hour' },
{ key: 'day', label: t('天'), value: 'day' },
{ key: 'week', label: t('周'), value: 'week' },
];
const [loading, setLoading] = useState(false);
const [inputs, setInputs] = useState({
@@ -25,7 +28,7 @@ export default function DataDashboard(props) {
function onSubmit() {
const updateArray = compareObjects(inputs, inputsRow);
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
const requestQueue = updateArray.map((item) => {
let value = '';
if (typeof inputs[item.key] === 'boolean') {
@@ -44,13 +47,13 @@ export default function DataDashboard(props) {
if (requestQueue.length === 1) {
if (res.includes(undefined)) return;
} else if (requestQueue.length > 1) {
if (res.includes(undefined)) return showError('部分保存失败,请重试');
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
}
showSuccess('保存成功');
showSuccess(t('保存成功'));
props.refresh();
})
.catch(() => {
showError('保存失败,请重试');
showError(t('保存失败,请重试'));
})
.finally(() => {
setLoading(false);
@@ -81,12 +84,12 @@ export default function DataDashboard(props) {
getFormApi={(formAPI) => (refForm.current = formAPI)}
style={{ marginBottom: 15 }}
>
<Form.Section text={'数据看板设置'}>
<Form.Section text={t('数据看板设置')}>
<Row gutter={16}>
<Col span={8}>
<Form.Switch
field={'DataExportEnabled'}
label={'启用数据看板(实验性)'}
label={t('启用数据看板(实验性)')}
size='default'
checkedText=''
uncheckedText=''
@@ -102,12 +105,12 @@ export default function DataDashboard(props) {
<Row>
<Col span={8}>
<Form.InputNumber
label={'数据看板更新间隔 '}
label={t('数据看板更新间隔')}
step={1}
min={1}
suffix={'分钟'}
extraText={'设置过短会影响数据库性能'}
placeholder={'数据看板更新间隔'}
suffix={t('分钟')}
extraText={t('设置过短会影响数据库性能')}
placeholder={t('数据看板更新间隔')}
field={'DataExportInterval'}
onChange={(value) =>
setInputs({
@@ -119,11 +122,11 @@ export default function DataDashboard(props) {
</Col>
<Col span={8}>
<Form.Select
label='数据看板默认时间粒度'
label={t('数据看板默认时间粒度')}
optionList={optionsDataExportDefaultTime}
field={'DataExportDefaultTime'}
extraText={'仅修改展示粒度,统计精确到小时'}
placeholder={'数据看板默认时间粒度'}
extraText={t('仅修改展示粒度,统计精确到小时')}
placeholder={t('数据看板默认时间粒度')}
style={{ width: 180 }}
onChange={(value) =>
setInputs({
@@ -136,7 +139,7 @@ export default function DataDashboard(props) {
</Row>
<Row>
<Button size='default' onClick={onSubmit}>
保存数据看板设置
{t('保存数据看板设置')}
</Button>
</Row>
</Form.Section>

View File

@@ -7,8 +7,10 @@ import {
showSuccess,
showWarning,
} from '../../../helpers';
import { useTranslation } from 'react-i18next';
export default function SettingsDrawing(props) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [inputs, setInputs] = useState({
DrawingEnabled: false,
@@ -23,7 +25,7 @@ export default function SettingsDrawing(props) {
function onSubmit() {
const updateArray = compareObjects(inputs, inputsRow);
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
const requestQueue = updateArray.map((item) => {
let value = '';
if (typeof inputs[item.key] === 'boolean') {
@@ -42,13 +44,13 @@ export default function SettingsDrawing(props) {
if (requestQueue.length === 1) {
if (res.includes(undefined)) return;
} else if (requestQueue.length > 1) {
if (res.includes(undefined)) return showError('部分保存失败,请重试');
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
}
showSuccess('保存成功');
showSuccess(t('保存成功'));
props.refresh();
})
.catch(() => {
showError('保存失败,请重试');
showError(t('保存失败,请重试'));
})
.finally(() => {
setLoading(false);
@@ -67,6 +69,7 @@ export default function SettingsDrawing(props) {
refForm.current.setValues(currentInputs);
localStorage.setItem('mj_notify_enabled', String(inputs.MjNotifyEnabled));
}, [props.options]);
return (
<>
<Spin spinning={loading}>
@@ -75,12 +78,12 @@ export default function SettingsDrawing(props) {
getFormApi={(formAPI) => (refForm.current = formAPI)}
style={{ marginBottom: 15 }}
>
<Form.Section text={'绘图设置'}>
<Form.Section text={t('绘图设置')}>
<Row gutter={16}>
<Col span={8}>
<Form.Switch
field={'DrawingEnabled'}
label={'启用绘图功能'}
label={t('启用绘图功能')}
size='default'
checkedText=''
uncheckedText=''
@@ -95,7 +98,7 @@ export default function SettingsDrawing(props) {
<Col span={8}>
<Form.Switch
field={'MjNotifyEnabled'}
label={'允许回调(会泄露服务器 IP 地址)'}
label={t('允许回调(会泄露服务器 IP 地址)')}
size='default'
checkedText=''
uncheckedText=''
@@ -110,7 +113,7 @@ export default function SettingsDrawing(props) {
<Col span={8}>
<Form.Switch
field={'MjAccountFilterEnabled'}
label={'允许 AccountFilter 参数'}
label={t('允许 AccountFilter 参数')}
size='default'
checkedText=''
uncheckedText=''
@@ -125,7 +128,7 @@ export default function SettingsDrawing(props) {
<Col span={8}>
<Form.Switch
field={'MjForwardUrlEnabled'}
label={'开启之后将上游地址替换为服务器地址'}
label={t('开启之后将上游地址替换为服务器地址')}
size='default'
checkedText=''
uncheckedText=''
@@ -142,8 +145,8 @@ export default function SettingsDrawing(props) {
field={'MjModeClearEnabled'}
label={
<>
开启之后会清除用户提示词中的 <Tag>--fast</Tag>
<Tag>--relax</Tag> <Tag>--turbo</Tag>
{t('开启之后会清除用户提示词中的')} <Tag>--fast</Tag>
<Tag>--relax</Tag> {t('')} <Tag>--turbo</Tag> {t('')}
</>
}
size='default'
@@ -160,11 +163,7 @@ export default function SettingsDrawing(props) {
<Col span={8}>
<Form.Switch
field={'MjActionCheckSuccessEnabled'}
label={
<>
检测必须等待绘图成功才能进行放大等操作
</>
}
label={t('检测必须等待绘图成功才能进行放大等操作')}
size='default'
checkedText=''
uncheckedText=''
@@ -179,7 +178,7 @@ export default function SettingsDrawing(props) {
</Row>
<Row>
<Button size='default' onClick={onSubmit}>
保存绘图设置
{t('保存绘图设置')}
</Button>
</Row>
</Form.Section>

View File

@@ -7,8 +7,10 @@ import {
showSuccess,
showWarning,
} from '../../../helpers';
import { useTranslation } from 'react-i18next';
export default function GeneralSettings(props) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [inputs, setInputs] = useState({
TopUpLink: '',
@@ -22,13 +24,15 @@ export default function GeneralSettings(props) {
});
const refForm = useRef();
const [inputsRow, setInputsRow] = useState(inputs);
function onChange(value, e) {
const name = e.target.id;
setInputs((inputs) => ({ ...inputs, [name]: value }));
}
function onSubmit() {
const updateArray = compareObjects(inputs, inputsRow);
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
const requestQueue = updateArray.map((item) => {
let value = '';
if (typeof inputs[item.key] === 'boolean') {
@@ -47,13 +51,13 @@ export default function GeneralSettings(props) {
if (requestQueue.length === 1) {
if (res.includes(undefined)) return;
} else if (requestQueue.length > 1) {
if (res.includes(undefined)) return showError('部分保存失败,请重试');
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
}
showSuccess('保存成功');
showSuccess(t('保存成功'));
props.refresh();
})
.catch(() => {
showError('保存失败,请重试');
showError(t('保存失败,请重试'));
})
.finally(() => {
setLoading(false);
@@ -71,26 +75,27 @@ export default function GeneralSettings(props) {
setInputsRow(structuredClone(currentInputs));
refForm.current.setValues(currentInputs);
}, [props.options]);
return (
<>
<Spin spinning={loading}>
<Banner
type='warning'
description={'聊天链接功能已经弃用,请使用下方聊天设置功能'}
description={t('聊天链接功能已经弃用,请使用下方聊天设置功能')}
/>
<Form
values={inputs}
getFormApi={(formAPI) => (refForm.current = formAPI)}
style={{ marginBottom: 15 }}
>
<Form.Section text={'通用设置'}>
<Form.Section text={t('通用设置')}>
<Row gutter={16}>
<Col span={8}>
<Form.Input
field={'TopUpLink'}
label={'充值链接'}
label={t('充值链接')}
initValue={''}
placeholder={'例如发卡网站的购买链接'}
placeholder={t('例如发卡网站的购买链接')}
onChange={onChange}
showClear
/>
@@ -98,9 +103,9 @@ export default function GeneralSettings(props) {
<Col span={8}>
<Form.Input
field={'ChatLink'}
label={'默认聊天页面链接'}
label={t('默认聊天页面链接')}
initValue={''}
placeholder='例如 ChatGPT Next Web 的部署地址'
placeholder={t('例如 ChatGPT Next Web 的部署地址')}
onChange={onChange}
showClear
/>
@@ -108,9 +113,9 @@ export default function GeneralSettings(props) {
<Col span={8}>
<Form.Input
field={'ChatLink2'}
label={'聊天页面 2 链接'}
label={t('聊天页面 2 链接')}
initValue={''}
placeholder='例如 ChatGPT Next Web 的部署地址'
placeholder={t('例如 ChatGPT Next Web 的部署地址')}
onChange={onChange}
showClear
/>
@@ -118,9 +123,9 @@ export default function GeneralSettings(props) {
<Col span={8}>
<Form.Input
field={'QuotaPerUnit'}
label={'单位美元额度'}
label={t('单位美元额度')}
initValue={''}
placeholder='一单位货币能兑换的额度'
placeholder={t('一单位货币能兑换的额度')}
onChange={onChange}
showClear
/>
@@ -128,9 +133,9 @@ export default function GeneralSettings(props) {
<Col span={8}>
<Form.Input
field={'RetryTimes'}
label={'失败重试次数'}
label={t('失败重试次数')}
initValue={''}
placeholder='失败重试次数'
placeholder={t('失败重试次数')}
onChange={onChange}
showClear
/>
@@ -140,7 +145,7 @@ export default function GeneralSettings(props) {
<Col span={8}>
<Form.Switch
field={'DisplayInCurrencyEnabled'}
label={'以货币形式显示额度'}
label={t('以货币形式显示额度')}
size='default'
checkedText=''
uncheckedText=''
@@ -155,7 +160,7 @@ export default function GeneralSettings(props) {
<Col span={8}>
<Form.Switch
field={'DisplayTokenStatEnabled'}
label={'Billing 相关 API 显示令牌额度而非用户额度'}
label={t('额度查询接口返回令牌额度而非用户额度')}
size='default'
checkedText=''
uncheckedText=''
@@ -170,7 +175,7 @@ export default function GeneralSettings(props) {
<Col span={8}>
<Form.Switch
field={'DefaultCollapseSidebar'}
label={'默认折叠侧边栏'}
label={t('默认折叠侧边栏')}
size='default'
checkedText=''
uncheckedText=''
@@ -185,7 +190,7 @@ export default function GeneralSettings(props) {
</Row>
<Row>
<Button size='default' onClick={onSubmit}>
保存通用设置
{t('保存通用设置')}
</Button>
</Row>
</Form.Section>

View File

@@ -1,6 +1,7 @@
import React, { useEffect, useState, useRef } from 'react';
import { Button, Col, Form, Row, Spin, DatePicker } from '@douyinfe/semi-ui';
import dayjs from 'dayjs';
import { useTranslation } from 'react-i18next';
import {
compareObjects,
API,
@@ -10,6 +11,7 @@ import {
} from '../../../helpers';
export default function SettingsLog(props) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [loadingCleanHistoryLog, setLoadingCleanHistoryLog] = useState(false);
const [inputs, setInputs] = useState({
@@ -24,7 +26,7 @@ export default function SettingsLog(props) {
(item) => item.key !== 'historyTimestamp',
);
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
const requestQueue = updateArray.map((item) => {
let value = '';
if (typeof inputs[item.key] === 'boolean') {
@@ -43,13 +45,13 @@ export default function SettingsLog(props) {
if (requestQueue.length === 1) {
if (res.includes(undefined)) return;
} else if (requestQueue.length > 1) {
if (res.includes(undefined)) return showError('部分保存失败,请重试');
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
}
showSuccess('保存成功');
showSuccess(t('保存成功'));
props.refresh();
})
.catch(() => {
showError('保存失败,请重试');
showError(t('保存失败,请重试'));
})
.finally(() => {
setLoading(false);
@@ -58,16 +60,16 @@ export default function SettingsLog(props) {
async function onCleanHistoryLog() {
try {
setLoadingCleanHistoryLog(true);
if (!inputs.historyTimestamp) throw new Error('请选择日志记录时间');
if (!inputs.historyTimestamp) throw new Error(t('请选择日志记录时间'));
const res = await API.delete(
`/api/log/?target_timestamp=${Date.parse(inputs.historyTimestamp) / 1000}`,
);
const { success, message, data } = res.data;
if (success) {
showSuccess(`${data} 条日志已清理!`);
showSuccess(`${data} ${t('条日志已清理!')}`);
return;
} else {
throw new Error('日志清理失败:' + message);
throw new Error(t('日志清理失败:') + message);
}
} catch (error) {
showError(error.message);
@@ -96,12 +98,12 @@ export default function SettingsLog(props) {
getFormApi={(formAPI) => (refForm.current = formAPI)}
style={{ marginBottom: 15 }}
>
<Form.Section text={'日志设置'}>
<Form.Section text={t('日志设置')}>
<Row gutter={16}>
<Col span={8}>
<Form.Switch
field={'LogConsumeEnabled'}
label={'启用额度消费日志记录'}
label={t('启用额度消费日志记录')}
size='default'
checkedText=''
uncheckedText=''
@@ -116,7 +118,7 @@ export default function SettingsLog(props) {
<Col span={8}>
<Spin spinning={loadingCleanHistoryLog}>
<Form.DatePicker
label='日志记录时间'
label={t('日志记录时间')}
field={'historyTimestamp'}
type='dateTime'
inputReadOnly={true}
@@ -128,7 +130,7 @@ export default function SettingsLog(props) {
}}
/>
<Button size='default' onClick={onCleanHistoryLog}>
清除历史日志
{t('清除历史日志')}
</Button>
</Spin>
</Col>
@@ -136,7 +138,7 @@ export default function SettingsLog(props) {
<Row>
<Button size='default' onClick={onSubmit}>
保存日志设置
{t('保存日志设置')}
</Button>
</Row>
</Form.Section>

View File

@@ -7,8 +7,10 @@ import {
showSuccess,
showWarning,
} from '../../../helpers';
import { useTranslation } from 'react-i18next';
export default function SettingsMonitoring(props) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [inputs, setInputs] = useState({
ChannelDisableThreshold: '',
@@ -21,7 +23,7 @@ export default function SettingsMonitoring(props) {
function onSubmit() {
const updateArray = compareObjects(inputs, inputsRow);
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
const requestQueue = updateArray.map((item) => {
let value = '';
if (typeof inputs[item.key] === 'boolean') {
@@ -40,13 +42,13 @@ export default function SettingsMonitoring(props) {
if (requestQueue.length === 1) {
if (res.includes(undefined)) return;
} else if (requestQueue.length > 1) {
if (res.includes(undefined)) return showError('部分保存失败,请重试');
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
}
showSuccess('保存成功');
showSuccess(t('保存成功'));
props.refresh();
})
.catch(() => {
showError('保存失败,请重试');
showError(t('保存失败,请重试'));
})
.finally(() => {
setLoading(false);
@@ -64,6 +66,7 @@ export default function SettingsMonitoring(props) {
setInputsRow(structuredClone(currentInputs));
refForm.current.setValues(currentInputs);
}, [props.options]);
return (
<>
<Spin spinning={loading}>
@@ -72,15 +75,15 @@ export default function SettingsMonitoring(props) {
getFormApi={(formAPI) => (refForm.current = formAPI)}
style={{ marginBottom: 15 }}
>
<Form.Section text={'监控设置'}>
<Form.Section text={t('监控设置')}>
<Row gutter={16}>
<Col span={8}>
<Form.InputNumber
label={'最长响应时间'}
label={t('最长响应时间')}
step={1}
min={0}
suffix={'秒'}
extraText={'当运行通道全部测试时,超过此时间将自动禁用通道'}
suffix={t('秒')}
extraText={t('当运行通道全部测试时,超过此时间将自动禁用通道')}
placeholder={''}
field={'ChannelDisableThreshold'}
onChange={(value) =>
@@ -93,11 +96,11 @@ export default function SettingsMonitoring(props) {
</Col>
<Col span={8}>
<Form.InputNumber
label={'额度提醒阈值'}
label={t('额度提醒阈值')}
step={1}
min={0}
suffix={'Token'}
extraText={'低于此额度时将发送邮件提醒用户'}
extraText={t('低于此额度时将发送邮件提醒用户')}
placeholder={''}
field={'QuotaRemindThreshold'}
onChange={(value) =>
@@ -113,7 +116,7 @@ export default function SettingsMonitoring(props) {
<Col span={8}>
<Form.Switch
field={'AutomaticDisableChannelEnabled'}
label={'失败时自动禁用通道'}
label={t('失败时自动禁用通道')}
size='default'
checkedText=''
uncheckedText=''
@@ -128,7 +131,7 @@ export default function SettingsMonitoring(props) {
<Col span={8}>
<Form.Switch
field={'AutomaticEnableChannelEnabled'}
label={'成功时自动启用通道'}
label={t('成功时自动启用通道')}
size='default'
checkedText=''
uncheckedText=''
@@ -143,7 +146,7 @@ export default function SettingsMonitoring(props) {
</Row>
<Row>
<Button size='default' onClick={onSubmit}>
保存监控设置
{t('保存监控设置')}
</Button>
</Row>
</Form.Section>

View File

@@ -7,8 +7,10 @@ import {
showSuccess,
showWarning,
} from '../../../helpers';
import { useTranslation } from 'react-i18next';
export default function SettingsSensitiveWords(props) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [inputs, setInputs] = useState({
CheckSensitiveEnabled: false,
@@ -20,7 +22,7 @@ export default function SettingsSensitiveWords(props) {
function onSubmit() {
const updateArray = compareObjects(inputs, inputsRow);
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
const requestQueue = updateArray.map((item) => {
let value = '';
if (typeof inputs[item.key] === 'boolean') {
@@ -39,13 +41,13 @@ export default function SettingsSensitiveWords(props) {
if (requestQueue.length === 1) {
if (res.includes(undefined)) return;
} else if (requestQueue.length > 1) {
if (res.includes(undefined)) return showError('部分保存失败,请重试');
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
}
showSuccess('保存成功');
showSuccess(t('保存成功'));
props.refresh();
})
.catch(() => {
showError('保存失败,请重试');
showError(t('保存失败,请重试'));
})
.finally(() => {
setLoading(false);
@@ -71,12 +73,12 @@ export default function SettingsSensitiveWords(props) {
getFormApi={(formAPI) => (refForm.current = formAPI)}
style={{ marginBottom: 15 }}
>
<Form.Section text={'屏蔽词过滤设置'}>
<Form.Section text={t('屏蔽词过滤设置')}>
<Row gutter={16}>
<Col span={8}>
<Form.Switch
field={'CheckSensitiveEnabled'}
label={'启用屏蔽词过滤功能'}
label={t('启用屏蔽词过滤功能')}
size='default'
checkedText=''
uncheckedText=''
@@ -91,7 +93,7 @@ export default function SettingsSensitiveWords(props) {
<Col span={8}>
<Form.Switch
field={'CheckSensitiveOnPromptEnabled'}
label={'启用 Prompt 检查'}
label={t('启用 Prompt 检查')}
size='default'
checkedText=''
uncheckedText=''
@@ -107,9 +109,9 @@ export default function SettingsSensitiveWords(props) {
<Row>
<Col span={16}>
<Form.TextArea
label={'屏蔽词列表'}
extraText={'一行一个屏蔽词,不需要符号分割'}
placeholder={'一行一个屏蔽词,不需要符号分割'}
label={t('屏蔽词列表')}
extraText={t('一行一个屏蔽词,不需要符号分割')}
placeholder={t('一行一个屏蔽词,不需要符号分割')}
field={'SensitiveWords'}
onChange={(value) =>
setInputs({
@@ -124,7 +126,7 @@ export default function SettingsSensitiveWords(props) {
</Row>
<Row>
<Button size='default' onClick={onSubmit}>
保存屏蔽词过滤设置
{t('保存屏蔽词过滤设置')}
</Button>
</Row>
</Form.Section>

View File

@@ -1,19 +1,22 @@
import React, { useEffect, useState } from 'react';
import { Layout, TabPane, Tabs } from '@douyinfe/semi-ui';
import { useNavigate, useLocation } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import SystemSetting from '../../components/SystemSetting';
import { isRoot } from '../../helpers';
import OtherSetting from '../../components/OtherSetting';
import PersonalSetting from '../../components/PersonalSetting';
import OperationSetting from '../../components/OperationSetting';
const Setting = () => {
const { t } = useTranslation();
const navigate = useNavigate();
const location = useLocation();
const [tabActiveKey, setTabActiveKey] = useState('1');
let panes = [
{
tab: '个人设置',
tab: t('个人设置'),
content: <PersonalSetting />,
itemKey: 'personal',
},
@@ -21,17 +24,17 @@ const Setting = () => {
if (isRoot()) {
panes.push({
tab: '运营设置',
tab: t('运营设置'),
content: <OperationSetting />,
itemKey: 'operation',
});
panes.push({
tab: '系统设置',
tab: t('系统设置'),
content: <SystemSetting />,
itemKey: 'system',
});
panes.push({
tab: '其他设置',
tab: t('其他设置'),
content: <OtherSetting />,
itemKey: 'other',
});