Konfiguration¶
Alle Einstellungen befinden sich in der Erweiterungskonfiguration: Admin Tools → Settings → Extension Configuration → nt_ai.
Werte lassen sich auch je Umgebung über den Standard-TYPO3-Mechanismus in config/system/settings.php überschreiben:
Für Geheimnisse können Umgebungsvariablen-Platzhalter direkt im Erweiterungskonfigurationsformular verwendet werden:
provider.anthropic.apiKey = %env(NT_AI_ANTHROPIC_KEY)%
provider.openai.apiKey = %env(NT_AI_OPENAI_KEY)%
nt-ai löst diese zur Laufzeit über getenv() auf.
Modellnamen aus der Umgebung¶
Modellnamen verstehen denselben Platzhalter. Ein Projekt kann sie damit aus der versionierten config/system/settings.php heraushalten und das Modell wechseln, indem es eine Umgebungsvariable ändert — ohne Commit und ohne Deployment:
// config/system/settings.php (Auszug)
'EXTENSIONS' => [
'nt_ai' => [
'provider' => [
'openai' => [
'apiKey' => '%env(NT_AI_OPENAI_KEY)%',
'model' => '%env(AI_MODEL_OPENAI)%',
],
],
],
],
Das gilt für die Modell-Einstellung jedes Anbieters und für tts.model. Der Platzhalter muss den ganzen Wert bilden, der Variablenname darf A–Z, 0–9 und _ enthalten. Die Variable muss für PHPs getenv() sichtbar sein — gesetzt vom Webserver oder Container oder aus einer .env geladen, etwa über helhum/dotenv-connector.
Ein bewusster Unterschied zu den API-Schlüsseln: Ist die Variable leer oder fehlt sie, gilt der unten genannte Standard des Anbieters, kein leerer Wert. Ein fehlender API-Schlüssel macht einen Anbieter zu Recht unverfügbar. Ein leerer Modellname dagegen ginge an den Anbieter und ließe jeden Aufruf scheitern — ein vergessener ENV-Eintrag soll die KI-Funktionen nicht lahmlegen. Derselbe Rückfall gilt für ein im Backend leer gespeichertes Modellfeld.
Verfügbar ab 1.15.0. Wörtliche Modellnamen funktionieren unverändert weiter.
Anbieter-Einstellungen¶
provider.default legt fest, welcher Anbieter verwendet wird, wenn bei einem Aufruf kein Anbieter angegeben ist. Mögliche Werte: anthropic, openai, gemini, deepseek, mistral, groq, ollama.
Anthropic Claude¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.anthropic.apiKey |
string | (leer) | API-Schlüssel von console.anthropic.com. Erforderlich zur Nutzung von Claude. Unterstützt %env(VAR)%-Platzhalter. |
provider.anthropic.model |
string | claude-sonnet-4-5 |
Modell-Bezeichner. Beispiele: claude-opus-4-5, claude-haiku-4-5. Vision wird bei allen Claude-3+- und 4+-Modellen unterstützt. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
provider.anthropic.baseUrl |
string | https://api.anthropic.com/v1 |
Nur überschreiben, wenn Anthropic über eine eigene Infrastruktur als Proxy betrieben wird. |
OpenAI¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.openai.apiKey |
string | (leer) | API-Schlüssel von platform.openai.com. Erforderlich zur Nutzung von OpenAI. |
provider.openai.model |
string | gpt-4o-mini |
Beispiele: gpt-4o, gpt-4o-mini, gpt-4-turbo. Für die Alt-Text-Generierung ein Vision-Modell verwenden (gpt-4o, gpt-4o-mini). Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
provider.openai.baseUrl |
string | https://api.openai.com/v1 |
Überschreiben für Azure OpenAI, OpenRouter, LM Studio oder andere OpenAI-API-kompatible Endpunkte. |
Google Gemini¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.gemini.apiKey |
string | (leer) | API-Schlüssel von aistudio.google.com. Erforderlich zur Nutzung von Gemini. |
provider.gemini.model |
string | gemini-2.0-flash |
Beispiele: gemini-2.5-pro, gemini-2.0-flash, gemini-1.5-flash. Alle aufgeführten Modelle unterstützen Vision. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
provider.gemini.baseUrl |
string | https://generativelanguage.googleapis.com/v1beta |
Überschreiben bei Proxy-Setups. |
DeepSeek¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.deepseek.apiKey |
string | (leer) | API-Schlüssel von platform.deepseek.com. Erforderlich zur Nutzung von DeepSeek. |
provider.deepseek.model |
string | deepseek-chat |
deepseek-chat = DeepSeek-V3 (allgemein), deepseek-reasoner = R1 (Chain-of-Thought). Keines der Modelle unterstützt Vision. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
provider.deepseek.baseUrl |
string | https://api.deepseek.com/v1 |
Überschreiben bei Proxy-Setups. |
Mistral AI¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.mistral.apiKey |
string | (leer) | API-Schlüssel von console.mistral.ai. |
provider.mistral.model |
string | mistral-small-latest |
Beispiele: mistral-large-latest, pixtral-large-latest (Vision). Vision ist nur bei pixtral-*-Modellen verfügbar. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
provider.mistral.baseUrl |
string | https://api.mistral.ai/v1 |
Überschreiben bei Proxy-Setups. |
Groq¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.groq.apiKey |
string | (leer) | API-Schlüssel von console.groq.com. |
provider.groq.model |
string | llama-3.3-70b-versatile |
Beispiele: llama-3.1-8b-instant, gemma2-9b-it. Groq unterstützt kein Vision. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
provider.groq.baseUrl |
string | https://api.groq.com/openai/v1 |
Überschreiben bei Proxy-Setups. |
Ollama (lokal)¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.ollama.baseUrl |
string | http://localhost:11434 |
URL der Ollama-Instanz. Bei getrennten Containern für TYPO3 und Ollama die container-interne URL verwenden (z. B. http://host.docker.internal:11434). |
provider.ollama.model |
string | llama3.2 |
Lokal installierter Modellname. Für Vision-Funktionen zuerst ein multimodales Modell installieren: ollama pull llama3.2-vision Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
Verhalten¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
behavior.timeout |
integer (Sekunden) | 60 |
Maximale Wartezeit für KI-Anfragen. Bei sehr langsamen lokalen Modellen erhöhen. |
behavior.maxTokens |
integer | 2048 |
Maximale Token pro Antwort. Gilt für alle Anbieter. |
behavior.logRequests |
boolean | aus | Wenn aktiv, wird jeder KI-Aufruf über den Standard-TYPO3-Logger protokolliert. Hilfreich zum Debuggen, kann jedoch sensible Prompt-Inhalte in Log-Dateien schreiben. Im Produktivbetrieb deaktiviert lassen. |
behavior.defaultLanguage |
string (ISO 639-1) | en |
Wird verwendet, wenn bei einem Aufruf keine Sprache angegeben ist. Beeinflusst Inhaltserstellung, Übersetzungen und Alt-Texte. |
Alt-Text-Anpassung¶
Diese Einstellungen formen die von der KI erzeugten Alt-Texte so, dass sie zur Tonalität und Barrierefreiheitsrichtlinie Ihrer Website passen. Die Einstellungen gelten für jede Alt-Text-Generierung, einschließlich Massen-CLI-Läufen und den „Alt-Text generieren"-Schaltflächen.
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
altText.customInstructions |
mehrzeiliger Text | (leer) | Freiformige zusätzliche Regeln für die KI. Eine Anweisung pro Zeile. Werden wörtlich an den System-Prompt angehängt. |
altText.maxLength |
integer | 125 |
Weiche Obergrenze für die Alt-Text-Länge in Zeichen. 0 deaktiviert die Begrenzung. Die KI wird angewiesen, das Limit einzuhalten; die Ausgabe wird zusätzlich hart an Wortgrenzen gekürzt, falls das Modell es überschreitet. WCAG-/Screenreader-Best-Practice liegt bei ca. 125 Zeichen. |
altText.style |
enum | concise |
concise — ein kurzer Satz. descriptive — 1–2 Sätze. detailed — 2–3 Sätze, geeignet für Diagramme und Inhaltsbilder. |
altText.forbidImagePrefix |
boolean | an | Entfernt Formulierungen wie „Bild von…", „Abbildung zeigt…", „Image of…" aus dem Prompt und defensiv aus der Antwort. Screenreader kündigen Grafiken bereits an, solche Präfixe sind daher überflüssig. |
altText.includeDetectedText |
boolean | an | Die KI transkribiert sichtbaren Text im Bild (Schilder, Screenshots, Beschriftungen, Verpackungen). Wichtig für die Barrierefreiheit — Text in Bildern ist für Screenreader-Nutzer sonst nicht zugänglich. |
altText.tone |
string | neutral, factual |
Freiformige Tonbeschreibung. Beispiele: friendly, casual (Blogs), marketing, enthusiastic (Landingpages), technical, precise (Dokumentation). |
altText.brandContext |
string (max. 500 Zeichen) | (leer) | Ein kurzer Hinweis zu Ihrer Website oder Marke, der jeder Alt-Text-Anfrage beigefügt wird. Nützlich für kontextsensitive Beschreibungen. |
Strikte Alt-Text-Richtlinie — deutsches Kunstmuseum
altText.style = descriptive
altText.maxLength = 200
altText.tone = neutral, sachlich
altText.brandContext = Museum für moderne Kunst. Bildbeschreibungen für ein Fachpublikum, Künstlernamen nur wenn klar erkennbar.
altText.customInstructions:
Bei Kunstwerken: Stil, Material und ungefähre Epoche nennen.
Personen nur als "Besucher", "Mitarbeiter" o.ä. bezeichnen.
Texttafeln und Beschriftungen wörtlich übernehmen.
Audit-Einstellungen¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
audit.enabled |
boolean | an | Hauptschalter für das Barrierefreiheits-Audit-Backend-Modul. |
audit.autoOnSave |
boolean | aus | Wenn aktiv, wird nach jedem Speichern einer Seite im Backend automatisch ein Audit ausgelöst (durch audit.autoCooldown ratenbegrenzt). |
audit.autoCooldown |
integer (Sekunden) | 120 |
Mindestabstand zwischen automatischen Audits für dieselbe Seite. Verhindert Audit-Stürme bei schnellem Speichern durch Redakteure. |
audit.aiRules |
boolean | an | Legt fest, ob KI-gestützte Audit-Regeln ausgeführt werden. Bei Deaktivierung laufen nur deterministische regelbasierte Prüfungen. KI-Regeln werden auch automatisch übersprungen, wenn kein Anbieter konfiguriert ist. |
audit.retentionDays |
integer (Tage) | 90 |
Audit-Berichte, die älter als dieser Wert sind, können über den Standard-TYPO3-Garbage-Collection-Task gelöscht werden. 0 deaktiviert die Bereinigung. |
audit.maxReportsPerPage |
integer | 10 |
Maximale Anzahl gespeicherter Berichte pro Seite. Ältere Berichte werden nach jedem neuen Audit-Lauf automatisch bereinigt. |
audit.explainPrompt |
mehrzeiliger Text | (integriert) | Benutzerdefinierte Prompt-Vorlage für KI-generierte Befund-Erläuterungen. Verfügbare Platzhalter: {ruleId}, {severity}, {message}, {wcagReference}, {snippet}. |
Barrierefreiheitserklärung¶
Angaben für den Reiter „Erklärung" im Audit-Modul, der aus den Audit-Daten einen Entwurf einer Erklärung zur Barrierefreiheit erzeugt (siehe Benutzerhandbuch → „Barrierefreiheitserklärung erstellen").
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
declaration.targetPageUid |
integer | 0 |
Zielseite, auf der die Erklärung veröffentlicht wird. 0 = automatisch die Seite mit dem Slug /barrierefreiheit. |
declaration.organisation |
string | (leer) | Name der Organisation in der Erklärung. Leer = Website-Titel aus der Site-Konfiguration. |
declaration.feedbackContact |
Text | (leer) | Ansprechpartner für Barrierefreiheits-Feedback (Name, E-Mail, Telefon). Pflichtangabe der Erklärung. |
declaration.enforcementBody |
Text | (leer) | Zuständige Durchsetzungs-/Schlichtungsstelle (für Unternehmen unter BFSG i. d. R. die Marktüberwachungsstelle der Länder). |
declaration.enforcementUrl |
string | (leer) | Link zur zuständigen Stelle (optional). |
declaration.measures |
Text | (integriert) | Bereits umgesetzte Maßnahmen, eine pro Zeile oder mit \| getrennt. Installierte Schwester-Erweiterungen (nt-lingua) und das nt-ai-Audit werden automatisch ergänzt. |
Publishing Quality Gate¶
Warnt beim Veröffentlichen einer Seite vor offenen Barrierefreiheits-Findings oder blockiert die Veröffentlichung, bis kritische Punkte behoben sind. Das Gate nutzt den zuletzt gespeicherten Audit-Bericht der Seite — daher audit.autoOnSave aktiviert lassen, damit der Bericht aktuell bleibt. Ablauf: beheben → speichern (re-Audit) → Bericht aktualisiert → Veröffentlichen erlaubt.
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
audit.qualityGate |
Optionen (off/warn/block) |
off |
warn: Flash-Warnung beim Veröffentlichen. block: Veröffentlichen wird verhindert (Seite bleibt versteckt), solange das Gate nicht bestanden ist. |
audit.qualityGateSeverity |
Optionen (error/warning) |
error |
Ab welchem Schweregrad das Gate greift. error = nur kritische Fehler, warning = Fehler und Warnungen. |
audit.qualityGateScope |
Optionen (onPublish/onSave) |
onPublish |
onPublish: nur beim Sichtbarschalten (hidden=0). onSave: bei jedem Speichern einer nicht versteckten Seite. |
audit.qualityGateAdminBypass |
boolean | an | Administratoren dürfen trotz Findings veröffentlichen (erhalten nur eine Warnung). |
Für Pipelines: nt_ai:audit --fail-on=error (bzw. warning) liefert Exit-Code ≠ 0 bei Findings — nutzbar als CI/CD-Gate.
PDF-Barrierefreiheit (Upload-Gate)¶
Prüft PDFs beim Backend-Upload auf Barrierefreiheit (getaggtes PDF, Textebene, Dokumentsprache, Titel, Alternativtexte …) und warnt oder blockiert je nach Modus. Unabhängig vom Modus wird bei jedem Backend-PDF-Upload ein Bericht für das Modul Medien → PDF-Barrierefreiheit gespeichert. Frontend-Formular-Uploads sind ausgenommen. Details zu den Prüfregeln: Benutzerhandbuch.
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
pdf.uploadGate |
Optionen (off/warn/block) |
off |
warn: Datei wird gespeichert, der Redakteur erhält eine bleibende Warnmeldung mit den Befunden. block: Der Upload wird mit einer Meldung inkl. Befunden abgelehnt — es entsteht keine Datei. |
pdf.uploadGateSeverity |
Optionen (error/warning) |
warning |
Ab welchem Schweregrad das Gate greift. warning = Fehler und Warnungen (z. B. fehlender Dokumenttitel), error = nur kritische Fehler. |
pdf.uploadGateAdminBypass |
boolean | an | Administratoren dürfen trotz Befunden hochladen (erhalten nur die Warnung statt einer Blockade). |
Für Bestandsprüfung und Pipelines: nt_ai:pdf-audit [--limit N] [--force] [--fail-on=error|warning]
— rein PHP-basiert (keine Systemwerkzeuge nötig), unveränderte Dateien werden übersprungen.
Token-Tracking und Kostenschätzung¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
tokenTracking.enabled |
boolean | aus | Wenn aktiv, wird jeder KI-Aufruf in tx_ntai_token_usage protokolliert. Erforderlich für die Token-Verbrauchs-Dashboard-Widgets. |
tokenTracking.currency |
Optionen | USD |
Anzeigewährung für geschätzte Kosten. USD → ~$0.19, EUR → ~0,18 €. |
tokenTracking.eurRate |
float | 0.92 |
USD-zu-EUR-Umrechnungskurs. Wird nur verwendet, wenn die Währung auf EUR gesetzt ist. |
tokenTracking.customPricing |
Text (JSON) | (leer) | Integrierte Modellpreistabelle überschreiben oder erweitern. Preise in USD pro 1.000.000 Token. Präfix-Matching wird angewendet — "gpt-4o" trifft auf gpt-4o-2024-08-06. |
{
"my-fine-tuned-gpt4o": {"input": 4.00, "output": 12.00},
"custom-ollama-model": {"input": 0.00, "output": 0.00}
}
Integrierte Preistabelle (Stand 2026-07)¶
| Modell-Präfix | Anbieter | Input $/1M | Output $/1M |
|---|---|---|---|
gpt-4o-mini |
OpenAI | 0.15 | 0.60 |
gpt-4o |
OpenAI | 2.50 | 10.00 |
claude-haiku-4 |
Anthropic | 0.80 | 4.00 |
claude-sonnet-4 |
Anthropic | 3.00 | 15.00 |
claude-opus-4 |
Anthropic | 15.00 | 75.00 |
gemini-2.0-flash |
0.10 | 0.40 | |
gemini-2.5-pro |
1.25 | 10.00 | |
deepseek-chat |
DeepSeek | 0.27 | 1.10 |
mistral-small |
Mistral AI | 0.20 | 0.60 |
llama-3.3-70b |
Groq | 0.59 | 0.79 |
Die vollständige Tabelle befindet sich in EXT:nt_ai/Configuration/ModelPricing.php. Unbekannte Modelle werden im Dashboard-Widget als Warnung angezeigt. TTS-Modelle (tts-1, tts-1-hd, gpt-4o-mini-tts) sind dort mit dem Preis pro 1 Mio. Zeichen hinterlegt.
Vorlesen (TTS)¶
Engine, Tempo und Vorlese-Bereich werden in den Site-Einstellungen gewählt (Kategorie „Vorlesen (TTS)"). Die folgenden Werte gelten nur für die Cloud-Engine und stehen in der Erweiterungskonfiguration (Tab „Vorlesen (TTS)"):
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
tts.cloudProvider |
Optionen | openai |
Anbieter der Premium-Sprachausgabe. API-Key = der des jeweiligen Providers (Tab „Anbieter-Einstellungen"). |
tts.voice |
string | alloy |
Stimme des Anbieters (OpenAI: alloy, echo, fable, onyx, nova, shimmer). |
tts.model |
string | tts-1 |
TTS-Modell (OpenAI: tts-1, tts-1-hd, gpt-4o-mini-tts). Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
tts.rateLimit |
integer | 30 |
Max. neue Cloud-Anfragen pro IP und Minute (Schutz vor Bots/Massennutzung). 0 = unbegrenzt; Cache-Treffer zählen nicht. |
Der Cloud-Endpunkt /nt-ai/tts antwortet nur, wenn die Site-Engine auf cloud steht; er weist Cross-Site-Anfragen ab und ist rate-limitiert. Erzeugte Audios werden serverseitig gecacht, wiederholte Vorlesevorgänge desselben Textes sind kostenlos. Details siehe Benutzerhandbuch → Vorlesefunktion.
Lighthouse-Monitoring¶
Öffentlich erreichbare URLs erforderlich
Die PSI-API kann ausschließlich öffentlich zugängliche URLs analysieren. Diese Funktion auf Staging- oder Produktivservern verwenden, nicht auf lokalen DDEV-Instanzen — Google kann *.ddev.site-URLs nicht erreichen.
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
lighthouse.apiKey |
string | (leer) | Google-API-Schlüssel von console.cloud.google.com (API „PageSpeed Insights" aktivieren). Ohne Schlüssel sind Anfragen auf ~25 pro 100 Sekunden begrenzt. Im Produktivbetrieb immer einen Schlüssel konfigurieren. Unterstützt %env(NT_AI_LIGHTHOUSE_KEY)%. |
lighthouse.strategy |
Optionen | mobile |
Geräteprofil für Lighthouse. mobile (Standard), desktop oder both (führt zwei PSI-Aufrufe pro Seite durch — verdoppelt den Kontingentverbrauch). |
# Alle Seiten, mobile Strategie (liest Einstellung aus der Erweiterungskonfiguration).
vendor/bin/typo3 nt_ai:lighthouse
# Seite 42 und vollständiger Teilbaum, nur Desktop.
vendor/bin/typo3 nt_ai:lighthouse 42 99 --strategy=desktop
# Unterseiten von Seite 1, beide Strategien ausführen.
vendor/bin/typo3 nt_ai:lighthouse 1 1 --strategy=both
Ergebnisse werden als rein additive Verlaufshistorie in tx_ntai_lighthouse_report gespeichert. Das Dashboard-Widget Lighthouse-Scores zeigt die durchschnittlichen Scores über alle analysierten Seiten.
Score-Schwellenwert-Alarme¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
alerting.enabled |
boolean | aus | Hauptschalter. Kein E-Mail wird versendet, solange dieser deaktiviert ist. |
alerting.recipient |
string | (leer) | Eine oder mehrere E-Mail-Adressen, kommagetrennt. Beispiel: webmaster@example.com, seo@example.com. |
alerting.thresholdGeo |
integer (0–100) | 0 |
Alarm, wenn der GEO/SEO-KI-Score einer Seite diesen Wert unterschreitet. 0 deaktiviert den Alarm für diese Kategorie. |
alerting.thresholdPerformance |
integer (0–100) | 0 |
Schwellenwert für den Performance-KI-Score. |
alerting.thresholdSemantics |
integer (0–100) | 0 |
Schwellenwert für den Semantics-KI-Score. |
alerting.thresholdKeywords |
integer (0–100) | 0 |
Schwellenwert für den Keywords-KI-Score. |
alerting.thresholdAccessibility |
integer (0–100) | 0 |
Schwellenwert für den Barrierefreiheits-KI-Score. |
alerting.thresholdLighthousePerformance |
integer (0–100) | 0 |
Schwellenwert für den Lighthouse-Performance-Score. |
alerting.thresholdLighthouseAccessibility |
integer (0–100) | 0 |
Schwellenwert für den Lighthouse-Accessibility-Score. |
alerting.thresholdLighthouseBestPractices |
integer (0–100) | 0 |
Schwellenwert für den Lighthouse-Best-Practices-Score. |
alerting.thresholdLighthouseSeo |
integer (0–100) | 0 |
Schwellenwert für den Lighthouse-SEO-Score. |
Empfohlene Scheduler-Konfiguration — nt_ai:alert-check nach den Analyse-Befehlen ausführen, damit aktuelle Daten gelesen werden:
03:00 nt_ai:analyze-pages (KI-Inhalts-Scores)
03:30 nt_ai:lighthouse (Lighthouse-PSI-Scores)
04:00 nt_ai:alert-check (vergleichen + E-Mail senden falls nötig)
Welche Sprache ein Audit abdeckt¶
Eine Seite wird in der Sprache geprüft, auf die die Aufgabe eingestellt ist —
indem für die UID des Satzes in der Standardsprache die URL dieser Sprache
gebaut wird. Übersetzte Seitensätze sind deshalb keine eigenen Prüfziele und
werden übersprungen: Als eigener Kandidat ergäbe ein solcher Satz den
übersetzten Slug ohne Sprachpräfix — etwa /about-us/ statt /en/about-us/ —
also eine URL, die es nicht gibt und die nur 404 antworten kann.
Für mehrere Sprachen richtet man je Sprache eine Aufgabe ein, jede mit ihrer eigenen Spracheinstellung. Sie teilen sich die Sperrtabelle und doppeln ihr Wissen über unerreichbare Seiten deshalb nicht.
Bis einschließlich 1.13.1
Übersetzte Sätze wurden als Kandidaten ausgewählt. Jeder von ihnen antwortete 404, belegte damit einen Platz je Lauf und konnte — vor 1.13.0, als die Sperrfrist einen Lauf noch nicht überlebte — den Stapel vollständig füllen. Auf einer zweisprachigen Site betraf das rund die Hälfte aller Kandidaten. Nach dem Update verschwinden sie von selbst aus dem Umlauf; Sperreinträge aus früheren Läufen laufen von allein ab.
Seiten ohne Übersetzung
Ob eine Seite ohne Übersetzung in der Zielsprache 404 antwortet oder die
Standardsprache ausliefert, hängt von der Fallback-Einstellung der Site ab.
Bei strict antwortet sie 404 und wird als Ergebnis eine Woche
zurückgestellt — richtig und unschädlich; mit Fallback wird geprüft, was
ausgeliefert wird.
Seiten, die derzeit nicht veröffentlicht sind — verborgen oder außerhalb ihrer Zeitsteuerung — sind ebenfalls keine Kandidaten. Eine Seite mit abgelaufener Endzeit antwortet 404 wie eine verborgene, und anders als eine Seite im Wartungsmodus wird sie nie von selbst wieder prüfbar; eine Seite mit künftigem Startdatum tritt von allein in den Umlauf ein, sobald sie live geht. Eine Seite bewusst vor der Veröffentlichung zu prüfen, ist Aufgabe des signierten Vorschau-Tokens im Backend.
Seiten, die der Audit nicht erreicht¶
Der geplante Audit arbeitet den Seitenbaum ab, die am längsten nicht geprüfte Seite zuerst. Eine Seite, die nicht abgerufen werden kann, schreibt keinen Bericht — ihr „zuletzt geprüft" bleibt leer, und sie stünde beim nächsten Lauf wieder ganz vorn. Wenige unerreichbare Seiten können so jeden Stapel belegen und den Umlauf zum Stillstand bringen.
Deshalb wird eine solche Seite eine Zeit lang zurückgestellt. Wie lange, hängt von der Antwort des Servers ab:
- 404 oder 410 — ein beabsichtigtes „nicht gefunden", typischerweise eine Detail-URL ohne Datensatz. Eine Woche Pause: Das ist ein Ergebnis, kein Fehler, und der Inhalt entsteht selten kurzfristig.
- 503 oder 429 — „vorübergehend nicht verfügbar", also Wartungsseite oder
Drosselung. Zurückgestellt für die Zeit, die der Server im Kopffeld
Retry-Afternennt, sonst eine Stunde. Eine Site im Wartungsmodus braucht damit keine weitere Einstellung: Sie nimmt sich selbst aus dem Umlauf und kehrt zurück, sobald sie wieder da ist. - Alles andere (HTTP 5xx, Zeitüberschreitungen, Verbindungsfehler) gilt als technischer Fehler. Die Pause wächst mit jedem weiteren Fehlschlag — 6 Stunden, 24 Stunden, 3 Tage, dann 7 Tage. Ein erfolgreicher Audit löscht den Eintrag.
Nur ein echter technischer Fehler zählt für die Regel, die die Aufgabe rot färbt, wenn jede prüfbare Seite eines Stapels gescheitert ist. Seiten, die lediglich 404 oder 503 geantwortet haben, zählen nicht mit.
Die Einträge stehen in tx_ntai_audit_deferral (eine Zeile je Seite und Sprache,
mit Grund und Ende der Pause) und sind damit einsehbar:
SELECT page_uid, status_code, failure_count,
FROM_UNIXTIME(deferred_until) AS pausiert_bis, reason
FROM tx_ntai_audit_deferral ORDER BY page_uid;
Abgelaufene Einträge werden automatisch entfernt.
Die Spalte reason nennt auch die Herkunft der Frist — Retry-After: 1800s,
no Retry-After, default, clean 404/410 oder die Stufe der Fehler-Eskalation.
Ohne diese Angabe lässt sich die Frage nicht beantworten: Ein Server mit
Retry-After: 3600 und der eingebaute Vorgabewert von einer Stunde ergeben
denselben Zeitpunkt.
Vor 1.13.0
Dieser Zustand lag auf dem Objekt der Planer-Aufgabe und konnte einen Lauf
nicht überleben: Der Planer speichert eine Aufgabe vor der Ausführung und
schreibt danach nur ihre Ausführungsdaten zurück, nie ihre Parameter. Die
Pause griff deshalb nie, und ein Stapel unerreichbarer Seiten konnte den
Umlauf aushungern. Zu konfigurieren ist nichts — extension:setup muss
einmal laufen, damit die neue Tabelle entsteht.
Optionale Argumente in einer Planer-Aufgabe¶
Eine über das TYPO3-Backend angelegte Aufgabe speichert alle Argumente des
Befehls — auch die, die Sie leer gelassen haben: Eine nicht gesetzte pageId
wird als leerer String abgelegt, nicht als „nicht vorhanden". nt_ai:analyze-pages
und nt_ai:lighthouse behandeln eine leere pageId als „nicht angegeben" und
messen dann alle Seiten — das Feld im Backend leer zu lassen tut also das, wonach
es aussieht.
Zwei Hinweise dazu:
- Eine
pageIdvon0wird mit einer Fehlermeldung abgewiesen. Seite 0 ist die Baumwurzel und nie eine echte Seite: Sie gehört zu keiner Site und hat keine URL, kann also nur unerreichbare Ergebnisse liefern. - Wer Aufgaben per Skript statt über das Backend anlegt, übergibt am besten
arguments: [], damit gar keine leeren Werte gespeichert werden.