Add per-category translations and improve preferences panel preview

Introduce category-level name/description translations in the cookie
banner i18n flow. Seed default translations for fr/de/es on banner
creation, parse them from the stored JSON, and manage them via
react-hook-form Controllers instead of a manual ref/callback pattern.
Enhance the panel preview with category descriptions and all three
action buttons.

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-04-23 20:05:04 +04:00
parent 165b9ad9d3
commit cd824c2c55
7 changed files with 327 additions and 82 deletions

View File

@@ -30,6 +30,33 @@ var defaultCategories = []struct {
{"Uncategorised", "uncategorised", "Cookies that have not been assigned to a category yet.", coredata.CookieCategoryKindUncategorised, 4},
}
var defaultCategoryTranslationsByLanguage = map[string]map[string]struct {
Name string
Description string
}{
"fr": {
"necessary": {"Nécessaires", "Cookies essentiels au bon fonctionnement du site web."},
"analytics": {"Analytiques", "Cookies qui aident à comprendre comment les visiteurs interagissent avec le site web."},
"advertising": {"Publicitaires", "Cookies utilisés pour diffuser des publicités pertinentes et suivre les campagnes."},
"functional": {"Fonctionnels", "Cookies qui permettent des fonctionnalités améliorées et la personnalisation."},
"uncategorised": {"Non classés", "Cookies qui n'ont pas encore été assignés à une catégorie."},
},
"de": {
"necessary": {"Notwendige", "Wesentliche Cookies, die für das ordnungsgemäße Funktionieren der Website erforderlich sind."},
"analytics": {"Analytische", "Cookies, die helfen zu verstehen, wie Besucher mit der Website interagieren."},
"advertising": {"Werbe", "Cookies, die verwendet werden, um relevante Werbung zu liefern und Kampagnen zu verfolgen."},
"functional": {"Funktionale", "Cookies, die erweiterte Funktionalität und Personalisierung ermöglichen."},
"uncategorised": {"Nicht kategorisiert", "Cookies, die noch keiner Kategorie zugeordnet wurden."},
},
"es": {
"necessary": {"Necesarias", "Cookies esenciales necesarias para el correcto funcionamiento del sitio web."},
"analytics": {"Analíticas", "Cookies que ayudan a entender cómo los visitantes interactúan con el sitio web."},
"advertising": {"Publicitarias", "Cookies utilizadas para mostrar anuncios relevantes y rastrear campañas."},
"functional": {"Funcionales", "Cookies que permiten funcionalidades mejoradas y personalización."},
"uncategorised": {"Sin categoría", "Cookies que aún no han sido asignadas a una categoría."},
},
}
var defaultUIStringsByLanguage = map[string]map[string]string{
"en": {
"banner_title": "Cookie Preferences",

View File

@@ -531,6 +531,7 @@ func (s *Service) CreateCookieBanner(
return fmt.Errorf("cannot insert cookie banner: %w", err)
}
slugToGID := make(map[string]gid.GID, len(defaultCategories))
for _, dc := range defaultCategories {
category := &coredata.CookieCategory{
ID: gid.New(scope.GetTenantID(), coredata.CookieCategoryEntityType),
@@ -548,12 +549,34 @@ func (s *Service) CreateCookieBanner(
if err := category.Insert(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot insert default cookie category %q: %w", dc.Name, err)
}
slugToGID[dc.Slug] = category.ID
}
for lang, uiStrings := range defaultUIStringsByLanguage {
translationsJSON, err := json.Marshal(uiStrings)
blob := make(map[string]any, len(uiStrings)+1)
for k, v := range uiStrings {
blob[k] = v
}
if catDefaults, ok := defaultCategoryTranslationsByLanguage[lang]; ok {
catMap := make(map[string]map[string]string, len(catDefaults))
for slug, ct := range catDefaults {
if id, exists := slugToGID[slug]; exists {
catMap[id.String()] = map[string]string{
"name": ct.Name,
"description": ct.Description,
}
}
}
if len(catMap) > 0 {
blob["categories"] = catMap
}
}
translationsJSON, err := json.Marshal(blob)
if err != nil {
return fmt.Errorf("cannot marshal default UI strings for %s: %w", lang, err)
return fmt.Errorf("cannot marshal default translations for %s: %w", lang, err)
}
translation := &coredata.CookieBannerTranslation{