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
{
>
优先级
- 测试模型
- 操作
+ TestModel
+ 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
/>
{
testChannel(channel.id, channel.name, idx, channel.test_model);
}}
>
- 测试
+ Test
{/**/}
- 删除
+ Delete
}
on='click'
@@ -559,7 +559,7 @@ const ChannelsTable = () => {
manageChannel(channel.id, 'delete', idx);
}}
>
- 删除渠道 {channel.name}
+ Delete channel {channel.name}
@@ -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
- 忘记密码?
+ 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)
@@ -296,7 +296,7 @@ const RedemptionsTable = () => {
{
async function handleSubmit(e) {
if (password.length < 8) {
- showInfo('密码长度不得小于 8 位!');
+ showInfo('Password length must not be less than 8 characters!');
return;
}
if (password !== password2) {
- showInfo('两次输入的密码不一致');
+ showInfo('The two passwords entered do not match');
return;
}
if (username && password) {
if (turnstileEnabled && turnstileToken === '') {
- showInfo('请稍后几秒重试,Turnstile 正在检查用户环境!');
+ showInfo('Please try again in a few seconds, Turnstile is checking the user environment!');
return;
}
setLoading(true);
@@ -70,7 +70,7 @@ const RegisterForm = () => {
const { success, message } = res.data;
if (success) {
navigate('/login');
- showSuccess('注册成功!');
+ showSuccess('Registration successful!');
} else {
showError(message);
}
@@ -81,7 +81,7 @@ const RegisterForm = () => {
const sendVerificationCode = async () => {
if (inputs.email === '') return;
if (turnstileEnabled && turnstileToken === '') {
- showInfo('请稍后几秒重试,Turnstile 正在检查用户环境!');
+ showInfo('Please try again in a few seconds, Turnstile is checking the user environment!');
return;
}
setLoading(true);
@@ -90,7 +90,7 @@ const RegisterForm = () => {
);
const { success, message } = res.data;
if (success) {
- showSuccess('验证码发送成功,请检查你的邮箱!');
+ showSuccess('Verification code sent successfully, please check your email!');
} else {
showError(message);
}
@@ -101,7 +101,7 @@ const RegisterForm = () => {
- 新用户注册
+ New User Registration
- 已有账户?
+ Already have an account?
- 点击登录
+ Click to log in
diff --git a/web/default/src/components/SystemSetting.js b/web/default/src/components/SystemSetting.js
index 7eeae92e..0f049b70 100644
--- a/web/default/src/components/SystemSetting.js
+++ b/web/default/src/components/SystemSetting.js
@@ -260,25 +260,25 @@ const SystemSetting = () => {
- 更新服务器地址
+ Update Server Address
- 配置登录注册
+ Configure Login/Registration
@@ -292,10 +292,10 @@ const SystemSetting = () => {
>
警告
-
取消密码登录将导致所有未绑定其他登录方式的用户(包括管理员)无法通过密码登录,确认取消?
+
Canceling password login will cause all users (including administrators) who have not bound other login methods to be unable to log in via password, confirm cancel?
-
+
- 保存 Message Pusher 设置
+ 保存 Message Pusher Settings
- 配置 Turnstile
+ Configure Turnstile
- 用以支持用户校验,
+ To support user verification,
- 点击此处
+ Click here
- 管理你的 Turnstile Sites,推荐选择 Invisible Widget Type
+ Manage your Turnstile Sites, recommend selecting Invisible Widget Type
@@ -620,7 +620,7 @@ const SystemSetting = () => {
onChange={handleInputChange}
autoComplete='new-password'
value={inputs.TurnstileSiteKey}
- placeholder='输入你注册的 Turnstile Site Key'
+ placeholder='Enter your registered Turnstile Site Key'
/>
{
type='password'
autoComplete='new-password'
value={inputs.TurnstileSecretKey}
- placeholder='敏感信息不会发送到前端显示'
+ placeholder='Sensitive information will not be displayed in the frontend'
/>
- 保存 Turnstile 设置
+ Save Turnstile Settings
diff --git a/web/default/src/components/TokensTable.js b/web/default/src/components/TokensTable.js
index 9b772b22..13d333ac 100644
--- a/web/default/src/components/TokensTable.js
+++ b/web/default/src/components/TokensTable.js
@@ -30,15 +30,15 @@ function renderTimestamp(timestamp) {
function renderStatus(status) {
switch (status) {
case 1:
- return ;
+ return ;
case 2:
- return ;
+ return ;
case 3:
- return ;
+ return ;
case 4:
- return ;
+ return ;
default:
- return ;
+ return ;
}
}
@@ -122,9 +122,9 @@ const TokensTable = () => {
url = `sk-${key}`;
}
if (await copy(url)) {
- showSuccess('已复制到剪贴板!');
+ showSuccess('Copied to clipboard!');
} else {
- showWarning('无法复制到剪贴板,请手动复制,已将令牌填入搜索框。');
+ showWarning('Unable to copy to clipboard, please copy manually, the token has been entered into the search box。');
setSearchKeyword(url);
}
};
@@ -195,7 +195,7 @@ const TokensTable = () => {
}
const { success, message } = res.data;
if (success) {
- showSuccess('操作成功完成!');
+ showSuccess('Operation successfully completed!');
let token = res.data.data;
let newTokens = [...tokens];
let realIdx = (activePage - 1) * ITEMS_PER_PAGE + idx;
@@ -266,7 +266,7 @@ const TokensTable = () => {
icon='search'
fluid
iconPosition='left'
- placeholder='搜索令牌的名称 ...'
+ placeholder='Search for the name of the token...'
value={searchKeyword}
loading={searching}
onChange={handleKeywordChange}
@@ -282,7 +282,7 @@ const TokensTable = () => {
sortToken('name');
}}
>
- 名称
+ Name
{
sortToken('status');
}}
>
- 状态
+ Status
{
sortToken('used_quota');
}}
>
- 已用额度
+ Used quota
{
sortToken('remain_quota');
}}
>
- 剩余额度
+ Remaining quota
{
sortToken('created_time');
}}
>
- 创建时间
+ Creation time
{
sortToken('expired_time');
}}
>
- 过期时间
+ Expiration time
- 操作
+ Operation
@@ -338,12 +338,12 @@ const TokensTable = () => {
if (token.deleted) return <>>;
return (
- {token.name ? token.name : '无'}
+ {token.name ? token.name : 'None'}{renderStatus(token.status)}{renderQuota(token.used_quota)}
- {token.unlimited_quota ? '无限制' : renderQuota(token.remain_quota, 2)}
+ {token.unlimited_quota ? 'Unlimited' : renderQuota(token.remain_quota, 2)}{renderTimestamp(token.created_time)}
- {token.expired_time === -1 ? '永不过期' : renderTimestamp(token.expired_time)}
+ {token.expired_time === -1 ? 'Never expires' : renderTimestamp(token.expired_time)}