mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-04-19 22:38:37 +00:00
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:
@@ -33,10 +33,12 @@ import {
|
||||
stringToColor,
|
||||
} from '../helpers/render';
|
||||
import TelegramLoginButton from 'react-telegram-login';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const PersonalSetting = () => {
|
||||
const [userState, userDispatch] = useContext(UserContext);
|
||||
let navigate = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [inputs, setInputs] = useState({
|
||||
wechat_verification_code: '',
|
||||
@@ -110,7 +112,7 @@ const PersonalSetting = () => {
|
||||
if (success) {
|
||||
setSystemToken(data);
|
||||
await copy(data);
|
||||
showSuccess(`令牌已重置并已复制到剪贴板`);
|
||||
showSuccess(t('令牌已重置并已复制到剪贴板'));
|
||||
} else {
|
||||
showError(message);
|
||||
}
|
||||
@@ -151,18 +153,18 @@ const PersonalSetting = () => {
|
||||
const handleAffLinkClick = async (e) => {
|
||||
e.target.select();
|
||||
await copy(e.target.value);
|
||||
showSuccess(`邀请链接已复制到剪切板`);
|
||||
showSuccess(t('邀请链接已复制到剪切板'));
|
||||
};
|
||||
|
||||
const handleSystemTokenClick = async (e) => {
|
||||
e.target.select();
|
||||
await copy(e.target.value);
|
||||
showSuccess(`系统令牌已复制到剪切板`);
|
||||
showSuccess(t('系统令牌已复制到剪切板'));
|
||||
};
|
||||
|
||||
const deleteAccount = async () => {
|
||||
if (inputs.self_account_deletion_confirmation !== userState.user.username) {
|
||||
showError('请输入你的账户名以确认删除!');
|
||||
showError(t('请输入你的账户名以确认删除!'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -170,7 +172,7 @@ const PersonalSetting = () => {
|
||||
const {success, message} = res.data;
|
||||
|
||||
if (success) {
|
||||
showSuccess('账户已删除!');
|
||||
showSuccess(t('账户已删除!'));
|
||||
await API.get('/api/user/logout');
|
||||
userDispatch({type: 'logout'});
|
||||
localStorage.removeItem('user');
|
||||
@@ -187,7 +189,7 @@ const PersonalSetting = () => {
|
||||
);
|
||||
const {success, message} = res.data;
|
||||
if (success) {
|
||||
showSuccess('微信账户绑定成功!');
|
||||
showSuccess(t('微信账户绑定成功!'));
|
||||
setShowWeChatBindModal(false);
|
||||
} else {
|
||||
showError(message);
|
||||
@@ -196,7 +198,7 @@ const PersonalSetting = () => {
|
||||
|
||||
const changePassword = async () => {
|
||||
if (inputs.set_new_password !== inputs.set_new_password_confirmation) {
|
||||
showError('两次输入的密码不一致!');
|
||||
showError(t('两次输入的密码不一致!'));
|
||||
return;
|
||||
}
|
||||
const res = await API.put(`/api/user/self`, {
|
||||
@@ -204,7 +206,7 @@ const PersonalSetting = () => {
|
||||
});
|
||||
const {success, message} = res.data;
|
||||
if (success) {
|
||||
showSuccess('密码修改成功!');
|
||||
showSuccess(t('密码修改成功!'));
|
||||
setShowWeChatBindModal(false);
|
||||
} else {
|
||||
showError(message);
|
||||
@@ -214,7 +216,7 @@ const PersonalSetting = () => {
|
||||
|
||||
const transfer = async () => {
|
||||
if (transferAmount < getQuotaPerUnit()) {
|
||||
showError('划转金额最低为' + renderQuota(getQuotaPerUnit()));
|
||||
showError(t('划转金额最低为') + ' ' + renderQuota(getQuotaPerUnit()));
|
||||
return;
|
||||
}
|
||||
const res = await API.post(`/api/user/aff_transfer`, {
|
||||
@@ -232,7 +234,7 @@ const PersonalSetting = () => {
|
||||
|
||||
const sendVerificationCode = async () => {
|
||||
if (inputs.email === '') {
|
||||
showError('请输入邮箱!');
|
||||
showError(t('请输入邮箱!'));
|
||||
return;
|
||||
}
|
||||
setDisableButton(true);
|
||||
@@ -246,7 +248,7 @@ const PersonalSetting = () => {
|
||||
);
|
||||
const {success, message} = res.data;
|
||||
if (success) {
|
||||
showSuccess('验证码发送成功,请检查邮箱!');
|
||||
showSuccess(t('验证码发送成功,请检查邮箱!'));
|
||||
} else {
|
||||
showError(message);
|
||||
}
|
||||
@@ -255,7 +257,7 @@ const PersonalSetting = () => {
|
||||
|
||||
const bindEmail = async () => {
|
||||
if (inputs.email_verification_code === '') {
|
||||
showError('请输入邮箱验证码!');
|
||||
showError(t('请输入邮箱验证码!'));
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
@@ -264,7 +266,7 @@ const PersonalSetting = () => {
|
||||
);
|
||||
const {success, message} = res.data;
|
||||
if (success) {
|
||||
showSuccess('邮箱账户绑定成功!');
|
||||
showSuccess(t('邮箱账户绑定成功!'));
|
||||
setShowEmailBindModal(false);
|
||||
userState.user.email = inputs.email;
|
||||
} else {
|
||||
@@ -299,7 +301,7 @@ const PersonalSetting = () => {
|
||||
<Layout>
|
||||
<Layout.Content>
|
||||
<Modal
|
||||
title='请输入要划转的数量'
|
||||
title={t('请输入要划转的数量')}
|
||||
visible={openTransfer}
|
||||
onOk={transfer}
|
||||
onCancel={handleCancel}
|
||||
@@ -308,7 +310,7 @@ const PersonalSetting = () => {
|
||||
centered={true}
|
||||
>
|
||||
<div style={{marginTop: 20}}>
|
||||
<Typography.Text>{`可用额度${renderQuotaWithPrompt(userState?.user?.aff_quota)}`}</Typography.Text>
|
||||
<Typography.Text>{t('可用额度')}{renderQuotaWithPrompt(userState?.user?.aff_quota)}</Typography.Text>
|
||||
<Input
|
||||
style={{marginTop: 5}}
|
||||
value={userState?.user?.aff_quota}
|
||||
@@ -317,8 +319,7 @@ const PersonalSetting = () => {
|
||||
</div>
|
||||
<div style={{marginTop: 20}}>
|
||||
<Typography.Text>
|
||||
{`划转额度${renderQuotaWithPrompt(transferAmount)} 最低` +
|
||||
renderQuota(getQuotaPerUnit())}
|
||||
{t('划转额度')}{renderQuotaWithPrompt(transferAmount)} {t('最低') + renderQuota(getQuotaPerUnit())}
|
||||
</Typography.Text>
|
||||
<div>
|
||||
<InputNumber
|
||||
@@ -348,9 +349,9 @@ const PersonalSetting = () => {
|
||||
title={<Typography.Text>{getUsername()}</Typography.Text>}
|
||||
description={
|
||||
isRoot() ? (
|
||||
<Tag color='red'>管理员</Tag>
|
||||
<Tag color='red'>{t('管理员')}</Tag>
|
||||
) : (
|
||||
<Tag color='blue'>普通用户</Tag>
|
||||
<Tag color='blue'>{t('普通用户')}</Tag>
|
||||
)
|
||||
}
|
||||
></Card.Meta>
|
||||
@@ -365,13 +366,13 @@ const PersonalSetting = () => {
|
||||
}
|
||||
>
|
||||
<Descriptions row>
|
||||
<Descriptions.Item itemKey='当前余额'>
|
||||
<Descriptions.Item itemKey={t('当前余额')}>
|
||||
{renderQuota(userState?.user?.quota)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item itemKey='历史消耗'>
|
||||
<Descriptions.Item itemKey={t('历史消耗')}>
|
||||
{renderQuota(userState?.user?.used_quota)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item itemKey='请求次数'>
|
||||
<Descriptions.Item itemKey={t('请求次数')}>
|
||||
{userState.user?.request_count}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
@@ -380,7 +381,7 @@ const PersonalSetting = () => {
|
||||
style={{marginTop: 10}}
|
||||
footer={
|
||||
<div>
|
||||
<Typography.Text>邀请链接</Typography.Text>
|
||||
<Typography.Text>{t('邀请链接')}</Typography.Text>
|
||||
<Input
|
||||
style={{marginTop: 10}}
|
||||
value={affLink}
|
||||
@@ -390,35 +391,35 @@ const PersonalSetting = () => {
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Typography.Title heading={6}>邀请信息</Typography.Title>
|
||||
<Typography.Title heading={6}>{t('邀请信息')}</Typography.Title>
|
||||
<div style={{marginTop: 10}}>
|
||||
<Descriptions row>
|
||||
<Descriptions.Item itemKey='待使用收益'>
|
||||
<span style={{color: 'rgba(var(--semi-red-5), 1)'}}>
|
||||
{renderQuota(userState?.user?.aff_quota)}
|
||||
</span>
|
||||
<Descriptions.Item itemKey={t('待使用收益')}>
|
||||
<span style={{color: 'rgba(var(--semi-red-5), 1)'}}>
|
||||
{renderQuota(userState?.user?.aff_quota)}
|
||||
</span>
|
||||
<Button
|
||||
type={'secondary'}
|
||||
onClick={() => setOpenTransfer(true)}
|
||||
size={'small'}
|
||||
style={{marginLeft: 10}}
|
||||
>
|
||||
划转
|
||||
{t('划转')}
|
||||
</Button>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item itemKey='总收益'>
|
||||
<Descriptions.Item itemKey={t('总收益')}>
|
||||
{renderQuota(userState?.user?.aff_history_quota)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item itemKey='邀请人数'>
|
||||
<Descriptions.Item itemKey={t('邀请人数')}>
|
||||
{userState?.user?.aff_count}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</div>
|
||||
</Card>
|
||||
<Card style={{marginTop: 10}}>
|
||||
<Typography.Title heading={6}>个人信息</Typography.Title>
|
||||
<Typography.Title heading={6}>{t('个人信息')}</Typography.Title>
|
||||
<div style={{marginTop: 20}}>
|
||||
<Typography.Text strong>邮箱</Typography.Text>
|
||||
<Typography.Text strong>{t('邮箱')}</Typography.Text>
|
||||
<div
|
||||
style={{display: 'flex', justifyContent: 'space-between'}}
|
||||
>
|
||||
@@ -427,7 +428,7 @@ const PersonalSetting = () => {
|
||||
value={
|
||||
userState.user && userState.user.email !== ''
|
||||
? userState.user.email
|
||||
: '未绑定'
|
||||
: t('未绑定')
|
||||
}
|
||||
readonly={true}
|
||||
></Input>
|
||||
@@ -439,14 +440,14 @@ const PersonalSetting = () => {
|
||||
}}
|
||||
>
|
||||
{userState.user && userState.user.email !== ''
|
||||
? '修改绑定'
|
||||
: '绑定邮箱'}
|
||||
? t('修改绑定')
|
||||
: t('绑定邮箱')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{marginTop: 10}}>
|
||||
<Typography.Text strong>微信</Typography.Text>
|
||||
<Typography.Text strong>{t('微信')}</Typography.Text>
|
||||
<div
|
||||
style={{display: 'flex', justifyContent: 'space-between'}}
|
||||
>
|
||||
@@ -454,8 +455,8 @@ const PersonalSetting = () => {
|
||||
<Input
|
||||
value={
|
||||
userState.user && userState.user.wechat_id !== ''
|
||||
? '已绑定'
|
||||
: '未绑定'
|
||||
? t('已绑定')
|
||||
: t('未绑定')
|
||||
}
|
||||
readonly={true}
|
||||
></Input>
|
||||
@@ -467,13 +468,13 @@ const PersonalSetting = () => {
|
||||
!status.wechat_login
|
||||
}
|
||||
>
|
||||
{status.wechat_login ? '绑定' : '未启用'}
|
||||
{status.wechat_login ? t('绑定') : t('未启用')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{marginTop: 10}}>
|
||||
<Typography.Text strong>GitHub</Typography.Text>
|
||||
<Typography.Text strong>{t('GitHub')}</Typography.Text>
|
||||
<div
|
||||
style={{display: 'flex', justifyContent: 'space-between'}}
|
||||
>
|
||||
@@ -482,7 +483,7 @@ const PersonalSetting = () => {
|
||||
value={
|
||||
userState.user && userState.user.github_id !== ''
|
||||
? userState.user.github_id
|
||||
: '未绑定'
|
||||
: t('未绑定')
|
||||
}
|
||||
readonly={true}
|
||||
></Input>
|
||||
@@ -497,13 +498,13 @@ const PersonalSetting = () => {
|
||||
!status.github_oauth
|
||||
}
|
||||
>
|
||||
{status.github_oauth ? '绑定' : '未启用'}
|
||||
{status.github_oauth ? t('绑定') : t('未启用')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{marginTop: 10}}>
|
||||
<Typography.Text strong>Telegram</Typography.Text>
|
||||
<Typography.Text strong>{t('Telegram')}</Typography.Text>
|
||||
<div
|
||||
style={{display: 'flex', justifyContent: 'space-between'}}
|
||||
>
|
||||
@@ -512,7 +513,7 @@ const PersonalSetting = () => {
|
||||
value={
|
||||
userState.user && userState.user.telegram_id !== ''
|
||||
? userState.user.telegram_id
|
||||
: '未绑定'
|
||||
: t('未绑定')
|
||||
}
|
||||
readonly={true}
|
||||
></Input>
|
||||
@@ -520,7 +521,7 @@ const PersonalSetting = () => {
|
||||
<div>
|
||||
{status.telegram_oauth ? (
|
||||
userState.user.telegram_id !== '' ? (
|
||||
<Button disabled={true}>已绑定</Button>
|
||||
<Button disabled={true}>{t('已绑定')}</Button>
|
||||
) : (
|
||||
<TelegramLoginButton
|
||||
dataAuthUrl='/api/oauth/telegram/bind'
|
||||
@@ -528,13 +529,13 @@ const PersonalSetting = () => {
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<Button disabled={true}>未启用</Button>
|
||||
<Button disabled={true}>{t('未启用')}</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{marginTop: 10}}>
|
||||
<Typography.Text strong>LinuxDO</Typography.Text>
|
||||
<Typography.Text strong>{t('LinuxDO')}</Typography.Text>
|
||||
<div
|
||||
style={{display: 'flex', justifyContent: 'space-between'}}
|
||||
>
|
||||
@@ -543,7 +544,7 @@ const PersonalSetting = () => {
|
||||
value={
|
||||
userState.user && userState.user.linux_do_id !== ''
|
||||
? userState.user.linux_do_id
|
||||
: '未绑定'
|
||||
: t('未绑定')
|
||||
}
|
||||
readonly={true}
|
||||
></Input>
|
||||
@@ -558,7 +559,7 @@ const PersonalSetting = () => {
|
||||
!status.linuxdo_oauth
|
||||
}
|
||||
>
|
||||
{status.linuxdo_oauth ? '绑定' : '未启用'}
|
||||
{status.linuxdo_oauth ? t('绑定') : t('未启用')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -566,14 +567,14 @@ const PersonalSetting = () => {
|
||||
<div style={{marginTop: 10}}>
|
||||
<Space>
|
||||
<Button onClick={generateAccessToken}>
|
||||
生成系统访问令牌
|
||||
{t('生成系统访问令牌')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setShowChangePasswordModal(true);
|
||||
}}
|
||||
>
|
||||
修改密码
|
||||
{t('修改密码')}
|
||||
</Button>
|
||||
<Button
|
||||
type={'danger'}
|
||||
@@ -581,7 +582,7 @@ const PersonalSetting = () => {
|
||||
setShowAccountDeleteModal(true);
|
||||
}}
|
||||
>
|
||||
删除个人账户
|
||||
{t('删除个人账户')}
|
||||
</Button>
|
||||
</Space>
|
||||
|
||||
@@ -599,7 +600,7 @@ const PersonalSetting = () => {
|
||||
setShowWeChatBindModal(true);
|
||||
}}
|
||||
>
|
||||
绑定微信账号
|
||||
{t('绑定微信账号')}
|
||||
</Button>
|
||||
)}
|
||||
<Modal
|
||||
@@ -623,7 +624,7 @@ const PersonalSetting = () => {
|
||||
}
|
||||
/>
|
||||
<Button color='' fluid size='large' onClick={bindWeChat}>
|
||||
绑定
|
||||
{t('绑定')}
|
||||
</Button>
|
||||
</Modal>
|
||||
</div>
|
||||
@@ -637,7 +638,7 @@ const PersonalSetting = () => {
|
||||
centered={true}
|
||||
maskClosable={false}
|
||||
>
|
||||
<Typography.Title heading={6}>绑定邮箱地址</Typography.Title>
|
||||
<Typography.Title heading={6}>{t('绑定邮箱地址')}</Typography.Title>
|
||||
<div
|
||||
style={{
|
||||
marginTop: 20,
|
||||
@@ -729,7 +730,7 @@ const PersonalSetting = () => {
|
||||
<div style={{marginTop: 20}}>
|
||||
<Input
|
||||
name='set_new_password'
|
||||
placeholder='新密码'
|
||||
placeholder={t('新密码')}
|
||||
value={inputs.set_new_password}
|
||||
onChange={(value) =>
|
||||
handleInputChange('set_new_password', value)
|
||||
@@ -738,7 +739,7 @@ const PersonalSetting = () => {
|
||||
<Input
|
||||
style={{marginTop: 20}}
|
||||
name='set_new_password_confirmation'
|
||||
placeholder='确认新密码'
|
||||
placeholder={t('确认新密码')}
|
||||
value={inputs.set_new_password_confirmation}
|
||||
onChange={(value) =>
|
||||
handleInputChange('set_new_password_confirmation', value)
|
||||
|
||||
Reference in New Issue
Block a user