Merge remote-tracking branch 'origin/main' into front-styles

This commit is contained in:
2026-04-13 08:22:35 +02:00
114 changed files with 3000 additions and 543 deletions

View File

@@ -90,13 +90,24 @@ func (s *ProductTranslationService) GetProductDescription(userID uint, productID
// Updates relevant fields with the "updates" map
func (s *ProductTranslationService) SaveProductDescription(userID uint, productID uint, productLangID uint, updates map[string]string) error {
// only some fields can be affected
allowedFields := []string{"description", "description_short", "meta_description", "meta_title", "name", "available_now", "available_later", "usage"}
allowedFields := []string{"description", "description_short", "link_rewrite", "meta_description", "meta_keywords", "meta_title", "name",
"available_now", "available_later", "delivery_in_stock", "delivery_out_stock", "usage"}
for key := range updates {
if !slices.Contains(allowedFields, key) {
return responseErrors.ErrBadField
}
}
if text, exists := updates["link_rewrite"]; exists {
// sanitize and check that link_rewrite is a valid url slug
sanitized := SanitizeSlug(text)
if !IsValidSlug(sanitized) {
return responseErrors.ErrInvalidURLSlug
}
updates["link_rewrite"] = sanitized
}
// check that fields description, description_short and usage, if they exist, have a valid html format
mustBeHTML := []string{"description", "description_short", "usage"}
for i := 0; i < len(mustBeHTML); i++ {
@@ -138,20 +149,28 @@ func (s *ProductTranslationService) TranslateProductDescription(userID uint, pro
fields := []*string{&productDescription.Description,
&productDescription.DescriptionShort,
&productDescription.LinkRewrite,
&productDescription.MetaDescription,
&productDescription.MetaKeywords,
&productDescription.MetaTitle,
&productDescription.Name,
&productDescription.AvailableNow,
&productDescription.AvailableLater,
&productDescription.DeliveryInStock,
&productDescription.DeliveryOutStock,
&productDescription.Usage,
}
keys := []string{"translation_of_product_description",
"translation_of_product_short_description",
"translation_of_product_url_link",
"translation_of_product_meta_description",
"translation_of_product_meta_keywords",
"translation_of_product_meta_title",
"translation_of_product_name",
"translation_of_product_available_now",
"translation_of_product_available_later",
"translation_of_product_available_now_message",
"translation_of_product_available_later_message",
"translation_of_product_delivery_in_stock_message",
"translation_of_product_delivery_out_stock_message",
"translation_of_product_usage",
}

View File

@@ -0,0 +1,69 @@
package productTranslationService
import (
"strings"
"unicode"
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
"github.com/dlclark/regexp2"
"golang.org/x/text/runes"
"golang.org/x/text/transform"
"golang.org/x/text/unicode/norm"
)
func IsValidSlug(s string) bool {
var slug_regex2 = regexp2.MustCompile(constdata.SLUG_REGEX, regexp2.None)
ok, _ := slug_regex2.MatchString(s)
return ok
}
func SanitizeSlug(s string) string {
s = strings.TrimSpace(strings.ToLower(s))
// First apply explicit transliteration for language-specific letters.
s = transliterateWithTable(s)
// Then normalize and strip any remaining combining marks.
s = removeDiacritics(s)
// Replace all non-alphanumeric runs with "-"
var non_alphanum_regex2 = regexp2.MustCompile(constdata.NON_ALNUM_REGEX, regexp2.None)
s, _ = non_alphanum_regex2.Replace(s, "-", -1, -1)
// Collapse repeated "-" and trim edges
var multi_dash_regex2 = regexp2.MustCompile(constdata.MULTI_DASH_REGEX, regexp2.None)
s, _ = multi_dash_regex2.Replace(s, "-", -1, -1)
s = strings.Trim(s, "-")
return s
}
func transliterateWithTable(s string) string {
var b strings.Builder
b.Grow(len(s))
for _, r := range s {
if repl, ok := constdata.TRANSLITERATION_TABLE[r]; ok {
b.WriteString(repl)
} else {
b.WriteRune(r)
}
}
return b.String()
}
func removeDiacritics(s string) string {
t := transform.Chain(
norm.NFD,
runes.Remove(runes.In(unicode.Mn)),
norm.NFC,
)
out, _, err := transform.String(t, s)
if err != nil {
return s
}
return out
}