From 8eb5ba2ce276e3d52859b04995a83f8c8a50bd84 Mon Sep 17 00:00:00 2001 From: Giacomo Barbalinardo Date: Tue, 25 Jun 2024 01:08:15 +0200 Subject: [PATCH 1/6] feat: prepare custom language feature --- .../src/lib/config/custom-language-config.interface.ts | 6 ++++++ .../src/lib/config/ngx-cookie-consent-config.service.ts | 2 ++ 2 files changed, 8 insertions(+) create mode 100644 projects/ngx-cookie-consent/src/lib/config/custom-language-config.interface.ts diff --git a/projects/ngx-cookie-consent/src/lib/config/custom-language-config.interface.ts b/projects/ngx-cookie-consent/src/lib/config/custom-language-config.interface.ts new file mode 100644 index 0000000..123fb03 --- /dev/null +++ b/projects/ngx-cookie-consent/src/lib/config/custom-language-config.interface.ts @@ -0,0 +1,6 @@ +export interface CustomLanguageConfig { + languageKey: string; + languageName: string; + customIconPath: string|null; + translations: { [key: string]: string }; +} diff --git a/projects/ngx-cookie-consent/src/lib/config/ngx-cookie-consent-config.service.ts b/projects/ngx-cookie-consent/src/lib/config/ngx-cookie-consent-config.service.ts index d96472c..5c6600f 100644 --- a/projects/ngx-cookie-consent/src/lib/config/ngx-cookie-consent-config.service.ts +++ b/projects/ngx-cookie-consent/src/lib/config/ngx-cookie-consent-config.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core'; import { CookieItem } from './cookie-item.interface'; import { TranslatableString } from './translatable-string.interface'; +import { CustomLanguageConfig } from "./custom-language-config.interface"; @Injectable({ providedIn: 'root' @@ -10,6 +11,7 @@ export class NgxCookieConsentConfigService { imprintUrl?: string | TranslatableString = '#'; defaultLanguage?: string = 'en'; availableLanguages?: string[] = ['en', 'de', 'it', 'pt', 'fr']; + customLanguage?: CustomLanguageConfig|null = null; showLanguageSwitcher?: boolean = true; showBadgeOpener?: boolean = true; openerPosition?: 'left-top' | 'right-top' | 'left-bottom' | 'right-bottom' = 'left-bottom'; From f3b147b1e426a3ce210a3de4508e02df3606fe45 Mon Sep 17 00:00:00 2001 From: Giacomo Barbalinardo Date: Mon, 8 Jul 2024 19:02:07 +0200 Subject: [PATCH 2/6] feat: prepare lang service --- package.json | 3 ++- .../ngx-language/ngx-language.service.spec.ts | 17 +++++++++++++++-- .../ngx-language/ngx-language.service.ts | 11 +++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 78effef..dfec7b5 100644 --- a/package.json +++ b/package.json @@ -37,5 +37,6 @@ "karma-spec-reporter": "^0.0.36", "ng-packagr": "^17.2.1", "typescript": "~5.3.3" - } + }, + "packageManager": "yarn@1.22.19+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447" } diff --git a/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.spec.ts b/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.spec.ts index 84c68e6..bad3ff0 100644 --- a/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.spec.ts +++ b/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.spec.ts @@ -1,12 +1,24 @@ import { TestBed } from '@angular/core/testing'; import { NgxLanguageService } from './ngx-language.service'; +import { NgxCookieConsentConfigService } from '../../config/ngx-cookie-consent-config.service'; describe('NgxLanguageService', () => { let service: NgxLanguageService; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + providers: [ + {provide: NgxCookieConsentConfigService, useValue: { + customLanguage: { + languageKey: 'xx', + translations: { + other_title: 'Andere' + } + } + }} + ] + }); service = TestBed.inject(NgxLanguageService); }); @@ -18,12 +30,13 @@ describe('NgxLanguageService', () => { const translations = service.translations; expect(translations).toBeTruthy(); - expect(Object.keys(translations).length).toBe(5); + expect(Object.keys(translations).length).toBe(6); expect(translations.hasOwnProperty('lang_en')).toBeTruthy(); expect(translations.hasOwnProperty('lang_de')).toBeTruthy(); expect(translations.hasOwnProperty('lang_it')).toBeTruthy(); expect(translations.hasOwnProperty('lang_pt')).toBeTruthy(); expect(translations.hasOwnProperty('lang_fr')).toBeTruthy(); + expect(translations.hasOwnProperty('lang_xx')).toBeTruthy(); }); it('should contain default language', () => { diff --git a/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.ts b/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.ts index 7ef4bc4..22ae09c 100644 --- a/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.ts +++ b/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.ts @@ -12,6 +12,17 @@ export class NgxLanguageService { constructor(private config: NgxCookieConsentConfigService) { this.translationKey = 'lang_' + this.config.defaultLanguage; this.translations = languages; + + if (config.customLanguage !== null && config.customLanguage !== undefined) { + this.translations = { + ...this.translations, + ...{ + ['lang_' + config.customLanguage?.languageKey]: { + ...config.customLanguage?.translations + } + } + }; + } } From 6a68757205dab5b3d5513cc1a6717c46fa518990 Mon Sep 17 00:00:00 2001 From: Giacomo Barbalinardo Date: Mon, 8 Jul 2024 19:40:56 +0200 Subject: [PATCH 3/6] feat: custom language add fallback language --- .../ngx-language/ngx-language.service.spec.ts | 23 ++++++++++++++----- .../ngx-language/ngx-language.service.ts | 16 ++++++++++++- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.spec.ts b/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.spec.ts index bad3ff0..da453e1 100644 --- a/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.spec.ts +++ b/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.spec.ts @@ -10,10 +10,11 @@ describe('NgxLanguageService', () => { TestBed.configureTestingModule({ providers: [ {provide: NgxCookieConsentConfigService, useValue: { + defaultLanguage: 'en', customLanguage: { languageKey: 'xx', translations: { - other_title: 'Andere' + other_title: 'XX Other' } } }} @@ -61,9 +62,19 @@ describe('NgxLanguageService', () => { expect(translation).toBe('Andere'); }); + it('should return a translation for custom language', () => { + const translation = service.getTranslation('other_title', 'xx'); + expect(translation).toBe('XX Other'); + }); + + it('should return a fallback translation for custom language if key not translated', () => { + const translation = service.getTranslation('back_text', 'xx'); + expect(translation).toBe('Back'); + }); + it('should return a translation from an object for a specific language', () => { - const translation = service.getTranslationFromObject({en: 'Other', de: 'Andere'}, 'de'); - expect(translation).toBe('Andere'); + const translation = service.getTranslationFromObject({en: 'Other', de: 'Andere Andere'}, 'de'); + expect(translation).toBe('Andere Andere'); }); it('should return a translation from an object fallback language', () => { @@ -71,9 +82,9 @@ describe('NgxLanguageService', () => { expect(translation).toBe('Other'); }); - it('should return a translation from a string', () => { - const translation = service.getTranslationFromObject('Other'); - expect(translation).toBe('Other'); + it('should return a translation from a string return itself', () => { + const translation = service.getTranslationFromObject('Others'); + expect(translation).toBe('Others'); }); it('should return a empty string translation from an object while no fallback language', () => { diff --git a/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.ts b/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.ts index 22ae09c..8af5916 100644 --- a/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.ts +++ b/projects/ngx-cookie-consent/src/lib/services/ngx-language/ngx-language.service.ts @@ -18,7 +18,7 @@ export class NgxLanguageService { ...this.translations, ...{ ['lang_' + config.customLanguage?.languageKey]: { - ...config.customLanguage?.translations + ...this.sanitizeCustomTranslations(config.customLanguage?.translations) } } }; @@ -52,4 +52,18 @@ export class NgxLanguageService { return ''; } + + private sanitizeCustomTranslations(translations: { [p: string]: string } | undefined): { [p: string]: string } { + if (!translations) { + return {}; + } + + // get default english translations merge with custom translations + const defaultTranslations = this.translations['lang_en']; + + return { + ...defaultTranslations, + ...translations + }; + } } From 0997434bfa6542318f3698ce11943b6266cce328 Mon Sep 17 00:00:00 2001 From: Giacomo Barbalinardo Date: Thu, 11 Jul 2024 18:11:46 +0200 Subject: [PATCH 4/6] feat: custom translations --- projects/ngx-cookie-consent/README.md | 56 +++++++++++-------- .../src/lib/ngx-cookie-consent.component.html | 8 +++ .../src/lib/ngx-cookie-consent.component.scss | 4 ++ .../src/lib/ngx-cookie-consent.component.ts | 5 ++ src/app/app.module.ts | 8 +++ src/assets/images/flag_x.svg | 7 +++ 6 files changed, 65 insertions(+), 23 deletions(-) create mode 100644 src/assets/images/flag_x.svg diff --git a/projects/ngx-cookie-consent/README.md b/projects/ngx-cookie-consent/README.md index eb19e40..eec3793 100644 --- a/projects/ngx-cookie-consent/README.md +++ b/projects/ngx-cookie-consent/README.md @@ -64,29 +64,39 @@ import { NgxCookieConsentModule } from '@localia/ngx-cookie-consent'; ## Configuration -| Name | Type | Default | Description | -|-----------------------|----------------------------------|--------------------|------------------------------------------------------------------------------------| -| privacyPolicyUrl | string | TranslatableString | '#' | URL to your privacy policy ⚠ required ⚠ | -| imprintUrl | string | TranslatableString | '#' | URL to your imprint ⚠ required ⚠ | -| defaultLanguage | string | 'en' | Default language for the cookie consent banner | -| availableLanguages | string[] | ['en', 'de', 'it'] | Available languages for the cookie consent banner | -| showLanguageSwitcher | boolean | true | Show language switcher | -| showBadgeOpener | boolean | true | Show badge opener | -| openerPosition | enum | 'left-bottom' | Position of the badge eg. 'left-top', 'right-top' , 'left-bottom' , 'right-bottom' | -| customOpenerClass | string | '' | Custom class for the badge opener | -| customClass | string | '' | Custom class for the cookie consent banner | -| cookiePrefix | string | 'cookieconsent_' | Prefix for the cookie consent banner | -| cookieExpiryDays | number | 365 | Expiry days for the cookie consent banner | -| showCookieDetails | boolean | false | Show cookie details | -| showFunctionalCookies | boolean | true | Show functional cookies | -| functionalCookies | CookieItem[] | [] | Functional cookies | -| showMarketingCookies | boolean | true | Show marketing cookies | -| marketingCookies | CookieItem[] | [] | Marketing cookies | -| showEssentialCookies | boolean | true | Show essential cookies | -| essentialCookies | CookieItem[] | [] | Essential cookies | -| showOtherTools | boolean | true | Show other tools | -| otherTools | CookieItem[] | [] | Other tools | -| excludeRoutes | string[] | [] | Exclude routes eg. ['/privacy-policy'] | +| Name | Type | Default | Description | +|-----------------------|-----------------------------------|-------------------|------------------------------------------------------------------------------------| +| privacyPolicyUrl | string | TranslatableString | '#' | URL to your privacy policy ⚠ required ⚠ | +| imprintUrl | string | TranslatableString | '#' | URL to your imprint ⚠ required ⚠ | +| defaultLanguage | string | 'en' | Default language for the cookie consent banner | +| availableLanguages | string[] | ['en', 'de', 'it'] | Available languages for the cookie consent banner | +| customLanguage | CustomLanguageConfig | null | null | Custom language for the cookie consent banner | +| showLanguageSwitcher | boolean | true | Show language switcher | +| showBadgeOpener | boolean | true | Show badge opener | +| openerPosition | enum | 'left-bottom' | Position of the badge eg. 'left-top', 'right-top' , 'left-bottom' , 'right-bottom' | +| customOpenerClass | string | '' | Custom class for the badge opener | +| customClass | string | '' | Custom class for the cookie consent banner | +| cookiePrefix | string | 'cookieconsent_' | Prefix for the cookie consent banner | +| cookieExpiryDays | number | 365 | Expiry days for the cookie consent banner | +| showCookieDetails | boolean | false | Show cookie details | +| showFunctionalCookies | boolean | true | Show functional cookies | +| functionalCookies | CookieItem[] | [] | Functional cookies | +| showMarketingCookies | boolean | true | Show marketing cookies | +| marketingCookies | CookieItem[] | [] | Marketing cookies | +| showEssentialCookies | boolean | true | Show essential cookies | +| essentialCookies | CookieItem[] | [] | Essential cookies | +| showOtherTools | boolean | true | Show other tools | +| otherTools | CookieItem[] | [] | Other tools | +| excludeRoutes | string[] | [] | Exclude routes eg. ['/privacy-policy'] | + +### CustomLanguageConfig interface +| Name | Type | Description | +|----------------|------------------------------------------|-------------------------------------------------------------------------------------------| +| languageKey | string | Key for the custom language eg. 'custom' | +| languageName | string | Name for the custom language eg. 'Custom' | +| customIconPath | string | null | Path to the custom icon eg. 'assets/images/custom-icon.svg' | +| translations | translations: { [key: string]: string }; | Translations for the custom language as object please copy a example in languages folder. | + ### CookieItem interface diff --git a/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.html b/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.html index 0bc465a..e980063 100644 --- a/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.html +++ b/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.html @@ -16,6 +16,14 @@ {{ translate('language', lang) }} + diff --git a/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.scss b/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.scss index c8b5418..1a4b240 100644 --- a/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.scss +++ b/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.scss @@ -681,5 +681,9 @@ &fr { background-position: 0 -2852px; } + + &custom { + background-position: 0 -4px; + } } } diff --git a/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.ts b/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.ts index 39d7691..328cb07 100644 --- a/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.ts +++ b/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.ts @@ -3,6 +3,7 @@ import { FormBuilder, FormGroup } from '@angular/forms'; import { NgxCookieConsentService } from './services/ngx-cookie-consent/ngx-cookie-consent.service'; import { NavigationEnd, Router } from '@angular/router'; import { filter } from 'rxjs'; +import { CustomLanguageConfig } from './config/custom-language-config.interface'; @Component({ selector: 'ngx-cookie-consent', @@ -50,6 +51,10 @@ export class NgxCookieConsentComponent implements OnInit { return this.consentService.getConfig('availableLanguages'); } + get customLanguage(): CustomLanguageConfig | null { + return this.consentService.getConfig('customLanguage'); + } + get functionalCookiesAllSelected(): boolean { const arr = Object.values(this.cookieForm.get('functional')?.value); diff --git a/src/app/app.module.ts b/src/app/app.module.ts index c5d38c5..a77d329 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -27,6 +27,14 @@ import { RouterModule } from '@angular/router'; de: 'https://www.example.com/de/privacy-policy', pt: 'https://www.example.com/pt/privacy-policy', }, + customLanguage: { + languageKey: 'xx', + languageName: 'Custom', + customIconPath: null, + translations: { + back_text: 'Backxx', + } + }, functionalCookies: functionalCookies, marketingCookies: marketingCookies, essentialCookies: essentialCookies, diff --git a/src/assets/images/flag_x.svg b/src/assets/images/flag_x.svg new file mode 100644 index 0000000..a741409 --- /dev/null +++ b/src/assets/images/flag_x.svg @@ -0,0 +1,7 @@ + + + + + + + From 5672113fe3b88b339ca674b5dd2298ba6a42cb2e Mon Sep 17 00:00:00 2001 From: Giacomo Barbalinardo Date: Thu, 11 Jul 2024 18:12:55 +0200 Subject: [PATCH 5/6] update: readme updated --- README.md | 56 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index eb19e40..eec3793 100644 --- a/README.md +++ b/README.md @@ -64,29 +64,39 @@ import { NgxCookieConsentModule } from '@localia/ngx-cookie-consent'; ## Configuration -| Name | Type | Default | Description | -|-----------------------|----------------------------------|--------------------|------------------------------------------------------------------------------------| -| privacyPolicyUrl | string | TranslatableString | '#' | URL to your privacy policy ⚠ required ⚠ | -| imprintUrl | string | TranslatableString | '#' | URL to your imprint ⚠ required ⚠ | -| defaultLanguage | string | 'en' | Default language for the cookie consent banner | -| availableLanguages | string[] | ['en', 'de', 'it'] | Available languages for the cookie consent banner | -| showLanguageSwitcher | boolean | true | Show language switcher | -| showBadgeOpener | boolean | true | Show badge opener | -| openerPosition | enum | 'left-bottom' | Position of the badge eg. 'left-top', 'right-top' , 'left-bottom' , 'right-bottom' | -| customOpenerClass | string | '' | Custom class for the badge opener | -| customClass | string | '' | Custom class for the cookie consent banner | -| cookiePrefix | string | 'cookieconsent_' | Prefix for the cookie consent banner | -| cookieExpiryDays | number | 365 | Expiry days for the cookie consent banner | -| showCookieDetails | boolean | false | Show cookie details | -| showFunctionalCookies | boolean | true | Show functional cookies | -| functionalCookies | CookieItem[] | [] | Functional cookies | -| showMarketingCookies | boolean | true | Show marketing cookies | -| marketingCookies | CookieItem[] | [] | Marketing cookies | -| showEssentialCookies | boolean | true | Show essential cookies | -| essentialCookies | CookieItem[] | [] | Essential cookies | -| showOtherTools | boolean | true | Show other tools | -| otherTools | CookieItem[] | [] | Other tools | -| excludeRoutes | string[] | [] | Exclude routes eg. ['/privacy-policy'] | +| Name | Type | Default | Description | +|-----------------------|-----------------------------------|-------------------|------------------------------------------------------------------------------------| +| privacyPolicyUrl | string | TranslatableString | '#' | URL to your privacy policy ⚠ required ⚠ | +| imprintUrl | string | TranslatableString | '#' | URL to your imprint ⚠ required ⚠ | +| defaultLanguage | string | 'en' | Default language for the cookie consent banner | +| availableLanguages | string[] | ['en', 'de', 'it'] | Available languages for the cookie consent banner | +| customLanguage | CustomLanguageConfig | null | null | Custom language for the cookie consent banner | +| showLanguageSwitcher | boolean | true | Show language switcher | +| showBadgeOpener | boolean | true | Show badge opener | +| openerPosition | enum | 'left-bottom' | Position of the badge eg. 'left-top', 'right-top' , 'left-bottom' , 'right-bottom' | +| customOpenerClass | string | '' | Custom class for the badge opener | +| customClass | string | '' | Custom class for the cookie consent banner | +| cookiePrefix | string | 'cookieconsent_' | Prefix for the cookie consent banner | +| cookieExpiryDays | number | 365 | Expiry days for the cookie consent banner | +| showCookieDetails | boolean | false | Show cookie details | +| showFunctionalCookies | boolean | true | Show functional cookies | +| functionalCookies | CookieItem[] | [] | Functional cookies | +| showMarketingCookies | boolean | true | Show marketing cookies | +| marketingCookies | CookieItem[] | [] | Marketing cookies | +| showEssentialCookies | boolean | true | Show essential cookies | +| essentialCookies | CookieItem[] | [] | Essential cookies | +| showOtherTools | boolean | true | Show other tools | +| otherTools | CookieItem[] | [] | Other tools | +| excludeRoutes | string[] | [] | Exclude routes eg. ['/privacy-policy'] | + +### CustomLanguageConfig interface +| Name | Type | Description | +|----------------|------------------------------------------|-------------------------------------------------------------------------------------------| +| languageKey | string | Key for the custom language eg. 'custom' | +| languageName | string | Name for the custom language eg. 'Custom' | +| customIconPath | string | null | Path to the custom icon eg. 'assets/images/custom-icon.svg' | +| translations | translations: { [key: string]: string }; | Translations for the custom language as object please copy a example in languages folder. | + ### CookieItem interface From 14b5443b9f9c0898a255352fe4c606c131811c17 Mon Sep 17 00:00:00 2001 From: Giacomo Barbalinardo Date: Thu, 11 Jul 2024 18:13:56 +0200 Subject: [PATCH 6/6] bump: new version to 2.3.0 --- projects/ngx-cookie-consent/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/ngx-cookie-consent/package.json b/projects/ngx-cookie-consent/package.json index a654f0a..1b19368 100644 --- a/projects/ngx-cookie-consent/package.json +++ b/projects/ngx-cookie-consent/package.json @@ -1,6 +1,6 @@ { "name": "@localia/ngx-cookie-consent", - "version": "2.2.0", + "version": "2.3.0", "description": "Angular module to display a cookie consent banner without other dependencies.", "author": "Giacomo Barbalinardo ", "license": "MIT",