Fix PR review comments on cookie banner i18n
Address locale normalization for region-tagged values, guard language detection for non-DOM runtimes, validate DefaultLanguage on update, pass translated texts through the deactivation flow, handle slug collisions in migration, add organizations FK, fix consent migration from name-keyed to slug-keyed data, render all template placeholders in previews, and wrap helper text for i18n. Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -302,7 +302,7 @@ function deactivateScript(el: HTMLScriptElement): void {
|
||||
el.parentNode!.replaceChild(replacement, el);
|
||||
}
|
||||
|
||||
function deactivateElement(el: Element, label?: string): void {
|
||||
function deactivateElement(el: Element, label?: string, texts?: BannerTexts): void {
|
||||
const category = el.getAttribute(ATTR_ACTIVATED);
|
||||
|
||||
const src = el.getAttribute("src");
|
||||
@@ -323,7 +323,7 @@ function deactivateElement(el: Element, label?: string): void {
|
||||
el.removeAttribute(ATTR_ACTIVATED);
|
||||
|
||||
if (category && VISUAL_TAGS.has(el.tagName)) {
|
||||
createPlaceholder(el, category, label);
|
||||
createPlaceholder(el, category, label, texts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,6 +332,7 @@ export function deactivateElements(
|
||||
consentData: Record<string, boolean>,
|
||||
categoryCookies: Record<string, string[]>,
|
||||
categoryLabels: Record<string, string>,
|
||||
texts?: BannerTexts,
|
||||
): void {
|
||||
const elements = document.querySelectorAll(`[${ATTR_ACTIVATED}]`);
|
||||
const cookiesToRemove = new Set<string>();
|
||||
@@ -345,7 +346,7 @@ export function deactivateElements(
|
||||
if (el instanceof HTMLScriptElement) {
|
||||
deactivateScript(el);
|
||||
} else {
|
||||
deactivateElement(el, categoryLabels[category]);
|
||||
deactivateElement(el, categoryLabels[category], texts);
|
||||
}
|
||||
|
||||
const cookies = categoryCookies[category];
|
||||
|
||||
@@ -250,7 +250,7 @@ export class CookieBannerClient {
|
||||
}
|
||||
|
||||
const texts = this.config.texts;
|
||||
deactivateElements(consentData, categoryCookies, categoryLabels);
|
||||
deactivateElements(consentData, categoryCookies, categoryLabels, texts);
|
||||
activateElements(consentData);
|
||||
addPlaceholders(consentData, categoryLabels, texts);
|
||||
if (this.observer) {
|
||||
|
||||
@@ -110,8 +110,8 @@ export class ProboCookieBannerRoot extends ProboElement implements ProboRootElem
|
||||
for (const cat of config.categories) {
|
||||
if (cat.kind === "NECESSARY") {
|
||||
draft[cat.slug] = true;
|
||||
} else if (existing && cat.slug in existing) {
|
||||
draft[cat.slug] = existing[cat.slug];
|
||||
} else if (existing && (cat.slug in existing || cat.name in existing)) {
|
||||
draft[cat.slug] = existing[cat.slug] ?? existing[cat.name];
|
||||
} else {
|
||||
draft[cat.slug] = config.consent_mode === "OPT_OUT";
|
||||
}
|
||||
|
||||
@@ -29,6 +29,15 @@ export class ProboSettingsButton extends HTMLElement {
|
||||
return ["position", "aria-settings-label"];
|
||||
}
|
||||
|
||||
attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {
|
||||
if (name === "aria-settings-label") {
|
||||
const btn = this.shadow.querySelector("button");
|
||||
if (btn && newValue) {
|
||||
btn.setAttribute("aria-label", newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private get position(): string {
|
||||
return this.getAttribute("position") ?? "bottom-left";
|
||||
}
|
||||
|
||||
@@ -16,14 +16,20 @@ export interface BannerTexts {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export function detectLanguage(explicit?: string): string {
|
||||
if (explicit) return explicit;
|
||||
function normalizeLocale(locale: string): string {
|
||||
return locale.split("-")[0].toLowerCase();
|
||||
}
|
||||
|
||||
const htmlLang = document.documentElement.lang;
|
||||
if (htmlLang) return htmlLang.split("-")[0];
|
||||
export function detectLanguage(explicit?: string): string {
|
||||
if (explicit) return normalizeLocale(explicit);
|
||||
|
||||
if (typeof document !== "undefined" && document.documentElement) {
|
||||
const htmlLang = document.documentElement.lang;
|
||||
if (htmlLang) return normalizeLocale(htmlLang);
|
||||
}
|
||||
|
||||
if (typeof navigator !== "undefined" && navigator.language) {
|
||||
return navigator.language.split("-")[0];
|
||||
return normalizeLocale(navigator.language);
|
||||
}
|
||||
|
||||
return "";
|
||||
|
||||
@@ -40,7 +40,7 @@ if (script) {
|
||||
|
||||
const lang = script.getAttribute("data-lang");
|
||||
if (lang) {
|
||||
el.setAttribute("lang", lang);
|
||||
el.setAttribute("lang", lang.split("-")[0].toLowerCase());
|
||||
}
|
||||
|
||||
document.body.appendChild(el);
|
||||
|
||||
@@ -170,7 +170,7 @@ export class ProboThemedBanner extends HTMLElement {
|
||||
|
||||
this.shadow.querySelectorAll("[data-text]").forEach(el => {
|
||||
const key = el.getAttribute("data-text")!;
|
||||
const raw = texts[key];
|
||||
const raw = texts[key] ?? "";
|
||||
if (!raw) return;
|
||||
|
||||
if (key === "banner_description") {
|
||||
@@ -190,7 +190,7 @@ export class ProboThemedBanner extends HTMLElement {
|
||||
|
||||
this.shadow.querySelectorAll("[data-aria-text]").forEach(el => {
|
||||
const key = el.getAttribute("data-aria-text")!;
|
||||
const raw = texts[key];
|
||||
const raw = texts[key] ?? el.getAttribute("aria-label") ?? "";
|
||||
if (raw) el.setAttribute("aria-label", raw);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user