mirror of
https://github.com/songquanpeng/one-api.git
synced 2025-09-17 09:16:36 +08:00
feat: i18n support
This commit is contained in:
parent
958f2f4ea8
commit
ee3ed65356
@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/songquanpeng/one-api/common"
|
"github.com/songquanpeng/one-api/common"
|
||||||
"github.com/songquanpeng/one-api/common/config"
|
"github.com/songquanpeng/one-api/common/config"
|
||||||
)
|
)
|
||||||
@ -71,7 +72,7 @@ func memoryRateLimiter(c *gin.Context, maxRequestNum int, duration int64, mark s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func rateLimitFactory(maxRequestNum int, duration int64, mark string) func(c *gin.Context) {
|
func rateLimitFactory(maxRequestNum int, duration int64, mark string) func(c *gin.Context) {
|
||||||
if maxRequestNum == 0 {
|
if maxRequestNum == 0 || config.DebugEnabled {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
|
@ -305,6 +305,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
|
"title": "User Management",
|
||||||
"edit": {
|
"edit": {
|
||||||
"title": "Update User Information",
|
"title": "Update User Information",
|
||||||
"username": "Username",
|
"username": "Username",
|
||||||
@ -337,6 +338,50 @@
|
|||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
"create_success": "User account created successfully!"
|
"create_success": "User account created successfully!"
|
||||||
|
},
|
||||||
|
"search": "Search users...",
|
||||||
|
"table": {
|
||||||
|
"id": "ID",
|
||||||
|
"username": "Username",
|
||||||
|
"group": "Group",
|
||||||
|
"quota": "Quota",
|
||||||
|
"role_text": "Role",
|
||||||
|
"status_text": "Status",
|
||||||
|
"actions": "Actions",
|
||||||
|
"remaining_quota": "Remaining Quota",
|
||||||
|
"used_quota": "Used Quota",
|
||||||
|
"request_count": "Request Count",
|
||||||
|
"role_types": {
|
||||||
|
"normal": "Normal User",
|
||||||
|
"admin": "Admin",
|
||||||
|
"super_admin": "Super Admin",
|
||||||
|
"unknown": "Unknown Role"
|
||||||
|
},
|
||||||
|
"status_types": {
|
||||||
|
"activated": "Activated",
|
||||||
|
"banned": "Banned",
|
||||||
|
"unknown": "Unknown Status"
|
||||||
|
},
|
||||||
|
"sort": {
|
||||||
|
"default": "Default Order",
|
||||||
|
"by_quota": "Sort by Remaining Quota",
|
||||||
|
"by_used_quota": "Sort by Used Quota",
|
||||||
|
"by_request_count": "Sort by Request Count"
|
||||||
|
},
|
||||||
|
"sort_by": "Sort By"
|
||||||
|
},
|
||||||
|
"buttons": {
|
||||||
|
"add": "Add New User",
|
||||||
|
"delete": "Delete",
|
||||||
|
"delete_user": "Delete User",
|
||||||
|
"enable": "Enable",
|
||||||
|
"disable": "Disable",
|
||||||
|
"edit": "Edit",
|
||||||
|
"promote": "Promote",
|
||||||
|
"demote": "Demote"
|
||||||
|
},
|
||||||
|
"messages": {
|
||||||
|
"operation_success": "Operation completed successfully!"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,6 +305,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
|
"title": "用户管理",
|
||||||
"edit": {
|
"edit": {
|
||||||
"title": "更新用户信息",
|
"title": "更新用户信息",
|
||||||
"username": "用户名",
|
"username": "用户名",
|
||||||
@ -337,6 +338,50 @@
|
|||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
"create_success": "用户账户创建成功!"
|
"create_success": "用户账户创建成功!"
|
||||||
|
},
|
||||||
|
"search": "搜索用户...",
|
||||||
|
"table": {
|
||||||
|
"id": "ID",
|
||||||
|
"username": "用户名",
|
||||||
|
"group": "分组",
|
||||||
|
"quota": "额度",
|
||||||
|
"role_text": "角色",
|
||||||
|
"status_text": "状态",
|
||||||
|
"actions": "操作",
|
||||||
|
"remaining_quota": "剩余额度",
|
||||||
|
"used_quota": "已用额度",
|
||||||
|
"request_count": "请求次数",
|
||||||
|
"role_types": {
|
||||||
|
"normal": "普通用户",
|
||||||
|
"admin": "管理员",
|
||||||
|
"super_admin": "超级管理员",
|
||||||
|
"unknown": "未知身份"
|
||||||
|
},
|
||||||
|
"status_types": {
|
||||||
|
"activated": "已激活",
|
||||||
|
"banned": "已封禁",
|
||||||
|
"unknown": "未知状态"
|
||||||
|
},
|
||||||
|
"sort": {
|
||||||
|
"default": "默认排序",
|
||||||
|
"by_quota": "按剩余额度排序",
|
||||||
|
"by_used_quota": "按已用额度排序",
|
||||||
|
"by_request_count": "按请求次数排序"
|
||||||
|
},
|
||||||
|
"sort_by": "排序方式"
|
||||||
|
},
|
||||||
|
"buttons": {
|
||||||
|
"add": "添加新的用户",
|
||||||
|
"delete": "删除",
|
||||||
|
"delete_user": "删除用户",
|
||||||
|
"enable": "启用",
|
||||||
|
"disable": "禁用",
|
||||||
|
"edit": "编辑",
|
||||||
|
"promote": "提升",
|
||||||
|
"demote": "降级"
|
||||||
|
},
|
||||||
|
"messages": {
|
||||||
|
"operation_success": "操作成功完成!"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,16 +20,18 @@ import {
|
|||||||
renderText,
|
renderText,
|
||||||
} from '../helpers/render';
|
} from '../helpers/render';
|
||||||
|
|
||||||
function renderRole(role) {
|
function renderRole(role, t) {
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case 1:
|
case 1:
|
||||||
return <Label>普通用户</Label>;
|
return <Label>{t('user.table.role_types.normal')}</Label>;
|
||||||
case 10:
|
case 10:
|
||||||
return <Label color='yellow'>管理员</Label>;
|
return <Label color='yellow'>{t('user.table.role_types.admin')}</Label>;
|
||||||
case 100:
|
case 100:
|
||||||
return <Label color='orange'>超级管理员</Label>;
|
return (
|
||||||
|
<Label color='orange'>{t('user.table.role_types.super_admin')}</Label>
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return <Label color='red'>未知身份</Label>;
|
return <Label color='red'>{t('user.table.role_types.unknown')}</Label>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +87,7 @@ const UsersTable = () => {
|
|||||||
});
|
});
|
||||||
const { success, message } = res.data;
|
const { success, message } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
showSuccess('操作成功完成!');
|
showSuccess(t('user.messages.operation_success'));
|
||||||
let user = res.data.data;
|
let user = res.data.data;
|
||||||
let newUsers = [...users];
|
let newUsers = [...users];
|
||||||
let realIdx = (activePage - 1) * ITEMS_PER_PAGE + idx;
|
let realIdx = (activePage - 1) * ITEMS_PER_PAGE + idx;
|
||||||
@ -105,17 +107,17 @@ const UsersTable = () => {
|
|||||||
const renderStatus = (status) => {
|
const renderStatus = (status) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 1:
|
case 1:
|
||||||
return <Label basic>已激活</Label>;
|
return <Label basic>{t('user.table.status_types.activated')}</Label>;
|
||||||
case 2:
|
case 2:
|
||||||
return (
|
return (
|
||||||
<Label basic color='red'>
|
<Label basic color='red'>
|
||||||
已封禁
|
{t('user.table.status_types.banned')}
|
||||||
</Label>
|
</Label>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<Label basic color='grey'>
|
<Label basic color='grey'>
|
||||||
未知状态
|
{t('user.table.status_types.unknown')}
|
||||||
</Label>
|
</Label>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -177,7 +179,7 @@ const UsersTable = () => {
|
|||||||
icon='search'
|
icon='search'
|
||||||
fluid
|
fluid
|
||||||
iconPosition='left'
|
iconPosition='left'
|
||||||
placeholder='搜索用户的 ID,用户名,显示名称,以及邮箱地址 ...'
|
placeholder={t('user.search')}
|
||||||
value={searchKeyword}
|
value={searchKeyword}
|
||||||
loading={searching}
|
loading={searching}
|
||||||
onChange={handleKeywordChange}
|
onChange={handleKeywordChange}
|
||||||
@ -193,7 +195,7 @@ const UsersTable = () => {
|
|||||||
sortUser('id');
|
sortUser('id');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
ID
|
{t('user.table.id')}
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
<Table.HeaderCell
|
<Table.HeaderCell
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ cursor: 'pointer' }}
|
||||||
@ -201,7 +203,7 @@ const UsersTable = () => {
|
|||||||
sortUser('username');
|
sortUser('username');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
用户名
|
{t('user.table.username')}
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
<Table.HeaderCell
|
<Table.HeaderCell
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ cursor: 'pointer' }}
|
||||||
@ -209,7 +211,7 @@ const UsersTable = () => {
|
|||||||
sortUser('group');
|
sortUser('group');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
分组
|
{t('user.table.group')}
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
<Table.HeaderCell
|
<Table.HeaderCell
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ cursor: 'pointer' }}
|
||||||
@ -217,7 +219,7 @@ const UsersTable = () => {
|
|||||||
sortUser('quota');
|
sortUser('quota');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
统计信息
|
{t('user.table.quota')}
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
<Table.HeaderCell
|
<Table.HeaderCell
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ cursor: 'pointer' }}
|
||||||
@ -225,7 +227,7 @@ const UsersTable = () => {
|
|||||||
sortUser('role');
|
sortUser('role');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
用户角色
|
{t('user.table.role_text')}
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
<Table.HeaderCell
|
<Table.HeaderCell
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ cursor: 'pointer' }}
|
||||||
@ -233,9 +235,9 @@ const UsersTable = () => {
|
|||||||
sortUser('status');
|
sortUser('status');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
状态
|
{t('user.table.status_text')}
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
<Table.HeaderCell>操作</Table.HeaderCell>
|
<Table.HeaderCell>{t('user.table.actions')}</Table.HeaderCell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
</Table.Header>
|
</Table.Header>
|
||||||
|
|
||||||
@ -267,23 +269,25 @@ const UsersTable = () => {
|
|||||||
{/*</Table.Cell>*/}
|
{/*</Table.Cell>*/}
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
<Popup
|
<Popup
|
||||||
content='剩余额度'
|
content={t('user.table.remaining_quota')}
|
||||||
trigger={<Label basic>{renderQuota(user.quota, t)}</Label>}
|
trigger={
|
||||||
|
<Label basic>{renderQuota(user.quota, t)}</Label>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<Popup
|
<Popup
|
||||||
content='已用额度'
|
content={t('user.table.used_quota')}
|
||||||
trigger={
|
trigger={
|
||||||
<Label basic>{renderQuota(user.used_quota, t)}</Label>
|
<Label basic>{renderQuota(user.used_quota, t)}</Label>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Popup
|
<Popup
|
||||||
content='请求次数'
|
content={t('user.table.request_count')}
|
||||||
trigger={
|
trigger={
|
||||||
<Label basic>{renderNumber(user.request_count)}</Label>
|
<Label basic>{renderNumber(user.request_count)}</Label>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
<Table.Cell>{renderRole(user.role)}</Table.Cell>
|
<Table.Cell>{renderRole(user.role, t)}</Table.Cell>
|
||||||
<Table.Cell>{renderStatus(user.status)}</Table.Cell>
|
<Table.Cell>{renderStatus(user.status)}</Table.Cell>
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
<div>
|
<div>
|
||||||
@ -295,7 +299,7 @@ const UsersTable = () => {
|
|||||||
}}
|
}}
|
||||||
disabled={user.role === 100}
|
disabled={user.role === 100}
|
||||||
>
|
>
|
||||||
提升
|
{t('user.buttons.promote')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size={'small'}
|
size={'small'}
|
||||||
@ -305,7 +309,7 @@ const UsersTable = () => {
|
|||||||
}}
|
}}
|
||||||
disabled={user.role === 100}
|
disabled={user.role === 100}
|
||||||
>
|
>
|
||||||
降级
|
{t('user.buttons.demote')}
|
||||||
</Button>
|
</Button>
|
||||||
<Popup
|
<Popup
|
||||||
trigger={
|
trigger={
|
||||||
@ -314,7 +318,7 @@ const UsersTable = () => {
|
|||||||
negative
|
negative
|
||||||
disabled={user.role === 100}
|
disabled={user.role === 100}
|
||||||
>
|
>
|
||||||
删除
|
{t('user.buttons.delete')}
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
on='click'
|
on='click'
|
||||||
@ -327,7 +331,7 @@ const UsersTable = () => {
|
|||||||
manageUser(user.username, 'delete', idx);
|
manageUser(user.username, 'delete', idx);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
删除用户 {user.username}
|
{t('user.buttons.delete_user')} {user.username}
|
||||||
</Button>
|
</Button>
|
||||||
</Popup>
|
</Popup>
|
||||||
<Button
|
<Button
|
||||||
@ -341,14 +345,16 @@ const UsersTable = () => {
|
|||||||
}}
|
}}
|
||||||
disabled={user.role === 100}
|
disabled={user.role === 100}
|
||||||
>
|
>
|
||||||
{user.status === 1 ? '禁用' : '启用'}
|
{user.status === 1
|
||||||
|
? t('user.buttons.disable')
|
||||||
|
: t('user.buttons.enable')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size={'small'}
|
size={'small'}
|
||||||
as={Link}
|
as={Link}
|
||||||
to={'/user/edit/' + user.id}
|
to={'/user/edit/' + user.id}
|
||||||
>
|
>
|
||||||
编辑
|
{t('user.buttons.edit')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
@ -361,22 +367,26 @@ const UsersTable = () => {
|
|||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.HeaderCell colSpan='7'>
|
<Table.HeaderCell colSpan='7'>
|
||||||
<Button size='small' as={Link} to='/user/add' loading={loading}>
|
<Button size='small' as={Link} to='/user/add' loading={loading}>
|
||||||
添加新的用户
|
{t('user.buttons.add')}
|
||||||
</Button>
|
</Button>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
placeholder='排序方式'
|
placeholder={t('user.table.sort_by')}
|
||||||
selection
|
selection
|
||||||
options={[
|
options={[
|
||||||
{ key: '', text: '默认排序', value: '' },
|
{ key: '', text: t('user.table.sort.default'), value: '' },
|
||||||
{ key: 'quota', text: '按剩余额度排序', value: 'quota' },
|
{
|
||||||
|
key: 'quota',
|
||||||
|
text: t('user.table.sort.by_quota'),
|
||||||
|
value: 'quota',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'used_quota',
|
key: 'used_quota',
|
||||||
text: '按已用额度排序',
|
text: t('user.table.sort.by_used_quota'),
|
||||||
value: 'used_quota',
|
value: 'used_quota',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'request_count',
|
key: 'request_count',
|
||||||
text: '按请求次数排序',
|
text: t('user.table.sort.by_request_count'),
|
||||||
value: 'request_count',
|
value: 'request_count',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Card } from 'semantic-ui-react';
|
import { Card } from 'semantic-ui-react';
|
||||||
import UsersTable from '../../components/UsersTable';
|
import UsersTable from '../../components/UsersTable';
|
||||||
|
|
||||||
const User = () => (
|
const User = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
<div className='dashboard-container'>
|
<div className='dashboard-container'>
|
||||||
<Card fluid className='chart-card'>
|
<Card fluid className='chart-card'>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<Card.Header className='header'>用户管理</Card.Header>
|
<Card.Header className='header'>{t('user.title')}</Card.Header>
|
||||||
<UsersTable />
|
<UsersTable />
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default User;
|
export default User;
|
||||||
|
Loading…
Reference in New Issue
Block a user