mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
163 lines
6.1 KiB
Go
163 lines
6.1 KiB
Go
package domain
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Localizable defines an interface for entities that support localization
|
|
type Localizable interface {
|
|
GetEntityType() string
|
|
GetEntityID() string
|
|
}
|
|
|
|
// EntityLoadOptions contains options for loading entities for localization
|
|
type EntityLoadOptions struct {
|
|
IncludeAllSites bool
|
|
}
|
|
|
|
// EntityHandler defines the interface for handling entity-specific operations for localization
|
|
// This interface is implemented by handlers in the localization/handlers package
|
|
type EntityHandler[T any] interface {
|
|
// GetEntityID returns the unique identifier for an entity
|
|
GetEntityID(entity T) string
|
|
|
|
// GetFieldValue returns the value of a specific field from an entity
|
|
GetFieldValue(entity T, field string) string
|
|
|
|
// GetLocalizableFields returns the list of fields that can be localized
|
|
GetLocalizableFields() []string
|
|
|
|
// LoadEntities loads entities from the database with optional filtering
|
|
LoadEntities(db *gorm.DB, options EntityLoadOptions) ([]T, error)
|
|
|
|
// BuildFieldQuery builds a GORM query for finding entities with specific field values
|
|
BuildFieldQuery(db *gorm.DB, field, value string) *gorm.DB
|
|
|
|
// GetEntityType returns the entity type string
|
|
GetEntityType() string
|
|
}
|
|
|
|
// Localization represents localized strings for any entity and field
|
|
type Localization struct {
|
|
ID string `gorm:"primaryKey;type:text"`
|
|
EntityType string `gorm:"type:varchar(50);index"` // 'site', 'organization', 'business', 'user'
|
|
EntityID string `gorm:"type:text;index"`
|
|
Field string `gorm:"type:varchar(50);index"` // 'name', 'description'
|
|
Locale string `gorm:"type:varchar(10);index"` // 'ru', 'en', 'tt'
|
|
Value string `gorm:"type:text"`
|
|
|
|
// Timestamps
|
|
CreatedAt time.Time `gorm:"autoCreateTime"`
|
|
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
|
}
|
|
|
|
// TableName specifies the table name for GORM
|
|
func (Localization) TableName() string {
|
|
return "localizations"
|
|
}
|
|
|
|
// LocalizationService provides methods for managing localized content
|
|
type LocalizationService interface {
|
|
GetLocalizedValue(entityType, entityID, field, locale string) (string, error)
|
|
SetLocalizedValue(entityType, entityID, field, locale, value string) error
|
|
GetAllLocalizedValues(entityType, entityID string) (map[string]map[string]string, error) // field -> locale -> value
|
|
GetLocalizedEntity(entityType, entityID, locale string) (map[string]string, error)
|
|
GetSupportedLocalesForEntity(entityType, entityID string) ([]string, error)
|
|
DeleteLocalizedValue(entityType, entityID, field, locale string) error
|
|
BulkSetLocalizedValues(entityType, entityID string, values map[string]map[string]string) error
|
|
GetAllLocales() ([]string, error)
|
|
SearchLocalizations(query, locale string, limit int) ([]*Localization, error)
|
|
ApplyLocalizationToEntity(entity Localizable, locale string) error
|
|
}
|
|
|
|
// Helper methods for models to implement Localizable
|
|
func (s *Site) GetEntityType() string { return "site" }
|
|
func (s *Site) GetEntityID() string { return s.ID }
|
|
|
|
func (o *Organization) GetEntityType() string { return "organization" }
|
|
func (o *Organization) GetEntityID() string { return o.ID }
|
|
|
|
func (u *User) GetEntityType() string { return "user" }
|
|
func (u *User) GetEntityID() string { return u.ID }
|
|
|
|
// GetLocalizedName retrieves the localized name for an entity, falling back to primary name
|
|
func GetLocalizedName(entity Localizable, locale string, service LocalizationService) string {
|
|
if locale == "ru" {
|
|
// Return primary name for Russian
|
|
switch e := entity.(type) {
|
|
case *Site:
|
|
return e.Name
|
|
case *Organization:
|
|
return e.Name
|
|
case *User:
|
|
return e.Name
|
|
}
|
|
}
|
|
|
|
// Try to get localized value
|
|
value, err := service.GetLocalizedValue(entity.GetEntityType(), entity.GetEntityID(), "name", locale)
|
|
if err != nil || value == "" {
|
|
// Fallback to primary name
|
|
switch e := entity.(type) {
|
|
case *Site:
|
|
return e.Name
|
|
case *Organization:
|
|
return e.Name
|
|
case *User:
|
|
return e.Name
|
|
}
|
|
}
|
|
return value
|
|
}
|
|
|
|
// SetLocalizedName sets the localized name for an entity
|
|
func SetLocalizedName(entity Localizable, locale, value string, service LocalizationService) error {
|
|
return service.SetLocalizedValue(entity.GetEntityType(), entity.GetEntityID(), "name", locale, value)
|
|
}
|
|
|
|
// TranslationStats represents overall translation statistics
|
|
type TranslationStats struct {
|
|
TotalEntities int
|
|
TotalFields int
|
|
TotalTranslations int
|
|
EntityStats map[string]*EntityTranslationStats
|
|
}
|
|
|
|
// EntityTranslationStats represents translation statistics for a specific entity type
|
|
type EntityTranslationStats struct {
|
|
EntityType string
|
|
TotalEntities int
|
|
TotalFields int
|
|
RussianCount int
|
|
EnglishCount int
|
|
TatarCount int
|
|
TotalTranslations int
|
|
}
|
|
|
|
type LocalizationRepository interface {
|
|
Create(ctx context.Context, loc *Localization) error
|
|
GetByEntityAndField(ctx context.Context, entityType, entityID, field, locale string) (*Localization, error)
|
|
GetAllByEntity(ctx context.Context, entityType, entityID string) ([]*Localization, error)
|
|
Update(ctx context.Context, loc *Localization) error
|
|
Delete(ctx context.Context, id string) error
|
|
GetByEntityTypeAndLocale(ctx context.Context, entityType, locale string) ([]*Localization, error)
|
|
GetAllLocales(ctx context.Context) ([]string, error)
|
|
GetSupportedLocalesForEntity(ctx context.Context, entityType, entityID string) ([]string, error)
|
|
BulkCreate(ctx context.Context, localizations []*Localization) error
|
|
BulkDelete(ctx context.Context, ids []string) error
|
|
SearchLocalizations(ctx context.Context, query string, locale string, limit int) ([]*Localization, error)
|
|
GetTranslationReuseCandidates(ctx context.Context, entityType, field, locale string) ([]ReuseCandidate, error)
|
|
GetEntitiesNeedingTranslation(ctx context.Context, entityType, field, targetLocale string, limit int) ([]string, error)
|
|
FindExistingTranslationByRussianText(ctx context.Context, entityType, field, targetLocale, russianText string) (string, error)
|
|
GetTranslationCountsByEntity(ctx context.Context) (map[string]map[string]int, error)
|
|
}
|
|
|
|
// ReuseCandidate represents a piece of Russian text that appears in multiple entities
|
|
type ReuseCandidate struct {
|
|
RussianValue string
|
|
EntityCount int
|
|
}
|