Skip to content

Commit edde459

Browse files
committed
i18n: Fixing some non-internationalized label
1 parent 9813373 commit edde459

24 files changed

+431
-192
lines changed

cmd/server/main.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func serveStaticFile(c *gin.Context, fsys fs.FS, fileName, contentType string) {
5454
}
5555

5656
// parseFlags 解析命令行参数并处理基础配置
57-
func parseFlags() (resetPwd bool, port, certFile, keyFile string, showVersion, disableLogin, sseDebugLog, disableSSELog bool) {
57+
func parseFlags() (resetPwd bool, port, certFile, keyFile string, showVersion, disableLogin, sseDebugLog, disableSSELog, demoMode bool) {
5858
// 命令行参数处理
5959
resetPwdCmd := flag.Bool("resetpwd", false, "重置管理员密码")
6060
portFlag := flag.String("port", "", "HTTP 服务端口 (优先级高于环境变量 PORT),默认 3000")
@@ -70,6 +70,8 @@ func parseFlags() (resetPwd bool, port, certFile, keyFile string, showVersion, d
7070
sseDebugLogFlag := flag.Bool("sse-debug-log", false, "启用 SSE 消息调试日志")
7171
// 禁用 SSE 日志记录参数
7272
disableSSELogFlag := flag.Bool("disable-sse-log", false, "禁用 SSE 日志记录到文件")
73+
// Demo 模式参数
74+
demoModeFlag := flag.Bool("demo", false, "启用演示模式(默认密码为 Np123456. 并每天自动重置)")
7375

7476
flag.Parse()
7577

@@ -131,7 +133,16 @@ func parseFlags() (resetPwd bool, port, certFile, keyFile string, showVersion, d
131133
}
132134
}
133135

134-
return *resetPwdCmd, port, certFile, keyFile, *versionFlag || *vFlag, disableLogin, sseDebugLog, disableSSELog
136+
// 设置 Demo 模式配置
137+
// 优先级:命令行参数 > 环境变量
138+
demoMode = *demoModeFlag
139+
if !demoMode {
140+
if env := os.Getenv("DEMO_MODE"); env == "true" || env == "1" {
141+
demoMode = true
142+
}
143+
}
144+
145+
return *resetPwdCmd, port, certFile, keyFile, *versionFlag || *vFlag, disableLogin, sseDebugLog, disableSSELog, demoMode
135146
}
136147

137148
// setupStaticFiles 配置静态文件服务
@@ -201,14 +212,21 @@ func setupStaticFiles(ginRouter *gin.Engine) error {
201212
}
202213

203214
// initializeServices 初始化所有服务
204-
func initializeServices(sseDebugLog, disableSSELog bool) (*gorm.DB, *auth.Service, *endpoint.Service, *tunnel.Service, *dashboard.Service, *sse.Service, *sse.Manager, *websocket.Service, error) {
215+
func initializeServices(sseDebugLog, disableSSELog, demoMode bool) (*gorm.DB, *auth.Service, *endpoint.Service, *tunnel.Service, *dashboard.Service, *sse.Service, *sse.Manager, *websocket.Service, error) {
205216
// 获取GORM数据库连接
206217
gormDB := dbPkg.GetDB()
207218
log.Info("数据库连接成功")
208219

209220
// 系统初始化(首次启动输出初始用户名和密码) - 在所有其他初始化之前
210221
authService := auth.NewService(gormDB)
211-
if _, _, err := authService.InitializeSystem(); err != nil && err.Error() != "系统已初始化" {
222+
223+
// 如果启用 Demo 模式,需要在系统初始化前设置
224+
if demoMode {
225+
authService.SetDemoMode(true)
226+
log.Info("🎭 Demo 模式已启用")
227+
}
228+
229+
if _, _, err := authService.InitializeSystem(); err != nil && err.Error() != "system is already initialized" {
212230
log.Errorf("系统初始化失败: %v", err)
213231
}
214232

@@ -349,7 +367,7 @@ func gracefulShutdown(server *http.Server, trafficScheduler *dashboard.TrafficSc
349367
}
350368

351369
func main() {
352-
resetPwd, port, certFile, keyFile, showVersion, disableLogin, sseDebugLog, disableSSELog := parseFlags()
370+
resetPwd, port, certFile, keyFile, showVersion, disableLogin, sseDebugLog, disableSSELog, demoMode := parseFlags()
353371

354372
// 如果指定了版本参数,显示版本信息后退出
355373
if showVersion {
@@ -371,7 +389,7 @@ func main() {
371389
}
372390

373391
// 初始化所有服务
374-
gormDB, authService, endpointService, tunnelService, dashboardService, sseService, sseManager, wsService, err := initializeServices(sseDebugLog, disableSSELog)
392+
gormDB, authService, endpointService, tunnelService, dashboardService, sseService, sseManager, wsService, err := initializeServices(sseDebugLog, disableSSELog, demoMode)
375393
if err != nil {
376394
log.Errorf("服务初始化失败: %v", err)
377395
return
@@ -415,6 +433,12 @@ func main() {
415433
}
416434
}
417435

436+
// 设置并启动 Demo 模式定时任务
437+
if demoMode {
438+
// 启动定时任务(每天凌晨重置密码)
439+
authService.StartDemoModeScheduler()
440+
}
441+
418442
// 启动SSE系统
419443
if err := sseManager.InitializeSystem(); err != nil {
420444
log.Errorf("初始化SSE系统失败: %v", err)

internal/api/sse.go

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (h *SSEHandler) HandleTunnelSSE(c *gin.Context) {
7373
clientID := uuid.New().String()
7474

7575
// 发送连接成功消息(使用标准SSE格式)
76-
c.Writer.Write([]byte("data: " + `{"type":"connected","message":"连接成功"}` + "\n\n"))
76+
c.Writer.Write([]byte("data: " + `{"type":"connected","message":"Connected"}` + "\n\n"))
7777
c.Writer.Flush()
7878

7979
// log.Infof("前端请求隧道SSE订阅,tunnelID=%s clientID=%s remote=%s", tunnelID, clientID, c.ClientIP())
@@ -101,12 +101,12 @@ func (h *SSEHandler) HandleTestSSEEndpoint(c *gin.Context) {
101101
APIKey string `json:"apiKey"`
102102
}
103103
if err := c.ShouldBindJSON(&req); err != nil {
104-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "无效的JSON"})
104+
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "Invalid JSON"})
105105
return
106106
}
107107

108108
if req.URL == "" || req.APIPath == "" || req.APIKey == "" {
109-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "缺少必要参数"})
109+
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "Missing required parameters"})
110110
return
111111
}
112112

@@ -127,35 +127,35 @@ func (h *SSEHandler) HandleTestSSEEndpoint(c *gin.Context) {
127127

128128
request, err := http.NewRequestWithContext(ctx, http.MethodGet, sseURL, nil)
129129
if err != nil {
130-
h.loggerErrorGin(c, "构建请求失败", err)
130+
h.loggerErrorGin(c, "Failed to create request", err)
131131
return
132132
}
133133
request.Header.Set("X-API-Key", req.APIKey)
134134
request.Header.Set("Accept", "text/event-stream")
135135

136136
resp, err := client.Do(request)
137137
if err != nil {
138-
h.loggerErrorGin(c, "连接失败", err)
138+
h.loggerErrorGin(c, "Connection failed", err)
139139
return
140140
}
141141
defer resp.Body.Close()
142142

143143
if resp.StatusCode != http.StatusOK {
144-
msg := fmt.Sprintf("NodePass SSE返回状态码: %d", resp.StatusCode)
144+
msg := fmt.Sprintf("NodePass SSE returned status code: %d", resp.StatusCode)
145145
h.writeErrorGin(c, msg)
146146
return
147147
}
148148

149149
// 简单验证 Content-Type
150150
if ct := resp.Header.Get("Content-Type"); ct != "text/event-stream" && ct != "text/event-stream; charset=utf-8" {
151-
h.writeErrorGin(c, "响应Content-Type不是SSE流")
151+
h.writeErrorGin(c, "Response Content-Type is not SSE stream")
152152
return
153153
}
154154

155155
// 成功
156156
c.JSON(http.StatusOK, gin.H{
157157
"success": true,
158-
"message": "连接测试成功",
158+
"message": "Connection test successful",
159159
"details": gin.H{
160160
"url": req.URL,
161161
"apiPath": req.APIPath,
@@ -229,7 +229,7 @@ func (h *SSEHandler) updateLogCleanupConfig(c *gin.Context) {
229229
if err := c.ShouldBindJSON(&req); err != nil {
230230
c.JSON(http.StatusBadRequest, gin.H{
231231
"success": false,
232-
"error": "请求格式错误: " + err.Error(),
232+
"error": "Invalid request format: " + err.Error(),
233233
})
234234
return
235235
}
@@ -253,7 +253,7 @@ func (h *SSEHandler) updateLogCleanupConfig(c *gin.Context) {
253253
if interval, err := time.ParseDuration(*req.CleanupInterval); err != nil {
254254
c.JSON(http.StatusBadRequest, gin.H{
255255
"success": false,
256-
"error": "清理间隔格式错误: " + err.Error(),
256+
"error": "Invalid cleanup interval format: " + err.Error(),
257257
})
258258
return
259259
} else {
@@ -293,23 +293,23 @@ func (h *SSEHandler) updateLogCleanupConfig(c *gin.Context) {
293293
if retentionDays < 1 {
294294
c.JSON(http.StatusBadRequest, gin.H{
295295
"success": false,
296-
"error": "保留天数必须大于0",
296+
"error": "Retention days must be greater than 0",
297297
})
298298
return
299299
}
300300

301301
if cleanupInterval < time.Hour {
302302
c.JSON(http.StatusBadRequest, gin.H{
303303
"success": false,
304-
"error": "清理间隔不能小于1小时",
304+
"error": "Cleanup interval cannot be less than 1 hour",
305305
})
306306
return
307307
}
308308

309309
if maxRecordsPerDay < 0 {
310310
c.JSON(http.StatusBadRequest, gin.H{
311311
"success": false,
312-
"error": "每日最大记录数不能为负数",
312+
"error": "Max records per day cannot be negative",
313313
})
314314
return
315315
}
@@ -319,7 +319,7 @@ func (h *SSEHandler) updateLogCleanupConfig(c *gin.Context) {
319319

320320
c.JSON(http.StatusOK, gin.H{
321321
"success": true,
322-
"message": "日志清理配置已更新",
322+
"message": "Log cleanup configuration updated",
323323
"data": gin.H{
324324
"retentionDays": retentionDays,
325325
"cleanupInterval": cleanupInterval.String(),
@@ -337,7 +337,7 @@ func (h *SSEHandler) HandleTriggerLogCleanup(c *gin.Context) {
337337

338338
c.JSON(http.StatusOK, gin.H{
339339
"success": true,
340-
"message": "日志清理任务已启动,将在后台执行",
340+
"message": "Log cleanup task started, will execute in background",
341341
})
342342
}
343343

@@ -350,12 +350,12 @@ func (h *SSEHandler) HandleTestSSEEndpointWithVersion(c *gin.Context) {
350350
APIKey string `json:"apiKey"`
351351
}
352352
if err := c.ShouldBindJSON(&req); err != nil {
353-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "无效的JSON"})
353+
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "Invalid JSON"})
354354
return
355355
}
356356

357357
if req.URL == "" || req.APIPath == "" || req.APIKey == "" {
358-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "缺少必要参数"})
358+
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "Missing required parameters"})
359359
return
360360
}
361361

@@ -375,28 +375,28 @@ func (h *SSEHandler) HandleTestSSEEndpointWithVersion(c *gin.Context) {
375375

376376
request, err := http.NewRequestWithContext(ctx, http.MethodGet, sseURL, nil)
377377
if err != nil {
378-
h.loggerErrorGin(c, "构建请求失败", err)
378+
h.loggerErrorGin(c, "Failed to create request", err)
379379
return
380380
}
381381
request.Header.Set("X-API-Key", req.APIKey)
382382
request.Header.Set("Accept", "text/event-stream")
383383

384384
resp, err := client.Do(request)
385385
if err != nil {
386-
h.loggerErrorGin(c, "连接失败", err)
386+
h.loggerErrorGin(c, "Connection failed", err)
387387
return
388388
}
389389
defer resp.Body.Close()
390390

391391
if resp.StatusCode != http.StatusOK {
392-
msg := fmt.Sprintf("NodePass SSE返回状态码: %d", resp.StatusCode)
392+
msg := fmt.Sprintf("NodePass SSE returned status code: %d", resp.StatusCode)
393393
h.writeErrorGin(c, msg)
394394
return
395395
}
396396

397397
// 简单验证 Content-Type
398398
if ct := resp.Header.Get("Content-Type"); ct != "text/event-stream" && ct != "text/event-stream; charset=utf-8" {
399-
h.writeErrorGin(c, "响应Content-Type不是SSE流")
399+
h.writeErrorGin(c, "Response Content-Type is not SSE stream")
400400
return
401401
}
402402

@@ -419,7 +419,7 @@ func (h *SSEHandler) HandleTestSSEEndpointWithVersion(c *gin.Context) {
419419
"connected": true,
420420
"version": "unknown",
421421
"canAdd": false,
422-
"message": "连接成功但无法获取版本信息,可能是低版本主控(< 1.10.0",
422+
"message": "Connected successfully but cannot get version info, possibly an older version controller (< 1.10.0)",
423423
})
424424
return
425425
}
@@ -519,7 +519,7 @@ func (h *SSEHandler) HandleNodePassSSEProxy(c *gin.Context) {
519519
c.Header("Access-Control-Allow-Origin", "*")
520520

521521
// 发送连接成功消息
522-
fmt.Fprintf(c.Writer, "data: %s\n\n", `{"type":"connected","message":"NodePass SSE代理连接成功"}`)
522+
fmt.Fprintf(c.Writer, "data: %s\n\n", `{"type":"connected","message":"NodePass SSE proxy connected successfully"}`)
523523
c.Writer.Flush()
524524

525525
// 构造NodePass SSE URL
@@ -543,7 +543,7 @@ func (h *SSEHandler) HandleNodePassSSEProxy(c *gin.Context) {
543543
request, err := http.NewRequestWithContext(ctx, http.MethodGet, sseURL, nil)
544544
if err != nil {
545545
log.Errorf("[NodePass SSE Proxy] 创建请求失败: %v", err)
546-
fmt.Fprintf(c.Writer, "data: %s\n\n", `{"type":"error","message":"创建请求失败"}`)
546+
fmt.Fprintf(c.Writer, "data: %s\n\n", `{"type":"error","message":"Failed to create request"}`)
547547
c.Writer.Flush()
548548
return
549549
}
@@ -557,15 +557,15 @@ func (h *SSEHandler) HandleNodePassSSEProxy(c *gin.Context) {
557557
resp, err := client.Do(request)
558558
if err != nil {
559559
log.Errorf("[NodePass SSE Proxy] 连接失败: %v", err)
560-
fmt.Fprintf(c.Writer, "data: %s\n\n", `{"type":"error","message":"连接NodePass失败"}`)
560+
fmt.Fprintf(c.Writer, "data: %s\n\n", `{"type":"error","message":"Failed to connect to NodePass"}`)
561561
c.Writer.Flush()
562562
return
563563
}
564564
defer resp.Body.Close()
565565

566566
if resp.StatusCode != http.StatusOK {
567567
log.Errorf("[NodePass SSE Proxy] NodePass返回状态码: %d", resp.StatusCode)
568-
fmt.Fprintf(c.Writer, "data: %s\n\n", fmt.Sprintf(`{"type":"error","message":"NodePass返回状态码: %d"}`, resp.StatusCode))
568+
fmt.Fprintf(c.Writer, "data: %s\n\n", fmt.Sprintf(`{"type":"error","message":"NodePass returned status code: %d"}`, resp.StatusCode))
569569
c.Writer.Flush()
570570
return
571571
}
@@ -574,7 +574,7 @@ func (h *SSEHandler) HandleNodePassSSEProxy(c *gin.Context) {
574574
contentType := resp.Header.Get("Content-Type")
575575
if !strings.Contains(contentType, "text/event-stream") {
576576
log.Errorf("[NodePass SSE Proxy] 无效的Content-Type: %s", contentType)
577-
fmt.Fprintf(c.Writer, "data: %s\n\n", `{"type":"error","message":"无效的Content-Type"}`)
577+
fmt.Fprintf(c.Writer, "data: %s\n\n", `{"type":"error","message":"Invalid Content-Type"}`)
578578
c.Writer.Flush()
579579
return
580580
}
@@ -615,7 +615,7 @@ func (h *SSEHandler) HandleNodePassSSEProxy(c *gin.Context) {
615615

616616
if err := scanner.Err(); err != nil {
617617
log.Errorf("[NodePass SSE Proxy] 读取响应失败: %v", err)
618-
fmt.Fprintf(c.Writer, "data: %s\n\n", `{"type":"error","message":"读取响应失败"}`)
618+
fmt.Fprintf(c.Writer, "data: %s\n\n", `{"type":"error","message":"Failed to read response"}`)
619619
c.Writer.Flush()
620620
}
621621

internal/auth/models.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const (
4040

4141
// 默认账号密码常量
4242
const (
43-
DefaultAdminUsername = "nodepass"
44-
DefaultAdminPassword = "Np123456"
43+
DefaultAdminUsername = "nodepass"
44+
DefaultAdminPassword = "Np123456"
45+
DemoModeAdminPassword = "Np123456." // Demo 模式专用密码
4546
)

0 commit comments

Comments
 (0)