diff --git a/docs/docs/CHANGELOG.md b/docs/docs/CHANGELOG.md
index 88c8591..fdd553f 100644
--- a/docs/docs/CHANGELOG.md
+++ b/docs/docs/CHANGELOG.md
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Implement a [development container](https://containers.dev/) manifest to make contributions easier.
- Fix dynamic cookie domains functionality ([#731](https://github.com/TecharoHQ/anubis/pull/731))
- Add option for custom cookie prefix ([#732](https://github.com/TecharoHQ/anubis/pull/732))
+- Add translation for German language ([#741](https://github.com/TecharoHQ/anubis/pull/741))
- Remove the "Success" interstitial after a proof of work challenge is concluded.
- Add option for forcing a specific language ([#742](https://github.com/TecharoHQ/anubis/pull/742))
diff --git a/lib/localization/locales/de.json b/lib/localization/locales/de.json
new file mode 100644
index 0000000..ea1e27d
--- /dev/null
+++ b/lib/localization/locales/de.json
@@ -0,0 +1,63 @@
+{
+ "loading": "Ladevorgang...",
+ "why_am_i_seeing": "Warum sehe ich diese Seite?",
+ "protected_by": "Geschützt durch",
+ "made_with": "Mit ❤️ gemacht in 🇨🇦",
+ "mascot_design": "Maskottchen erstellt von",
+ "ai_companies_explanation": "Diese Seite wird angezeigt, da der Betreiber der Webseite Anubis eingerichtet hat, um sie vor aggressiven KI-Website-Scrapern zu schützen. Diese können Ausfälle der Webseite verursachen, wodurch die Webseite für jeden nicht erreichbar ist.",
+ "anubis_compromise": "Anubis ist eine Art Kompromiss. Es verwendet die sogenannte Proof-of-Work Methode nach Hashcash, ein Mechanismus, der ursprünglich zur E-Mail-Spam-Bekämpfung entwickelt wurde. Die Idee dahinter ist, dass ein einziger User nur eine kleine Verzögerung hat, auf die Webseite zu gelangen; bei Scrapern kann das allerdings große Auswirkungen haben.",
+ "hack_purpose": "Man könnte dies als eine Lösung bezeichnen, die gut genug ist, einem etwas Zeit zu verschaffen für Fingerprinting und dem Identifizieren von Headless Browsern, sodass im besten Fall normale User diese Seite garnicht erst zu sehen bekommen.",
+ "jshelter_note": "Anubis benötigt moderne JavaScript-Features, welche von Plugins wie zB JShelter deaktiviert werden. Bitte deaktiviere also JShelter oder ähnliche Plugins für diese Domain.",
+ "version_info": "Diese Webseite läuft mit Anubis version",
+ "try_again": "Nochmal probieren",
+ "go_home": "Zur Hauptseite",
+ "contact_webmaster": "oder wenn es sich hier um einen Fehler handelt, kontaktiere bitte den Administrator der Webseite unter",
+ "connection_security": "Bitte warte einen Moment während wir sicherstellen, dass eine sichere Verbindung verwendet wird.",
+ "javascript_required": "Es muss leider JavaScript aktiviert werden, um den Check durchführen zu können. Dies ist leider notwendig weil Firmen im KI-Sektor die sozialen Verhältnisse geändert haben, wie Website-Hosting funktioniert. Eine Lösung ohne JavaScript ist in Entwicklung.",
+ "benchmark_requires_js": "Das Benchmark-Tool benötigt das Aktivieren von JavaScript.",
+ "difficulty": "Schwierigkeit:",
+ "algorithm": "Algorithmus:",
+ "compare": "Vergleich:",
+ "time": "Zeit",
+ "iters": "Iterationen",
+ "time_a": "Zeit A",
+ "iters_a": "Iterationen A",
+ "time_b": "Zeit B",
+ "iters_b": "Iterationen B",
+ "static_check_endpoint": "Dies ist nur ein Check-Endpunkt, der von beispielsweise einem Reverse-Proxy geprüft werden kann.",
+ "authorization_required": "Zugriffserlaubnis benötigt",
+ "cookies_disabled": "Cookies sind in Ihrem Browser deaktiviert. Anubis benötigt Cookies um sicherzustellen, dass es sich hierbei um einen validen Zugriff handelt. Bitte aktiviere Cookies für diese Domain.",
+ "access_denied": "Zugriff verweigert: Fehlercode",
+ "dronebl_entry": "Eintrag in DroneBL",
+ "see_dronebl_lookup": "anzeigen",
+ "internal_server_error": "Interner Server Error: Misskonfiguration von Anubis. Bitte kontatkiere den Administrator damit dieser die Logs prüfen kann.",
+ "invalid_redirect": "Ungültige Weiterleitung",
+ "redirect_not_parseable": "URL der Weiterleitung kann nicht verarbeitet werden",
+ "redirect_domain_not_allowed": "Domain der Weiterleitung nicht erlaubt",
+ "failed_to_sign_jwt": "Signierung des JWT fehlgeschlagen",
+ "invalid_invocation": "Aufrufen von MakeChallenge ungültig",
+ "client_error_browser": "Client Error: Bitte stelle sicher, dass der Browser aktuell ist und probiere es später erneut.",
+ "oh_noes": "Vermaledeit!",
+ "benchmarking_anubis": "Benchmark wird durchgeführt!",
+ "you_are_not_a_bot": "Sie sind kein Bot!",
+ "making_sure_not_bot": "Ihr Browser wird geprüft!",
+ "celphase": "CELPHASE",
+ "js_web_crypto_error": "Ihr Browser hat leider kein funktionierendes web.crypto Element. Wird eine sichere Verbindung verwendet?",
+ "js_web_workers_error": "Ihr Browser unterstützt keine Web-Worker (Anubis verwendet diese, damit der Browser nicht unresponsive wird). Ist eventuell ein Plugin wie zB JShelter installiert?",
+ "js_cookies_error": "Ihr Browser speichert keine Cookies. Anubis verwendet Cookies um ein gültiges Token zu speichern damit es wissen kann, welche Browser bereits geprüft wurden. Bitte aktiviere Cookies für diese Domain. Die Cookie-Namen von Anubis könnten sich jederzeit ändern. Cookie-Namen sind kein Teil der öffentlichen API.",
+ "js_context_not_secure": "Diese Verbindung ist nicht sicher!",
+ "js_context_not_secure_msg": "Bitte probiere, dich via HTTPS zu verbinden und lass den Webseiten-Administrator wissen, sauber HTTPS einzurichten. Mehr Informationen unter: MDN.",
+ "js_calculating": "Berechnung wird durchgeführt...",
+ "js_missing_feature": "Fehlendes Feature",
+ "js_challenge_error": "Fehler während des Checks!",
+ "js_challenge_error_msg": "Der Check-Algorithmus konnte nicht geladen werden. Bitte lade diese Seite erneut.",
+ "js_calculating_difficulty": "Berechnung wird durchgeführt...
Schwierigkeit:",
+ "js_speed": "Geschwindigkeit:",
+ "js_verification_longer": "Der Check benötigt länger als erwartet. Bitte bleibe auf der Seite.",
+ "js_success": "Erfolgreich!",
+ "js_done_took": "Fertig! Dauer:",
+ "js_iterations": "Iterationen",
+ "js_finished_reading": "Fertig gelesen, weiter zur Seite →",
+ "js_calculation_error": "Fehler bei der Berechnung!",
+ "js_calculation_error_msg": "Fehler bei der Berechnung des Checks:"
+}
\ No newline at end of file
diff --git a/lib/localization/locales/manifest.json b/lib/localization/locales/manifest.json
index aa1341d..a5a0b9f 100644
--- a/lib/localization/locales/manifest.json
+++ b/lib/localization/locales/manifest.json
@@ -1,3 +1,3 @@
{
- "supportedLanguages": ["en", "fr", "es", "pt-BR"]
+ "supportedLanguages": ["en", "fr", "es", "pt-BR", "de"]
}
diff --git a/lib/localization/localization_test.go b/lib/localization/localization_test.go
index d416fc6..2761fbb 100644
--- a/lib/localization/localization_test.go
+++ b/lib/localization/localization_test.go
@@ -27,6 +27,14 @@ func TestLocalizationService(t *testing.T) {
}
})
+ t.Run("German localization", func(t *testing.T) {
+ localizer := service.GetLocalizer("de")
+ result := localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "loading"})
+ if result != "Ladevorgang..." {
+ t.Errorf("Expected 'Ladevorgang...', got '%s'", result)
+ }
+ })
+
t.Run("All required keys exist in English", func(t *testing.T) {
localizer := service.GetLocalizer("en")
requiredKeys := []string{