mirror of
https://github.com/songquanpeng/one-api.git
synced 2025-11-11 10:53:42 +08:00
Merge branch 'upstream/main'
This commit is contained in:
@@ -140,10 +140,10 @@ var ValidThemes = map[string]bool{
|
||||
// All duration's unit is seconds
|
||||
// Shouldn't larger then RateLimitKeyExpirationDuration
|
||||
var (
|
||||
GlobalApiRateLimitNum = env.Int("GLOBAL_API_RATE_LIMIT", 240)
|
||||
GlobalApiRateLimitNum = env.Int("GLOBAL_API_RATE_LIMIT", 480)
|
||||
GlobalApiRateLimitDuration int64 = 3 * 60
|
||||
|
||||
GlobalWebRateLimitNum = env.Int("GLOBAL_WEB_RATE_LIMIT", 120)
|
||||
GlobalWebRateLimitNum = env.Int("GLOBAL_WEB_RATE_LIMIT", 240)
|
||||
GlobalWebRateLimitDuration int64 = 3 * 60
|
||||
|
||||
UploadRateLimitNum = 10
|
||||
|
||||
72
common/i18n/i18n.go
Normal file
72
common/i18n/i18n.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
//go:embed locales/*.json
|
||||
var localesFS embed.FS
|
||||
|
||||
var (
|
||||
translations = make(map[string]map[string]string)
|
||||
defaultLang = "en"
|
||||
ContextKey = "i18n"
|
||||
)
|
||||
|
||||
// Init loads all translation files from embedded filesystem
|
||||
func Init() error {
|
||||
entries, err := localesFS.ReadDir("locales")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".json") {
|
||||
continue
|
||||
}
|
||||
|
||||
langCode := strings.TrimSuffix(entry.Name(), ".json")
|
||||
content, err := localesFS.ReadFile("locales/" + entry.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var translation map[string]string
|
||||
if err := json.Unmarshal(content, &translation); err != nil {
|
||||
return err
|
||||
}
|
||||
translations[langCode] = translation
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetLang(c *gin.Context) string {
|
||||
rawLang, ok := c.Get(ContextKey)
|
||||
if !ok {
|
||||
return defaultLang
|
||||
}
|
||||
lang, _ := rawLang.(string)
|
||||
if lang != "" {
|
||||
return lang
|
||||
}
|
||||
return defaultLang
|
||||
}
|
||||
|
||||
func Translate(c *gin.Context, message string) string {
|
||||
lang := GetLang(c)
|
||||
return translateHelper(lang, message)
|
||||
}
|
||||
|
||||
func translateHelper(lang, message string) string {
|
||||
if trans, ok := translations[lang]; ok {
|
||||
if translated, exists := trans[message]; exists {
|
||||
return translated
|
||||
}
|
||||
}
|
||||
return message
|
||||
}
|
||||
5
common/i18n/locales/en.json
Normal file
5
common/i18n/locales/en.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"invalid_input": "Invalid input, please check your input",
|
||||
"send_email_failed": "failed to send email: ",
|
||||
"invalid_parameter": "invalid parameter"
|
||||
}
|
||||
5
common/i18n/locales/zh-CN.json
Normal file
5
common/i18n/locales/zh-CN.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"invalid_input": "无效的输入,请检查您的输入",
|
||||
"send_email_failed": "发送邮件失败:",
|
||||
"invalid_parameter": "无效的参数"
|
||||
}
|
||||
@@ -57,6 +57,14 @@ func SysLogf(format string, a ...any) {
|
||||
logHelper(nil, loggerINFO, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func SysWarn(s string) {
|
||||
logHelper(nil, loggerWarn, s)
|
||||
}
|
||||
|
||||
func SysWarnf(format string, a ...any) {
|
||||
logHelper(nil, loggerWarn, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func SysError(s string) {
|
||||
logHelper(nil, loggerError, s)
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/songquanpeng/one-api/common/config"
|
||||
"net"
|
||||
"net/smtp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/songquanpeng/one-api/common/config"
|
||||
"github.com/songquanpeng/one-api/common/logger"
|
||||
)
|
||||
|
||||
func shouldAuth() bool {
|
||||
@@ -99,8 +101,12 @@ func SendEmail(subject string, receiver string, content string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = smtp.SendMail(addr, auth, config.SMTPAccount, to, mail)
|
||||
return nil
|
||||
}
|
||||
err = smtp.SendMail(addr, auth, config.SMTPAccount, to, mail)
|
||||
if err != nil && strings.Contains(err.Error(), "short response") { // 部分提供商返回该错误,但实际上邮件已经发送成功
|
||||
logger.SysWarnf("short response from SMTP server, return nil instead of error: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
34
common/message/template.go
Normal file
34
common/message/template.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package message
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/songquanpeng/one-api/common/config"
|
||||
)
|
||||
|
||||
// EmailTemplate 生成美观的 HTML 邮件内容
|
||||
func EmailTemplate(title, content string) string {
|
||||
return fmt.Sprintf(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
</head>
|
||||
<body style="margin: 0; padding: 20px; font-family: Arial, sans-serif; line-height: 1.6; background-color: #f4f4f4;">
|
||||
<div style="max-width: 600px; margin: 20px auto; padding: 30px; background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">
|
||||
<div style="text-align: center; margin-bottom: 30px;">
|
||||
<h2 style="color: #333; margin: 0; font-size: 24px;">%s</h2>
|
||||
</div>
|
||||
<div style="color: #555; font-size: 16px;">
|
||||
%s
|
||||
</div>
|
||||
<div style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #eee; color: #888; font-size: 14px; text-align: center;">
|
||||
<p style="margin: 5px 0;">此邮件由系统自动发送,请勿直接回复</p>
|
||||
<p style="margin: 5px 0;">%s</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`, title, content, config.SystemName)
|
||||
}
|
||||
Reference in New Issue
Block a user