feat: third-party-scripts blockieren (server + client-guard)
Loest die YouTube/Vimeo-API-Luecke: viele dienste laden ueber <script> (z. B. youtube.com/iframe_api, www-widgetapi.js, analytics) statt iframes - oft per JavaScript nachgeladen, daher fuer den scanner unsichtbar. - Pro dienst aktivierbar ueber das (umbenannte) feld "Zugehoerige Skripte blockieren (z. B. YouTube-/Vimeo-API)" = das vorhandene loads_script-flag. Presets (YouTube, Vimeo, Maps) haben es bereits an. - Server-seitig: passende <script src> werden zu type="text/plain" (src -> data-cb-src) neutralisiert, laden also nicht. - Client-seitig: winziger guard ganz frueh im <head> patcht appendChild/insertBefore/replaceChild und neutralisiert dynamisch injizierte scripts VOR dem einfuegen -> kein request. Faengt damit auch die per JS nachgeladene iframe_api ab. - Einwilligung (per-dienst-consent, z. B. ueber den video-platzhalter) schaltet die scripts via cbActivateScripts frei und laedt sie nach. - Neuer shortcode [content_blocker_consent id="…"] als einwilligungs-button fuer reine skript-dienste ohne sichtbaren platzhalter. - guard-logik mit DOM-mock getestet (block + reinject), server-regex isoliert geprueft. i18n DE/EN ergaenzt (127 strings). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -26,8 +26,26 @@
|
|||||||
} catch ( e ) {
|
} catch ( e ) {
|
||||||
// localStorage unavailable; allow the load for this session only.
|
// localStorage unavailable; allow the load for this session only.
|
||||||
}
|
}
|
||||||
|
// Release any third-party <script> blocked for this service (handled by
|
||||||
|
// the early head guard, which exposes cbActivateScripts).
|
||||||
|
if ( typeof window.cbActivateScripts === 'function' ) {
|
||||||
|
window.cbActivateScripts( serviceId );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public: grant consent for a service from a custom control
|
||||||
|
* ([content_blocker_consent]) — used for script-only services that have no
|
||||||
|
* visible embed. Reloads so blocked scripts/embeds load cleanly.
|
||||||
|
*/
|
||||||
|
window.cbConsent = function ( serviceId ) {
|
||||||
|
if ( ! serviceId ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
grantConsent( serviceId );
|
||||||
|
window.location.reload();
|
||||||
|
};
|
||||||
|
|
||||||
/* ───────────────────────── iframe loading ────────────────────────── */
|
/* ───────────────────────── iframe loading ────────────────────────── */
|
||||||
|
|
||||||
/** Replace a .cb-blocker element with the real iframe. src comes from data-src. */
|
/** Replace a .cb-blocker element with the real iframe. src comes from data-src. */
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Plugin Name: GDPR Content Blocker
|
* Plugin Name: GDPR Content Blocker
|
||||||
* Plugin URI: https://lucas-orth.de
|
* Plugin URI: https://lucas-orth.de
|
||||||
* Description: DSGVO-konformer Consent-Blocker für externe iframes. Lädt Drittinhalte erst nach aktiver Einwilligung.
|
* Description: DSGVO-konformer Consent-Blocker für externe iframes. Lädt Drittinhalte erst nach aktiver Einwilligung.
|
||||||
* Version: 1.3.0
|
* Version: 1.4.0
|
||||||
* Author: Lucas Orth
|
* Author: Lucas Orth
|
||||||
* Author URI: https://lucas-orth.de
|
* Author URI: https://lucas-orth.de
|
||||||
* Text Domain: gdpr-content-blocker
|
* Text Domain: gdpr-content-blocker
|
||||||
|
|||||||
@@ -47,23 +47,78 @@ class CB_Autodetect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static function process( string $html, array $services ): string {
|
public static function process( string $html, array $services ): string {
|
||||||
if ( $html === '' || stripos( $html, '<iframe' ) === false ) {
|
if ( $html === '' ) {
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locate iframe blocks only. Attribute parsing happens via DOMDocument below.
|
// Pass 1 — iframes: replace matched embeds with a consent placeholder.
|
||||||
$out = preg_replace_callback(
|
if ( stripos( $html, '<iframe' ) !== false ) {
|
||||||
'#<iframe\b[^>]*>.*?</iframe>#is',
|
$out = preg_replace_callback(
|
||||||
function ( array $m ) use ( $services ): string {
|
'#<iframe\b[^>]*>.*?</iframe>#is',
|
||||||
return self::maybe_replace_iframe( $m[0], $services );
|
function ( array $m ) use ( $services ): string {
|
||||||
},
|
return self::maybe_replace_iframe( $m[0], $services );
|
||||||
$html
|
},
|
||||||
);
|
$html
|
||||||
|
);
|
||||||
|
// On a PCRE error (e.g. backtrack/recursion limit on a huge page),
|
||||||
|
// preg_replace_callback returns null. Never blank the page.
|
||||||
|
if ( $out !== null ) {
|
||||||
|
$html = $out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// On a PCRE error (e.g. backtrack/recursion limit on a huge page),
|
// Pass 2 — scripts: neutralise <script src> of services that block scripts
|
||||||
// preg_replace_callback returns null. Never blank the page — fall back to
|
// so they don't execute/fetch until consent (the JS guard re-injects them).
|
||||||
// the original, unmodified HTML.
|
$script_services = array_values( array_filter(
|
||||||
return $out === null ? $html : $out;
|
$services,
|
||||||
|
static fn( $s ) => ! empty( $s['loads_script'] )
|
||||||
|
) );
|
||||||
|
if ( $script_services && stripos( $html, '<script' ) !== false ) {
|
||||||
|
$out = preg_replace_callback(
|
||||||
|
'#<script\b[^>]*\bsrc\s*=\s*["\'][^"\']+["\'][^>]*>#i',
|
||||||
|
function ( array $m ) use ( $script_services ): string {
|
||||||
|
return self::maybe_block_script( $m[0], $script_services );
|
||||||
|
},
|
||||||
|
$html
|
||||||
|
);
|
||||||
|
if ( $out !== null ) {
|
||||||
|
$html = $out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Neutralise a <script src="…"> opening tag if its src matches a script-
|
||||||
|
* blocking service: rename src→data-cb-src, force type="text/plain", and tag
|
||||||
|
* it with the service id. The early head guard re-injects it on consent.
|
||||||
|
*/
|
||||||
|
private static function maybe_block_script( string $tag, array $services ): string {
|
||||||
|
if ( ! preg_match( '/\bsrc\s*=\s*["\']([^"\']+)["\']/i', $tag, $m ) ) {
|
||||||
|
return $tag;
|
||||||
|
}
|
||||||
|
$src = str_replace( '&', '&', $m[1] );
|
||||||
|
|
||||||
|
foreach ( $services as $svc ) {
|
||||||
|
$pattern = $svc['match_pattern'] ?? '';
|
||||||
|
if ( $pattern === '' || ! str_contains( $src, $pattern ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$id = (string) ( $svc['id'] ?? '' );
|
||||||
|
// src → data-cb-src (first occurrence), drop any existing type, then
|
||||||
|
// force type="text/plain" + the service id on the opening tag.
|
||||||
|
$t = preg_replace( '#\bsrc(\s*=\s*)#i', 'data-cb-src$1', $tag, 1 );
|
||||||
|
$t = preg_replace( '#\btype\s*=\s*("[^"]*"|\'[^\']*\'|\S+)#i', '', $t );
|
||||||
|
$t = preg_replace(
|
||||||
|
'#^<script\b#i',
|
||||||
|
'<script type="text/plain" data-cb-id="' . esc_attr( $id ) . '"',
|
||||||
|
$t,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
return $t ?? $tag;
|
||||||
|
}
|
||||||
|
return $tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,7 +7,65 @@ class CB_Renderer {
|
|||||||
add_shortcode( 'content_blocker', [ __CLASS__, 'shortcode' ] );
|
add_shortcode( 'content_blocker', [ __CLASS__, 'shortcode' ] );
|
||||||
add_shortcode( 'content_blocker_revoke', [ __CLASS__, 'revoke_shortcode' ] );
|
add_shortcode( 'content_blocker_revoke', [ __CLASS__, 'revoke_shortcode' ] );
|
||||||
add_shortcode( 'content_blocker_services', [ __CLASS__, 'services_shortcode' ] );
|
add_shortcode( 'content_blocker_services', [ __CLASS__, 'services_shortcode' ] );
|
||||||
|
add_shortcode( 'content_blocker_consent', [ __CLASS__, 'consent_shortcode' ] );
|
||||||
add_action( 'wp_enqueue_scripts', [ __CLASS__, 'enqueue_assets' ] );
|
add_action( 'wp_enqueue_scripts', [ __CLASS__, 'enqueue_assets' ] );
|
||||||
|
// Earliest possible: install the dynamic-script guard before theme/builder
|
||||||
|
// scripts run, so JS-injected third-party scripts (e.g. YouTube iframe_api)
|
||||||
|
// are caught before they fetch.
|
||||||
|
add_action( 'wp_head', [ __CLASS__, 'print_script_guard' ], 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enabled services that should also block matching <script> tags. */
|
||||||
|
public static function script_services(): array {
|
||||||
|
$out = [];
|
||||||
|
foreach ( CB_Settings::get_services() as $svc ) {
|
||||||
|
if ( empty( $svc['match_pattern'] ) || empty( $svc['loads_script'] ) || ! ( $svc['enabled'] ?? true ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$out[] = [ 'id' => $svc['id'], 'match' => $svc['match_pattern'] ];
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inline guard printed very early in <head>. It blocks third-party scripts
|
||||||
|
* (both already in the DOM and dynamically injected) until the matching
|
||||||
|
* service has consent, by neutralising the <script> node right before it is
|
||||||
|
* inserted (no network request is made). Re-injection happens on consent.
|
||||||
|
*/
|
||||||
|
public static function print_script_guard(): void {
|
||||||
|
if ( is_admin() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$services = self::script_services();
|
||||||
|
if ( empty( $services ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$json = wp_json_encode( $services );
|
||||||
|
echo "<script>\n/* gdpr-content-blocker: script guard */\n";
|
||||||
|
echo '(function(){"use strict";var S=' . $json . ';if(!S.length)return;'
|
||||||
|
. 'var P="cb_consent_";'
|
||||||
|
. 'function ok(id){try{return localStorage.getItem(P+id)==="1";}catch(e){return false;}}'
|
||||||
|
. 'function find(u){u=String(u||"");for(var i=0;i<S.length;i++){if(u.indexOf(S[i].match)!==-1)return S[i];}return null;}'
|
||||||
|
. 'var blocked=[];'
|
||||||
|
. 'function neutralize(node){try{if(!node||node.tagName!=="SCRIPT")return;'
|
||||||
|
. 'var src=node.src||(node.getAttribute?node.getAttribute("src"):"")||"";if(!src)return;'
|
||||||
|
. 'var s=find(src);if(!s||ok(s.id))return;'
|
||||||
|
. 'node.type="text/plain";node.setAttribute("data-cb-src",src);node.setAttribute("data-cb-id",s.id);'
|
||||||
|
. 'if(node.removeAttribute)node.removeAttribute("src");blocked.push(node);}catch(e){}}'
|
||||||
|
. 'function patch(proto,name){var o=proto[name];if(!o)return;proto[name]=function(n){try{neutralize(n);}catch(e){}return o.apply(this,arguments);};}'
|
||||||
|
. 'patch(Node.prototype,"appendChild");patch(Node.prototype,"insertBefore");patch(Node.prototype,"replaceChild");'
|
||||||
|
. 'function rein(el){try{var src=el.getAttribute&&el.getAttribute("data-cb-src");if(!src)return;'
|
||||||
|
. 'var s=document.createElement("script");for(var i=0;i<el.attributes.length;i++){var a=el.attributes[i];'
|
||||||
|
. 'if(/^(type|src|data-cb-src|data-cb-id)$/i.test(a.name))continue;try{s.setAttribute(a.name,a.value);}catch(e){}}'
|
||||||
|
. 's.src=src;var p=el.parentNode;if(p){p.insertBefore(s,el.nextSibling);p.removeChild(el);}}catch(e){}}'
|
||||||
|
. 'window.cbActivateScripts=function(id){blocked.slice().forEach(function(el){if(el.getAttribute("data-cb-id")===id)rein(el);});'
|
||||||
|
. 'var n=document.querySelectorAll(\'script[type="text/plain"][data-cb-src][data-cb-id]\');'
|
||||||
|
. 'Array.prototype.forEach.call(n,function(el){if(el.getAttribute("data-cb-id")===id)rein(el);});};'
|
||||||
|
. 'function pre(){for(var i=0;i<S.length;i++){if(ok(S[i].id))window.cbActivateScripts(S[i].id);}}'
|
||||||
|
. 'if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",pre);}else{pre();}'
|
||||||
|
. '})();';
|
||||||
|
echo "\n</script>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function enqueue_assets(): void {
|
public static function enqueue_assets(): void {
|
||||||
@@ -147,6 +205,31 @@ class CB_Renderer {
|
|||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcode: [content_blocker_consent id="youtube" text="…" style="button|link"]
|
||||||
|
* A consent control for services that only block scripts (no visible embed
|
||||||
|
* to click). Grants consent for the given service id and reloads so the
|
||||||
|
* blocked scripts/embeds load.
|
||||||
|
*/
|
||||||
|
public static function consent_shortcode( array|string $atts = [] ): string {
|
||||||
|
$atts = shortcode_atts( [
|
||||||
|
'id' => '',
|
||||||
|
'text' => __( 'Externe Inhalte aktivieren', 'gdpr-content-blocker' ),
|
||||||
|
'style' => 'button',
|
||||||
|
], $atts, 'content_blocker_consent' );
|
||||||
|
|
||||||
|
$id = sanitize_key( $atts['id'] );
|
||||||
|
if ( $id === '' ) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
$class = $atts['style'] === 'link' ? 'cb-revoke-link' : 'cb-revoke-btn';
|
||||||
|
|
||||||
|
return '<a href="#" class="' . esc_attr( $class ) . '" role="button" '
|
||||||
|
. 'onclick="cbConsent(\'' . esc_js( $id ) . '\');return false;">'
|
||||||
|
. esc_html( $atts['text'] )
|
||||||
|
. '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shortcode: [content_blocker_services]
|
* Shortcode: [content_blocker_services]
|
||||||
* Lists every configured third-party service with the Art. 13 details
|
* Lists every configured third-party service with the Art. 13 details
|
||||||
|
|||||||
@@ -616,10 +616,10 @@ class CB_Settings {
|
|||||||
value="1" <?php checked( $b( 'sets_cookie' ) ); ?>>
|
value="1" <?php checked( $b( 'sets_cookie' ) ); ?>>
|
||||||
<?php esc_html_e( 'Setzt Cookies', 'gdpr-content-blocker' ); ?>
|
<?php esc_html_e( 'Setzt Cookies', 'gdpr-content-blocker' ); ?>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label title="<?php esc_attr_e( 'Blockiert zusätzlich passende <script>-Einbindungen (auch per JavaScript nachgeladene, z. B. die YouTube-/Vimeo-API) bis zur Einwilligung.', 'gdpr-content-blocker' ); ?>">
|
||||||
<input type="checkbox" name="cb_services[<?php echo esc_attr( (string) $index ); ?>][loads_script]"
|
<input type="checkbox" name="cb_services[<?php echo esc_attr( (string) $index ); ?>][loads_script]"
|
||||||
value="1" <?php checked( $b( 'loads_script' ) ); ?>>
|
value="1" <?php checked( $b( 'loads_script' ) ); ?>>
|
||||||
<?php esc_html_e( 'Lädt externe Skripte', 'gdpr-content-blocker' ); ?>
|
<?php esc_html_e( 'Zugehörige Skripte blockieren (z. B. YouTube-/Vimeo-API)', 'gdpr-content-blocker' ); ?>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -674,6 +674,11 @@ class CB_Settings {
|
|||||||
<?php echo $code( '[content_blocker_services]' ); ?></td>
|
<?php echo $code( '[content_blocker_services]' ); ?></td>
|
||||||
<td><?php esc_html_e( 'Listet alle konfigurierten Dienste mit Empfänger, Drittland-Hinweis, Zweck und Datenschutz-Link auf. Ideal zum Einbinden in die Datenschutzerklärung (Art. 13 DSGVO).', 'gdpr-content-blocker' ); ?></td>
|
<td><?php esc_html_e( 'Listet alle konfigurierten Dienste mit Empfänger, Drittland-Hinweis, Zweck und Datenschutz-Link auf. Ideal zum Einbinden in die Datenschutzerklärung (Art. 13 DSGVO).', 'gdpr-content-blocker' ); ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="vertical-align:top;"><strong><?php esc_html_e( 'Einwilligungs-Button (für reine Skript-Dienste)', 'gdpr-content-blocker' ); ?></strong><br>
|
||||||
|
<?php echo $code( '[content_blocker_consent id="youtube" text="…"]' ); ?></td>
|
||||||
|
<td><?php esc_html_e( 'Erteilt die Einwilligung für einen Dienst und lädt die Seite neu. Gedacht für Dienste, die nur Skripte blockieren und keinen sichtbaren Platzhalter haben. Optionen: id="…" (Dienst-ID, Pflicht), text="…", style="button|link".', 'gdpr-content-blocker' ); ?></td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<?php
|
<?php
|
||||||
|
|||||||
Binary file not shown.
@@ -114,6 +114,9 @@ msgstr "Withdraw consent for external content"
|
|||||||
msgid "Betrifft nur die Freigabe externer Einbettungen (z. B. Karten, Videos). Cookie-Einstellungen werden separat verwaltet."
|
msgid "Betrifft nur die Freigabe externer Einbettungen (z. B. Karten, Videos). Cookie-Einstellungen werden separat verwaltet."
|
||||||
msgstr "Affects only the release of external embeds (e.g. maps, videos). Cookie settings are managed separately."
|
msgstr "Affects only the release of external embeds (e.g. maps, videos). Cookie settings are managed separately."
|
||||||
|
|
||||||
|
msgid "Externe Inhalte aktivieren"
|
||||||
|
msgstr "Enable external content"
|
||||||
|
|
||||||
msgid "Übermittlung in ein Drittland außerhalb der EU/des EWR"
|
msgid "Übermittlung in ein Drittland außerhalb der EU/des EWR"
|
||||||
msgstr "Transfer to a third country outside the EU/EEA"
|
msgstr "Transfer to a third country outside the EU/EEA"
|
||||||
|
|
||||||
@@ -282,8 +285,11 @@ msgstr "Custom placeholder text (empty = default)"
|
|||||||
msgid "Datenübermittlung in Drittland (außerhalb EU/EWR)"
|
msgid "Datenübermittlung in Drittland (außerhalb EU/EWR)"
|
||||||
msgstr "Data transfer to a third country (outside EU/EEA)"
|
msgstr "Data transfer to a third country (outside EU/EEA)"
|
||||||
|
|
||||||
msgid "Lädt externe Skripte"
|
msgid "Blockiert zusätzlich passende <script>-Einbindungen (auch per JavaScript nachgeladene, z. B. die YouTube-/Vimeo-API) bis zur Einwilligung."
|
||||||
msgstr "Loads external scripts"
|
msgstr "Additionally blocks matching <script> includes (including ones injected via JavaScript, e.g. the YouTube/Vimeo API) until consent."
|
||||||
|
|
||||||
|
msgid "Zugehörige Skripte blockieren (z. B. YouTube-/Vimeo-API)"
|
||||||
|
msgstr "Also block related scripts (e.g. YouTube/Vimeo API)"
|
||||||
|
|
||||||
msgid "Textfarbe Platzhalter"
|
msgid "Textfarbe Platzhalter"
|
||||||
msgstr "Placeholder text color"
|
msgstr "Placeholder text color"
|
||||||
@@ -330,6 +336,12 @@ msgstr "Services overview (privacy policy)"
|
|||||||
msgid "Listet alle konfigurierten Dienste mit Empfänger, Drittland-Hinweis, Zweck und Datenschutz-Link auf. Ideal zum Einbinden in die Datenschutzerklärung (Art. 13 DSGVO)."
|
msgid "Listet alle konfigurierten Dienste mit Empfänger, Drittland-Hinweis, Zweck und Datenschutz-Link auf. Ideal zum Einbinden in die Datenschutzerklärung (Art. 13 DSGVO)."
|
||||||
msgstr "Lists all configured services with recipient, third-country note, purpose and privacy link. Ideal for inclusion in your privacy policy (Art. 13 GDPR)."
|
msgstr "Lists all configured services with recipient, third-country note, purpose and privacy link. Ideal for inclusion in your privacy policy (Art. 13 GDPR)."
|
||||||
|
|
||||||
|
msgid "Einwilligungs-Button (für reine Skript-Dienste)"
|
||||||
|
msgstr "Consent button (for script-only services)"
|
||||||
|
|
||||||
|
msgid "Erteilt die Einwilligung für einen Dienst und lädt die Seite neu. Gedacht für Dienste, die nur Skripte blockieren und keinen sichtbaren Platzhalter haben. Optionen: id=\"…\" (Dienst-ID, Pflicht), text=\"…\", style=\"button|link\"."
|
||||||
|
msgstr "Grants consent for a service and reloads the page. Intended for services that only block scripts and have no visible placeholder. Options: id=\"…\" (service ID, required), text=\"…\", style=\"button|link\"."
|
||||||
|
|
||||||
msgid "Version %s"
|
msgid "Version %s"
|
||||||
msgstr "Version %s"
|
msgstr "Version %s"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# 123 unique strings
|
# 127 unique strings
|
||||||
MSGID Ungültige Antwort vom Lizenzserver.
|
MSGID Ungültige Antwort vom Lizenzserver.
|
||||||
MSGID Keine Berechtigung.
|
MSGID Keine Berechtigung.
|
||||||
MSGID Bitte einen Lizenzschlüssel eingeben.
|
MSGID Bitte einen Lizenzschlüssel eingeben.
|
||||||
@@ -35,6 +35,7 @@ MSGID Diesen Dienst künftig immer laden
|
|||||||
MSGID Um diesen Inhalt von %s zu laden, ist Ihre Einwilligung erforderlich. Dabei werden personenbezogene Daten (z. B. Ihre IP-Adresse) an den Anbieter übertragen.
|
MSGID Um diesen Inhalt von %s zu laden, ist Ihre Einwilligung erforderlich. Dabei werden personenbezogene Daten (z. B. Ihre IP-Adresse) an den Anbieter übertragen.
|
||||||
MSGID Einwilligung für externe Inhalte widerrufen
|
MSGID Einwilligung für externe Inhalte widerrufen
|
||||||
MSGID Betrifft nur die Freigabe externer Einbettungen (z. B. Karten, Videos). Cookie-Einstellungen werden separat verwaltet.
|
MSGID Betrifft nur die Freigabe externer Einbettungen (z. B. Karten, Videos). Cookie-Einstellungen werden separat verwaltet.
|
||||||
|
MSGID Externe Inhalte aktivieren
|
||||||
MSGID Übermittlung in ein Drittland außerhalb der EU/des EWR
|
MSGID Übermittlung in ein Drittland außerhalb der EU/des EWR
|
||||||
MSGID Empfänger
|
MSGID Empfänger
|
||||||
MSGID Zweck
|
MSGID Zweck
|
||||||
@@ -91,7 +92,8 @@ MSGID Datenschutz-URL des Anbieters
|
|||||||
MSGID Verarbeitungszweck
|
MSGID Verarbeitungszweck
|
||||||
MSGID Individueller Platzhaltertext (leer = Standard)
|
MSGID Individueller Platzhaltertext (leer = Standard)
|
||||||
MSGID Datenübermittlung in Drittland (außerhalb EU/EWR)
|
MSGID Datenübermittlung in Drittland (außerhalb EU/EWR)
|
||||||
MSGID Lädt externe Skripte
|
MSGID Blockiert zusätzlich passende <script>-Einbindungen (auch per JavaScript nachgeladene, z. B. die YouTube-/Vimeo-API) bis zur Einwilligung.
|
||||||
|
MSGID Zugehörige Skripte blockieren (z. B. YouTube-/Vimeo-API)
|
||||||
MSGID Textfarbe Platzhalter
|
MSGID Textfarbe Platzhalter
|
||||||
MSGID Hintergrundfarbe Platzhalter
|
MSGID Hintergrundfarbe Platzhalter
|
||||||
MSGID Button: Hintergrundfarbe
|
MSGID Button: Hintergrundfarbe
|
||||||
@@ -107,6 +109,8 @@ MSGID Inhalt manuell blockieren
|
|||||||
MSGID Umschließt ein iframe und ersetzt es durch den Platzhalter des angegebenen Dienstes. Die ID ist der Anbietername in Kleinbuchstaben mit Bindestrichen (z. B. „Google Maps" → google-maps).
|
MSGID Umschließt ein iframe und ersetzt es durch den Platzhalter des angegebenen Dienstes. Die ID ist der Anbietername in Kleinbuchstaben mit Bindestrichen (z. B. „Google Maps" → google-maps).
|
||||||
MSGID Dienste-Übersicht (Datenschutzerklärung)
|
MSGID Dienste-Übersicht (Datenschutzerklärung)
|
||||||
MSGID Listet alle konfigurierten Dienste mit Empfänger, Drittland-Hinweis, Zweck und Datenschutz-Link auf. Ideal zum Einbinden in die Datenschutzerklärung (Art. 13 DSGVO).
|
MSGID Listet alle konfigurierten Dienste mit Empfänger, Drittland-Hinweis, Zweck und Datenschutz-Link auf. Ideal zum Einbinden in die Datenschutzerklärung (Art. 13 DSGVO).
|
||||||
|
MSGID Einwilligungs-Button (für reine Skript-Dienste)
|
||||||
|
MSGID Erteilt die Einwilligung für einen Dienst und lädt die Seite neu. Gedacht für Dienste, die nur Skripte blockieren und keinen sichtbaren Platzhalter haben. Optionen: id="…" (Dienst-ID, Pflicht), text="…", style="button|link".
|
||||||
MSGID Version %s
|
MSGID Version %s
|
||||||
MSGID GDPR Content Blocker lädt externe Einbindungen (z. B. Google Maps, YouTube, OpenStreetMap, Vimeo) erst nach aktiver Einwilligung der Besucher. Vor dem Klick wird keine Verbindung zum Drittanbieter aufgebaut – es werden also keine personenbezogenen Daten (z. B. die IP-Adresse) übertragen. So lassen sich externe Inhalte DSGVO-konform einbinden, ohne ein schweres Consent-Tool.
|
MSGID GDPR Content Blocker lädt externe Einbindungen (z. B. Google Maps, YouTube, OpenStreetMap, Vimeo) erst nach aktiver Einwilligung der Besucher. Vor dem Klick wird keine Verbindung zum Drittanbieter aufgebaut – es werden also keine personenbezogenen Daten (z. B. die IP-Adresse) übertragen. So lassen sich externe Inhalte DSGVO-konform einbinden, ohne ein schweres Consent-Tool.
|
||||||
MSGID Funktionen
|
MSGID Funktionen
|
||||||
|
|||||||
@@ -121,5 +121,10 @@
|
|||||||
"Unerwartete Antwort vom Lizenzserver.": "Unexpected response from the license server.",
|
"Unerwartete Antwort vom Lizenzserver.": "Unexpected response from the license server.",
|
||||||
"Lizenz upgraden": "Upgrade license",
|
"Lizenz upgraden": "Upgrade license",
|
||||||
"Schalten Sie weitere Domains frei, um diese Seite zusätzlich zu aktivieren – oder geben Sie unten eine bestehende Domain frei.": "Unlock more domains to additionally activate this site — or release an existing domain below.",
|
"Schalten Sie weitere Domains frei, um diese Seite zusätzlich zu aktivieren – oder geben Sie unten eine bestehende Domain frei.": "Unlock more domains to additionally activate this site — or release an existing domain below.",
|
||||||
"Schriftart für DSGVO-konformen Betrieb lokal hosten.": "Host this font locally for GDPR-compliant operation."
|
"Schriftart für DSGVO-konformen Betrieb lokal hosten.": "Host this font locally for GDPR-compliant operation.",
|
||||||
|
"Zugehörige Skripte blockieren (z. B. YouTube-/Vimeo-API)": "Also block related scripts (e.g. YouTube/Vimeo API)",
|
||||||
|
"Blockiert zusätzlich passende <script>-Einbindungen (auch per JavaScript nachgeladene, z. B. die YouTube-/Vimeo-API) bis zur Einwilligung.": "Additionally blocks matching <script> includes (including ones injected via JavaScript, e.g. the YouTube/Vimeo API) until consent.",
|
||||||
|
"Externe Inhalte aktivieren": "Enable external content",
|
||||||
|
"Einwilligungs-Button (für reine Skript-Dienste)": "Consent button (for script-only services)",
|
||||||
|
"Erteilt die Einwilligung für einen Dienst und lädt die Seite neu. Gedacht für Dienste, die nur Skripte blockieren und keinen sichtbaren Platzhalter haben. Optionen: id=\"…\" (Dienst-ID, Pflicht), text=\"…\", style=\"button|link\".": "Grants consent for a service and reloads the page. Intended for services that only block scripts and have no visible placeholder. Options: id=\"…\" (service ID, required), text=\"…\", style=\"button|link\"."
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user