diff --git a/README.md b/README.md index 32b558a..48a52db 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Angular multi-language module to display a cookie consent banner without other d [![Open in Codeflow](https://developer.stackblitz.com/img/open_in_codeflow.svg)](https:///pr.new/github.com/giacomo/ngx-cookie-consent) ###### Works with Angular v14+ -###### Available languages: English, German, Italian +###### Available languages: English, German, Italian, Portuguese ## Installation @@ -55,46 +55,59 @@ import { NgxCookieConsentModule } from '@localia/ngx-cookie-consent'; ## Configuration -| Name | Type | Default | Description | -|-----------------------|----------|-------------------|------------------------------------------------------------------------------------| -| privacyPolicyUrl | string | '#' | URL to your privacy policy ⚠ required ⚠ | -| imprintUrl | string | '#' | 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' | -| 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 | +| 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' | +| 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'] | ### CookieItem interface -| Name | Type | Description | -|-------------|--------|-------------------------------------------------------------------------------------------------------------------------------------| -|key | string | Key for the cookie eg. 'functional_google_analytics' | -|name | string | Name for the cookie eg. 'Google Analytics' | -|description | string | Description for the cookie eg. 'Google Analytics is a web analytics service offered by Google that tracks and reports website traffic.' | -|privacyPolicyUrl| string | URL to the privacy policy for the cookie eg. 'https://policies.google.com/privacy' | -|cookies | CookieDetail[] | Cookie details for the cookie | +| Name | Type | Description | +|------------------|----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------| +| key | string | Key for the cookie eg. 'functional_google_analytics' | +| name | string | TranslatableString | Name for the cookie eg. 'Google Analytics' | +| description | string | TranslatableString | Description for the cookie eg. 'Google Analytics is a web analytics service offered by Google that tracks and reports website traffic.' | +| privacyPolicyUrl | string | TranslatableString | URL to the privacy policy for the cookie eg. 'https://policies.google.com/privacy' | +| cookies | CookieDetail[] | Cookie details for the cookie | ### CookieDetail interface -| Name | Type | Description | -|-------------|--------|-----------------------------------------------------------------------------| -|name | string | Name for the saved cookie eg. '_ga' | -|description | string | Description for the saved cookie eg. 'This cookie is used to distinguish users.' | -|duration | string | Duration for the saved cookie eg. '2 years' | +| Name | Type | Description | +|-------------|----------------------------------|----------------------------------------------------------------------------------| +| name | string | Name for the saved cookie eg. '_ga' | +| description | string | TranslatableString | Description for the saved cookie eg. 'This cookie is used to distinguish users.' | +| duration | string | TranslatableString | Duration for the saved cookie eg. '2 years' | + +### TranslatableString interface + +The `TranslatableString` interface is used to define a string that can be translated into multiple languages. **It is optional to use this interface. If you don't use it, the string will be used as it is.** + +> ⚠ The `TranslatableString` interface if used, will automatically fall back to defaultLanguage used if no translation key defined for the desired language. + +| Name | Type | Description | +|------|--------|-----------------------------------------| +| en | string | English string for the specified key | +| de | string | German string for the specified key | +| it | string | Italian string for the specified key | +| pt | string | Portuguese string for the specified key | ## Contributing diff --git a/projects/ngx-cookie-consent/README.md b/projects/ngx-cookie-consent/README.md index 32b558a..48a52db 100644 --- a/projects/ngx-cookie-consent/README.md +++ b/projects/ngx-cookie-consent/README.md @@ -5,7 +5,7 @@ Angular multi-language module to display a cookie consent banner without other d [![Open in Codeflow](https://developer.stackblitz.com/img/open_in_codeflow.svg)](https:///pr.new/github.com/giacomo/ngx-cookie-consent) ###### Works with Angular v14+ -###### Available languages: English, German, Italian +###### Available languages: English, German, Italian, Portuguese ## Installation @@ -55,46 +55,59 @@ import { NgxCookieConsentModule } from '@localia/ngx-cookie-consent'; ## Configuration -| Name | Type | Default | Description | -|-----------------------|----------|-------------------|------------------------------------------------------------------------------------| -| privacyPolicyUrl | string | '#' | URL to your privacy policy ⚠ required ⚠ | -| imprintUrl | string | '#' | 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' | -| 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 | +| 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' | +| 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'] | ### CookieItem interface -| Name | Type | Description | -|-------------|--------|-------------------------------------------------------------------------------------------------------------------------------------| -|key | string | Key for the cookie eg. 'functional_google_analytics' | -|name | string | Name for the cookie eg. 'Google Analytics' | -|description | string | Description for the cookie eg. 'Google Analytics is a web analytics service offered by Google that tracks and reports website traffic.' | -|privacyPolicyUrl| string | URL to the privacy policy for the cookie eg. 'https://policies.google.com/privacy' | -|cookies | CookieDetail[] | Cookie details for the cookie | +| Name | Type | Description | +|------------------|----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------| +| key | string | Key for the cookie eg. 'functional_google_analytics' | +| name | string | TranslatableString | Name for the cookie eg. 'Google Analytics' | +| description | string | TranslatableString | Description for the cookie eg. 'Google Analytics is a web analytics service offered by Google that tracks and reports website traffic.' | +| privacyPolicyUrl | string | TranslatableString | URL to the privacy policy for the cookie eg. 'https://policies.google.com/privacy' | +| cookies | CookieDetail[] | Cookie details for the cookie | ### CookieDetail interface -| Name | Type | Description | -|-------------|--------|-----------------------------------------------------------------------------| -|name | string | Name for the saved cookie eg. '_ga' | -|description | string | Description for the saved cookie eg. 'This cookie is used to distinguish users.' | -|duration | string | Duration for the saved cookie eg. '2 years' | +| Name | Type | Description | +|-------------|----------------------------------|----------------------------------------------------------------------------------| +| name | string | Name for the saved cookie eg. '_ga' | +| description | string | TranslatableString | Description for the saved cookie eg. 'This cookie is used to distinguish users.' | +| duration | string | TranslatableString | Duration for the saved cookie eg. '2 years' | + +### TranslatableString interface + +The `TranslatableString` interface is used to define a string that can be translated into multiple languages. **It is optional to use this interface. If you don't use it, the string will be used as it is.** + +> ⚠ The `TranslatableString` interface if used, will automatically fall back to defaultLanguage used if no translation key defined for the desired language. + +| Name | Type | Description | +|------|--------|-----------------------------------------| +| en | string | English string for the specified key | +| de | string | German string for the specified key | +| it | string | Italian string for the specified key | +| pt | string | Portuguese string for the specified key | ## Contributing diff --git a/projects/ngx-cookie-consent/package.json b/projects/ngx-cookie-consent/package.json index fb66649..341c804 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": "1.0.3", + "version": "1.1.0", "description": "Angular module to display a cookie consent banner without other dependencies.", "author": "Giacomo Barbalinardo ", "license": "MIT", diff --git a/projects/ngx-cookie-consent/src/lib/config/cookie-detail.interface.ts b/projects/ngx-cookie-consent/src/lib/config/cookie-detail.interface.ts index d76ab93..b9867ba 100644 --- a/projects/ngx-cookie-consent/src/lib/config/cookie-detail.interface.ts +++ b/projects/ngx-cookie-consent/src/lib/config/cookie-detail.interface.ts @@ -1,5 +1,7 @@ +import { TranslatableString } from './translatable-string.interface'; + export interface CookieDetail { name: string; - description: string; - duration: string; + description: string | TranslatableString; + duration: string | TranslatableString; } diff --git a/projects/ngx-cookie-consent/src/lib/config/cookie-item.interface.ts b/projects/ngx-cookie-consent/src/lib/config/cookie-item.interface.ts index c29f911..c092f46 100644 --- a/projects/ngx-cookie-consent/src/lib/config/cookie-item.interface.ts +++ b/projects/ngx-cookie-consent/src/lib/config/cookie-item.interface.ts @@ -1,9 +1,10 @@ import { CookieDetail } from './cookie-detail.interface'; +import { TranslatableString } from './translatable-string.interface'; export interface CookieItem { key: string; - name: string; - description: string; - privacyPolicyUrl: string; + name: string | TranslatableString; + description: string | TranslatableString; + privacyPolicyUrl: string | TranslatableString; cookies: CookieDetail[]; } diff --git a/projects/ngx-cookie-consent/src/lib/config/ngx-cookie-consent-config.service.spec.ts b/projects/ngx-cookie-consent/src/lib/config/ngx-cookie-consent-config.service.spec.ts index 12db5ac..18645a3 100644 --- a/projects/ngx-cookie-consent/src/lib/config/ngx-cookie-consent-config.service.spec.ts +++ b/projects/ngx-cookie-consent/src/lib/config/ngx-cookie-consent-config.service.spec.ts @@ -18,7 +18,7 @@ describe('NgxCookieConsentConfigService', () => { expect(service.privacyPolicyUrl).toEqual('#'); expect(service.imprintUrl).toEqual('#'); expect(service.defaultLanguage).toEqual('en'); - expect(service.availableLanguages).toEqual(['en', 'de', 'it']); + expect(service.availableLanguages).toEqual(['en', 'de', 'it', 'pt']); expect(service.showLanguageSwitcher).toEqual(true); expect(service.showBadgeOpener).toEqual(true); expect(service.openerPosition).toEqual('left-bottom'); 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 a5ea1a1..0c2e5ae 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,14 +1,15 @@ import { Injectable } from '@angular/core'; import { CookieItem } from './cookie-item.interface'; +import { TranslatableString } from './translatable-string.interface'; @Injectable({ providedIn: 'root' }) export class NgxCookieConsentConfigService { - privacyPolicyUrl?: string = '#'; - imprintUrl?: string = '#'; + privacyPolicyUrl?: string | TranslatableString = '#'; + imprintUrl?: string | TranslatableString = '#'; defaultLanguage?: string = 'en'; - availableLanguages?: string[] = ['en', 'de', 'it']; + availableLanguages?: string[] = ['en', 'de', 'it', 'pt']; showLanguageSwitcher?: boolean = true; showBadgeOpener?: boolean = true; openerPosition?: 'left-top' | 'right-top' | 'left-bottom' | 'right-bottom' = 'left-bottom'; diff --git a/projects/ngx-cookie-consent/src/lib/config/translatable-string.interface.ts b/projects/ngx-cookie-consent/src/lib/config/translatable-string.interface.ts new file mode 100644 index 0000000..269ce15 --- /dev/null +++ b/projects/ngx-cookie-consent/src/lib/config/translatable-string.interface.ts @@ -0,0 +1,3 @@ +export interface TranslatableString { + [languageKey: string]: string; +} diff --git a/projects/ngx-cookie-consent/src/lib/languages/index.ts b/projects/ngx-cookie-consent/src/lib/languages/index.ts index d3d16e9..60437b6 100644 --- a/projects/ngx-cookie-consent/src/lib/languages/index.ts +++ b/projects/ngx-cookie-consent/src/lib/languages/index.ts @@ -1,4 +1,5 @@ // export all available languages -export { lang_en } from './en.language' -export { lang_de } from './de.language' -export { lang_it } from './it.language' +export { lang_en } from './en.language'; +export { lang_de } from './de.language'; +export { lang_it } from './it.language'; +export { lang_pt } from './pt.language'; diff --git a/projects/ngx-cookie-consent/src/lib/languages/pt.language.ts b/projects/ngx-cookie-consent/src/lib/languages/pt.language.ts new file mode 100644 index 0000000..67e567b --- /dev/null +++ b/projects/ngx-cookie-consent/src/lib/languages/pt.language.ts @@ -0,0 +1,30 @@ +export const lang_pt: { [key: string]: string } = { + language: 'Português', + title: 'Nós valorizamos sua privacidade', + text: 'Nós e nossos parceiros usamos tecnologias como cookies ou direcionamento e processamos dados pessoais como endereço IP ou informações do navegador para personalizar os anúncios que exibimos. Essas tecnologias podem acessar seu dispositivo e nos ajudar a mostrar anúncios mais relevantes e melhorar sua experiência no site. Também usamos essas tecnologias para medir resultados ou direcionar melhor o conteúdo do nosso site. Como valorizamos sua privacidade, pedimos seu consentimento para usar as seguintes tecnologias.', + right_bottom: 'Você pode alterar/revogar isso a qualquer momento clicando no botão Configurações no canto inferior direito da página.', + left_bottom: 'Você pode alterar/revogar isso a qualquer momento clicando no botão Configurações no canto inferior esquerdo da página.', + right_top: 'Você pode alterar/revogar isso a qualquer momento clicando no botão Configurações no canto superior direito da página.', + left_top: 'Você pode alterar/revogar isso a qualquer momento clicando no botão Configurações no canto superior esquerdo da página.', + privacy_text: 'Política de Privacidade', + imprint_text: 'Dados da Empresa', + privacy_settings_text: 'Configuração de Privacidade', + privacy_settings_title: 'Configuração de Privacidade', + privacy_settings_title_text: 'Esta ferramenta ajuda você a selecionar e desativar vários cookies, rastreadores e ferramentas de análise usadas neste site.', + functional_title: 'Funcional', + functional_description: 'Esses cookies nos permitem analisar o uso do site para que possamos medir e melhorar seu desempenho.', + marketing_title: 'Marketing', + marketing_description: 'Os cookies de marketing geralmente são usados para mostrar anúncios que atendem aos seus interesses. Quando você visita outro site, o cookie do seu navegador é reconhecido e os anúncios selecionados são exibidos para você com base nas informações armazenadas neste cookie (art. 6 par. 1 p. 1 a) GDPR).', + essential_title: 'Essencial', + essential_description: 'Esses cookies são necessários para as funções básicas do site.', + other_title: 'Outros', + other_description: 'Dentro de nossa organização, usamos outras ferramentas para processamento de dados. Estes também estão listados aqui para fins informativos. No entanto, os dados são coletados somente após uma determinada interação, por exemplo, quando você concorda com uma demonstração. Se você deseja se opor ao processamento de dados por esses processadores, entre em contato conosco.', + save_text: 'Salvar', + accept_text: 'Aceitar e fechar', + decline_text: 'Recusar', + choose_language_text: 'Selecionar linguagem', + back_text: 'Voltar', + cookie_name: 'Nome', + cookie_description: 'Descrição', + cookie_duration: 'Duração', +}; 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 130cc40..ef9db71 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 @@ -84,16 +84,16 @@

{{ translate('functional_title') }}

'icon--arrow-down': functionalCookiesClosed, 'icon--arrow-up': !functionalCookiesClosed }" (click)="functionalCookiesClosed = !functionalCookiesClosed" - *ngIf="config('functionalCookies').length > 0"> + *ngIf="config('functionalCookies').length > 0">
-
{{ functional.name }}
-
{{ functional.description }}
- {{ functional.privacyPolicyUrl }} +
{{ translate_o(functional.name) }}
+
{{ translate_o(functional.description) }}
+ {{ translate_o(functional.privacyPolicyUrl) }}
@@ -105,8 +105,8 @@
{{ functional.name }}
{{ translate('cookie_name') }}: {{ functionalCookie.name }}
-
{{ translate('cookie_description') }}: {{ functionalCookie.description }}
-
{{ translate('cookie_duration') }}: {{ functionalCookie.duration }}
+
{{ translate('cookie_description') }}: {{ translate_o(functionalCookie.description) }}
+
{{ translate('cookie_duration') }}: {{ translate_o(functionalCookie.duration) }}
@@ -131,16 +131,16 @@

{{ translate('marketing_title') }}

'icon--arrow-down': marketingCookiesClosed, 'icon--arrow-up': !marketingCookiesClosed }" (click)="marketingCookiesClosed = !marketingCookiesClosed" - *ngIf="config('marketingCookies').length > 0"> + *ngIf="config('marketingCookies').length > 0">
-
{{ marketing.name }}
-
{{ marketing.description }}
- {{ marketing.privacyPolicyUrl }} +
{{ translate_o(marketing.name) }}
+
{{ translate_o(marketing.description) }}
+ {{ translate_o(marketing.privacyPolicyUrl) }}
@@ -152,8 +152,8 @@
{{ marketing.name }}
{{ translate('cookie_name') }}: {{ marketingCookie.name }}
-
{{ translate('cookie_description') }}: {{ marketingCookie.description }}
-
{{ translate('cookie_duration') }}: {{ marketingCookie.duration }}
+
{{ translate('cookie_description') }}: {{ translate_o(marketingCookie.description) }}
+
{{ translate('cookie_duration') }}: {{ translate_o(marketingCookie.duration) }}
@@ -184,9 +184,9 @@

{{ translate('essential_title') }}

-
{{ essential.name }}
-
{{ essential.description }}
- {{ essential.privacyPolicyUrl }} +
{{ translate_o(essential.name) }}
+
{{ translate_o(essential.description) }}
+ {{ translate_o(essential.privacyPolicyUrl) }}
@@ -198,8 +198,8 @@
{{ essential.name }}
{{ translate('cookie_name') }}: {{ essentialCookie.name }}
-
{{ translate('cookie_description') }}: {{ essentialCookie.description }}
-
{{ translate('cookie_duration') }}: {{ essentialCookie.duration }}
+
{{ translate('cookie_description') }}: {{ translate_o(essentialCookie.description) }}
+
{{ translate('cookie_duration') }}: {{ translate_o(essentialCookie.duration) }}
@@ -223,16 +223,16 @@

{{ translate('other_title') }}

'icon--arrow-down': otherToolsClosed, 'icon--arrow-up': !otherToolsClosed }" (click)="otherToolsClosed = !otherToolsClosed" - *ngIf="config('otherTools').length > 0"> + *ngIf="config('otherTools').length > 0">
-
{{ other.name }}
-
{{ other.description }}
- {{ other.privacyPolicyUrl }} +
{{ translate_o(other.name) }}
+
{{ translate_o(other.description) }}
+ {{ translate_o(other.privacyPolicyUrl) }}
@@ -244,8 +244,8 @@
{{ other.name }}
{{ translate('cookie_name') }}: {{ otherCookie.name }}
-
{{ translate('cookie_description') }}: {{ otherCookie.description }}
-
{{ translate('cookie_duration') }}: {{ otherCookie.duration }}
+
{{ translate('cookie_description') }}: {{ translate_o(otherCookie.description) }}
+
{{ translate('cookie_duration') }}: {{ translate_o(otherCookie.duration) }}
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 1de0c08..49fcf64 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 @@ -13,7 +13,7 @@ bottom: 0; left: 0; right: 0; - background-color: rgba(33, 41, 52, .85); + background-color: rgba(33, 41, 52, 0.85); display: flex; flex-direction: column; align-items: center; @@ -100,13 +100,13 @@ } &__modal { - font-family: 'Lato', sans-serif; + font-family: "Lato", sans-serif; display: block; max-width: 560px; background-color: #ffffff; border-radius: 4px; padding: 4rem 6rem; - box-shadow: 0 1px 3px rgba(33, 41, 52, .75); + box-shadow: 0 1px 3px rgba(33, 41, 52, 0.75); overflow-y: auto; position: relative; box-sizing: content-box; @@ -135,7 +135,6 @@ max-width: 32px; } - &__footer { padding-top: 1rem; } @@ -167,7 +166,7 @@ background-color: #368bd6; border: 2px solid #368bd6; border-radius: 3px; - box-shadow: 0 1px 1px 0 rgba(0, 0, 0, .2); + box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.2); box-sizing: border-box; color: #fff; flex: 1 0 auto !important; @@ -178,7 +177,7 @@ padding: 0 13px; text-decoration: none; text-transform: uppercase; - transition: all .2s ease-in-out; + transition: all 0.2s ease-in-out; white-space: nowrap; cursor: pointer; @@ -225,7 +224,6 @@ } } - .consent_purposes { text-align: left; display: none; @@ -296,7 +294,7 @@ width: 18px; background-color: #fff; border-radius: 10px; - transition: all .5s ease; + transition: all 0.5s ease; } } @@ -330,12 +328,12 @@ input[type="checkbox"] { &:checked { + label { - background-color: #5DD56E; - border: 1px solid #5DD56E; + background-color: #5dd56e; + border: 1px solid #5dd56e; &:after { left: 14px; - border: 1px solid #5DD56E; + border: 1px solid #5dd56e; } } } @@ -371,12 +369,12 @@ input[type="checkbox"] { &:checked { + label { - background-color: #5DD56E; - border: 1px solid #5DD56E; + background-color: #5dd56e; + border: 1px solid #5dd56e; &:after { left: 18px; - border: 1px solid #5DD56E; + border: 1px solid #5dd56e; } } } @@ -403,7 +401,7 @@ &:after { text-indent: 40px; - content: 'OFF'; + content: "OFF"; font-size: 14px; color: #dfdfdf; font-family: Arial, sans-serif; @@ -415,7 +413,7 @@ &:after { left: 60px; text-indent: -50px; - content: 'ON'; + content: "ON"; font-size: 14px; color: #dfdfdf; font-family: Arial, sans-serif; @@ -467,14 +465,14 @@ .dropdown { max-width: 160px; border-radius: 4px; - background-color: #FFFFFF; + background-color: #ffffff; height: 0; overflow: hidden; &--active { height: auto; border: 1px solid rgba(0, 0, 0, 0.2); - box-shadow: 0 0 10px rgba(0, 0, 0, 0.2) + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); } &__item { @@ -519,17 +517,17 @@ } &--arrow-down { - background-image: url('../assets/down.svg'); + background-image: url("../assets/down.svg"); } &--arrow-up { - background-image: url('../assets/down.svg'); + background-image: url("../assets/down.svg"); transform: rotate(180deg); } &--language { display: inline-block; - background-image: url('../assets/language-icon.svg'); + background-image: url("../assets/language-icon.svg"); } } @@ -583,7 +581,7 @@ background-color: #f2f2f2; border-radius: 6px; margin: 0 8px 16px 8px; - font-size: .8rem; + font-size: 0.8rem; color: #686868; .detail__item { @@ -634,9 +632,7 @@ display: block; } - &--closed { - .block__header { border-radius: 4px 4px 4px 4px; border-bottom: none; @@ -651,7 +647,7 @@ } .flag-icon { - background-image: url('../assets/flags.png'); + background-image: url("../assets/flags.png"); background-size: cover; background-repeat: no-repeat; display: inline-block; @@ -663,19 +659,23 @@ &.flag- { &ru { - background-position:0 -6212px; + background-position: 0 -6212px; } &en { - background-position:0 -2916px; + background-position: 0 -2916px; } &it { - background-position:0 -3844px; + background-position: 0 -3844px; } &de { - background-position:0 -2308px; + background-position: 0 -2308px; + } + + &pt { + background-position: 0 -1604px; } } } diff --git a/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.spec.ts b/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.spec.ts index 7838308..39331c6 100644 --- a/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.spec.ts +++ b/projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.component.spec.ts @@ -146,6 +146,22 @@ describe('NgxCookieConsentComponent', () => { expect(consentServiceMock.getTranslation).toHaveBeenCalledWith('some key', 'en'); }); + it('should get translation for object from consent service', () => { + const consentServiceMock = TestBed.inject(NgxCookieConsentService); + spyOn(consentServiceMock, 'getTranslationFromObject').and.returnValue('some translation'); + + expect(component.translate_o('some key')).toEqual('some translation'); + expect(consentServiceMock.getTranslationFromObject).toHaveBeenCalledWith('some key', undefined); + }); + + it('should get translation from consent service with language', () => { + const consentServiceMock = TestBed.inject(NgxCookieConsentService); + spyOn(consentServiceMock, 'getTranslationFromObject').and.returnValue('some translation'); + + expect(component.translate_o('some key', 'en')).toEqual('some translation'); + expect(consentServiceMock.getTranslationFromObject).toHaveBeenCalledWith('some key', 'en'); + }); + it('should get config from consent service', () => { const consentServiceMock = TestBed.inject(NgxCookieConsentService); spyOn(consentServiceMock, 'getConfig').and.returnValue('some config'); 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 554d74b..39d7691 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 @@ -7,7 +7,7 @@ import { filter } from 'rxjs'; @Component({ selector: 'ngx-cookie-consent', templateUrl: './ngx-cookie-consent.component.html', - styleUrls: ['./ngx-cookie-consent.component.scss'] + styleUrls: ['./ngx-cookie-consent.component.scss'], }) export class NgxCookieConsentComponent implements OnInit { cookieConsentVisible = false; @@ -19,8 +19,8 @@ export class NgxCookieConsentComponent implements OnInit { otherToolsClosed = true; cookieForm: FormGroup; private cookieFields: { - functional: {key: string, selected: boolean}[], - marketing: {key: string, selected: boolean}[], + functional: { key: string; selected: boolean }[], + marketing: { key: string; selected: boolean }[], }; constructor( @@ -37,11 +37,13 @@ export class NgxCookieConsentComponent implements OnInit { } get privacyPolicyUrl(): string { - return this.consentService.getConfig('privacyPolicyUrl'); + const config = this.consentService.getConfig('privacyPolicyUrl'); + return this.consentService.getTranslationFromObject(config); } get imprintUrl(): string { - return this.consentService.getConfig('imprintUrl'); + const config = this.consentService.getConfig('imprintUrl'); + return this.consentService.getTranslationFromObject(config); } get availableLanguages(): string[] { @@ -55,7 +57,7 @@ export class NgxCookieConsentComponent implements OnInit { return false; } - return arr.every(value => value === true); + return arr.every((value) => value === true); } get marketingCookiesAllSelected(): boolean { @@ -65,13 +67,17 @@ export class NgxCookieConsentComponent implements OnInit { return false; } - return arr.every(value => value === true); + return arr.every((value) => value === true); } translate(key: string, translationLang?: string): string { return this.consentService.getTranslation(key, translationLang); } + translate_o(key: string | object, translationLang?: string): string { + return this.consentService.getTranslationFromObject(key, translationLang); + } + config(key: string) { return this.consentService.getConfig(key); } @@ -85,12 +91,15 @@ export class NgxCookieConsentComponent implements OnInit { const fields: any = this.consentService.getCookieFields(); const cookies = fields[category]; cookies.forEach((field: any) => { - this.cookieForm.get(category)?.get(field.key)?.setValue($event.currentTarget.checked); + this.cookieForm + .get(category) + ?.get(field.key) + ?.setValue($event.currentTarget.checked); }); } back() { - this.showSettingsDialog = false + this.showSettingsDialog = false; this.resetDropdowns(); this.resetForm(); } @@ -119,9 +128,9 @@ export class NgxCookieConsentComponent implements OnInit { }); } - private buildCookieFields(fields: { key: string, selected: boolean }[]) { + private buildCookieFields(fields: { key: string; selected: boolean }[]) { const group: any = {}; - fields.forEach(field => { + fields.forEach((field) => { group[field.key] = this.formBuilder.control(field.selected); }); @@ -131,13 +140,15 @@ export class NgxCookieConsentComponent implements OnInit { private resetForm() { const fields: any = this.consentService.getCookieFields(); const categoryKeys = Object.keys(fields); - categoryKeys.forEach(categoryKey => { + categoryKeys.forEach((categoryKey) => { const category = fields[categoryKey]; category.forEach((field: any) => { - this.cookieForm.get(categoryKey)?.get(field.key)?.setValue(field.selected); + this.cookieForm + .get(categoryKey) + ?.get(field.key) + ?.setValue(field.selected); }); }); - } private resetDropdowns() { @@ -154,28 +165,32 @@ export class NgxCookieConsentComponent implements OnInit { } ngOnInit(): void { - this.router.events.pipe( - filter(event => event instanceof NavigationEnd) - ).subscribe({ + this.router.events + .pipe(filter((event) => event instanceof NavigationEnd)) + .subscribe({ next: (event: any) => { - const excludedRoutes = this.consentService.getConfig('excludeRoutes'); + const excludedRoutes = + this.consentService.getConfig('excludeRoutes'); const realPath = event.urlAfterRedirects.split('?')[0]; if (excludedRoutes.includes(realPath)) { this.cookieConsentVisible = false; } else { - this.cookieConsentVisible = this.consentService.shouldDisplayCookieConsent(); + this.cookieConsentVisible = + this.consentService.shouldDisplayCookieConsent(); } }, - } - ); + }); } closeDropDown($event: Event) { const eventTarget = $event.target as HTMLElement; const parentTarget = eventTarget.parentElement as HTMLElement; - if (eventTarget.classList.contains('language-chooser') || parentTarget.classList.contains('language-chooser')) { + if ( + eventTarget.classList.contains('language-chooser') || + parentTarget.classList.contains('language-chooser') + ) { return; } diff --git a/projects/ngx-cookie-consent/src/lib/services/ngx-cookie-consent/ngx-cookie-consent.service.spec.ts b/projects/ngx-cookie-consent/src/lib/services/ngx-cookie-consent/ngx-cookie-consent.service.spec.ts index b2bee99..2a74881 100644 --- a/projects/ngx-cookie-consent/src/lib/services/ngx-cookie-consent/ngx-cookie-consent.service.spec.ts +++ b/projects/ngx-cookie-consent/src/lib/services/ngx-cookie-consent/ngx-cookie-consent.service.spec.ts @@ -32,6 +32,22 @@ describe('NgxCookieConsentService', () => { expect(languageService.getTranslation).toHaveBeenCalledWith('test', 'de'); }); + it('should get a translationFromObject from languageService', () => { + const languageService = TestBed.inject(NgxLanguageService); + spyOn(languageService, 'getTranslationFromObject').and.returnValue('test'); + + expect(service.getTranslationFromObject('test')).toEqual('test'); + expect(languageService.getTranslationFromObject).toHaveBeenCalledWith('test', 'en'); + }); + + it('should get a translationFromObject from languageService with a different language', () => { + const languageService = TestBed.inject(NgxLanguageService); + spyOn(languageService, 'getTranslationFromObject').and.returnValue('test'); + + expect(service.getTranslationFromObject('test', 'de')).toEqual('test'); + expect(languageService.getTranslationFromObject).toHaveBeenCalledWith('test', 'de'); + }); + it('should get a config value', () => { expect(service.getConfig('defaultLanguage')).toEqual('en'); }); diff --git a/projects/ngx-cookie-consent/src/lib/services/ngx-cookie-consent/ngx-cookie-consent.service.ts b/projects/ngx-cookie-consent/src/lib/services/ngx-cookie-consent/ngx-cookie-consent.service.ts index fa09936..cc858ce 100644 --- a/projects/ngx-cookie-consent/src/lib/services/ngx-cookie-consent/ngx-cookie-consent.service.ts +++ b/projects/ngx-cookie-consent/src/lib/services/ngx-cookie-consent/ngx-cookie-consent.service.ts @@ -24,6 +24,11 @@ export class NgxCookieConsentService { return this.languageService.getTranslation(key, lang); } + getTranslationFromObject(obj: any, translationLang?: string): string { + const lang = translationLang || this.activeLang; + return this.languageService.getTranslationFromObject(obj, lang); + } + getConfig(key: string): any { return (this.cookieConsentConfig as any)[key]; } 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 447c3e9..4562569 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 @@ -18,10 +18,11 @@ describe('NgxLanguageService', () => { const translations = service.translations; expect(translations).toBeTruthy(); - expect(Object.keys(translations).length).toBe(3); + expect(Object.keys(translations).length).toBe(4); expect(translations.hasOwnProperty('lang_en')).toBeTruthy(); expect(translations.hasOwnProperty('lang_de')).toBeTruthy(); expect(translations.hasOwnProperty('lang_it')).toBeTruthy(); + expect(translations.hasOwnProperty('lang_pt')).toBeTruthy(); }); it('should contain default language', () => { @@ -45,4 +46,24 @@ describe('NgxLanguageService', () => { const translation = service.getTranslation('other_title', 'de'); expect(translation).toBe('Andere'); }); + + 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'); + }); + + it('should return a translation from an object fallback language', () => { + const translation = service.getTranslationFromObject({en: 'Other', de: 'Andere'}); + 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 empty string translation from an object while no fallback language', () => { + const translation = service.getTranslationFromObject({fr: 'Autre'}); + expect(translation).toBe(''); + }); }); 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 2594a4d..7ef4bc4 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 @@ -24,4 +24,21 @@ export class NgxLanguageService { return this.translations[this.translationKey][sanitizedKey] || ''; } + + getTranslationFromObject(obj: any, translationLang?: string): string { + if (typeof obj === 'string') { + return obj; + } + + if (translationLang && obj.hasOwnProperty(translationLang)) { + return obj[translationLang]; + } + + const fallback = this.translationKey.replace('lang_', ''); + if (obj.hasOwnProperty(fallback)) { + return obj[fallback]; + } + + return ''; + } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index c3ad3c9..c5d38c5 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -4,36 +4,38 @@ import { NgxCookieConsentModule } from 'projects/ngx-cookie-consent/src/public-a import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; -import { essentialCookies, functionalCookies, marketingCookies, otherTools } from './cookie.config'; +import { + essentialCookies, + functionalCookies, + marketingCookies, + otherTools, +} from './cookie.config'; import { HomeComponent } from './pages/home/home.component'; import { AboutComponent } from './pages/about/about.component'; import { RouterModule } from '@angular/router'; - - @NgModule({ - declarations: [ - AppComponent, - HomeComponent, - AboutComponent, - ], + declarations: [AppComponent, HomeComponent, AboutComponent], imports: [ BrowserModule, RouterModule, AppRoutingModule, NgxCookieConsentModule.forRoot({ imprintUrl: 'https://www.example.com/imprint', - privacyPolicyUrl: 'https://www.example.com/privacy-policy', + privacyPolicyUrl: { + en: 'https://www.example.com/privacy-policy', + de: 'https://www.example.com/de/privacy-policy', + pt: 'https://www.example.com/pt/privacy-policy', + }, functionalCookies: functionalCookies, marketingCookies: marketingCookies, essentialCookies: essentialCookies, otherTools: otherTools, showCookieDetails: true, - excludeRoutes: ['/about'] + excludeRoutes: ['/about'], }), ], providers: [], - bootstrap: [AppComponent] + bootstrap: [AppComponent], }) -export class AppModule { -} +export class AppModule {} diff --git a/src/app/cookie.config.ts b/src/app/cookie.config.ts index b5954d1..f3b3560 100644 --- a/src/app/cookie.config.ts +++ b/src/app/cookie.config.ts @@ -12,8 +12,17 @@ export const marketingCookies = [ { key: 'marketing_google_analytics', name: 'Google Analytics', - description: 'Google Analytics is a web analytics service offered by Google that tracks and reports website traffic.', - privacyPolicyUrl: 'https://policies.google.com/privacy', + description: { + en: 'Google Analytics is a web analytics service offered by Google that tracks and reports website traffic.', + de: 'Google Analytics ist ein Webanalysedienst von Google, der Website-Traffic erfasst und berichtet.', + pt: 'Google Analytics é um serviço de análise da web oferecido pela Google que rastreia e relata o tráfego do site.' + }, + privacyPolicyUrl: { + en: 'https://policies.google.com/privacy', + de: 'https://policies.google.com/privacy?hl=de', + it: 'https://policies.google.com/privacy?hl=it', + pt: 'https://policies.google.com/privacy?hl=pt' + }, cookies: [ { name: '_ga', diff --git a/src/app/pages/about/about.component.spec.ts b/src/app/pages/about/about.component.spec.ts index c53fb84..339d18b 100644 --- a/src/app/pages/about/about.component.spec.ts +++ b/src/app/pages/about/about.component.spec.ts @@ -2,6 +2,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { AboutComponent } from './about.component'; import { RouterTestingModule } from '@angular/router/testing'; +import { NgxCookieConsentModule } from '../../../../projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.module'; describe('AboutComponent', () => { let component: AboutComponent; @@ -10,7 +11,10 @@ describe('AboutComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [AboutComponent], - imports: [RouterTestingModule], + imports: [ + RouterTestingModule, + NgxCookieConsentModule.forRoot({}), + ], }) .compileComponents(); diff --git a/src/app/pages/home/home.component.spec.ts b/src/app/pages/home/home.component.spec.ts index 483268b..5f0edbf 100644 --- a/src/app/pages/home/home.component.spec.ts +++ b/src/app/pages/home/home.component.spec.ts @@ -2,6 +2,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HomeComponent } from './home.component'; import { RouterTestingModule } from '@angular/router/testing'; +import { NgxCookieConsentModule } from '../../../../projects/ngx-cookie-consent/src/lib/ngx-cookie-consent.module'; describe('HomeComponent', () => { let component: HomeComponent; @@ -10,7 +11,10 @@ describe('HomeComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [HomeComponent], - imports: [RouterTestingModule], + imports: [ + RouterTestingModule, + NgxCookieConsentModule.forRoot({}), + ], }) .compileComponents();