137 lines
3.6 KiB
Go
137 lines
3.6 KiB
Go
package localization
|
|
|
|
import (
|
|
"RenewCMS/internal/domain/language"
|
|
"regexp"
|
|
"slices"
|
|
"strings"
|
|
)
|
|
|
|
var socialLocalePattern = regexp.MustCompile(`^([A-Za-z]{2,3})_([A-Za-z]{2})$`)
|
|
|
|
func NormalizeSocialLocale(tag string, social *string) (*string, error) {
|
|
if social == nil {
|
|
return nil, nil
|
|
}
|
|
parts := socialLocalePattern.FindStringSubmatch(*social)
|
|
if parts == nil {
|
|
return nil, ErrInvalidSocialLocale
|
|
}
|
|
tagLanguage, _, _ := strings.Cut(tag, "-")
|
|
if !strings.EqualFold(parts[1], tagLanguage) {
|
|
return nil, ErrInvalidSocialLocale
|
|
}
|
|
normalized := strings.ToLower(parts[1]) + "_" + strings.ToUpper(parts[2])
|
|
return &normalized, nil
|
|
}
|
|
|
|
func SocialLocaleState(row Row) string {
|
|
if row.SocialLocale != nil {
|
|
return SocialLocaleSet
|
|
}
|
|
if _, region, found := strings.Cut(row.Tag, "-"); found && region != "" {
|
|
return SocialLocaleDerived
|
|
}
|
|
return SocialLocaleNotSet
|
|
}
|
|
|
|
func EffectiveSocialLocale(row Row) *string {
|
|
switch SocialLocaleState(row) {
|
|
case SocialLocaleSet:
|
|
return row.SocialLocale
|
|
case SocialLocaleDerived:
|
|
derived := strings.Replace(row.Tag, "-", "_", 1)
|
|
return &derived
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func normalizeEntries(entries []Entry) ([]Entry, error) {
|
|
normalized := make([]Entry, 0, len(entries))
|
|
seen := map[string]bool{}
|
|
for _, entry := range entries {
|
|
tag, err := language.Normalize(entry.Tag)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if seen[tag] {
|
|
return nil, ErrDuplicateLanguage
|
|
}
|
|
seen[tag] = true
|
|
social, err := NormalizeSocialLocale(tag, entry.SocialLocale)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
normalized = append(normalized, Entry{Tag: tag, Enabled: entry.Enabled, SocialLocale: social})
|
|
}
|
|
return normalized, nil
|
|
}
|
|
|
|
func Plan(current []Row, counts map[string]VersionCount, change Change) ([]Row, error) {
|
|
entries, err := normalizeEntries(change.Languages)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !slices.ContainsFunc(entries, func(entry Entry) bool { return entry.Enabled }) {
|
|
return nil, ErrNoEnabledLanguage
|
|
}
|
|
defaultTag, err := language.Normalize(change.Default)
|
|
if err != nil || !slices.ContainsFunc(entries, func(entry Entry) bool { return entry.Tag == defaultTag && entry.Enabled }) {
|
|
return nil, ErrDefaultNotEnabled
|
|
}
|
|
confirmed := map[string]bool{}
|
|
for _, row := range current {
|
|
confirmed[row.Tag] = row.Confirmed
|
|
if !slices.ContainsFunc(entries, func(entry Entry) bool { return entry.Tag == row.Tag }) && counts[row.Tag].Total+counts[row.Tag].Trashed > 0 {
|
|
return nil, ErrLanguageInUse
|
|
}
|
|
}
|
|
next := make([]Row, 0, len(entries))
|
|
for _, entry := range entries {
|
|
isDefault := entry.Tag == defaultTag
|
|
next = append(next, Row{Tag: entry.Tag, IsDefault: isDefault, Enabled: entry.Enabled, Confirmed: confirmed[entry.Tag] || isDefault, SocialLocale: entry.SocialLocale})
|
|
}
|
|
return next, nil
|
|
}
|
|
|
|
func EnabledTag(rows []Row, tag string) bool {
|
|
return slices.ContainsFunc(rows, func(row Row) bool { return row.Tag == tag && row.Enabled })
|
|
}
|
|
|
|
func HasRow(rows []Row, tag string) bool {
|
|
return slices.ContainsFunc(rows, func(row Row) bool { return row.Tag == tag })
|
|
}
|
|
|
|
func MissingTags(rows []Row, tags []string) []string {
|
|
missing := []string{}
|
|
for _, tag := range tags {
|
|
if tag != language.Unassigned && !EnabledTag(rows, tag) && !slices.Contains(missing, tag) {
|
|
missing = append(missing, tag)
|
|
}
|
|
}
|
|
slices.Sort(missing)
|
|
return missing
|
|
}
|
|
|
|
func DefaultTag(rows []Row) string {
|
|
for _, row := range rows {
|
|
if row.IsDefault {
|
|
return row.Tag
|
|
}
|
|
}
|
|
return language.Unassigned
|
|
}
|
|
|
|
func CompareTags(defaultTag string, left string, right string) int {
|
|
if left == right {
|
|
return 0
|
|
}
|
|
if left == defaultTag {
|
|
return -1
|
|
}
|
|
if right == defaultTag {
|
|
return 1
|
|
}
|
|
return strings.Compare(left, right)
|
|
}
|