mengstack-api/internal/kernel/i18n/i18n.go
MengStack Dev df809f1045
Some checks failed
CI / Build & Test (push) Failing after 1m31s
feat: user CRUD API + dashboard stats + kernel infrastructure
- Add user management endpoints (list/create/get/update/delete) with pagination and search
- Add dashboard stats endpoint with tenant/user/online counts and growth metrics
- Add tenant resolver middleware for multi-tenant request scoping
- Add i18n kernel with zh/en message files and AcceptLanguage middleware
- Add WebSocket hub/handler for real-time communication
- Add job scheduler kernel with cron support
- Add plugin sandbox for isolated execution
- Add storage kernel (local filesystem)
- Add event bus kernel for pub/sub
- Add cache kernel abstraction
- Add database migration runner and version upgrade checker
- Add rate limiting middleware with Redis backend
- Add SQL migrations for rbac, audit_logs, settings, notifications, examples
- Extend user repository with list/delete/count operations
- Register all module routes with tenant resolver
2026-10-03 03:42:58 +08:00

82 lines
1.4 KiB
Go

package i18n
import (
"encoding/json"
"fmt"
"io/fs"
"sync"
)
var (
mu sync.RWMutex
messages map[string]map[string]string
fallback string
)
func Init(fsys fs.FS, defaultLang string) error {
mu.Lock()
defer mu.Unlock()
messages = make(map[string]map[string]string)
fallback = defaultLang
entries, err := fs.ReadDir(fsys, ".")
if err != nil {
return fmt.Errorf("i18n: read messages dir: %w", err)
}
for _, e := range entries {
if e.IsDir() {
continue
}
data, err := fs.ReadFile(fsys, e.Name())
if err != nil {
return fmt.Errorf("i18n: read %s: %w", e.Name(), err)
}
lang := langFromFilename(e.Name())
kv := make(map[string]string)
if err := json.Unmarshal(data, &kv); err != nil {
return fmt.Errorf("i18n: parse %s: %w", e.Name(), err)
}
messages[lang] = kv
}
return nil
}
func T(lang, key string) string {
mu.RLock()
defer mu.RUnlock()
if msgs, ok := messages[lang]; ok {
if v, ok := msgs[key]; ok {
return v
}
}
if msgs, ok := messages[fallback]; ok {
if v, ok := msgs[key]; ok {
return v
}
}
return key
}
func SupportedLanguages() []string {
mu.RLock()
defer mu.RUnlock()
out := make([]string, 0, len(messages))
for k := range messages {
out = append(out, k)
}
return out
}
func langFromFilename(name string) string {
for i, c := range name {
if c == '.' {
return name[:i]
}
}
return name
}