Files
GDPR-Content-Blocker/hilfsdaten/build-en-mo.py
s4luorth 4f0f8ea170 feat: pfeile statt +/-, shortcodes-tab, funktionen aus darstellung entfernt
- Ein-/Ausklappen wieder mit schwarzem Pfeil (>/v) ohne Box.
- Neuer Tab Shortcodes; Darstellung listet keine Funktionen mehr.
- CSS-Klassen-Referenz in den Darstellung-Tab (unter Custom CSS) verschoben.
- EN-Uebersetzung (121 Strings) neu gebaut.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 15:22:20 +02:00

184 lines
7.3 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Build gdpr-content-blocker-en_US.po + .mo from strings.txt (German keys in
file order) + the EN list below (same order)."""
import struct, sys, os
EN = [
"Invalid response from the license server.",
"Insufficient permissions.",
"Please enter a license key.",
"License activated successfully.",
"All seats for this license are in use. Release a domain to activate this site.",
"Activation failed.",
"Please select a valid domain to release.",
"Released %s and activated this site.",
"License is no longer valid.",
"GDPR Content Blocker is not licensed. Protection stays active, but please add a %s for updates and support.",
"License key",
"Active",
"Invalid",
"All seats in use",
"Not activated",
"Status",
"Domain",
"Release domain",
"This license is already active on the domains listed. Choose one to release — it will be deactivated and this site activated instead.",
"Release and activate this site",
"Hidden for security. To change it, deactivate first.",
"Deactivate license",
"Try again",
"Activate license",
"Recipient:",
"Purpose:",
"⚠ Data transfer to a third country outside the EU/EEA",
"Provider's privacy policy",
"Load %s now",
"Always load this service from now on",
"Loading this content from %s requires your consent. Personal data (e.g. your IP address) will be transmitted to the provider.",
"Withdraw consent for external content",
"Affects only the release of external embeds (e.g. maps, videos). Cookie settings are managed separately.",
"Transfer to a third country outside the EU/EEA",
"Recipient",
"Purpose",
"Sets cookies",
"Yes",
"No",
"Privacy policy",
"GDPR Content Blocker",
"Really remove this service?",
"New service",
"Scanning website …",
"Scan failed:",
"No external resources found.",
"Provider / Host",
"Type",
"Count",
"Example URL",
"Action",
"covered",
"third party",
"own domain",
"Add as service",
"Use template",
"Template available",
"Scanned pages:",
"Found on",
"Google Ireland Ltd., Ireland / Google LLC, USA",
"Display of interactive maps and location information.",
"Embedding and playback of videos.",
"OpenStreetMap Foundation, United Kingdom",
"Display of interactive maps.",
"Vimeo LLC, USA",
"Settings saved.",
"Services",
"Scan",
"Appearance",
"Shortcodes",
"License",
"About the plugin",
"+ Add empty service",
"— Insert template —",
"Save services",
"The license server visits your website and lists all embedded third-party resources (iframes, scripts, fonts, images, …). This shows at a glance which external services you should block. Requires an active license.",
"Scan website",
"Save appearance",
"new",
"Show/hide details",
"Blocker on/off",
"Remove service",
"Internal name (slug)",
"Provider name",
"Detection pattern (domain/path)",
"Recipient (incl. country)",
"Provider's privacy policy URL",
"Processing purpose",
"Custom placeholder text (empty = default)",
"Data transfer to a third country (outside EU/EEA)",
"Loads external scripts",
"Placeholder text color",
"Placeholder background color",
"Button: background color",
"Button: text color",
"Button hover: background color",
"Button hover: text color",
"Custom CSS",
"Loaded after the CSS variables and can override them. Tip: use the same prefix, e.g. .cb-blocker .cb-blocker__button { … }",
"CSS classes:",
"Withdrawal (privacy policy)",
"Renders a clearly visible link that withdraws consent for external embeds and reloads the page (Art. 7(3) GDPR). Does NOT affect the cookie consent of a separate cookie plugin. Options: text=\"\", style=\"link|button\", note=\"yes|no\".",
"Block content manually",
"Wraps an iframe and replaces it with the placeholder of the given service. Use the internal name from the \"Services\" tab.",
"Services overview (privacy policy)",
"Lists all configured services with recipient, third-country note, purpose and privacy link. Ideal for inclusion in your privacy policy (Art. 13 GDPR).",
"Version %s",
"GDPR Content Blocker loads external embeds (e.g. Google Maps, YouTube, OpenStreetMap, Vimeo) only after the visitor actively consents. Before the click no connection to the third party is made — so no personal data (e.g. the IP address) is transmitted. This lets you embed external content in a GDPR-compliant way without a heavy consent tool.",
"Features",
"True click-to-load (no preloaded iframe)",
"Granular consent per service",
"Art.-13-compliant placeholder with recipient, purpose, third-country note and privacy link",
"Easy withdrawal via shortcode (Art. 7(3) GDPR)",
"Automatic detection of common providers + manual shortcode",
"Legal",
"Imprint",
"Privacy policy",
"Note: This plugin is a technical tool and does not constitute legal advice. The site operator is responsible for the legally compliant configuration (recipients, purposes, privacy policy).",
"Developed by %s",
"Please activate a license first (\"License\" tab).",
"Unexpected response from the license server.",
]
base = sys.argv[1]
strings_file = os.path.join(base, 'hilfsdaten', 'strings.txt')
de = []
with open(strings_file, encoding='utf-8') as f:
for line in f:
if line.startswith('MSGID\t'):
de.append(line[len('MSGID\t'):].rstrip('\n'))
if len(de) != len(EN):
print(f"MISMATCH: {len(de)} German vs {len(EN)} English"); sys.exit(1)
header = ("Project-Id-Version: GDPR Content Blocker\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: en_US\n")
entries = {'': header}
for d, e in zip(de, EN):
entries[d] = e
def po_escape(s):
return s.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n')
po_path = os.path.join(base, 'gdpr-content-blocker', 'languages', 'gdpr-content-blocker-en_US.po')
with open(po_path, 'w', encoding='utf-8') as f:
f.write('msgid ""\nmsgstr ""\n')
for line in header.rstrip('\n').split('\n'):
f.write('"%s\\n"\n' % po_escape(line))
f.write('\n')
for d, e in zip(de, EN):
f.write('msgid "%s"\n' % po_escape(d))
f.write('msgstr "%s"\n\n' % po_escape(e))
def write_mo(entries, out):
keys = sorted(entries.keys())
ids = b''; strs = b''; offsets = []
for k in keys:
kb = k.encode('utf-8'); vb = entries[k].encode('utf-8')
offsets.append((len(ids), len(kb), len(strs), len(vb)))
ids += kb + b'\x00'; strs += vb + b'\x00'
keystart = 7 * 4 + 16 * len(keys)
valuestart = keystart + len(ids)
ko = []; vo = []
for o1, l1, o2, l2 in offsets:
ko += [l1, o1 + keystart]; vo += [l2, o2 + valuestart]
out_b = struct.pack("Iiiiiii", 0x950412de, 0, len(keys), 7 * 4, 7 * 4 + len(keys) * 8, 0, 0)
out_b += struct.pack("i" * len(ko), *ko) + struct.pack("i" * len(vo), *vo) + ids + strs
with open(out, 'wb') as f:
f.write(out_b)
mo_path = os.path.join(base, 'gdpr-content-blocker', 'languages', 'gdpr-content-blocker-en_US.mo')
write_mo(entries, mo_path)
print(f"OK: {len(de)} strings -> {os.path.basename(po_path)} + .mo")