Some checks failed
CI / Build & Test (push) Failing after 1m31s
- 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
82 lines
1.4 KiB
Go
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
|
|
}
|