mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 18:52:56 +00:00
hot fix #1
This commit is contained in:
@@ -0,0 +1,385 @@
|
||||
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"})
|
||||
}
|
||||
Reference in New Issue
Block a user