From 13b1b165bdda641ef0994fda0a1b7cbe647bdd8f Mon Sep 17 00:00:00 2001 From: "Laisky.Cai" Date: Sun, 19 Jan 2025 12:59:58 +0000 Subject: [PATCH] refactor: update UI text and error messages to English for better accessibility --- Dockerfile | 2 +- common/utils.go | 4 +- controller/auth/github.go | 18 +-- controller/auth/lark.go | 12 +- controller/auth/oidc.go | 16 +- controller/auth/wechat.go | 14 +- controller/channel-billing.go | 6 +- controller/channel-test.go | 8 +- controller/misc.go | 32 ++-- controller/option.go | 12 +- controller/redemption.go | 6 +- controller/relay.go | 2 +- controller/token.go | 20 +-- controller/user.go | 72 ++++----- middleware/auth.go | 16 +- middleware/distributor.go | 12 +- middleware/turnstile-check.go | 6 +- model/redemption.go | 16 +- model/token.go | 34 ++--- model/user.go | 40 ++--- monitor/channel.go | 12 +- relay/adaptor/cohere/model.go | 16 +- relay/adaptor/tencent/model.go | 32 ++-- relay/billing/billing.go | 2 +- relay/controller/helper.go | 4 +- relay/controller/image.go | 2 +- web/default/public/index.html | 2 +- web/default/src/App.js | 4 +- web/default/src/components/ChannelsTable.js | 94 ++++++------ web/default/src/components/GitHubOAuth.js | 10 +- web/default/src/components/Header.js | 32 ++-- web/default/src/components/LarkOAuth.js | 10 +- web/default/src/components/Loading.js | 2 +- web/default/src/components/LoginForm.js | 32 ++-- web/default/src/components/LogsTable.js | 70 ++++----- .../src/components/OperationSetting.js | 96 ++++++------ web/default/src/components/OtherSetting.js | 56 +++---- .../src/components/PasswordResetConfirm.js | 12 +- .../src/components/PasswordResetForm.js | 10 +- web/default/src/components/PersonalSetting.js | 70 ++++----- .../src/components/RedemptionsTable.js | 44 +++--- web/default/src/components/RegisterForm.js | 32 ++-- web/default/src/components/SystemSetting.js | 138 +++++++++--------- web/default/src/components/TokensTable.js | 58 ++++---- web/default/src/components/UsersTable.js | 62 ++++---- .../src/constants/channel.constants.js | 24 +-- web/default/src/helpers/render.js | 2 +- web/default/src/helpers/utils.js | 14 +- web/default/src/pages/About/index.js | 8 +- web/default/src/pages/Channel/EditChannel.js | 104 ++++++------- web/default/src/pages/Channel/index.js | 2 +- web/default/src/pages/Home/index.js | 44 +++--- web/default/src/pages/NotFound/index.js | 4 +- .../src/pages/Redemption/EditRedemption.js | 22 +-- web/default/src/pages/Redemption/index.js | 2 +- web/default/src/pages/Setting/index.js | 8 +- web/default/src/pages/Token/EditToken.js | 44 +++--- web/default/src/pages/Token/index.js | 2 +- web/default/src/pages/TopUp/index.js | 18 +-- web/default/src/pages/User/AddUser.js | 18 +-- web/default/src/pages/User/EditUser.js | 42 +++--- web/default/src/pages/User/index.js | 2 +- 62 files changed, 805 insertions(+), 805 deletions(-) diff --git a/Dockerfile b/Dockerfile index 052547ed..d85eafe3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ WORKDIR /web/air RUN npm install RUN DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat ../VERSION) npm run build -FROM golang:1.23.3-bullseye AS builder2 +FROM golang:1.23.5-bullseye AS builder2 RUN apt-get update RUN apt-get install -y --no-install-recommends g++ make gcc git build-essential ca-certificates \ diff --git a/common/utils.go b/common/utils.go index ecee2c8e..a3323526 100644 --- a/common/utils.go +++ b/common/utils.go @@ -7,8 +7,8 @@ import ( func LogQuota(quota int64) string { if config.DisplayInCurrencyEnabled { - return fmt.Sprintf("$%.6f 额度", float64(quota)/config.QuotaPerUnit) + return fmt.Sprintf("$%.6f quota", float64(quota)/config.QuotaPerUnit) } else { - return fmt.Sprintf("%d 点额度", quota) + return fmt.Sprintf("%d point quota", quota) } } diff --git a/controller/auth/github.go b/controller/auth/github.go index 5d8029b7..95d44822 100644 --- a/controller/auth/github.go +++ b/controller/auth/github.go @@ -31,7 +31,7 @@ type GitHubUser struct { func getGitHubUserInfoByCode(code string) (*GitHubUser, error) { if code == "" { - return nil, errors.New("无效的参数") + return nil, errors.New("Invalid parameter") } values := map[string]string{"client_id": config.GitHubClientId, "client_secret": config.GitHubClientSecret, "code": code} jsonData, err := json.Marshal(values) @@ -50,7 +50,7 @@ func getGitHubUserInfoByCode(code string) (*GitHubUser, error) { res, err := client.Do(req) if err != nil { logger.SysLog(err.Error()) - return nil, errors.New("无法连接至 GitHub 服务器,请稍后重试!") + return nil, errors.New("Unable to connect to GitHub server, please try again later!") } defer res.Body.Close() var oAuthResponse GitHubOAuthResponse @@ -66,7 +66,7 @@ func getGitHubUserInfoByCode(code string) (*GitHubUser, error) { res2, err := client.Do(req) if err != nil { logger.SysLog(err.Error()) - return nil, errors.New("无法连接至 GitHub 服务器,请稍后重试!") + return nil, errors.New("Unable to connect to GitHub server, please try again later!") } defer res2.Body.Close() var githubUser GitHubUser @@ -75,7 +75,7 @@ func getGitHubUserInfoByCode(code string) (*GitHubUser, error) { return nil, err } if githubUser.Login == "" { - return nil, errors.New("返回值非法,用户字段为空,请稍后重试!") + return nil, errors.New("The return value is illegal, the user field is empty, please try again later!") } return &githubUser, nil } @@ -99,7 +99,7 @@ func GitHubOAuth(c *gin.Context) { if !config.GitHubOAuthEnabled { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "管理员未开启通过 GitHub 登录以及注册", + "message": "The administrator did not turn on login and registration via GitHub", }) return } @@ -146,7 +146,7 @@ func GitHubOAuth(c *gin.Context) { } else { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "管理员关闭了新用户注册", + "message": "The administrator has turned off new user registration", }) return } @@ -154,7 +154,7 @@ func GitHubOAuth(c *gin.Context) { if user.Status != model.UserStatusEnabled { c.JSON(http.StatusOK, gin.H{ - "message": "用户已被封禁", + "message": "User has been banned", "success": false, }) return @@ -166,7 +166,7 @@ func GitHubBind(c *gin.Context) { if !config.GitHubOAuthEnabled { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "管理员未开启通过 GitHub 登录以及注册", + "message": "The administrator did not turn on login and registration via GitHub", }) return } @@ -185,7 +185,7 @@ func GitHubBind(c *gin.Context) { if model.IsGitHubIdAlreadyTaken(user.GitHubId) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "该 GitHub 账户已被绑定", + "message": "The GitHub account has been bound", }) return } diff --git a/controller/auth/lark.go b/controller/auth/lark.go index d4ff8a57..43977d54 100644 --- a/controller/auth/lark.go +++ b/controller/auth/lark.go @@ -28,7 +28,7 @@ type LarkUser struct { func getLarkUserInfoByCode(code string) (*LarkUser, error) { if code == "" { - return nil, errors.New("无效的参数") + return nil, errors.New("Invalid parameter") } values := map[string]string{ "client_id": config.LarkClientId, @@ -53,7 +53,7 @@ func getLarkUserInfoByCode(code string) (*LarkUser, error) { res, err := client.Do(req) if err != nil { logger.SysLog(err.Error()) - return nil, errors.New("无法连接至飞书服务器,请稍后重试!") + return nil, errors.New("None法连接至飞书服务器,请稍后Retry!") } defer res.Body.Close() var oAuthResponse LarkOAuthResponse @@ -69,7 +69,7 @@ func getLarkUserInfoByCode(code string) (*LarkUser, error) { res2, err := client.Do(req) if err != nil { logger.SysLog(err.Error()) - return nil, errors.New("无法连接至飞书服务器,请稍后重试!") + return nil, errors.New("None法连接至飞书服务器,请稍后Retry!") } var larkUser LarkUser err = json.NewDecoder(res2.Body).Decode(&larkUser) @@ -136,7 +136,7 @@ func LarkOAuth(c *gin.Context) { } else { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "管理员关闭了新用户注册", + "message": "The administrator has turned off new user registration", }) return } @@ -144,7 +144,7 @@ func LarkOAuth(c *gin.Context) { if user.Status != model.UserStatusEnabled { c.JSON(http.StatusOK, gin.H{ - "message": "用户已被封禁", + "message": "User has been banned", "success": false, }) return @@ -168,7 +168,7 @@ func LarkBind(c *gin.Context) { if model.IsLarkIdAlreadyTaken(user.LarkId) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "该飞书账户已被绑定", + "message": "该飞书账户已被Bind", }) return } diff --git a/controller/auth/oidc.go b/controller/auth/oidc.go index 7b4ad4b9..6eafecb8 100644 --- a/controller/auth/oidc.go +++ b/controller/auth/oidc.go @@ -35,7 +35,7 @@ type OidcUser struct { func getOidcUserInfoByCode(code string) (*OidcUser, error) { if code == "" { - return nil, errors.New("无效的参数") + return nil, errors.New("Invalid parameter") } values := map[string]string{ "client_id": config.OidcClientId, @@ -60,7 +60,7 @@ func getOidcUserInfoByCode(code string) (*OidcUser, error) { res, err := client.Do(req) if err != nil { logger.SysLog(err.Error()) - return nil, errors.New("无法连接至 OIDC 服务器,请稍后重试!") + return nil, errors.New("None法连接至 OIDC 服务器,请稍后Retry!") } defer res.Body.Close() var oidcResponse OidcResponse @@ -76,7 +76,7 @@ func getOidcUserInfoByCode(code string) (*OidcUser, error) { res2, err := client.Do(req) if err != nil { logger.SysLog(err.Error()) - return nil, errors.New("无法连接至 OIDC 服务器,请稍后重试!") + return nil, errors.New("None法连接至 OIDC 服务器,请稍后Retry!") } var oidcUser OidcUser err = json.NewDecoder(res2.Body).Decode(&oidcUser) @@ -104,7 +104,7 @@ func OidcAuth(c *gin.Context) { if !config.OidcEnabled { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "管理员未开启通过 OIDC 登录以及注册", + "message": "Administrator未开启通过 OIDC Log in以及Sign up", }) return } @@ -153,7 +153,7 @@ func OidcAuth(c *gin.Context) { } else { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "管理员关闭了新用户注册", + "message": "The administrator has turned off new user registration", }) return } @@ -161,7 +161,7 @@ func OidcAuth(c *gin.Context) { if user.Status != model.UserStatusEnabled { c.JSON(http.StatusOK, gin.H{ - "message": "用户已被封禁", + "message": "User has been banned", "success": false, }) return @@ -173,7 +173,7 @@ func OidcBind(c *gin.Context) { if !config.OidcEnabled { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "管理员未开启通过 OIDC 登录以及注册", + "message": "Administrator未开启通过 OIDC Log in以及Sign up", }) return } @@ -192,7 +192,7 @@ func OidcBind(c *gin.Context) { if model.IsOidcIdAlreadyTaken(user.OidcId) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "该 OIDC 账户已被绑定", + "message": "该 OIDC 账户已被Bind", }) return } diff --git a/controller/auth/wechat.go b/controller/auth/wechat.go index 12aec05b..859ae262 100644 --- a/controller/auth/wechat.go +++ b/controller/auth/wechat.go @@ -23,7 +23,7 @@ type wechatLoginResponse struct { func getWeChatIdByCode(code string) (string, error) { if code == "" { - return "", errors.New("无效的参数") + return "", errors.New("Invalid parameter") } req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/wechat/user?code=%s", config.WeChatServerAddress, code), nil) if err != nil { @@ -47,7 +47,7 @@ func getWeChatIdByCode(code string) (string, error) { return "", errors.New(res.Message) } if res.Data == "" { - return "", errors.New("验证码错误或已过期") + return "", errors.New("Verification code error or expired") } return res.Data, nil } @@ -55,7 +55,7 @@ func getWeChatIdByCode(code string) (string, error) { func WeChatAuth(c *gin.Context) { if !config.WeChatAuthEnabled { c.JSON(http.StatusOK, gin.H{ - "message": "管理员未开启通过微信登录以及注册", + "message": "The administrator has not enabled login and registration via WeChat", "success": false, }) return @@ -98,7 +98,7 @@ func WeChatAuth(c *gin.Context) { } else { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "管理员关闭了新用户注册", + "message": "The administrator has turned off new user registration", }) return } @@ -106,7 +106,7 @@ func WeChatAuth(c *gin.Context) { if user.Status != model.UserStatusEnabled { c.JSON(http.StatusOK, gin.H{ - "message": "用户已被封禁", + "message": "User has been banned", "success": false, }) return @@ -117,7 +117,7 @@ func WeChatAuth(c *gin.Context) { func WeChatBind(c *gin.Context) { if !config.WeChatAuthEnabled { c.JSON(http.StatusOK, gin.H{ - "message": "管理员未开启通过微信登录以及注册", + "message": "The administrator has not enabled login and registration via WeChat", "success": false, }) return @@ -134,7 +134,7 @@ func WeChatBind(c *gin.Context) { if model.IsWeChatIdAlreadyTaken(wechatId) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "该微信账号已被绑定", + "message": "The WeChat account has been bound", }) return } diff --git a/controller/channel-billing.go b/controller/channel-billing.go index c7d2d240..f594831e 100644 --- a/controller/channel-billing.go +++ b/controller/channel-billing.go @@ -295,7 +295,7 @@ func updateChannelBalance(channel *model.Channel) (float64, error) { baseURL = channel.GetBaseURL() } case channeltype.Azure: - return 0, errors.New("尚未实现") + return 0, errors.New("Not yet implemented") case channeltype.Custom: baseURL = channel.GetBaseURL() case channeltype.CloseAI: @@ -313,7 +313,7 @@ func updateChannelBalance(channel *model.Channel) (float64, error) { case channeltype.DeepSeek: return updateChannelDeepSeekBalance(channel) default: - return 0, errors.New("尚未实现") + return 0, errors.New("Not yet implemented") } url := fmt.Sprintf("%s/v1/dashboard/billing/subscription", baseURL) @@ -399,7 +399,7 @@ func updateAllChannelsBalance() error { } else { // err is nil & balance <= 0 means quota is used up if balance <= 0 { - monitor.DisableChannel(channel.Id, channel.Name, "余额不足") + monitor.DisableChannel(channel.Id, channel.Name, "Insufficient balance") } } time.Sleep(config.RequestInterval) diff --git a/controller/channel-test.go b/controller/channel-test.go index a49dacbc..ed755d28 100644 --- a/controller/channel-test.go +++ b/controller/channel-test.go @@ -173,7 +173,7 @@ func testChannels(notify bool, scope string) error { testAllChannelsLock.Lock() if testAllChannelsRunning { testAllChannelsLock.Unlock() - return errors.New("测试已在运行中") + return errors.New("Test is already running") } testAllChannelsRunning = true testAllChannelsLock.Unlock() @@ -194,11 +194,11 @@ func testChannels(notify bool, scope string) error { tok := time.Now() milliseconds := tok.Sub(tik).Milliseconds() if isChannelEnabled && milliseconds > disableThreshold { - err = fmt.Errorf("响应时间 %.2fs 超过阈值 %.2fs", float64(milliseconds)/1000.0, float64(disableThreshold)/1000.0) + err = fmt.Errorf("Response time %.2fs exceeds threshold %.2fs", float64(milliseconds)/1000.0, float64(disableThreshold)/1000.0) if config.AutomaticDisableChannelEnabled { monitor.DisableChannel(channel.Id, channel.Name, err.Error()) } else { - _ = message.Notify(message.ByAll, fmt.Sprintf("渠道 %s (%d)测试超时", channel.Name, channel.Id), "", err.Error()) + _ = message.Notify(message.ByAll, fmt.Sprintf("Channel %s (%d)Test超时", channel.Name, channel.Id), "", err.Error()) } } if isChannelEnabled && monitor.ShouldDisableChannel(openaiErr, -1) { @@ -214,7 +214,7 @@ func testChannels(notify bool, scope string) error { testAllChannelsRunning = false testAllChannelsLock.Unlock() if notify { - err := message.Notify(message.ByAll, "渠道测试完成", "", "渠道测试完成,如果没有收到禁用通知,说明所有渠道都正常") + err := message.Notify(message.ByAll, "Channel test completed", "", "Channel test completed, if you have not received the disable notification, it means that all channels are normal") if err != nil { logger.SysError(fmt.Sprintf("failed to send email: %s", err.Error())) } diff --git a/controller/misc.go b/controller/misc.go index ae900870..633a0354 100644 --- a/controller/misc.go +++ b/controller/misc.go @@ -85,7 +85,7 @@ func SendEmailVerification(c *gin.Context) { if err := common.Validate.Var(email, "required,email"); err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无效的参数", + "message": "Invalid parameter", }) return } @@ -100,7 +100,7 @@ func SendEmailVerification(c *gin.Context) { if !allowed { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "管理员启用了邮箱域名白名单,您的邮箱地址的域名不在白名单中", + "message": "AdministratorEnable了邮箱域名白名单,您的Email address的域名不在白名单中", }) return } @@ -108,16 +108,16 @@ func SendEmailVerification(c *gin.Context) { if model.IsEmailAlreadyTaken(email) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "邮箱地址已被占用", + "message": "Email address is occupied", }) return } code := common.GenerateVerificationCode(6) common.RegisterVerificationCodeWithKey(email, code, common.EmailVerificationPurpose) - subject := fmt.Sprintf("%s邮箱验证邮件", config.SystemName) - content := fmt.Sprintf("

您好,你正在进行%s邮箱验证。

"+ - "

您的验证码为: %s

"+ - "

验证码 %d 分钟内有效,如果不是本人操作,请忽略。

", config.SystemName, code, common.VerificationValidMinutes) + subject := fmt.Sprintf("%s Email verification email", config.SystemName) + content := fmt.Sprintf("

Hello, you are verifying %s email.

"+ + "

Your verification code is: %s

"+ + "

The verification code is valid within %d minutes. If it is not your operation, please ignore it.

", config.SystemName, code, common.VerificationValidMinutes) err := message.SendEmail(subject, email, content) if err != nil { c.JSON(http.StatusOK, gin.H{ @@ -138,25 +138,25 @@ func SendPasswordResetEmail(c *gin.Context) { if err := common.Validate.Var(email, "required,email"); err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无效的参数", + "message": "Invalid parameter", }) return } if !model.IsEmailAlreadyTaken(email) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "该邮箱地址未注册", + "message": "The email address is not registered", }) return } code := common.GenerateVerificationCode(0) common.RegisterVerificationCodeWithKey(email, code, common.PasswordResetPurpose) link := fmt.Sprintf("%s/user/reset?email=%s&token=%s", config.ServerAddress, email, code) - subject := fmt.Sprintf("%s密码重置", config.SystemName) - content := fmt.Sprintf("

您好,你正在进行%s密码重置。

"+ - "

点击 此处 进行密码重置。

"+ - "

如果链接无法点击,请尝试点击下面的链接或将其复制到浏览器中打开:
%s

"+ - "

重置链接 %d 分钟内有效,如果不是本人操作,请忽略。

", config.SystemName, link, link, common.VerificationValidMinutes) + subject := fmt.Sprintf("%s Password reset", config.SystemName) + content := fmt.Sprintf("

Hello, you are resetting %s password.

"+ + "

点击 此处 进行Password reset。

"+ + "

如果链接None法点击,请尝试点击下面的链接或将其Copy到浏览器中打开:
%s

"+ + "

The reset link is valid within %d minutes. If it is not your operation, please ignore it.

", config.SystemName, link, link, common.VerificationValidMinutes) err := message.SendEmail(subject, email, content) if err != nil { c.JSON(http.StatusOK, gin.H{ @@ -183,14 +183,14 @@ func ResetPassword(c *gin.Context) { if req.Email == "" || req.Token == "" { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无效的参数", + "message": "Invalid parameter", }) return } if !common.VerifyCodeWithKey(req.Email, req.Token, common.PasswordResetPurpose) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "重置链接非法或已过期", + "message": "Reset link is illegal or expired", }) return } diff --git a/controller/option.go b/controller/option.go index f86e3a64..3f16060e 100644 --- a/controller/option.go +++ b/controller/option.go @@ -38,7 +38,7 @@ func UpdateOption(c *gin.Context) { if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "success": false, - "message": "无效的参数", + "message": "Invalid parameter", }) return } @@ -47,7 +47,7 @@ func UpdateOption(c *gin.Context) { if !config.ValidThemes[option.Value] { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无效的主题", + "message": "None效的主题", }) return } @@ -55,7 +55,7 @@ func UpdateOption(c *gin.Context) { if option.Value == "true" && config.GitHubClientId == "" { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无法启用 GitHub OAuth,请先填入 GitHub Client Id 以及 GitHub Client Secret!", + "message": "None法Enable GitHub OAuth,请先填入 GitHub Client Id 以及 GitHub Client Secret!", }) return } @@ -63,7 +63,7 @@ func UpdateOption(c *gin.Context) { if option.Value == "true" && len(config.EmailDomainWhitelist) == 0 { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无法启用邮箱域名限制,请先填入限制的邮箱域名!", + "message": "None法Enable邮箱域名限制,请先填入限制的邮箱域名!", }) return } @@ -71,7 +71,7 @@ func UpdateOption(c *gin.Context) { if option.Value == "true" && config.WeChatServerAddress == "" { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无法启用微信登录,请先填入微信登录相关配置信息!", + "message": "Unable to enable WeChat login, please fill in the relevant configuration information for WeChat login first!", }) return } @@ -79,7 +79,7 @@ func UpdateOption(c *gin.Context) { if option.Value == "true" && config.TurnstileSiteKey == "" { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无法启用 Turnstile 校验,请先填入 Turnstile 校验相关配置信息!", + "message": "Unable to enable Turnstile verification, please fill in the relevant configuration information for Turnstile verification first!", }) return } diff --git a/controller/redemption.go b/controller/redemption.go index 88227241..69ebc6d0 100644 --- a/controller/redemption.go +++ b/controller/redemption.go @@ -89,21 +89,21 @@ func AddRedemption(c *gin.Context) { if len(redemption.Name) == 0 || len(redemption.Name) > 20 { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "兑换码名称长度必须在1-20之间", + "message": "The length of the redemption code name must be between 1-20", }) return } if redemption.Count <= 0 { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "兑换码个数必须大于0", + "message": "The number of redemption codes must be greater than 0", }) return } if redemption.Count > 100 { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "一次兑换码批量生成的个数不能大于 100", + "message": "The number of redemption codes generated in a batch cannot be greater than 100", }) return } diff --git a/controller/relay.go b/controller/relay.go index 94c75104..92019fd6 100644 --- a/controller/relay.go +++ b/controller/relay.go @@ -90,7 +90,7 @@ func Relay(c *gin.Context) { if bizErr != nil { if bizErr.StatusCode == http.StatusTooManyRequests { - bizErr.Error.Message = "当前分组上游负载已饱和,请稍后再试" + bizErr.Error.Message = "The current group load is saturated, please try again later" } // BUG: bizErr is in race condition diff --git a/controller/token.go b/controller/token.go index 7c26dbf8..7d1a8066 100644 --- a/controller/token.go +++ b/controller/token.go @@ -134,13 +134,13 @@ func GetTokenStatus(c *gin.Context) { func validateToken(c *gin.Context, token *model.Token) error { if len(token.Name) > 30 { - return fmt.Errorf("令牌名称过长") + return fmt.Errorf("Token name is too long") } if token.Subnet != nil && *token.Subnet != "" { err := network.IsValidSubnets(*token.Subnet) if err != nil { - return fmt.Errorf("无效的网段:%s", err.Error()) + return fmt.Errorf("None效的网段:%s", err.Error()) } } @@ -162,7 +162,7 @@ func AddToken(c *gin.Context) { if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": fmt.Sprintf("参数错误:%s", err.Error()), + "message": fmt.Sprintf("参数Error:%s", err.Error()), }) return } @@ -247,7 +247,7 @@ func ConsumeToken(c *gin.Context) { if cleanToken.Status != model.TokenStatusEnabled { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "令牌未启用", + "message": "API KeysNot enabled", }) return } @@ -256,7 +256,7 @@ func ConsumeToken(c *gin.Context) { cleanToken.ExpiredTime <= helper.GetTimestamp() && cleanToken.ExpiredTime != -1 { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "令牌已过期,无法启用,请先修改令牌过期时间,或者设置为永不过期", + "message": "The token has expired and cannot be enabled. Please modify the expiration time of the token, or set it to never expire.", }) return } @@ -264,7 +264,7 @@ func ConsumeToken(c *gin.Context) { cleanToken.RemainQuota <= 0 && !cleanToken.UnlimitedQuota { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "令牌可用额度已用尽,无法启用,请先修改令牌剩余额度,或者设置为无限额度", + "message": "The available quota of the token has been used up and cannot be enabled. Please modify the remaining quota of the token, or set it to unlimited quota", }) return } @@ -274,7 +274,7 @@ func ConsumeToken(c *gin.Context) { if cleanToken.RemainQuota < int64(tokenPatch.AddUsedQuota) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "剩余额度不足", + "message": "Remaining quota不足", }) return } @@ -336,7 +336,7 @@ func UpdateToken(c *gin.Context) { if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": fmt.Sprintf("参数错误:%s", err.Error()), + "message": fmt.Sprintf("参数Error:%s", err.Error()), }) return } @@ -357,7 +357,7 @@ func UpdateToken(c *gin.Context) { token.ExpiredTime != -1 && token.ExpiredTime < helper.GetTimestamp() { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "令牌已过期,无法启用,请先修改令牌过期时间,或者设置为永不过期", + "message": "The token has expired and cannot be enabled. Please modify the expiration time of the token, or set it to never expire.", }) return } @@ -366,7 +366,7 @@ func UpdateToken(c *gin.Context) { token.RemainQuota <= 0 && !token.UnlimitedQuota { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "令牌可用额度已用尽,无法启用,请先修改令牌剩余额度,或者设置为无限额度", + "message": "The available quota of the token has been used up and cannot be enabled. Please modify the remaining quota of the token, or set it to unlimited quota", }) return } diff --git a/controller/user.go b/controller/user.go index 05c4d66a..dd2762b2 100644 --- a/controller/user.go +++ b/controller/user.go @@ -24,7 +24,7 @@ type LoginRequest struct { func Login(c *gin.Context) { if !config.PasswordLoginEnabled { c.JSON(http.StatusOK, gin.H{ - "message": "管理员关闭了密码登录", + "message": "The administrator has turned off password login", "success": false, }) return @@ -33,7 +33,7 @@ func Login(c *gin.Context) { err := json.NewDecoder(c.Request.Body).Decode(&loginRequest) if err != nil { c.JSON(http.StatusOK, gin.H{ - "message": "无效的参数", + "message": "Invalid parameter", "success": false, }) return @@ -42,7 +42,7 @@ func Login(c *gin.Context) { password := loginRequest.Password if username == "" || password == "" { c.JSON(http.StatusOK, gin.H{ - "message": "无效的参数", + "message": "Invalid parameter", "success": false, }) return @@ -72,7 +72,7 @@ func SetupLogin(user *model.User, c *gin.Context) { err := session.Save() if err != nil { c.JSON(http.StatusOK, gin.H{ - "message": "无法保存会话信息,请重试", + "message": "Unable to save session information, please try again", "success": false, }) return @@ -117,14 +117,14 @@ func Logout(c *gin.Context) { func Register(c *gin.Context) { if !config.RegisterEnabled { c.JSON(http.StatusOK, gin.H{ - "message": "管理员关闭了新用户注册", + "message": "The administrator has turned off new user registration", "success": false, }) return } if !config.PasswordRegisterEnabled { c.JSON(http.StatusOK, gin.H{ - "message": "管理员关闭了通过密码进行注册,请使用第三方账户验证的形式进行注册", + "message": "The administrator has turned off registration via password. Please use the form of third-party account verification to register", "success": false, }) return @@ -134,14 +134,14 @@ func Register(c *gin.Context) { if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无效的参数", + "message": "Invalid parameter", }) return } if err := common.Validate.Struct(&user); err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "输入不合法 " + err.Error(), + "message": "Input is illegal " + err.Error(), }) return } @@ -149,14 +149,14 @@ func Register(c *gin.Context) { if user.Email == "" || user.VerificationCode == "" { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "管理员开启了邮箱验证,请输入邮箱地址和验证码", + "message": "The administrator has turned on email verification, please enter the email address and verification code", }) return } if !common.VerifyCodeWithKey(user.Email, user.VerificationCode, common.EmailVerificationPurpose) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "验证码错误或已过期", + "message": "Verification code error or expired", }) return } @@ -249,7 +249,7 @@ func GetUser(c *gin.Context) { if myRole <= user.Role && myRole != model.RoleRootUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无权获取同级或更高等级用户的信息", + "message": "No permission to get information of users at the same level or higher", }) return } @@ -271,7 +271,7 @@ func GetUserDashboard(c *gin.Context) { if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无法获取统计信息", + "message": "None法获取Statistics", "data": nil, }) return @@ -299,7 +299,7 @@ func GenerateAccessToken(c *gin.Context) { if model.DB.Where("access_token = ?", user.AccessToken).First(user).RowsAffected != 0 { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "请重试,系统生成的 UUID 竟然重复了!", + "message": "Please try again, the system-generated UUID is actually duplicated!", }) return } @@ -382,7 +382,7 @@ func UpdateUser(c *gin.Context) { if err != nil || updatedUser.Id == 0 { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无效的参数", + "message": "Invalid parameter", }) return } @@ -392,7 +392,7 @@ func UpdateUser(c *gin.Context) { if err := common.Validate.Struct(&updatedUser); err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "输入不合法 " + err.Error(), + "message": "Input is illegal " + err.Error(), }) return } @@ -408,14 +408,14 @@ func UpdateUser(c *gin.Context) { if myRole <= originUser.Role && myRole != model.RoleRootUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无权更新同权限等级或更高权限等级的用户信息", + "message": "No permission to update user information with the same permission level or higher permission level", }) return } if myRole <= updatedUser.Role && myRole != model.RoleRootUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无权将其他用户权限等级提升到大于等于自己的权限等级", + "message": "None权将其他Users权限等级Promote到大于Equals自己的权限等级", }) return } @@ -431,7 +431,7 @@ func UpdateUser(c *gin.Context) { return } if originUser.Quota != updatedUser.Quota { - model.RecordLog(originUser.Id, model.LogTypeManage, fmt.Sprintf("管理员将用户额度从 %s修改为 %s", common.LogQuota(originUser.Quota), common.LogQuota(updatedUser.Quota))) + model.RecordLog(originUser.Id, model.LogTypeManage, fmt.Sprintf("The administrator changed the user quota from %s to %s", common.LogQuota(originUser.Quota), common.LogQuota(updatedUser.Quota))) } c.JSON(http.StatusOK, gin.H{ "success": true, @@ -446,7 +446,7 @@ func UpdateSelf(c *gin.Context) { if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无效的参数", + "message": "Invalid parameter", }) return } @@ -456,7 +456,7 @@ func UpdateSelf(c *gin.Context) { if err := common.Validate.Struct(&user); err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "输入不合法 " + err.Error(), + "message": "Input is illegal " + err.Error(), }) return } @@ -508,7 +508,7 @@ func DeleteUser(c *gin.Context) { if myRole <= originUser.Role { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无权删除同权限等级或更高权限等级的用户", + "message": "No permission to delete users with the same permission level or higher permission level", }) return } @@ -529,7 +529,7 @@ func DeleteSelf(c *gin.Context) { if user.Role == model.RoleRootUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "不能删除超级管理员账户", + "message": "不能DeleteSuper administrator账户", }) return } @@ -555,14 +555,14 @@ func CreateUser(c *gin.Context) { if err != nil || user.Username == "" || user.Password == "" { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无效的参数", + "message": "Invalid parameter", }) return } if err := common.Validate.Struct(&user); err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "输入不合法 " + err.Error(), + "message": "Input is illegal " + err.Error(), }) return } @@ -573,7 +573,7 @@ func CreateUser(c *gin.Context) { if user.Role >= myRole { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无法创建权限大于等于自己的用户", + "message": "Unable to create users with permissions greater than or equal to your own", }) return } @@ -611,7 +611,7 @@ func ManageUser(c *gin.Context) { if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无效的参数", + "message": "Invalid parameter", }) return } @@ -623,7 +623,7 @@ func ManageUser(c *gin.Context) { if user.Id == 0 { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "用户不存在", + "message": "User does not exist", }) return } @@ -631,7 +631,7 @@ func ManageUser(c *gin.Context) { if myRole <= user.Role && myRole != model.RoleRootUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无权更新同权限等级或更高权限等级的用户信息", + "message": "No permission to update user information with the same permission level or higher permission level", }) return } @@ -641,7 +641,7 @@ func ManageUser(c *gin.Context) { if user.Role == model.RoleRootUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无法禁用超级管理员用户", + "message": "Unable to disable super administrator user", }) return } @@ -651,7 +651,7 @@ func ManageUser(c *gin.Context) { if user.Role == model.RoleRootUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无法删除超级管理员用户", + "message": "Unable to delete super administrator user", }) return } @@ -666,14 +666,14 @@ func ManageUser(c *gin.Context) { if myRole != model.RoleRootUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "普通管理员用户无法提升其他用户为管理员", + "message": "Ordinary administrator users cannot promote other users to administrators", }) return } if user.Role >= model.RoleAdminUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "该用户已经是管理员", + "message": "The user is already an administrator", }) return } @@ -682,14 +682,14 @@ func ManageUser(c *gin.Context) { if user.Role == model.RoleRootUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无法降级超级管理员用户", + "message": "Unable to downgrade super administrator user", }) return } if user.Role == model.RoleCommonUser { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "该用户已经是普通用户", + "message": "The user is already an ordinary user", }) return } @@ -721,7 +721,7 @@ func EmailBind(c *gin.Context) { if !common.VerifyCodeWithKey(email, code, common.EmailVerificationPurpose) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "验证码错误或已过期", + "message": "Verification code error or expired", }) return } @@ -813,7 +813,7 @@ func AdminTopUp(c *gin.Context) { return } if req.Remark == "" { - req.Remark = fmt.Sprintf("通过 API 充值 %s", common.LogQuota(int64(req.Quota))) + req.Remark = fmt.Sprintf("通过 API Recharge %s", common.LogQuota(int64(req.Quota))) } model.RecordTopupLog(req.UserId, req.Remark, req.Quota) c.JSON(http.StatusOK, gin.H{ diff --git a/middleware/auth.go b/middleware/auth.go index 4b0fbe89..8fc62027 100644 --- a/middleware/auth.go +++ b/middleware/auth.go @@ -27,7 +27,7 @@ func authHelper(c *gin.Context, minRole int) { if accessToken == "" { c.JSON(http.StatusUnauthorized, gin.H{ "success": false, - "message": "无权进行此操作,未登录且未提供 access token", + "message": "No permission to perform this operation, not logged in and no access token provided", }) c.Abort() return @@ -43,7 +43,7 @@ func authHelper(c *gin.Context, minRole int) { } else { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无权进行此操作,access token 无效", + "message": "No permission to perform this operation, access token is invalid", }) c.Abort() return @@ -52,7 +52,7 @@ func authHelper(c *gin.Context, minRole int) { if status.(int) == model.UserStatusDisabled || blacklist.IsUserBanned(id.(int)) { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "用户已被封禁", + "message": "User has been banned", }) session := sessions.Default(c) session.Clear() @@ -63,7 +63,7 @@ func authHelper(c *gin.Context, minRole int) { if role.(int) < minRole { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "无权进行此操作,权限不足", + "message": "No permission to perform this operation, insufficient permissions", }) c.Abort() return @@ -107,7 +107,7 @@ func TokenAuth() func(c *gin.Context) { } if token.Subnet != nil && *token.Subnet != "" { if !network.IsIpInSubnets(ctx, c.ClientIP(), *token.Subnet) { - abortWithMessage(c, http.StatusForbidden, fmt.Sprintf("该令牌只能在指定网段使用:%s,当前 ip:%s", *token.Subnet, c.ClientIP())) + abortWithMessage(c, http.StatusForbidden, fmt.Sprintf("该API Keys只能在指定网段使用:%s,当前 ip:%s", *token.Subnet, c.ClientIP())) return } } @@ -117,7 +117,7 @@ func TokenAuth() func(c *gin.Context) { return } if !userEnabled || blacklist.IsUserBanned(token.UserId) { - abortWithMessage(c, http.StatusForbidden, "用户已被封禁") + abortWithMessage(c, http.StatusForbidden, "User has been banned") return } requestModel, err := getRequestModel(c) @@ -129,7 +129,7 @@ func TokenAuth() func(c *gin.Context) { if token.Models != nil && *token.Models != "" { c.Set(ctxkey.AvailableModels, *token.Models) if requestModel != "" && !isModelInList(requestModel, *token.Models) { - abortWithMessage(c, http.StatusForbidden, fmt.Sprintf("该令牌无权使用模型:%s", requestModel)) + abortWithMessage(c, http.StatusForbidden, fmt.Sprintf("该API KeysNone权使用Model:%s", requestModel)) return } } @@ -144,7 +144,7 @@ func TokenAuth() func(c *gin.Context) { if model.IsAdmin(token.UserId) { c.Set(ctxkey.SpecificChannelId, parts[1]) } else { - abortWithMessage(c, http.StatusForbidden, "普通用户不支持指定渠道") + abortWithMessage(c, http.StatusForbidden, "Ordinary users do not support specifying channels") return } } diff --git a/middleware/distributor.go b/middleware/distributor.go index 1d376dfc..8098c307 100644 --- a/middleware/distributor.go +++ b/middleware/distributor.go @@ -30,16 +30,16 @@ func Distribute() func(c *gin.Context) { if ok { id, err := strconv.Atoi(channelId.(string)) if err != nil { - abortWithMessage(c, http.StatusBadRequest, "无效的渠道 Id") + abortWithMessage(c, http.StatusBadRequest, "None效的Channel Id") return } channel, err = model.GetChannelById(id, true) if err != nil { - abortWithMessage(c, http.StatusBadRequest, "无效的渠道 Id") + abortWithMessage(c, http.StatusBadRequest, "None效的Channel Id") return } if channel.Status != model.ChannelStatusEnabled { - abortWithMessage(c, http.StatusForbidden, "该渠道已被禁用") + abortWithMessage(c, http.StatusForbidden, "The channel has been disabled") return } } else { @@ -47,10 +47,10 @@ func Distribute() func(c *gin.Context) { var err error channel, err = model.CacheGetRandomSatisfiedChannel(userGroup, requestModel, false) if err != nil { - message := fmt.Sprintf("当前分组 %s 下对于模型 %s 无可用渠道", userGroup, requestModel) + message := fmt.Sprintf("当前Group %s 下对于Model %s No available channels", userGroup, requestModel) if channel != nil { - logger.SysError(fmt.Sprintf("渠道不存在:%d", channel.Id)) - message = "数据库一致性已被破坏,请联系管理员" + logger.SysError(fmt.Sprintf("Channel does not exist: %d", channel.Id)) + message = "Database consistency has been broken, please contact the administrator" } abortWithMessage(c, http.StatusServiceUnavailable, message) return diff --git a/middleware/turnstile-check.go b/middleware/turnstile-check.go index 403bcb34..c3451afa 100644 --- a/middleware/turnstile-check.go +++ b/middleware/turnstile-check.go @@ -27,7 +27,7 @@ func TurnstileCheck() gin.HandlerFunc { if response == "" { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "Turnstile token 为空", + "message": "Turnstile token is empty", }) c.Abort() return @@ -61,7 +61,7 @@ func TurnstileCheck() gin.HandlerFunc { if !res.Success { c.JSON(http.StatusOK, gin.H{ "success": false, - "message": "Turnstile 校验失败,请刷新重试!", + "message": "Turnstile verification failed, please refresh and try again!", }) c.Abort() return @@ -70,7 +70,7 @@ func TurnstileCheck() gin.HandlerFunc { err = session.Save() if err != nil { c.JSON(http.StatusOK, gin.H{ - "message": "无法保存会话信息,请重试", + "message": "Unable to save session information, please try again", "success": false, }) return diff --git a/model/redemption.go b/model/redemption.go index 6c1a63d3..4f5ae4c9 100644 --- a/model/redemption.go +++ b/model/redemption.go @@ -40,7 +40,7 @@ func SearchRedemptions(keyword string) (redemptions []*Redemption, err error) { func GetRedemptionById(id int) (*Redemption, error) { if id == 0 { - return nil, errors.New("id 为空!") + return nil, errors.New("id is empty!") } redemption := Redemption{Id: id} var err error = nil @@ -50,10 +50,10 @@ func GetRedemptionById(id int) (*Redemption, error) { func Redeem(key string, userId int) (quota int64, err error) { if key == "" { - return 0, errors.New("未提供兑换码") + return 0, errors.New("No redemption code provided") } if userId == 0 { - return 0, errors.New("无效的 user id") + return 0, errors.New("Invalid user id") } redemption := &Redemption{} @@ -65,10 +65,10 @@ func Redeem(key string, userId int) (quota int64, err error) { err = DB.Transaction(func(tx *gorm.DB) error { err := tx.Set("gorm:query_option", "FOR UPDATE").Where(keyCol+" = ?", key).First(redemption).Error if err != nil { - return errors.New("无效的兑换码") + return errors.New("Invalid redemption code") } if redemption.Status != RedemptionCodeStatusEnabled { - return errors.New("该兑换码已被使用") + return errors.New("The redemption code has been used") } err = tx.Model(&User{}).Where("id = ?", userId).Update("quota", gorm.Expr("quota + ?", redemption.Quota)).Error if err != nil { @@ -80,9 +80,9 @@ func Redeem(key string, userId int) (quota int64, err error) { return err }) if err != nil { - return 0, errors.New("兑换失败," + err.Error()) + return 0, errors.New("Redeem失败," + err.Error()) } - RecordLog(userId, LogTypeTopup, fmt.Sprintf("通过兑换码充值 %s", common.LogQuota(redemption.Quota))) + RecordLog(userId, LogTypeTopup, fmt.Sprintf("Recharge %s through redemption code", common.LogQuota(redemption.Quota))) return redemption.Quota, nil } @@ -112,7 +112,7 @@ func (redemption *Redemption) Delete() error { func DeleteRedemptionById(id int) (err error) { if id == 0 { - return errors.New("id 为空!") + return errors.New("id is empty!") } redemption := Redemption{Id: id} err = DB.Where(redemption).First(&redemption).Error diff --git a/model/token.go b/model/token.go index a8351b24..ce281923 100644 --- a/model/token.go +++ b/model/token.go @@ -60,7 +60,7 @@ func SearchUserTokens(userId int, keyword string) (tokens []*Token, err error) { func ValidateUserToken(key string) (token *Token, err error) { if key == "" { - return nil, errors.New("未提供令牌") + return nil, errors.New("No token provided") } token, err = CacheGetTokenByKey(key) if err != nil { @@ -72,12 +72,12 @@ func ValidateUserToken(key string) (token *Token, err error) { return nil, errors.Wrap(err, "failed to get token by key") } if token.Status == TokenStatusExhausted { - return nil, fmt.Errorf("令牌 %s(#%d)额度已用尽", token.Name, token.Id) + return nil, fmt.Errorf("API Keys %s(#%d)Quota已用尽", token.Name, token.Id) } else if token.Status == TokenStatusExpired { - return nil, errors.New("该令牌已过期") + return nil, errors.New("The token has expired") } if token.Status != TokenStatusEnabled { - return nil, errors.New("该令牌状态不可用") + return nil, errors.New("The token status is not available") } if token.ExpiredTime != -1 && token.ExpiredTime < helper.GetTimestamp() { if !common.RedisEnabled { @@ -87,7 +87,7 @@ func ValidateUserToken(key string) (token *Token, err error) { logger.SysError("failed to update token status" + err.Error()) } } - return nil, errors.New("该令牌已过期") + return nil, errors.New("The token has expired") } if !token.UnlimitedQuota && token.RemainQuota <= 0 { if !common.RedisEnabled { @@ -98,14 +98,14 @@ func ValidateUserToken(key string) (token *Token, err error) { logger.SysError("failed to update token status" + err.Error()) } } - return nil, errors.New("该令牌额度已用尽") + return nil, errors.New("The token quota has been used up") } return token, nil } func GetTokenByIds(id int, userId int) (*Token, error) { if id == 0 || userId == 0 { - return nil, errors.New("id 或 userId 为空!") + return nil, errors.New("id or userId is empty!") } token := Token{Id: id, UserId: userId} var err error = nil @@ -115,7 +115,7 @@ func GetTokenByIds(id int, userId int) (*Token, error) { func GetTokenById(id int) (*Token, error) { if id == 0 { - return nil, errors.New("id 为空!") + return nil, errors.New("id is empty!") } token := Token{Id: id} var err error = nil @@ -160,7 +160,7 @@ func (t *Token) GetModels() string { func DeleteTokenById(id int, userId int) (err error) { // Why we need userId here? In case user want to delete other's token. if id == 0 || userId == 0 { - return errors.New("id 或 userId 为空!") + return errors.New("id or userId is empty!") } token := Token{Id: id, UserId: userId} err = DB.Where(token).First(&token).Error @@ -172,7 +172,7 @@ func DeleteTokenById(id int, userId int) (err error) { func IncreaseTokenQuota(id int, quota int64) (err error) { if quota < 0 { - return errors.New("quota 不能为负数!") + return errors.New("quota cannot be negative!") } if config.BatchUpdateEnabled { addNewRecord(BatchUpdateTypeTokenQuota, id, quota) @@ -194,7 +194,7 @@ func increaseTokenQuota(id int, quota int64) (err error) { func DecreaseTokenQuota(id int, quota int64) (err error) { if quota < 0 { - return errors.New("quota 不能为负数!") + return errors.New("quota cannot be negative!") } if config.BatchUpdateEnabled { addNewRecord(BatchUpdateTypeTokenQuota, id, -quota) @@ -216,21 +216,21 @@ func decreaseTokenQuota(id int, quota int64) (err error) { func PreConsumeTokenQuota(tokenId int, quota int64) (err error) { if quota < 0 { - return errors.New("quota 不能为负数!") + return errors.New("quota cannot be negative!") } token, err := GetTokenById(tokenId) if err != nil { return err } if !token.UnlimitedQuota && token.RemainQuota < quota { - return errors.New("令牌额度不足") + return errors.New("Insufficient token quota") } userQuota, err := GetUserQuota(token.UserId) if err != nil { return err } if userQuota < quota { - return errors.New("用户额度不足") + return errors.New("Insufficient user quota") } quotaTooLow := userQuota >= config.QuotaRemindThreshold && userQuota-quota < config.QuotaRemindThreshold noMoreQuota := userQuota-quota <= 0 @@ -240,14 +240,14 @@ func PreConsumeTokenQuota(tokenId int, quota int64) (err error) { if err != nil { logger.SysError("failed to fetch user email: " + err.Error()) } - prompt := "您的额度即将用尽" + prompt := "Your quota is about to run out" if noMoreQuota { - prompt = "您的额度已用尽" + prompt = "Your quota has been used up" } if email != "" { topUpLink := fmt.Sprintf("%s/topup", config.ServerAddress) err = message.SendEmail(prompt, email, - fmt.Sprintf("%s,当前剩余额度为 %d,为了不影响您的使用,请及时充值。
充值链接:%s", prompt, userQuota, topUpLink, topUpLink)) + fmt.Sprintf("%s, the current remaining quota is %d, in order not to affect your use, please recharge in time.
Recharge link: %s", prompt, userQuota, topUpLink, topUpLink)) if err != nil { logger.SysError("failed to send email" + err.Error()) } diff --git a/model/user.go b/model/user.go index 55dd0570..9ff8a093 100644 --- a/model/user.go +++ b/model/user.go @@ -86,7 +86,7 @@ func SearchUsers(keyword string) (users []*User, err error) { func GetUserById(id int, selectAll bool) (*User, error) { if id == 0 { - return nil, errors.New("id 为空!") + return nil, errors.New("id is empty!") } user := User{Id: id} var err error = nil @@ -100,7 +100,7 @@ func GetUserById(id int, selectAll bool) (*User, error) { func GetUserIdByAffCode(affCode string) (int, error) { if affCode == "" { - return 0, errors.New("affCode 为空!") + return 0, errors.New("affCode is empty!") } var user User err := DB.Select("id").First(&user, "aff_code = ?", affCode).Error @@ -109,7 +109,7 @@ func GetUserIdByAffCode(affCode string) (int, error) { func DeleteUserById(id int) (err error) { if id == 0 { - return errors.New("id 为空!") + return errors.New("id is empty!") } user := User{Id: id} return user.Delete() @@ -131,16 +131,16 @@ func (user *User) Insert(inviterId int) error { return result.Error } if config.QuotaForNewUser > 0 { - RecordLog(user.Id, LogTypeSystem, fmt.Sprintf("新用户注册赠送 %s", common.LogQuota(config.QuotaForNewUser))) + RecordLog(user.Id, LogTypeSystem, fmt.Sprintf("New user registration gives %s", common.LogQuota(config.QuotaForNewUser))) } if inviterId != 0 { if config.QuotaForInvitee > 0 { _ = IncreaseUserQuota(user.Id, config.QuotaForInvitee) - RecordLog(user.Id, LogTypeSystem, fmt.Sprintf("使用邀请码赠送 %s", common.LogQuota(config.QuotaForInvitee))) + RecordLog(user.Id, LogTypeSystem, fmt.Sprintf("Use invitation code to give %s", common.LogQuota(config.QuotaForInvitee))) } if config.QuotaForInviter > 0 { _ = IncreaseUserQuota(inviterId, config.QuotaForInviter) - RecordLog(inviterId, LogTypeSystem, fmt.Sprintf("邀请用户赠送 %s", common.LogQuota(config.QuotaForInviter))) + RecordLog(inviterId, LogTypeSystem, fmt.Sprintf("Invite users to give %s", common.LogQuota(config.QuotaForInviter))) } } // create default token @@ -181,7 +181,7 @@ func (user *User) Update(updatePassword bool) error { func (user *User) Delete() error { if user.Id == 0 { - return errors.New("id 为空!") + return errors.New("id is empty!") } blacklist.BanUser(user.Id) user.Username = fmt.Sprintf("deleted_%s", random.GetUUID()) @@ -197,7 +197,7 @@ func (user *User) ValidateAndFill() (err error) { // it won’t be used to build query conditions password := user.Password if user.Username == "" || password == "" { - return errors.New("用户名或密码为空") + return errors.New("Username or password is empty") } err = DB.Where("username = ?", user.Username).First(user).Error if err != nil { @@ -205,19 +205,19 @@ func (user *User) ValidateAndFill() (err error) { // consider this case: a malicious user set his username as other's email err := DB.Where("email = ?", user.Username).First(user).Error if err != nil { - return errors.New("用户名或密码错误,或用户已被封禁") + return errors.New("Username or password is wrong, or user has been banned") } } okay := common.ValidatePasswordAndHash(password, user.Password) if !okay || user.Status != UserStatusEnabled { - return errors.New("用户名或密码错误,或用户已被封禁") + return errors.New("Username or password is wrong, or user has been banned") } return nil } func (user *User) FillUserById() error { if user.Id == 0 { - return errors.New("id 为空!") + return errors.New("id is empty!") } DB.Where(User{Id: user.Id}).First(user) return nil @@ -225,7 +225,7 @@ func (user *User) FillUserById() error { func (user *User) FillUserByEmail() error { if user.Email == "" { - return errors.New("email 为空!") + return errors.New("email is empty!") } DB.Where(User{Email: user.Email}).First(user) return nil @@ -233,7 +233,7 @@ func (user *User) FillUserByEmail() error { func (user *User) FillUserByGitHubId() error { if user.GitHubId == "" { - return errors.New("GitHub id 为空!") + return errors.New("GitHub id is empty!") } DB.Where(User{GitHubId: user.GitHubId}).First(user) return nil @@ -241,7 +241,7 @@ func (user *User) FillUserByGitHubId() error { func (user *User) FillUserByLarkId() error { if user.LarkId == "" { - return errors.New("lark id 为空!") + return errors.New("lark id is empty!") } DB.Where(User{LarkId: user.LarkId}).First(user) return nil @@ -249,7 +249,7 @@ func (user *User) FillUserByLarkId() error { func (user *User) FillUserByOidcId() error { if user.OidcId == "" { - return errors.New("oidc id 为空!") + return errors.New("oidc id is empty!") } DB.Where(User{OidcId: user.OidcId}).First(user) return nil @@ -257,7 +257,7 @@ func (user *User) FillUserByOidcId() error { func (user *User) FillUserByWeChatId() error { if user.WeChatId == "" { - return errors.New("WeChat id 为空!") + return errors.New("WeChat id is empty!") } DB.Where(User{WeChatId: user.WeChatId}).First(user) return nil @@ -265,7 +265,7 @@ func (user *User) FillUserByWeChatId() error { func (user *User) FillUserByUsername() error { if user.Username == "" { - return errors.New("username 为空!") + return errors.New("username is empty!") } DB.Where(User{Username: user.Username}).First(user) return nil @@ -297,7 +297,7 @@ func IsUsernameAlreadyTaken(username string) bool { func ResetUserPasswordByEmail(email string, password string) error { if email == "" || password == "" { - return errors.New("邮箱地址或密码为空!") + return errors.New("Email address or password is empty!") } hashedPassword, err := common.Password2Hash(password) if err != nil { @@ -371,7 +371,7 @@ func GetUserGroup(id int) (group string, err error) { func IncreaseUserQuota(id int, quota int64) (err error) { if quota < 0 { - return errors.New("quota 不能为负数!") + return errors.New("quota cannot be negative!") } if config.BatchUpdateEnabled { addNewRecord(BatchUpdateTypeUserQuota, id, quota) @@ -387,7 +387,7 @@ func increaseUserQuota(id int, quota int64) (err error) { func DecreaseUserQuota(id int, quota int64) (err error) { if quota < 0 { - return errors.New("quota 不能为负数!") + return errors.New("quota cannot be negative!") } if config.BatchUpdateEnabled { addNewRecord(BatchUpdateTypeUserQuota, id, -quota) diff --git a/monitor/channel.go b/monitor/channel.go index 7e5dc58a..39705e40 100644 --- a/monitor/channel.go +++ b/monitor/channel.go @@ -30,16 +30,16 @@ func notifyRootUser(subject string, content string) { func DisableChannel(channelId int, channelName string, reason string) { model.UpdateChannelStatusById(channelId, model.ChannelStatusAutoDisabled) logger.SysLog(fmt.Sprintf("channel #%d has been disabled: %s", channelId, reason)) - subject := fmt.Sprintf("渠道「%s」(#%d)已被禁用", channelName, channelId) - content := fmt.Sprintf("渠道「%s」(#%d)已被禁用,原因:%s", channelName, channelId, reason) + subject := fmt.Sprintf("Channel %s (#%d) has been disabled", channelName, channelId) + content := fmt.Sprintf("Channel %s (#%d) has been disabled, reason: %s", channelName, channelId, reason) notifyRootUser(subject, content) } func MetricDisableChannel(channelId int, successRate float64) { model.UpdateChannelStatusById(channelId, model.ChannelStatusAutoDisabled) logger.SysLog(fmt.Sprintf("channel #%d has been disabled due to low success rate: %.2f", channelId, successRate*100)) - subject := fmt.Sprintf("渠道 #%d 已被禁用", channelId) - content := fmt.Sprintf("该渠道(#%d)在最近 %d 次调用中成功率为 %.2f%%,低于阈值 %.2f%%,因此被系统自动禁用。", + subject := fmt.Sprintf("Channel #%d 已被Disable", channelId) + content := fmt.Sprintf("该Channel(#%d)在最近 %d 次调用中成功率为 %.2f%%,低于阈值 %.2f%%,因此被System自动Disable。", channelId, config.MetricQueueSize, successRate*100, config.MetricSuccessRateThreshold*100) notifyRootUser(subject, content) } @@ -48,7 +48,7 @@ func MetricDisableChannel(channelId int, successRate float64) { func EnableChannel(channelId int, channelName string) { model.UpdateChannelStatusById(channelId, model.ChannelStatusEnabled) logger.SysLog(fmt.Sprintf("channel #%d has been enabled", channelId)) - subject := fmt.Sprintf("渠道「%s」(#%d)已被启用", channelName, channelId) - content := fmt.Sprintf("渠道「%s」(#%d)已被启用", channelName, channelId) + subject := fmt.Sprintf("Channel「%s」(#%d)已被Enable", channelName, channelId) + content := fmt.Sprintf("Channel「%s」(#%d)已被Enable", channelName, channelId) notifyRootUser(subject, content) } diff --git a/relay/adaptor/cohere/model.go b/relay/adaptor/cohere/model.go index 3a8bc99d..c613c3d9 100644 --- a/relay/adaptor/cohere/model.go +++ b/relay/adaptor/cohere/model.go @@ -2,23 +2,23 @@ package cohere type Request struct { Message string `json:"message" required:"true"` - Model string `json:"model,omitempty"` // 默认值为"command-r" - Stream bool `json:"stream,omitempty"` // 默认值为false + Model string `json:"model,omitempty"` // Default值为"command-r" + Stream bool `json:"stream,omitempty"` // Default值为false Preamble string `json:"preamble,omitempty"` ChatHistory []ChatMessage `json:"chat_history,omitempty"` ConversationID string `json:"conversation_id,omitempty"` - PromptTruncation string `json:"prompt_truncation,omitempty"` // 默认值为"AUTO" + PromptTruncation string `json:"prompt_truncation,omitempty"` // Default值为"AUTO" Connectors []Connector `json:"connectors,omitempty"` Documents []Document `json:"documents,omitempty"` - Temperature *float64 `json:"temperature,omitempty"` // 默认值为0.3 + Temperature *float64 `json:"temperature,omitempty"` // Default值为0.3 MaxTokens int `json:"max_tokens,omitempty"` MaxInputTokens int `json:"max_input_tokens,omitempty"` - K int `json:"k,omitempty"` // 默认值为0 - P *float64 `json:"p,omitempty"` // 默认值为0.75 + K int `json:"k,omitempty"` // Default值为0 + P *float64 `json:"p,omitempty"` // Default值为0.75 Seed int `json:"seed,omitempty"` StopSequences []string `json:"stop_sequences,omitempty"` - FrequencyPenalty *float64 `json:"frequency_penalty,omitempty"` // 默认值为0.0 - PresencePenalty *float64 `json:"presence_penalty,omitempty"` // 默认值为0.0 + FrequencyPenalty *float64 `json:"frequency_penalty,omitempty"` // Default值为0.0 + PresencePenalty *float64 `json:"presence_penalty,omitempty"` // Default值为0.0 Tools []Tool `json:"tools,omitempty"` ToolResults []ToolResult `json:"tool_results,omitempty"` } diff --git a/relay/adaptor/tencent/model.go b/relay/adaptor/tencent/model.go index fb97724e..7f5e7eb2 100644 --- a/relay/adaptor/tencent/model.go +++ b/relay/adaptor/tencent/model.go @@ -6,39 +6,39 @@ type Message struct { } type ChatRequest struct { - // 模型名称,可选值包括 hunyuan-lite、hunyuan-standard、hunyuan-standard-256K、hunyuan-pro。 - // 各模型介绍请阅读 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 中的说明。 + // Model name,Optional values包括 hunyuan-lite、hunyuan-standard、hunyuan-standard-256K、hunyuan-pro。 + // 各Model介绍请阅读 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 中的说明。 // - // 注意: - // 不同的模型计费不同,请根据 [购买指南](https://cloud.tencent.com/document/product/1729/97731) 按需调用。 + // Note: + // 不同的Model计费不同,请根据 [购买指南](https://cloud.tencent.com/document/product/1729/97731) 按需调用。 Model *string `json:"Model"` - // 聊天上下文信息。 + // Chat上下文信息。 // 说明: - // 1. 长度最多为 40,按对话时间从旧到新在数组中排列。 - // 2. Message.Role 可选值:system、user、assistant。 + // 1. 长度最多为 40,按对话Time从旧到新在数Group中排列。 + // 2. Message.Role Optional values:system、user、assistant。 // 其中,system 角色可选,如存在则必须位于列表的最开始。user 和 assistant 需交替出现(一问一答),以 user 提问开始和结束,且 Content 不能为空。Role 的顺序示例:[system(可选) user assistant user assistant user ...]。 - // 3. Messages 中 Content 总长度不能超过模型输入长度上限(可参考 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 文档),超过则会截断最前面的内容,只保留尾部内容。 + // 3. Messages 中 Content 总长度不能超过ModelEnter长度上限(可参考 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 文档),超过则会截断最前面的内容,只保留尾部内容。 Messages []*Message `json:"Messages"` // 流式调用开关。 // 说明: - // 1. 未传值时默认为非流式调用(false)。 + // 1. 未传值时Default为非流式调用(false)。 // 2. 流式调用时以 SSE 协议增量返回结果(返回值取 Choices[n].Delta 中的值,需要拼接增量数据才能获得完整结果)。 // 3. 非流式调用时: - // 调用方式与普通 HTTP 请求无异。 - // 接口响应耗时较长,**如需更低时延建议设置为 true**。 + // 调用方式与普通 HTTP 请求None异。 + // 接口响应耗时较长,**如需更低时延建议Settings为 true**。 // 只返回一次最终结果(返回值取 Choices[n].Message 中的值)。 // - // 注意: + // Note: // 通过 SDK 调用时,流式和非流式调用需用**不同的方式**获取返回值,具体参考 SDK 中的注释或示例(在各语言 SDK 代码仓库的 examples/hunyuan/v20230901/ 目录中)。 Stream *bool `json:"Stream"` // 说明: // 1. 影响输出文本的多样性,取值越大,生成文本的多样性越强。 - // 2. 取值区间为 [0.0, 1.0],未传值时使用各模型推荐值。 + // 2. 取值区间为 [0.0, 1.0],未传值时使用各Model推荐值。 // 3. 非必要不建议使用,不合理的取值会影响效果。 TopP *float64 `json:"TopP"` // 说明: // 1. 较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。 - // 2. 取值区间为 [0.0, 2.0],未传值时使用各模型推荐值。 + // 2. 取值区间为 [0.0, 2.0],未传值时使用各Model推荐值。 // 3. 非必要不建议使用,不合理的取值会影响效果。 Temperature *float64 `json:"Temperature"` } @@ -62,10 +62,10 @@ type ResponseChoices struct { type ChatResponse struct { Choices []ResponseChoices `json:"Choices,omitempty"` // 结果 - Created int64 `json:"Created,omitempty"` // unix 时间戳的字符串 + Created int64 `json:"Created,omitempty"` // unix Time戳的字符串 Id string `json:"Id,omitempty"` // 会话 id Usage Usage `json:"Usage,omitempty"` // token 数量 - Error Error `json:"Error,omitempty"` // 错误信息 注意:此字段可能返回 null,表示取不到有效值 + Error Error `json:"Error,omitempty"` // 错误信息 Note:此字段可能返回 null,表示取不到有效值 Note string `json:"Note,omitempty"` // 注释 ReqID string `json:"Req_id,omitempty"` // 唯一请求 Id,每次请求都会返回。用于反馈接口入参 } diff --git a/relay/billing/billing.go b/relay/billing/billing.go index a99d37ee..6017b1af 100644 --- a/relay/billing/billing.go +++ b/relay/billing/billing.go @@ -31,7 +31,7 @@ func PostConsumeQuota(ctx context.Context, tokenId int, quotaDelta int64, totalQ } // totalQuota is total quota consumed if totalQuota != 0 { - logContent := fmt.Sprintf("模型倍率 %.2f,分组倍率 %.2f", modelRatio, groupRatio) + logContent := fmt.Sprintf("model rate %.2f, group rate %.2f", modelRatio, groupRatio) model.RecordConsumeLog(ctx, userId, channelId, int(totalQuota), 0, modelName, tokenName, totalQuota, logContent) model.UpdateUserUsedQuotaAndRequestCount(userId, totalQuota) model.UpdateChannelUsedQuota(channelId, totalQuota) diff --git a/relay/controller/helper.go b/relay/controller/helper.go index e45e278b..f9d4fd48 100644 --- a/relay/controller/helper.go +++ b/relay/controller/helper.go @@ -125,9 +125,9 @@ func postConsumeQuota(ctx context.Context, usage *relaymodel.Usage, meta *meta.M } var extraLog string if systemPromptReset { - extraLog = " (注意系统提示词已被重置)" + extraLog = " (NoteSystemPrompt词已被重置)" } - logContent := fmt.Sprintf("模型倍率 %.2f,分组倍率 %.2f,补全倍率 %.2f%s", modelRatio, groupRatio, completionRatio, extraLog) + logContent := fmt.Sprintf("model rate %.2f, group rate %.2f, completion rate %.2f%s", modelRatio, groupRatio, completionRatio, extraLog) model.RecordConsumeLog(ctx, meta.UserId, meta.ChannelId, promptTokens, completionTokens, textRequest.Model, meta.TokenName, quota, logContent) model.UpdateUserUsedQuotaAndRequestCount(meta.UserId, quota) model.UpdateChannelUsedQuota(meta.ChannelId, quota) diff --git a/relay/controller/image.go b/relay/controller/image.go index 613fde8b..a3ae3b76 100644 --- a/relay/controller/image.go +++ b/relay/controller/image.go @@ -225,7 +225,7 @@ func RelayImageHelper(c *gin.Context, relayMode int) *relaymodel.ErrorWithStatus } if quota >= 0 { tokenName := c.GetString(ctxkey.TokenName) - logContent := fmt.Sprintf("模型倍率 %.2f,分组倍率 %.2f", modelRatio, groupRatio) + logContent := fmt.Sprintf("model rate %.2f, group rate %.2f", modelRatio, groupRatio) model.RecordConsumeLog(ctx, meta.UserId, meta.ChannelId, 0, 0, imageRequest.Model, tokenName, quota, logContent) model.UpdateUserUsedQuotaAndRequestCount(meta.UserId, quota) channelId := c.GetInt(ctxkey.ChannelId) diff --git a/web/default/public/index.html b/web/default/public/index.html index f22b8843..4e30ff92 100644 --- a/web/default/public/index.html +++ b/web/default/public/index.html @@ -7,7 +7,7 @@ One API diff --git a/web/default/src/App.js b/web/default/src/App.js index 4ece4eeb..bd1b920a 100644 --- a/web/default/src/App.js +++ b/web/default/src/App.js @@ -62,11 +62,11 @@ function App() { process.env.REACT_APP_VERSION !== '' ) { showNotice( - `新版本可用:${data.version},请使用快捷键 Shift + F5 刷新页面` + `New version available: ${data.version}, please refresh the page using the shortcut key Shift + F5` ); } } else { - showError('无法正常连接至服务器!'); + showError('Unable to connect to the server normally!'); } }; diff --git a/web/default/src/components/ChannelsTable.js b/web/default/src/components/ChannelsTable.js index e745814b..38a180d5 100644 --- a/web/default/src/components/ChannelsTable.js +++ b/web/default/src/components/ChannelsTable.js @@ -31,7 +31,7 @@ function renderType(type) { for (let i = 0; i < CHANNEL_OPTIONS.length; i++) { type2label[CHANNEL_OPTIONS[i].value] = CHANNEL_OPTIONS[i]; } - type2label[0] = { value: 0, text: '未知类型', color: 'grey' }; + type2label[0] = { value: 0, text: 'Unknown type', color: 'grey' }; } return ; } @@ -42,7 +42,7 @@ function renderBalance(type, balance) { return ${balance.toFixed(2)}; case 4: // CloseAI return ¥{balance.toFixed(2)}; - case 8: // 自定义 + case 8: // Custom return ${balance.toFixed(2)}; case 5: // OpenAI-SB return ¥{(balance / 10000).toFixed(2)}; @@ -57,7 +57,7 @@ function renderBalance(type, balance) { case 44: // SiliconFlow return ¥{balance.toFixed(2)}; default: - return 不支持; + return Not supported; } } @@ -178,7 +178,7 @@ const ChannelsTable = () => { } const { success, message } = res.data; if (success) { - showSuccess('操作成功完成!'); + showSuccess('Operation successfully completed!'); let channel = res.data.data; let newChannels = [...channels]; let realIdx = (activePage - 1) * ITEMS_PER_PAGE + idx; @@ -196,14 +196,14 @@ const ChannelsTable = () => { const renderStatus = (status) => { switch (status) { case 1: - return ; + return ; case 2: return ( - 已禁用 + Disabled } - content='本渠道被手动禁用' + content='本Channel被手动Disable' basic /> ); @@ -211,16 +211,16 @@ const ChannelsTable = () => { return ( - 已禁用 + Disabled } - content='本渠道被程序自动禁用' + content='本Channel被程序自动Disable' basic /> ); default: return ( ); } @@ -228,9 +228,9 @@ const ChannelsTable = () => { const renderResponseTime = (responseTime) => { let time = responseTime / 1000; - time = time.toFixed(2) + ' 秒'; + time = time.toFixed(2) + 's'; if (responseTime === 0) { - return ; + return ; } else if (responseTime <= 1000) { return ; } else if (responseTime <= 3000) { @@ -277,7 +277,7 @@ const ChannelsTable = () => { newChannels[realIdx].response_time = time * 1000; newChannels[realIdx].test_time = Date.now() / 1000; setChannels(newChannels); - showInfo(`渠道 ${name} 测试成功,模型 ${model},耗时 ${time.toFixed(2)} 秒。`); + showInfo(`Channel ${name} Test成功,Model ${model},耗时 ${time.toFixed(2)}s。`); } else { showError(message); } @@ -292,7 +292,7 @@ const ChannelsTable = () => { const res = await API.get(`/api/channel/test?scope=${scope}`); const { success, message } = res.data; if (success) { - showInfo('已成功开始测试渠道,请刷新页面查看结果。'); + showInfo('已成功开始TestChannel,请Refresh页面查看结果。'); } else { showError(message); } @@ -302,7 +302,7 @@ const ChannelsTable = () => { const res = await API.delete(`/api/channel/disabled`); const { success, message, data } = res.data; if (success) { - showSuccess(`已删除所有禁用渠道,共计 ${data} 个`); + showSuccess(`已Delete所有DisableChannel,共计 ${data} 个`); await refresh(); } else { showError(message); @@ -318,7 +318,7 @@ const ChannelsTable = () => { newChannels[realIdx].balance = balance; newChannels[realIdx].balance_updated_time = Date.now() / 1000; setChannels(newChannels); - showInfo(`渠道 ${name} 余额更新成功!`); + showInfo(`Channel ${name} balance updated successfully!`); } else { showError(message); } @@ -329,7 +329,7 @@ const ChannelsTable = () => { const res = await API.get(`/api/channel/update_balance`); const { success, message } = res.data; if (success) { - showInfo('已更新完毕所有已启用渠道余额!'); + showInfo('The balance of all enabled channels has been updated!'); } else { showError(message); } @@ -368,7 +368,7 @@ const ChannelsTable = () => { icon='search' fluid iconPosition='left' - placeholder='搜索渠道的 ID,名称和密钥 ...' + placeholder='Search for channel ID, name and key ...' value={searchKeyword} loading={searching} onChange={handleKeywordChange} @@ -380,11 +380,11 @@ const ChannelsTable = () => { setShowPrompt(false); setPromptShown(promptID); }}> - OpenAI 渠道已经不再支持通过 key 获取余额,因此余额显示为 0。对于支持的渠道类型,请点击余额进行刷新。 + OpenAI Channel已经不再支持通过 key 获取Balance,因此Balance显示为 0。对于支持的ChannelType,请点击Balance进行Refresh。
- 渠道测试仅支持 chat 模型,优先使用 gpt-3.5-turbo,如果该模型不可用则使用你所配置的模型列表中的第一个模型。 + ChannelTest仅支持 chat Model,优先使用 gpt-3.5-turbo,如果该Model不可用则使用你所配置的Model列表中的第一个Model。
- 点击下方详情按钮可以显示余额以及设置额外的测试模型。 + 点击下方Details按钮可以显示Balance以及Settings额外的TestModel。 ) } @@ -405,7 +405,7 @@ const ChannelsTable = () => { sortChannel('name'); }} > - 名称 + Name { sortChannel('group'); }} > - 分组 + Group { sortChannel('type'); }} > - 类型 + Type { sortChannel('status'); }} > - 状态 + Status { sortChannel('response_time'); }} > - 响应时间 + Response time { }} hidden={!showDetail} > - 余额 + Balance { > 优先级 - - 操作 + + Operation @@ -472,13 +472,13 @@ const ChannelsTable = () => { return ( {channel.id} - {channel.name ? channel.name : '无'} + {channel.name ? channel.name : 'None'} {renderGroup(channel.group)} {renderType(channel.type)} {renderStatus(channel.status)} { }}> } - content='渠道选择优先级,越高越优先' + content='Channel选择优先级,越高越优先' basic /> @@ -592,20 +592,20 @@ const ChannelsTable = () => { {/**/} + {/* loading={loading || updatingBalance}>Update the balance of enabled channels*/} - 删除禁用渠道 + DeleteDisableChannel } on='click' @@ -613,7 +613,7 @@ const ChannelsTable = () => { hoverable > { (channels.length % ITEMS_PER_PAGE === 0 ? 1 : 0) } /> - - + + diff --git a/web/default/src/components/GitHubOAuth.js b/web/default/src/components/GitHubOAuth.js index c43ed2a1..c0f3ac65 100644 --- a/web/default/src/components/GitHubOAuth.js +++ b/web/default/src/components/GitHubOAuth.js @@ -8,7 +8,7 @@ const GitHubOAuth = () => { const [searchParams, setSearchParams] = useSearchParams(); const [userState, userDispatch] = useContext(UserContext); - const [prompt, setPrompt] = useState('处理中...'); + const [prompt, setPrompt] = useState('Processing...'); const [processing, setProcessing] = useState(true); let navigate = useNavigate(); @@ -18,23 +18,23 @@ const GitHubOAuth = () => { const { success, message, data } = res.data; if (success) { if (message === 'bind') { - showSuccess('绑定成功!'); + showSuccess('Binding successful!'); navigate('/setting'); } else { userDispatch({ type: 'login', payload: data }); localStorage.setItem('user', JSON.stringify(data)); - showSuccess('登录成功!'); + showSuccess('Login successful!'); navigate('/'); } } else { showError(message); if (count === 0) { - setPrompt(`操作失败,重定向至登录界面中...`); + setPrompt(`Operation failed, redirecting to login screen...`); navigate('/setting'); // in case this is failed to bind GitHub return; } count++; - setPrompt(`出现错误,第 ${count} 次重试中...`); + setPrompt(`An error occurred, retrying ${count}...`); await new Promise((resolve) => setTimeout(resolve, count * 2000)); await sendCode(code, state, count); } diff --git a/web/default/src/components/Header.js b/web/default/src/components/Header.js index 21ebcab6..091a4b5e 100644 --- a/web/default/src/components/Header.js +++ b/web/default/src/components/Header.js @@ -9,50 +9,50 @@ import '../index.css'; // Header Buttons let headerButtons = [ { - name: '首页', + name: 'Home', to: '/', icon: 'home' }, { - name: '渠道', + name: 'Channel', to: '/channel', icon: 'sitemap', admin: true }, { - name: '令牌', + name: 'API Keys', to: '/token', icon: 'key' }, { - name: '兑换', + name: 'Redeem', to: '/redemption', icon: 'dollar sign', admin: true }, { - name: '充值', + name: 'Recharge', to: '/topup', icon: 'cart' }, { - name: '用户', + name: 'Users', to: '/user', icon: 'user', admin: true }, { - name: '日志', + name: 'Logs', to: '/log', icon: 'book' }, { - name: '设置', + name: 'Settings', to: '/setting', icon: 'setting' }, { - name: '关于', + name: 'About', to: '/about', icon: 'info circle' } @@ -60,7 +60,7 @@ let headerButtons = [ if (localStorage.getItem('chat_link')) { headerButtons.splice(1, 0, { - name: '聊天', + name: 'Chat', to: '/chat', icon: 'comments' }); @@ -77,7 +77,7 @@ const Header = () => { async function logout() { setShowSidebar(false); await API.get('/api/user/logout'); - showSuccess('注销成功!'); + showSuccess('Logout successful!'); userDispatch({ type: 'logout' }); localStorage.removeItem('user'); navigate('/login'); @@ -152,7 +152,7 @@ const Header = () => { {renderButtons(true)} {userState.user ? ( - + ) : ( <> )} @@ -202,12 +202,12 @@ const Header = () => { className='link item' > - 注销 + Log out ) : ( { const [searchParams, setSearchParams] = useSearchParams(); const [userState, userDispatch] = useContext(UserContext); - const [prompt, setPrompt] = useState('处理中...'); + const [prompt, setPrompt] = useState('Processing...'); const [processing, setProcessing] = useState(true); let navigate = useNavigate(); @@ -18,23 +18,23 @@ const LarkOAuth = () => { const { success, message, data } = res.data; if (success) { if (message === 'bind') { - showSuccess('绑定成功!'); + showSuccess('Binding successful!'); navigate('/setting'); } else { userDispatch({ type: 'login', payload: data }); localStorage.setItem('user', JSON.stringify(data)); - showSuccess('登录成功!'); + showSuccess('Login successful!'); navigate('/'); } } else { showError(message); if (count === 0) { - setPrompt(`操作失败,重定向至登录界面中...`); + setPrompt(`Operation failed, redirecting to login screen...`); navigate('/setting'); // in case this is failed to bind lark return; } count++; - setPrompt(`出现错误,第 ${count} 次重试中...`); + setPrompt(`An error occurred, retrying ${count}...`); await new Promise((resolve) => setTimeout(resolve, count * 2000)); await sendCode(code, state, count); } diff --git a/web/default/src/components/Loading.js b/web/default/src/components/Loading.js index 1210a56f..b2cb728d 100644 --- a/web/default/src/components/Loading.js +++ b/web/default/src/components/Loading.js @@ -5,7 +5,7 @@ const Loading = ({ prompt: name = 'page' }) => { return ( - 加载{name}中... + Loading {name}... ); diff --git a/web/default/src/components/LoginForm.js b/web/default/src/components/LoginForm.js index 71566ef8..68a19581 100644 --- a/web/default/src/components/LoginForm.js +++ b/web/default/src/components/LoginForm.js @@ -22,7 +22,7 @@ const LoginForm = () => { useEffect(() => { if (searchParams.get('expired')) { - showError('未登录或登录已过期,请重新登录!'); + showError('Not logged in or login has expired, please log in again!'); } let status = localStorage.getItem('status'); if (status) { @@ -46,7 +46,7 @@ const LoginForm = () => { userDispatch({ type: 'login', payload: data }); localStorage.setItem('user', JSON.stringify(data)); navigate('/'); - showSuccess('登录成功!'); + showSuccess('Login successful!'); setShowWeChatLoginModal(false); } else { showError(message); @@ -71,11 +71,11 @@ const LoginForm = () => { localStorage.setItem('user', JSON.stringify(data)); if (username === 'root' && password === '123456') { navigate('/user/edit'); - showSuccess('登录成功!'); - showWarning('请立刻修改默认密码!'); + showSuccess('Login successful!'); + showWarning('Please change the default password immediately!'); } else { navigate('/token'); - showSuccess('登录成功!'); + showSuccess('Login successful!'); } } else { showError(message); @@ -87,7 +87,7 @@ const LoginForm = () => {
- 用户登录 + User login
@@ -95,7 +95,7 @@ const LoginForm = () => { fluid icon='user' iconPosition='left' - placeholder='用户名 / 邮箱地址' + placeholder='Username / Email address' name='username' value={username} onChange={handleChange} @@ -104,25 +104,25 @@ const LoginForm = () => { fluid icon='lock' iconPosition='left' - placeholder='密码' + placeholder='Password' name='password' type='password' value={password} onChange={handleChange} />
- 忘记密码? + Forget password? - 点击重置 + Click to reset - ; 没有账户? + ; No account? - 点击注册 + Click to register {status.github_oauth || status.wechat_login || status.lark_client_id ? ( @@ -186,13 +186,13 @@ const LoginForm = () => {

- 微信扫码关注公众号,输入「验证码」获取验证码(三分钟内有效) + Scan the QR code with WeChat, follow the official account and enter 'verification code' to get the verification code (valid within three minutes)

{ size='large' onClick={onSubmitWeChatVerificationCode} > - 登录 + Log in diff --git a/web/default/src/components/LogsTable.js b/web/default/src/components/LogsTable.js index 308aff98..813e62fe 100644 --- a/web/default/src/components/LogsTable.js +++ b/web/default/src/components/LogsTable.js @@ -14,30 +14,30 @@ function renderTimestamp(timestamp) { } const MODE_OPTIONS = [ - { key: 'all', text: '全部用户', value: 'all' }, - { key: 'self', text: '当前用户', value: 'self' } + { key: 'all', text: 'All users', value: 'all' }, + { key: 'self', text: 'Current user', value: 'self' } ]; const LOG_OPTIONS = [ - { key: '0', text: '全部', value: 0 }, - { key: '1', text: '充值', value: 1 }, - { key: '2', text: '消费', value: 2 }, - { key: '3', text: '管理', value: 3 }, - { key: '4', text: '系统', value: 4 } + { key: '0', text: 'All', value: 0 }, + { key: '1', text: 'Recharge', value: 1 }, + { key: '2', text: 'Consumption', value: 2 }, + { key: '3', text: 'Management', value: 3 }, + { key: '4', text: 'System', value: 4 } ]; function renderType(type) { switch (type) { case 1: - return ; + return ; case 2: - return ; + return ; case 3: - return ; + return ; case 4: - return ; + return ; default: - return ; + return ; } } @@ -199,34 +199,34 @@ const LogsTable = () => { <>
- 使用明细(总消耗额度: + Usages(Total consumption limit: {showStat && renderQuota(stat.quota)} - {!showStat && 点击查看} + {!showStat && click to view} )
- - + - - - 查询 + Query { isAdminUser && <> - - @@ -243,7 +243,7 @@ const LogsTable = () => { }} width={3} > - 时间 + Time { isAdminUser && { }} width={1} > - 渠道 + Channel } { @@ -264,7 +264,7 @@ const LogsTable = () => { }} width={1} > - 用户 + Users } { }} width={1} > - 令牌 + API Keys { }} width={1} > - 类型 + Type { }} width={2} > - 模型 + Model { }} width={1} > - 提示 + Prompt { }} width={1} > - 补全 + Completion { }} width={isAdminUser ? 4 : 6} > - 详情 + Details @@ -370,7 +370,7 @@ const LogsTable = () => { 填入 } - placeholder='输入自定义模型名称' + placeholder='EnterCustomModel name' value={customModel} onChange={(e, { value }) => { setCustomModel(value); @@ -429,8 +429,8 @@ const EditChannel = () => { inputs.type !== 43 && (<> { { label='User ID' name='user_id' required - placeholder={'生成该密钥的用户 ID'} + placeholder={'生成该Key的Users ID'} onChange={handleConfigChange} value={config.user_id} autoComplete='' @@ -533,10 +533,10 @@ const EditChannel = () => { { inputs.type !== 33 && inputs.type !== 42 && (batch ? { /> : { label='Account ID' name='user_id' required - placeholder={'请输入 Account ID,例如:d8d7c61dbc334c32d3ced580e4bf42b4'} + placeholder={'请Enter Account ID,For example:d8d7c61dbc334c32d3ced580e4bf42b4'} onChange={handleConfigChange} value={config.user_id} autoComplete='' @@ -573,7 +573,7 @@ const EditChannel = () => { inputs.type !== 33 && !isEdit && ( setBatch(!batch)} /> @@ -583,9 +583,9 @@ const EditChannel = () => { inputs.type !== 3 && inputs.type !== 33 && inputs.type !== 8 && inputs.type !== 22 && ( { { ) } - - + +
diff --git a/web/default/src/pages/Channel/index.js b/web/default/src/pages/Channel/index.js index edf668b3..5b2f47c6 100644 --- a/web/default/src/pages/Channel/index.js +++ b/web/default/src/pages/Channel/index.js @@ -5,7 +5,7 @@ import ChannelsTable from '../../components/ChannelsTable'; const Channel = () => ( <> -
管理渠道
+
Manage Channels
diff --git a/web/default/src/pages/Home/index.js b/web/default/src/pages/Home/index.js index 63d6d77a..3dd57392 100644 --- a/web/default/src/pages/Home/index.js +++ b/web/default/src/pages/Home/index.js @@ -37,7 +37,7 @@ const Home = () => { localStorage.setItem('home_page_content', content); } else { showError(message); - setHomePageContent('加载首页内容失败...'); + setHomePageContent('Failed to load homepage content...'); } setHomePageContentLoaded(true); }; @@ -56,18 +56,18 @@ const Home = () => { { homePageContentLoaded && homePageContent === '' ? <> -
系统状况
+
System status
- 系统信息 - 系统信息总览 + System information + System information overview -

名称:{statusState?.status?.system_name}

-

版本:{statusState?.status?.version ? statusState?.status?.version : "unknown"}

+

Name:{statusState?.status?.system_name}

+

Version:{statusState?.status?.version ? statusState?.status?.version : "unknown"}

- 源码: + Source code: { https://github.com/songquanpeng/one-api

-

启动时间:{getStartTimeString()}

+

Startup time:{getStartTimeString()}

@@ -83,32 +83,32 @@ const Home = () => { - 系统配置 - 系统配置总览 + System configuration + System configuration overview

- 邮箱验证: + Email verification: {statusState?.status?.email_verification === true - ? '已启用' - : '未启用'} + ? 'Enabled' + : 'Not enabled'}

- GitHub 身份验证: + GitHub Authentication: {statusState?.status?.github_oauth === true - ? '已启用' - : '未启用'} + ? 'Enabled' + : 'Not enabled'}

- 微信身份验证: + WeChat Authentication: {statusState?.status?.wechat_login === true - ? '已启用' - : '未启用'} + ? 'Enabled' + : 'Not enabled'}

- Turnstile 用户校验: + Turnstile user verification: {statusState?.status?.turnstile_check === true - ? '已启用' - : '未启用'} + ? 'Enabled' + : 'Not enabled'}

diff --git a/web/default/src/pages/NotFound/index.js b/web/default/src/pages/NotFound/index.js index f92dbc90..013bf6ce 100644 --- a/web/default/src/pages/NotFound/index.js +++ b/web/default/src/pages/NotFound/index.js @@ -4,8 +4,8 @@ import { Message } from 'semantic-ui-react'; const NotFound = () => ( <> - 页面不存在 -

请检查你的浏览器地址是否正确

+ Page does not exist +

Please check if your browser address is correct

); diff --git a/web/default/src/pages/Redemption/EditRedemption.js b/web/default/src/pages/Redemption/EditRedemption.js index 7a33f770..31db9109 100644 --- a/web/default/src/pages/Redemption/EditRedemption.js +++ b/web/default/src/pages/Redemption/EditRedemption.js @@ -58,9 +58,9 @@ const EditRedemption = () => { const { success, message, data } = res.data; if (success) { if (isEdit) { - showSuccess('兑换码更新成功!'); + showSuccess('Redemption code updated successfully!'); } else { - showSuccess('兑换码创建成功!'); + showSuccess('Redemption code created successfully!'); setInputs(originInputs); } } else { @@ -78,13 +78,13 @@ const EditRedemption = () => { return ( <> -
{isEdit ? '更新兑换码信息' : '创建新的兑换码'}
+
{isEdit ? 'Update redemption code information' : 'Create a new redemption code'}
{ { !isEdit && <> { } - - + +
diff --git a/web/default/src/pages/Redemption/index.js b/web/default/src/pages/Redemption/index.js index c0649412..879584c2 100644 --- a/web/default/src/pages/Redemption/index.js +++ b/web/default/src/pages/Redemption/index.js @@ -5,7 +5,7 @@ import RedemptionsTable from '../../components/RedemptionsTable'; const Redemption = () => ( <> -
管理兑换码
+
Manage Redeem Codes
diff --git a/web/default/src/pages/Setting/index.js b/web/default/src/pages/Setting/index.js index 30d0ef28..e77bb472 100644 --- a/web/default/src/pages/Setting/index.js +++ b/web/default/src/pages/Setting/index.js @@ -9,7 +9,7 @@ import OperationSetting from '../../components/OperationSetting'; const Setting = () => { let panes = [ { - menuItem: '个人设置', + menuItem: 'Personal settings', render: () => ( @@ -20,7 +20,7 @@ const Setting = () => { if (isRoot()) { panes.push({ - menuItem: '运营设置', + menuItem: 'Operations settings', render: () => ( @@ -28,7 +28,7 @@ const Setting = () => { ) }); panes.push({ - menuItem: '系统设置', + menuItem: 'System settings', render: () => ( @@ -36,7 +36,7 @@ const Setting = () => { ) }); panes.push({ - menuItem: '其他设置', + menuItem: 'Other settings', render: () => ( diff --git a/web/default/src/pages/Token/EditToken.js b/web/default/src/pages/Token/EditToken.js index 684b7e92..f13a8a69 100644 --- a/web/default/src/pages/Token/EditToken.js +++ b/web/default/src/pages/Token/EditToken.js @@ -95,7 +95,7 @@ const EditToken = () => { if (localInputs.expired_time !== -1) { let time = Date.parse(localInputs.expired_time); if (isNaN(time)) { - showError('过期时间格式错误!'); + showError('Expiration time format error!'); return; } localInputs.expired_time = Math.ceil(time / 1000); @@ -110,9 +110,9 @@ const EditToken = () => { const { success, message } = res.data; if (success) { if (isEdit) { - showSuccess('令牌更新成功!'); + showSuccess('Token updated successfully!'); } else { - showSuccess('令牌创建成功,请在列表页面点击复制获取令牌!'); + showSuccess('Token created successfully, please click copy on the list page to get the token!'); setInputs(originInputs); } } else { @@ -123,13 +123,13 @@ const EditToken = () => { return ( <> -
{isEdit ? '更新令牌信息' : '创建新的令牌'}
+
{isEdit ? 'Update key information' : 'Create a new key'}
{ { { {
+ }}>Never expires + }}>Expires after one month + }}>Expires after one day + }}>Expires after one hour + }}>Expires after one minute
- 注意,令牌的额度仅用于限制令牌本身的最大额度使用量,实际的使用受到账户的剩余额度限制。 + Note that the quota of the token is only used to limit the maximum quota usage of the token itself, and the actual usage is limited by the remaining quota of the account. { - - + }}>{unlimited_quota ? 'Cancel unlimited quota' : 'Set to unlimited quota'} + +
diff --git a/web/default/src/pages/Token/index.js b/web/default/src/pages/Token/index.js index c995131e..0e3e9385 100644 --- a/web/default/src/pages/Token/index.js +++ b/web/default/src/pages/Token/index.js @@ -5,7 +5,7 @@ import TokensTable from '../../components/TokensTable'; const Token = () => ( <> -
我的令牌
+
My keys
diff --git a/web/default/src/pages/TopUp/index.js b/web/default/src/pages/TopUp/index.js index 2fcf0eae..ffaa129e 100644 --- a/web/default/src/pages/TopUp/index.js +++ b/web/default/src/pages/TopUp/index.js @@ -12,7 +12,7 @@ const TopUp = () => { const topUp = async () => { if (redemptionCode === '') { - showInfo('请输入充值码!') + showInfo('Please enter the recharge code!') return; } setIsSubmitting(true); @@ -22,7 +22,7 @@ const TopUp = () => { }); const { success, message, data } = res.data; if (success) { - showSuccess('充值成功!'); + showSuccess('Recharge successful!'); setUserQuota((quota) => { return quota + data; }); @@ -31,7 +31,7 @@ const TopUp = () => { showError(message); } } catch (err) { - showError('请求失败'); + showError('Request failed'); } finally { setIsSubmitting(false); } @@ -39,7 +39,7 @@ const TopUp = () => { const openTopUpLink = () => { if (!topUpLink) { - showError('超级管理员未设置充值链接!'); + showError('The super administrator did not set a recharge link!'); return; } let url = new URL(topUpLink); @@ -76,12 +76,12 @@ const TopUp = () => { return ( -
充值额度
+
Recharge quota
{ @@ -89,10 +89,10 @@ const TopUp = () => { }} />
@@ -100,7 +100,7 @@ const TopUp = () => { {renderQuota(userQuota)} - 剩余额度 + Remaining quota
diff --git a/web/default/src/pages/User/AddUser.js b/web/default/src/pages/User/AddUser.js index f9f4bc18..4fa7b72b 100644 --- a/web/default/src/pages/User/AddUser.js +++ b/web/default/src/pages/User/AddUser.js @@ -20,7 +20,7 @@ const AddUser = () => { const res = await API.post(`/api/user/`, inputs); const { success, message } = res.data; if (success) { - showSuccess('用户账户创建成功!'); + showSuccess('User account created successfully!'); setInputs(originInputs); } else { showError(message); @@ -30,13 +30,13 @@ const AddUser = () => { return ( <> -
创建新用户账户
+
Create new user account
{ { { />
diff --git a/web/default/src/pages/User/EditUser.js b/web/default/src/pages/User/EditUser.js index 8ae0e556..6556407c 100644 --- a/web/default/src/pages/User/EditUser.js +++ b/web/default/src/pages/User/EditUser.js @@ -76,7 +76,7 @@ const EditUser = () => { } const { success, message } = res.data; if (success) { - showSuccess('用户信息更新成功!'); + showSuccess('User information updated successfully!'); } else { showError(message); } @@ -85,13 +85,13 @@ const EditUser = () => { return ( <> -
更新用户信息
+
Update user information
{ { { userId && <> { { } - - + +
diff --git a/web/default/src/pages/User/index.js b/web/default/src/pages/User/index.js index 29f7437a..dfdf7a85 100644 --- a/web/default/src/pages/User/index.js +++ b/web/default/src/pages/User/index.js @@ -5,7 +5,7 @@ import UsersTable from '../../components/UsersTable'; const User = () => ( <> -
管理用户
+
Manage Users