@ecomconsult/consentkit 0.5.4 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -555,6 +555,11 @@ Removing it is a supported, first-class option — no obligation, no nag:
555
555
  node tools/build-inline.mjs --langs=en,ru --no-branding # block without it
556
556
  ```
557
557
 
558
+ The line is `branding.poweredBy.text`; with `language: 'auto'` supply
559
+ `branding.poweredBy.texts` instead — `{ ru: '…', ro: '…', en: '…' }`, resolved
560
+ against the language the banner actually picked (`texts[lang]` → base code →
561
+ `texts.en` → `text`), so the attribution matches what the visitor is reading.
562
+
558
563
  If you write the config by hand, simply omit the `branding` object; nothing
559
564
  renders without it. Either way costs you ~200 bytes, not a licence: the client
560
565
  is MIT and the line is yours to drop.
@@ -28,7 +28,7 @@ export function undecidedState() {
28
28
  */
29
29
  export function createStub() {
30
30
  const stub = {
31
- version: '0.5.4',
31
+ version: '0.5.6',
32
32
  config: {},
33
33
  init: function () { return undecidedState(); },
34
34
  allowed: function (cat) { return cat === 'necessary'; },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecomconsult/consentkit",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "GDPR cookie consent core with blocking engine, Shadow DOM UI and Google Consent Mode v2. Zero dependencies, no build step.",
5
5
  "repository": {
6
6
  "type": "git",
package/src/ck-core.js CHANGED
@@ -1537,7 +1537,7 @@
1537
1537
  // Public API
1538
1538
  // ---------------------------------------------------------------------------
1539
1539
  var ConsentKit = {
1540
- version: '0.5.4',
1540
+ version: '0.5.6',
1541
1541
  config: config,
1542
1542
 
1543
1543
  init: function (userConfig) {
package/src/ck-locales.js CHANGED
@@ -553,30 +553,30 @@
553
553
  };
554
554
 
555
555
  L.ro = {
556
- bannerTitle: 'Folosim cookie-uri',
557
- bannerText: 'Cookie-urile necesare mențin site-ul în funcțiune. Restul analiză, marketing, funcții suplimentare pornește doar dacă permiteți. Vă puteți răzgândi oricând.',
556
+ bannerTitle: 'Cookie-uri pe acest site',
557
+ bannerText: 'Cookie-urile necesare mențin site-ul în funcțiune. Restul pornesc doar cu acordul dumneavoastră. Puteți schimba decizia oricând.',
558
558
  more: 'Aflați mai multe',
559
559
  acceptAll: 'Acceptă tot',
560
560
  rejectAll: 'Respinge tot',
561
561
  customize: 'Personalizează',
562
562
  bannerLabel: 'Consimțământ pentru cookie-uri',
563
563
  panelTitle: 'Setări cookie-uri',
564
- panelIntro: 'Alegeți ce cookie-uri permiteți. Nimic opțional nu este pornit până nu îl porniți dumneavoastră.',
564
+ panelIntro: 'Alegeți ce permiteți. Implicit este pornit doar strictul necesar.',
565
565
  save: 'Salvează alegerea',
566
566
  close: 'Închide',
567
567
  alwaysOn: 'mereu active',
568
- cookiesIn: 'Cookie-uri din acest grup',
568
+ cookiesIn: 'Ce cookie-uri',
569
569
  noCookies: 'Nu au fost declarate cookie-uri pentru acest grup.',
570
- colName: 'Nume',
571
- colVendor: 'Furnizor',
572
- colPurpose: 'Scop',
570
+ colName: 'Denumire',
571
+ colVendor: 'Cine le pune',
572
+ colPurpose: 'Pentru ce',
573
573
  colExpiry: 'Expiră',
574
574
  floating: 'Setări cookie-uri',
575
575
  cat: {
576
- necessary: { title: 'Necesare', desc: 'Sunt necesare pentru funcționarea site-ului: autentificare, securitate, reținerea consimțământului. Nu pot fi dezactivate.' },
577
- functional: { title: 'Funcționale', desc: 'Rețin preferințele dumneavoastră, precum limba sau chatul, ca să nu le setați din nou.' },
578
- analytics: { title: 'Analiză', desc: 'Ne arată ce pagini sunt folosite, ca reparăm ce derutează. Doar cifre, fără nume.' },
579
- marketing: { title: 'Marketing', desc: 'Ne permit arătăm reclame pe alte site-uri și să măsurăm dacă au fost de folos.' }
576
+ necessary: { title: 'Necesare', desc: 'Sunt necesare pentru funcționarea site-ului: autentificare, securitate, reținerea alegerii dumneavoastră. Nu pot fi dezactivate.' },
577
+ functional: { title: 'Funcționale', desc: 'Rețin alegerile dumneavoastră: limba, coșul, chatul.' },
578
+ analytics: { title: 'Analiză', desc: 'Ne ajută să înțelegem ce merge bine pe site și ce nu.' },
579
+ marketing: { title: 'Marketing', desc: 'Potrivesc reclamele cu interesele dumneavoastră pe alte site-uri.' }
580
580
  }
581
581
  };
582
582
 
@@ -348,6 +348,34 @@
348
348
  return out.join('\n');
349
349
  }
350
350
 
351
+ /* Pick the attribution line for the language the banner actually resolved to.
352
+
353
+ A SaaS server renders one config per site but cannot know the visitor's
354
+ language: with `language: 'auto'` the code that decides is ck-ui's
355
+ resolveLang(), in the browser, long after the config was serialised. So a
356
+ single `poweredBy.text` produced "Made by E-COM Consult" under a fully
357
+ Russian banner. `poweredBy.texts` lets the server send every line it has
358
+ and leaves the choice here, where the resolved language is known.
359
+
360
+ host.lang is the code ck-ui resolved ('ru', 'pt-br', ...). It is optional
361
+ on purpose: a page still running an older cached ck-ui.js passes no lang,
362
+ and that must degrade to the English/`text` line rather than throw. */
363
+ function pickPoweredByText(texts, lang, str) {
364
+ if (!texts || typeof texts !== 'object' || Array.isArray(texts)) return null;
365
+ var code = (typeof lang === 'string') ? lang.toLowerCase() : '';
366
+ // Own keys only. ck-ui's resolveLang() can only return a real locale key or
367
+ // 'en', so 'constructor' never arrives through the normal path — but `host`
368
+ // is caller-supplied on a published extension entry point, and reading an
369
+ // inherited key would hand str() a function instead of a missing line.
370
+ // Values go through str() as well, so anything non-string falls through.
371
+ function own(k) {
372
+ return (k && Object.prototype.hasOwnProperty.call(texts, k)) ? str(texts[k]) : null;
373
+ }
374
+ var hit = own(code);
375
+ if (!hit && code.length > 2) hit = own(code.slice(0, 2)); // ru-RU -> ru
376
+ return hit || own('en');
377
+ }
378
+
351
379
  /* Powered-by line. true -> localised default; object -> caller's text/url.
352
380
  Rendered after the actions in DOM order and styled quiet on purpose. */
353
381
  function buildPoweredBy(cfg, host) {
@@ -361,7 +389,8 @@
361
389
  if (pb === true) {
362
390
  text = T.poweredBy; // en fallback guaranteed by STR_KEYS
363
391
  } else if (typeof pb === 'object' && !Array.isArray(pb)) {
364
- text = str(pb.text) || T.poweredBy;
392
+ // texts[lang] -> texts[base] -> texts.en -> text -> T.poweredBy
393
+ text = pickPoweredByText(pb.texts, host.lang, str) || str(pb.text) || T.poweredBy;
365
394
  url = safeLinkUrl(pb.url);
366
395
  } else {
367
396
  return null;
@@ -467,12 +496,26 @@
467
496
  styling, so a config that gains a logo after the first ck:init has to
468
497
  rebuild rather than restyle. Returns '-' when there is no branding config,
469
498
  which is what keeps an unbranded page's signature stable. */
499
+ function textsSig(texts) {
500
+ if (!texts || typeof texts !== 'object' || Array.isArray(texts)) return '-';
501
+ var keys = [], k;
502
+ for (k in texts) {
503
+ if (Object.prototype.hasOwnProperty.call(texts, k) && str(texts[k])) keys.push(k);
504
+ }
505
+ keys.sort();
506
+ var out = [];
507
+ for (var i = 0; i < keys.length; i++) out.push(keys[i] + '=' + str(texts[keys[i]]));
508
+ return out.join(',');
509
+ }
510
+
470
511
  function brandSignature(cfg) {
471
512
  var b = brandingCfg(cfg);
472
513
  if (!b) return '-';
473
514
  var pb = b.poweredBy;
515
+ // texts is folded in with sorted keys so the signature is stable across key
516
+ // order — without it a server swapping only `texts` would not remount.
474
517
  var pbSig = (pb && typeof pb === 'object')
475
- ? 'o:' + String(pb.text || '') + ':' + String(pb.url || '')
518
+ ? 'o:' + String(pb.text || '') + ':' + String(pb.url || '') + ':' + textsSig(pb.texts)
476
519
  : String(!!pb);
477
520
  // Logos are hashed by length + head so a long data: URI does not bloat the key.
478
521
  function tag(v) {
package/src/ck-ui.js CHANGED
@@ -12,82 +12,82 @@
12
12
 
13
13
  var DICT = {
14
14
  en: {
15
- bannerTitle: 'We use cookies',
16
- bannerText: 'Necessary cookies keep the site working. Everything else analytics, marketing, extra features — runs only if you allow it. You can change your mind at any time.',
15
+ bannerTitle: 'Cookies on this site',
16
+ bannerText: 'Necessary cookies keep the site working. The rest are used only if you allow them. You can change your choice at any time.',
17
17
  more: 'Learn more',
18
18
  acceptAll: 'Accept all',
19
19
  rejectAll: 'Reject all',
20
20
  customize: 'Customize',
21
21
  bannerLabel: 'Cookie consent',
22
22
  panelTitle: 'Cookie settings',
23
- panelIntro: 'Choose which cookies you allow. Nothing optional is on until you turn it on.',
23
+ panelIntro: 'Choose what to allow. By default only the necessary ones are on.',
24
24
  save: 'Save choices',
25
25
  close: 'Close',
26
26
  alwaysOn: 'always on',
27
- cookiesIn: 'Cookies in this group',
27
+ cookiesIn: 'Which cookies',
28
28
  noCookies: 'No cookies declared for this group.',
29
29
  colName: 'Name',
30
- colVendor: 'Provider',
31
- colPurpose: 'Purpose',
30
+ colVendor: 'Who sets it',
31
+ colPurpose: 'What for',
32
32
  colExpiry: 'Expires',
33
33
  floating: 'Cookie settings',
34
34
  poweredBy: 'Powered by ConsentKit',
35
35
  cat: {
36
36
  necessary: {
37
37
  title: 'Necessary',
38
- desc: 'Needed for the site to work signing in, security, remembering your consent. They cannot be turned off.'
38
+ desc: 'Needed for the site to work: signing in, security, remembering your choice. They cannot be turned off.'
39
39
  },
40
40
  functional: {
41
41
  title: 'Functional',
42
- desc: 'Remember your preferences, such as language or chat, so you do not set them up again.'
42
+ desc: 'Remember your choices: language, basket, chat.'
43
43
  },
44
44
  analytics: {
45
45
  title: 'Analytics',
46
- desc: 'Help us see which pages people use, so we can fix what is confusing. Numbers only, no names.'
46
+ desc: 'Help us understand what works well on the site and what does not.'
47
47
  },
48
48
  marketing: {
49
49
  title: 'Marketing',
50
- desc: 'Let us show you ads on other sites and measure whether they were any use.'
50
+ desc: 'Match ads to your interests on other sites.'
51
51
  }
52
52
  }
53
53
  },
54
54
  ru: {
55
- bannerTitle: 'Мы используем cookie',
56
- bannerText: 'Необходимые cookie нужны, чтобы сайт работал. Всё остальное — аналитика, маркетинг, дополнительные удобства — включается только с вашего согласия. Решение можно изменить в любой момент.',
55
+ bannerTitle: 'Cookie на этом сайте',
56
+ bannerText: 'Необходимые cookie нужны, чтобы сайт работал. Остальные включаются только с вашего согласия. Решение можно изменить в любой момент.',
57
57
  more: 'Подробнее',
58
58
  acceptAll: 'Принять всё',
59
59
  rejectAll: 'Отклонить всё',
60
60
  customize: 'Настроить',
61
61
  bannerLabel: 'Согласие на cookie',
62
62
  panelTitle: 'Настройки cookie',
63
- panelIntro: 'Выберите, какие cookie вы разрешаете. Ничего необязательного не включено, пока вы сами это не сделаете.',
63
+ panelIntro: 'Выберите, что разрешить. По умолчанию включено только необходимое.',
64
64
  save: 'Сохранить выбор',
65
65
  close: 'Закрыть',
66
66
  alwaysOn: 'всегда активны',
67
- cookiesIn: 'Cookie в этой группе',
67
+ cookiesIn: 'Какие cookie',
68
68
  noCookies: 'Для этой группы cookie не заявлены.',
69
- colName: 'Имя',
70
- colVendor: 'Поставщик',
71
- colPurpose: 'Цель',
69
+ colName: 'Название',
70
+ colVendor: 'Кто ставит',
71
+ colPurpose: 'Зачем',
72
72
  colExpiry: 'Срок',
73
73
  floating: 'Настройки cookie',
74
74
  poweredBy: 'Работает на ConsentKit',
75
75
  cat: {
76
76
  necessary: {
77
77
  title: 'Необходимые',
78
- desc: 'Без них сайт не работает: вход, безопасность, память о вашем выборе. Отключить нельзя.'
78
+ desc: 'Нужны, чтобы сайт работал: вход, безопасность, память о вашем выборе. Отключить нельзя.'
79
79
  },
80
80
  functional: {
81
81
  title: 'Функциональные',
82
- desc: 'Запоминают ваши настройки например язык или чат, — чтобы вы не задавали их заново.'
82
+ desc: 'Запоминают ваш выбор: язык, корзину, чат.'
83
83
  },
84
84
  analytics: {
85
85
  title: 'Аналитика',
86
- desc: 'Показывают нам, какими страницами вы пользуетесь, чтобы мы исправили неудобное. Только цифры, без имён.'
86
+ desc: 'Помогают нам понять, что на сайте удобно, а что нет.'
87
87
  },
88
88
  marketing: {
89
89
  title: 'Маркетинг',
90
- desc: 'Позволяют показывать вам рекламу на других сайтах и понимать, была ли от неё польза.'
90
+ desc: 'Подбирают рекламу под ваши интересы на других сайтах.'
91
91
  }
92
92
  }
93
93
  }
@@ -370,8 +370,12 @@
370
370
  return (b && typeof b === 'object') ? b : null;
371
371
  }
372
372
 
373
+ /* LANG travels with T: an extension that renders language-dependent text of
374
+ its own (branding.poweredBy.texts) needs the code the banner resolved to,
375
+ which only this file knows — the config may say 'auto' and the answer then
376
+ comes from the visitor's browser at mount time. */
373
377
  function extHost() {
374
- return { el: el, str: str, T: T };
378
+ return { el: el, str: str, T: T, lang: LANG };
375
379
  }
376
380
 
377
381
  function buildBrandLogo(cfg) {
@@ -427,6 +431,7 @@
427
431
  var mountedSig = null;
428
432
  var host = null, root = null;
429
433
  var T = DICT.en;
434
+ var LANG = 'en'; // the code T was built from, reassigned per mount
430
435
  var nodes = {}; // banner/panel/fab refs
431
436
  var switches = {}; // category -> button
432
437
  var panelOpen = false;
@@ -1649,7 +1654,8 @@
1649
1654
  }
1650
1655
 
1651
1656
  var table = localeTable(); // read at render time
1652
- T = buildStrings(resolveLang(cfg && cfg.language, table), table);
1657
+ LANG = resolveLang(cfg && cfg.language, table);
1658
+ T = buildStrings(LANG, table);
1653
1659
 
1654
1660
  host = document.getElementById('ck-root');
1655
1661
  if (!host) {