mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 10:42:57 +00:00
182 lines
4.7 KiB
Go
182 lines
4.7 KiB
Go
package middleware
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"fotbal-club/internal/models"
|
|
"fotbal-club/pkg/database"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// I18nMiddleware handles internationalization
|
|
type I18nMiddleware struct {
|
|
db *gorm.DB
|
|
defaultLang *models.Language
|
|
}
|
|
|
|
// NewI18nMiddleware creates a new i18n middleware
|
|
func NewI18nMiddleware() (*I18nMiddleware, error) {
|
|
db := database.GetDB()
|
|
|
|
// Get default language
|
|
defaultLang, err := models.GetDefaultLanguage(db)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &I18nMiddleware{
|
|
db: db,
|
|
defaultLang: defaultLang,
|
|
}, nil
|
|
}
|
|
|
|
// Middleware returns the Gin middleware function
|
|
func (m *I18nMiddleware) Middleware() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
// Try to get language from various sources in priority order
|
|
|
|
// 1. User preference (if authenticated)
|
|
if userID, exists := c.Get("user_id"); exists {
|
|
if userPref, err := m.getUserLanguage(userID.(uint)); err == nil {
|
|
c.Set("language", userPref.LanguageCode)
|
|
c.Set("language_name", userPref.Language.Name)
|
|
c.Next()
|
|
return
|
|
}
|
|
}
|
|
|
|
// 2. URL parameter (?lang=en)
|
|
if lang := c.Query("lang"); lang != "" && m.isValidLanguage(lang) {
|
|
c.Set("language", lang)
|
|
c.Set("language_name", m.getLanguageName(lang))
|
|
c.Next()
|
|
return
|
|
}
|
|
|
|
// 3. Cookie
|
|
if cookie, err := c.Cookie("lang"); err == nil && m.isValidLanguage(cookie) {
|
|
c.Set("language", cookie)
|
|
c.Set("language_name", m.getLanguageName(cookie))
|
|
c.Next()
|
|
return
|
|
}
|
|
|
|
// 4. Accept-Language header
|
|
if header := c.GetHeader("Accept-Language"); header != "" {
|
|
if lang := m.parseAcceptLanguage(header); lang != "" {
|
|
c.Set("language", lang)
|
|
c.Set("language_name", m.getLanguageName(lang))
|
|
c.Next()
|
|
return
|
|
}
|
|
}
|
|
|
|
// 5. Default language
|
|
c.Set("language", m.defaultLang.Code)
|
|
c.Set("language_name", m.defaultLang.Name)
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// getUserLanguage gets user's preferred language from database
|
|
func (m *I18nMiddleware) getUserLanguage(userID uint) (*models.UserLanguagePreference, error) {
|
|
var pref models.UserLanguagePreference
|
|
err := m.db.Where("user_id = ?", userID).Preload("Language").First(&pref).Error
|
|
return &pref, err
|
|
}
|
|
|
|
// isValidLanguage checks if language code is valid and active
|
|
func (m *I18nMiddleware) isValidLanguage(code string) bool {
|
|
var count int64
|
|
m.db.Model(&models.Language{}).Where("code = ? AND is_active = ?", code, true).Count(&count)
|
|
return count > 0
|
|
}
|
|
|
|
// getLanguageName returns the name of a language
|
|
func (m *I18nMiddleware) getLanguageName(code string) string {
|
|
var lang models.Language
|
|
err := m.db.Where("code = ?", code).First(&lang).Error
|
|
if err != nil {
|
|
return m.defaultLang.Name
|
|
}
|
|
return lang.Name
|
|
}
|
|
|
|
// parseAcceptLanguage parses Accept-Language header and returns best match
|
|
func (m *I18nMiddleware) parseAcceptLanguage(header string) string {
|
|
// Simple implementation - split by comma and take first
|
|
// In production, you'd want to parse q-values
|
|
langs := strings.Split(header, ",")
|
|
for _, lang := range langs {
|
|
lang = strings.TrimSpace(strings.Split(lang, ";")[0])
|
|
// Convert en-US to en, de-DE to de, etc.
|
|
if len(lang) > 2 {
|
|
lang = lang[:2]
|
|
}
|
|
if m.isValidLanguage(lang) {
|
|
return lang
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetLanguage returns the current language code from context
|
|
func GetLanguage(c *gin.Context) string {
|
|
if lang, exists := c.Get("language"); exists {
|
|
return lang.(string)
|
|
}
|
|
return "cs" // fallback to Czech
|
|
}
|
|
|
|
// GetLanguageName returns the current language name from context
|
|
func GetLanguageName(c *gin.Context) string {
|
|
if name, exists := c.Get("language_name"); exists {
|
|
return name.(string)
|
|
}
|
|
return "Čeština"
|
|
}
|
|
|
|
// SetLanguageCookie sets the language preference in a cookie
|
|
func SetLanguageCookie(c *gin.Context, languageCode string) {
|
|
c.SetCookie("lang", languageCode, 365*24*60*60, "/", "", false, true)
|
|
}
|
|
|
|
// TranslationHelper provides translation functions
|
|
type TranslationHelper struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewTranslationHelper creates a new translation helper
|
|
func NewTranslationHelper() *TranslationHelper {
|
|
return &TranslationHelper{
|
|
db: database.GetDB(),
|
|
}
|
|
}
|
|
|
|
// T translates a key using the current language context
|
|
func (th *TranslationHelper) T(c *gin.Context, key string) string {
|
|
lang := GetLanguage(c)
|
|
|
|
translation, err := models.GetTranslationWithFallback(th.db, key, lang)
|
|
if err != nil {
|
|
// Return key if translation not found
|
|
return key
|
|
}
|
|
|
|
return translation.Value
|
|
}
|
|
|
|
// TWithParams translates a key with parameters
|
|
func (th *TranslationHelper) TWithParams(c *gin.Context, key string, params map[string]interface{}) string {
|
|
result := th.T(c, key)
|
|
|
|
// Simple parameter replacement
|
|
for k, v := range params {
|
|
result = strings.ReplaceAll(result, "{{"+k+"}}", v.(string))
|
|
}
|
|
|
|
return result
|
|
}
|