mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 10:42:57 +00:00
386 lines
9.9 KiB
Go
386 lines
9.9 KiB
Go
package controllers
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"fotbal-club/internal/models"
|
|
"fotbal-club/pkg/database"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// I18nController handles internationalization endpoints
|
|
type I18nController struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewI18nController creates a new i18n controller
|
|
func NewI18nController() *I18nController {
|
|
return &I18nController{
|
|
db: database.GetDB(),
|
|
}
|
|
}
|
|
|
|
// GetLanguages returns all active languages
|
|
func (ctrl *I18nController) GetLanguages(c *gin.Context) {
|
|
languages, err := models.GetActiveLanguages(ctrl.db)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch languages"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"languages": languages,
|
|
})
|
|
}
|
|
|
|
// GetTranslations returns translations for a specific language
|
|
func (ctrl *I18nController) GetTranslations(c *gin.Context) {
|
|
languageCode := c.Param("language")
|
|
context := c.Query("context") // optional context filter
|
|
|
|
var translations []models.Translation
|
|
query := ctrl.db.Where("language_code = ?", languageCode)
|
|
|
|
if context != "" {
|
|
query = query.Where("context = ?", context)
|
|
}
|
|
|
|
err := query.Order("key ASC").Find(&translations).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch translations"})
|
|
return
|
|
}
|
|
|
|
// Convert to key-value map for easier frontend consumption
|
|
result := make(map[string]string)
|
|
for _, t := range translations {
|
|
result[t.Key] = t.Value
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"translations": result,
|
|
"language": languageCode,
|
|
"context": context,
|
|
})
|
|
}
|
|
|
|
// SetUserLanguage sets user's preferred language
|
|
func (ctrl *I18nController) SetUserLanguage(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
LanguageCode string `json:"language_code" binding:"required"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// Validate language
|
|
var lang models.Language
|
|
err := ctrl.db.Where("code = ? AND is_active = ?", req.LanguageCode, true).First(&lang).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid language code"})
|
|
return
|
|
}
|
|
|
|
// Update or create user preference
|
|
var pref models.UserLanguagePreference
|
|
err = ctrl.db.Where("user_id = ?", userID).First(&pref).Error
|
|
|
|
if err == gorm.ErrRecordNotFound {
|
|
// Create new preference
|
|
pref = models.UserLanguagePreference{
|
|
UserID: userID.(uint),
|
|
LanguageCode: req.LanguageCode,
|
|
}
|
|
err = ctrl.db.Create(&pref).Error
|
|
} else {
|
|
// Update existing preference
|
|
pref.LanguageCode = req.LanguageCode
|
|
err = ctrl.db.Save(&pref).Error
|
|
}
|
|
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save language preference"})
|
|
return
|
|
}
|
|
|
|
// Set cookie
|
|
c.SetCookie("lang", req.LanguageCode, 365*24*60*60, "/", "", false, true)
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"message": "Language preference saved",
|
|
"language": req.LanguageCode,
|
|
})
|
|
}
|
|
|
|
// AdminGetAllLanguages returns all languages (including inactive) for admin
|
|
func (ctrl *I18nController) AdminGetAllLanguages(c *gin.Context) {
|
|
var languages []models.Language
|
|
err := ctrl.db.Order("sort_order ASC, name ASC").Find(&languages).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch languages"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"languages": languages})
|
|
}
|
|
|
|
// AdminCreateLanguage creates a new language
|
|
func (ctrl *I18nController) AdminCreateLanguage(c *gin.Context) {
|
|
var req struct {
|
|
ID string `json:"id" binding:"required"`
|
|
Name string `json:"name" binding:"required"`
|
|
NativeName string `json:"native_name" binding:"required"`
|
|
Code string `json:"code" binding:"required"`
|
|
IsDefault bool `json:"is_default"`
|
|
IsActive bool `json:"is_default"`
|
|
SortOrder int `json:"sort_order"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// If setting as default, unset other defaults
|
|
if req.IsDefault {
|
|
ctrl.db.Model(&models.Language{}).Where("is_default = ?", true).Update("is_default", false)
|
|
}
|
|
|
|
language := models.Language{
|
|
ID: req.ID,
|
|
Name: req.Name,
|
|
NativeName: req.NativeName,
|
|
Code: req.Code,
|
|
IsDefault: req.IsDefault,
|
|
IsActive: req.IsActive,
|
|
SortOrder: req.SortOrder,
|
|
}
|
|
|
|
err := ctrl.db.Create(&language).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create language"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{"language": language})
|
|
}
|
|
|
|
// AdminUpdateLanguage updates a language
|
|
func (ctrl *I18nController) AdminUpdateLanguage(c *gin.Context) {
|
|
id := c.Param("id")
|
|
|
|
var req struct {
|
|
Name string `json:"name"`
|
|
NativeName string `json:"native_name"`
|
|
Code string `json:"code"`
|
|
IsDefault bool `json:"is_default"`
|
|
IsActive bool `json:"is_active"`
|
|
SortOrder int `json:"sort_order"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
var language models.Language
|
|
err := ctrl.db.Where("id = ?", id).First(&language).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "Language not found"})
|
|
return
|
|
}
|
|
|
|
// If setting as default, unset other defaults
|
|
if req.IsDefault && !language.IsDefault {
|
|
ctrl.db.Model(&models.Language{}).Where("is_default = ?", true).Update("is_default", false)
|
|
}
|
|
|
|
// Update fields
|
|
if req.Name != "" {
|
|
language.Name = req.Name
|
|
}
|
|
if req.NativeName != "" {
|
|
language.NativeName = req.NativeName
|
|
}
|
|
if req.Code != "" {
|
|
language.Code = req.Code
|
|
}
|
|
language.IsDefault = req.IsDefault
|
|
language.IsActive = req.IsActive
|
|
if req.SortOrder != 0 {
|
|
language.SortOrder = req.SortOrder
|
|
}
|
|
|
|
err = ctrl.db.Save(&language).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update language"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"language": language})
|
|
}
|
|
|
|
// AdminDeleteLanguage deletes a language
|
|
func (ctrl *I18nController) AdminDeleteLanguage(c *gin.Context) {
|
|
id := c.Param("id")
|
|
|
|
var language models.Language
|
|
err := ctrl.db.Where("id = ?", id).First(&language).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "Language not found"})
|
|
return
|
|
}
|
|
|
|
// Don't allow deletion of default language
|
|
if language.IsDefault {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Cannot delete default language"})
|
|
return
|
|
}
|
|
|
|
err = ctrl.db.Delete(&language).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete language"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Language deleted"})
|
|
}
|
|
|
|
// AdminGetTranslations returns translations for admin
|
|
func (ctrl *I18nController) AdminGetTranslations(c *gin.Context) {
|
|
languageCode := c.Query("language")
|
|
context := c.Query("context")
|
|
page := c.DefaultQuery("page", "1")
|
|
limit := c.DefaultQuery("limit", "100")
|
|
|
|
pageInt, _ := strconv.Atoi(page)
|
|
limitInt, _ := strconv.Atoi(limit)
|
|
offset := (pageInt - 1) * limitInt
|
|
|
|
var translations []models.Translation
|
|
var total int64
|
|
|
|
query := ctrl.db.Model(&models.Translation{})
|
|
|
|
if languageCode != "" {
|
|
query = query.Where("language_code = ?", languageCode)
|
|
}
|
|
if context != "" {
|
|
query = query.Where("context = ?", context)
|
|
}
|
|
|
|
// Count total
|
|
query.Count(&total)
|
|
|
|
// Get paginated results
|
|
err := query.Preload("Language").Order("key ASC, language_code ASC").
|
|
Limit(limitInt).Offset(offset).Find(&translations).Error
|
|
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch translations"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"translations": translations,
|
|
"total": total,
|
|
"page": pageInt,
|
|
"limit": limitInt,
|
|
})
|
|
}
|
|
|
|
// AdminCreateTranslation creates a new translation
|
|
func (ctrl *I18nController) AdminCreateTranslation(c *gin.Context) {
|
|
var req struct {
|
|
Key string `json:"key" binding:"required"`
|
|
LanguageCode string `json:"language_code" binding:"required"`
|
|
Value string `json:"value" binding:"required"`
|
|
Context string `json:"context"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
translation := models.Translation{
|
|
Key: req.Key,
|
|
LanguageCode: req.LanguageCode,
|
|
Value: req.Value,
|
|
Context: req.Context,
|
|
}
|
|
|
|
err := ctrl.db.Create(&translation).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create translation"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{"translation": translation})
|
|
}
|
|
|
|
// AdminUpdateTranslation updates a translation
|
|
func (ctrl *I18nController) AdminUpdateTranslation(c *gin.Context) {
|
|
id := c.Param("id")
|
|
|
|
var req struct {
|
|
Key string `json:"key"`
|
|
Value string `json:"value"`
|
|
Context string `json:"context"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
var translation models.Translation
|
|
err := ctrl.db.Where("id = ?", id).First(&translation).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "Translation not found"})
|
|
return
|
|
}
|
|
|
|
if req.Key != "" {
|
|
translation.Key = req.Key
|
|
}
|
|
if req.Value != "" {
|
|
translation.Value = req.Value
|
|
}
|
|
if req.Context != "" {
|
|
translation.Context = req.Context
|
|
}
|
|
|
|
err = ctrl.db.Save(&translation).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update translation"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"translation": translation})
|
|
}
|
|
|
|
// AdminDeleteTranslation deletes a translation
|
|
func (ctrl *I18nController) AdminDeleteTranslation(c *gin.Context) {
|
|
id := c.Param("id")
|
|
|
|
err := ctrl.db.Delete(&models.Translation{}, id).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete translation"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Translation deleted"})
|
|
}
|