From 879b6dd733adc79d02f6430393c68fd1352f3466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Thu, 23 Apr 2026 18:08:58 +0400 Subject: [PATCH] Add cookie banner translations UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add default language select to the settings page and a new Translations tab with react-hook-form-based editing of banner, preferences panel, and placeholder UI strings with live previews. Signed-off-by: Émile Ré --- .../CookieBannerConfigLayout.tsx | 5 + .../_components/BannerSettingsForm.tsx | 15 +- .../CookieBannerTranslationsPage.tsx | 147 ++++++++++++++ .../CookieBannerTranslationsPageLoader.tsx | 45 +++++ .../_components/BannerPreview.tsx | 189 ++++++++++++++++++ .../_components/BannerTranslationSection.tsx | 131 ++++++++++++ .../translations/_components/PanelPreview.tsx | 147 ++++++++++++++ .../_components/PanelTranslationSection.tsx | 138 +++++++++++++ .../_components/PlaceholderPreview.tsx | 93 +++++++++ .../PlaceholderTranslationSection.tsx | 80 ++++++++ .../_components/TranslationEditor.tsx | 139 +++++++++++++ .../_components/translationDefaults.ts | 73 +++++++ .../organizations/cookie-banners/routes.ts | 5 + 13 files changed, 1206 insertions(+), 1 deletion(-) create mode 100644 apps/console/src/pages/organizations/cookie-banners/configuration/translations/CookieBannerTranslationsPage.tsx create mode 100644 apps/console/src/pages/organizations/cookie-banners/configuration/translations/CookieBannerTranslationsPageLoader.tsx create mode 100644 apps/console/src/pages/organizations/cookie-banners/configuration/translations/_components/BannerPreview.tsx create mode 100644 apps/console/src/pages/organizations/cookie-banners/configuration/translations/_components/BannerTranslationSection.tsx create mode 100644 apps/console/src/pages/organizations/cookie-banners/configuration/translations/_components/PanelPreview.tsx create mode 100644 apps/console/src/pages/organizations/cookie-banners/configuration/translations/_components/PanelTranslationSection.tsx create mode 100644 apps/console/src/pages/organizations/cookie-banners/configuration/translations/_components/PlaceholderPreview.tsx create mode 100644 apps/console/src/pages/organizations/cookie-banners/configuration/translations/_components/PlaceholderTranslationSection.tsx create mode 100644 apps/console/src/pages/organizations/cookie-banners/configuration/translations/_components/TranslationEditor.tsx create mode 100644 apps/console/src/pages/organizations/cookie-banners/configuration/translations/_components/translationDefaults.ts diff --git a/apps/console/src/pages/organizations/cookie-banners/configuration/CookieBannerConfigLayout.tsx b/apps/console/src/pages/organizations/cookie-banners/configuration/CookieBannerConfigLayout.tsx index d3120295f..1c262a796 100644 --- a/apps/console/src/pages/organizations/cookie-banners/configuration/CookieBannerConfigLayout.tsx +++ b/apps/console/src/pages/organizations/cookie-banners/configuration/CookieBannerConfigLayout.tsx @@ -18,6 +18,7 @@ import { Badge, Breadcrumb, Button, + IconGlobe, IconListStack, IconPageTextLine, IconSettingsGear2, @@ -242,6 +243,10 @@ export default function CookieBannerConfigLayout({ queryRef }: CookieBannerConfi {__("Cookies")} + + + {__("Translations")} + {__("JS / CSS snippets")} diff --git a/apps/console/src/pages/organizations/cookie-banners/configuration/_components/BannerSettingsForm.tsx b/apps/console/src/pages/organizations/cookie-banners/configuration/_components/BannerSettingsForm.tsx index c41b834cc..5a42182bd 100644 --- a/apps/console/src/pages/organizations/cookie-banners/configuration/_components/BannerSettingsForm.tsx +++ b/apps/console/src/pages/organizations/cookie-banners/configuration/_components/BannerSettingsForm.tsx @@ -30,6 +30,7 @@ const bannerSettingsFormFragment = graphql` privacyPolicyUrl consentExpiryDays consentMode + defaultLanguage } `; @@ -43,6 +44,7 @@ const updateBannerMutation = graphql` privacyPolicyUrl consentExpiryDays consentMode + defaultLanguage latestVersion { id version @@ -70,6 +72,7 @@ export function BannerSettingsForm({ cookieBannerKey }: BannerSettingsFormProps) const [privacyPolicyUrl, setPrivacyPolicyUrl] = useState(banner.privacyPolicyUrl); const [consentExpiryDays, setConsentExpiryDays] = useState(String(banner.consentExpiryDays)); const [consentMode, setConsentMode] = useState(banner.consentMode); + const [defaultLanguage, setDefaultLanguage] = useState(banner.defaultLanguage); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); @@ -83,6 +86,7 @@ export function BannerSettingsForm({ cookieBannerKey }: BannerSettingsFormProps) privacyPolicyUrl, consentExpiryDays: parseInt(consentExpiryDays, 10), consentMode: consentMode, + defaultLanguage, }, }, onCompleted() { @@ -111,7 +115,7 @@ export function BannerSettingsForm({ cookieBannerKey }: BannerSettingsFormProps) setPrivacyPolicyUrl(e.target.value)} required /> -
+
{__("Opt-out")}
+
+ + +
+ + + + + + + +
+ {showBranding && ( +
+ Privacy by + {" "} + +
+ )} + + ); +} diff --git a/apps/console/src/pages/organizations/cookie-banners/configuration/translations/_components/BannerTranslationSection.tsx b/apps/console/src/pages/organizations/cookie-banners/configuration/translations/_components/BannerTranslationSection.tsx new file mode 100644 index 000000000..fc9eef3ff --- /dev/null +++ b/apps/console/src/pages/organizations/cookie-banners/configuration/translations/_components/BannerTranslationSection.tsx @@ -0,0 +1,131 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { useTranslate } from "@probo/i18n"; +import { Card, Field, Input, Textarea } from "@probo/ui"; +import { Controller, useFormContext, useWatch } from "react-hook-form"; + +import { BannerPreview } from "./BannerPreview"; +import { TRANSLATION_LABELS } from "./translationDefaults"; +import type { TranslationFormValues } from "./TranslationEditor"; + +interface BannerTranslationSectionProps { + showBranding: boolean; +} + +export function BannerTranslationSection({ + showBranding, +}: BannerTranslationSectionProps) { + const { __ } = useTranslate(); + const { control } = useFormContext(); + + const bannerTitle = useWatch({ control, name: "banner_title" }); + const bannerDescription = useWatch({ control, name: "banner_description" }); + const buttonAcceptAll = useWatch({ control, name: "button_accept_all" }); + const buttonRejectAll = useWatch({ control, name: "button_reject_all" }); + const buttonCustomize = useWatch({ control, name: "button_customize" }); + const privacyPolicyLinkText = useWatch({ + control, + name: "privacy_policy_link_text", + }); + + return ( +
+

{__("Banner")}

+
+ +
+ ( + + + + )} + /> + ( + +