diff --git a/.wordpress-org/banner-1544x500.png b/.wordpress-org/banner-1544x500.png index f76d097..6b70384 100644 Binary files a/.wordpress-org/banner-1544x500.png and b/.wordpress-org/banner-1544x500.png differ diff --git a/.wordpress-org/banner-772x250.png b/.wordpress-org/banner-772x250.png index 884fe58..cf12920 100644 Binary files a/.wordpress-org/banner-772x250.png and b/.wordpress-org/banner-772x250.png differ diff --git a/.wordpress-org/icon-128x128.gif b/.wordpress-org/icon-128x128.gif new file mode 100644 index 0000000..578c8f7 Binary files /dev/null and b/.wordpress-org/icon-128x128.gif differ diff --git a/.wordpress-org/icon-128x128.png b/.wordpress-org/icon-128x128.png deleted file mode 100644 index 6a174d9..0000000 Binary files a/.wordpress-org/icon-128x128.png and /dev/null differ diff --git a/.wordpress-org/icon-256x256.gif b/.wordpress-org/icon-256x256.gif new file mode 100644 index 0000000..a2992c9 Binary files /dev/null and b/.wordpress-org/icon-256x256.gif differ diff --git a/.wordpress-org/icon-256x256.png b/.wordpress-org/icon-256x256.png deleted file mode 100644 index c30d3e4..0000000 Binary files a/.wordpress-org/icon-256x256.png and /dev/null differ diff --git a/.wordpress-org/screenshot-1.png b/.wordpress-org/screenshot-1.png index 0a606e2..adbe23e 100644 Binary files a/.wordpress-org/screenshot-1.png and b/.wordpress-org/screenshot-1.png differ diff --git a/.wordpress-org/screenshot-2.png b/.wordpress-org/screenshot-2.png index d830e20..a754bba 100644 Binary files a/.wordpress-org/screenshot-2.png and b/.wordpress-org/screenshot-2.png differ diff --git a/.wordpress-org/screenshot-3.png b/.wordpress-org/screenshot-3.png index 3f5fc36..c9d547e 100644 Binary files a/.wordpress-org/screenshot-3.png and b/.wordpress-org/screenshot-3.png differ diff --git a/.wordpress-org/screenshot-4.png b/.wordpress-org/screenshot-4.png index 869ad3a..a7cfc3e 100644 Binary files a/.wordpress-org/screenshot-4.png and b/.wordpress-org/screenshot-4.png differ diff --git a/.wordpress-org/screenshot-5.png b/.wordpress-org/screenshot-5.png index 37b91d2..c1b70b8 100644 Binary files a/.wordpress-org/screenshot-5.png and b/.wordpress-org/screenshot-5.png differ diff --git a/.wordpress-org/screenshot-6.png b/.wordpress-org/screenshot-6.png index bae1b29..482f337 100644 Binary files a/.wordpress-org/screenshot-6.png and b/.wordpress-org/screenshot-6.png differ diff --git a/.wordpress-org/screenshot-7.png b/.wordpress-org/screenshot-7.png new file mode 100644 index 0000000..cc4212a Binary files /dev/null and b/.wordpress-org/screenshot-7.png differ diff --git a/i18n/de_DE/core.json b/i18n/de_DE/core.json index 034ff29..7d4e2cb 100644 --- a/i18n/de_DE/core.json +++ b/i18n/de_DE/core.json @@ -1,128 +1,136 @@ { - "Mail Log": "Mail-Log", - "Log": "Protokoll", - "Settings": "Einstellungen", - "Sent": "Gesendet", - "Failed": "Fehlgeschlagen", - "Unknown": "Unbekannt", - "No emails found.": "Noch keine E-Mails protokolliert.", - "No emails match these filters.": "Keine E-Mails passen zu diesen Filtern.", + "%1$s entries, %2$s": "%1$s Einträge, %2$s", + "%1$s imported, %2$s duplicates, %3$s too old": "%1$s importiert, %2$s Duplikate, %3$s zu alt", + "%1$s of %2$s entries processed …": "%1$s von %2$s Einträgen verarbeitet …", "%s entries": "%s Einträge", + "%s imported entries removed.": "%s importierte Einträge entfernt.", "%s selected": "%s ausgewählt", "(no subject)": "(kein Betreff)", - "WordPress": "WordPress", - "Resent from log": "Erneut gesendet", - "View": "Ansehen", - "Resend": "Erneut senden", - "Delete": "Löschen", - "Delete this log entry?": "Diesen Protokolleintrag löschen?", - "Delete %s selected log entries?": "%s ausgewählte Protokolleinträge löschen?", - "Empty log": "Protokoll leeren", - "Delete ALL log entries? This cannot be undone.": "ALLE Protokolleinträge löschen? Das kann nicht rückgängig gemacht werden.", - "Send this email again to %s?": "Diese E-Mail erneut an %s senden?", - "Email sent again.": "E-Mail wurde erneut gesendet.", - "Sending failed – see the new log entry for details.": "Senden fehlgeschlagen – Details im neuen Protokolleintrag.", - "Attachments no longer available: %s": "Anhänge nicht mehr vorhanden: %s", - "Deleted.": "Gelöscht.", - "Request failed: %s": "Anfrage fehlgeschlagen: %s", - "Attachments": "Anhänge", - "From": "Von", - "To": "An", - "Date": "Datum", - "Status": "Status", - "Source": "Quelle", - "Format": "Format", - "Error": "Fehler", - "Remote images and fonts are blocked so senders cannot track when you open this entry.": "Externe Bilder und Schriften sind blockiert, damit niemand verfolgen kann, wann du diesen Eintrag öffnest.", - "Remote content is loaded.": "Externe Inhalte werden geladen.", - "Load remote content": "Externe Inhalte laden", - "Block again": "Wieder blockieren", - "of %s": "von %s", - "Sorry, you are not allowed to access this page.": "Du hast leider keine Berechtigung, auf diese Seite zuzugreifen.", - "Mail Log sections": "Mail-Log-Bereiche", - "The mail log requires JavaScript.": "Das Mail-Log benötigt JavaScript.", - "Filter by status": "Nach Status filtern", + "0 keeps entries forever. Cleanup runs once a day.": "0 behält Einträge für immer. Die Bereinigung läuft einmal täglich.", + "0 means no limit. The oldest entries are removed first.": "0 bedeutet kein Limit. Die ältesten Einträge werden zuerst entfernt.", + "Access": "Zugriff", + "Actions": "Aktionen", + "Administrators": "Administratoren", "All": "Alle", - "Search recipient or subject": "Empfänger oder Betreff suchen", - "Search recipient or subject …": "Empfänger oder Betreff suchen …", "Also search content": "Auch Inhalt durchsuchen", - "From date": "Von Datum", - "To date": "Bis Datum", - "Reset filters": "Filter zurücksetzen", - "Delete selected": "Auswahl löschen", + "Always load remote images and fonts in the preview": "Externe Bilder und Schriften in der Vorschau immer laden", + "Attachments": "Anhänge", + "Attachments no longer available: %s": "Anhänge nicht mehr vorhanden: %s", + "Block again": "Wieder blockieren", "Clear selection": "Auswahl aufheben", - "Select all": "Alle auswählen", - "Recipient": "Empfänger", - "Subject": "Betreff", - "Actions": "Aktionen", - "Per page": "Pro Seite", - "Pagination": "Seitennavigation", - "First page": "Erste Seite", - "Previous page": "Vorherige Seite", - "Current page": "Aktuelle Seite", - "Next page": "Nächste Seite", - "Last page": "Letzte Seite", - "Previous email": "Vorherige E-Mail", - "Previous email (k)": "Vorherige E-Mail (k)", - "Next email": "Nächste E-Mail", - "Next email (j)": "Nächste E-Mail (j)", "Close": "Schließen", "Close (Esc)": "Schließen (Esc)", - "Preview": "Vorschau", - "Headers": "Header", - "Administrators": "Administratoren", - "Editors and above": "Redakteure und höher", - "Shop managers and above": "Shop-Manager und höher", - "Access": "Zugriff", - "Who can view the log": "Wer darf das Protokoll sehen", - "Logged emails can contain personal data. Grant access as narrowly as possible. Settings always require administrator rights.": "Protokollierte E-Mails können personenbezogene Daten enthalten. Vergib den Zugriff so eng wie möglich. Die Einstellungen erfordern immer Administratorrechte.", - "Menu position": "Menüposition", - "Own top-level menu item": "Eigener Hauptmenüpunkt", - "Under Tools": "Unter Werkzeuge", - "Privacy & security": "Datenschutz & Sicherheit", - "Redact secrets": "Geheimnisse schwärzen", - "Mask password-reset, activation and access keys in logged links": "Passwort-Reset-, Aktivierungs- und Zugriffsschlüssel in protokollierten Links maskieren", - "Recommended. Otherwise anyone with log access could use a logged reset link to take over an account. Resending such an email sends the masked version.": "Empfohlen. Sonst könnte jeder mit Zugriff auf das Protokoll einen gespeicherten Reset-Link nutzen, um ein Konto zu übernehmen. Wird eine solche E-Mail erneut gesendet, geht die maskierte Fassung raus.", - "Remote content": "Externe Inhalte", - "Always load remote images and fonts in the preview": "Externe Bilder und Schriften in der Vorschau immer laden", - "When off, tracking pixels cannot tell when you open an entry. You can still load remote content for a single email. Scripts and forms are always blocked.": "Ist das aus, können Tracking-Pixel nicht erkennen, wann du einen Eintrag öffnest. Für einzelne E-Mails kannst du externe Inhalte trotzdem laden. Skripte und Formulare sind immer blockiert.", - "Retention": "Aufbewahrung", + "Copies the existing log of another mail logging plugin into Mailspur, so old emails can be searched and previewed here. The other plugin and its data stay untouched; running the import again only adds new entries.": "Übernimmt das vorhandene Protokoll eines anderen Mail-Log-Plugins in Mailspur, damit alte E-Mails hier durchsucht und angesehen werden können. Das andere Plugin und seine Daten bleiben unverändert; ein erneuter Import übernimmt nur neue Einträge.", + "Current page": "Aktuelle Seite", + "Current size": "Aktuelle Größe", + "Date": "Datum", + "Delete": "Löschen", + "Delete %s selected log entries?": "%s ausgewählte Protokolleinträge löschen?", + "Delete ALL log entries? This cannot be undone.": "ALLE Protokolleinträge löschen? Das kann nicht rückgängig gemacht werden.", "Delete entries after": "Einträge löschen nach", - "days": "Tagen", - "0 keeps entries forever. Cleanup runs once a day.": "0 behält Einträge für immer. Die Bereinigung läuft einmal täglich.", - "Keep at most": "Höchstens behalten", - "entries": "Einträge", - "0 means no limit. The oldest entries are removed first.": "0 bedeutet kein Limit. Die ältesten Einträge werden zuerst entfernt.", - "Uninstall": "Deinstallation", + "Delete selected": "Auswahl löschen", "Delete the log table and settings when the plugin is deleted": "Protokolltabelle und Einstellungen löschen, wenn das Plugin gelöscht wird", - "Current size": "Aktuelle Größe", - "%1$s entries, %2$s": "%1$s Einträge, %2$s", + "Delete this log entry?": "Diesen Protokolleintrag löschen?", + "Deleted.": "Gelöscht.", + "Done: %1$s imported, %2$s duplicates, %3$s too old.": "Fertig: %1$s importiert, %2$s Duplikate, %3$s zu alt.", + "Editors and above": "Redakteure und höher", "Email log": "E-Mail-Protokoll", - "Mailspur – Email Log": "Mailspur – E-Mail-Log", - "This site keeps a log of emails it sends (recipient, subject, content and delivery status) to verify delivery and troubleshoot problems. Log entries are deleted automatically after the configured retention period.": "Diese Website protokolliert die von ihr versendeten E-Mails (Empfänger, Betreff, Inhalt und Zustellstatus), um die Zustellung zu prüfen und Fehler zu beheben. Protokolleinträge werden nach der eingestellten Aufbewahrungsdauer automatisch gelöscht.", - "Only administrators can empty the log.": "Nur Administratoren können das Protokoll leeren.", - "Log entry not found.": "Protokolleintrag nicht gefunden.", - "%1$s of %2$s entries processed …": "%1$s von %2$s Einträgen verarbeitet …", - "%s imported entries removed.": "%s importierte Einträge entfernt.", - "Copies the existing log of another mail logging plugin into Mailspur, so old emails can be searched and previewed here. The other plugin and its data stay untouched; running the import again only adds new entries.": "Übernimmt das vorhandene Protokoll eines anderen Mail-Log-Plugins in Mailspur, damit alte E-Mails hier durchsucht und angesehen werden können. Das andere Plugin und seine Daten bleiben unverändert; ein erneuter Import übernimmt nur neue Einträge.", + "Email sent again.": "E-Mail wurde erneut gesendet.", + "Emails that are already in the log – logged by Mailspur itself or imported from another plugin – are recognized by recipients, subject and send time and skipped as duplicates.": "E-Mails, die bereits im Protokoll stehen – von Mailspur selbst protokolliert oder aus einem anderen Plugin importiert –, werden an Empfängern, Betreff und Versandzeit erkannt und als Duplikat übersprungen.", + "Empty log": "Protokoll leeren", "Entries": "Einträge", "Entries older than %s days are skipped because the retention setting would delete them anyway. Change the retention above first to import everything.": "Einträge, die älter als %s Tage sind, werden übersprungen, weil die Aufbewahrungseinstellung sie ohnehin löschen würde. Passe die Aufbewahrung oben zuerst an, um alles zu importieren.", + "Error": "Fehler", + "Failed": "Fehlgeschlagen", + "Filter by status": "Nach Status filtern", + "First page": "Erste Seite", + "Format": "Format", + "From": "Von", + "From date": "Von Datum", + "Headers": "Header", + "Held": "Zurückgehalten", + "I already did": "Hab ich schon", "Import": "Importieren", "Import failed: %s": "Import fehlgeschlagen: %s", "Import from other plugins": "Aus anderen Plugins importieren", "Import new entries": "Neue Einträge importieren", "Imported": "Importiert", "Imported from %s": "Importiert aus %s", + "Is Mailspur helping you?": "Hilft dir Mailspur?", + "Keep at most": "Höchstens behalten", + "Last page": "Letzte Seite", + "Leave a ★★★★★ review": "Gib eine ★★★★★-Bewertung ab", + "Load remote content": "Externe Inhalte laden", + "Log": "Protokoll", + "Log entry not found.": "Protokolleintrag nicht gefunden.", + "Logged emails can contain personal data. Grant access as narrowly as possible. Settings always require administrator rights.": "Protokollierte E-Mails können personenbezogene Daten enthalten. Vergib den Zugriff so eng wie möglich. Die Einstellungen erfordern immer Administratorrechte.", + "Mail Log": "Mail-Log", + "Mail Log sections": "Mail-Log-Bereiche", + "Mailspur has logged %s delivered emails on this site so far. If it saves you time, a short review on WordPress.org would mean a lot – it helps others find the plugin and keeps it free.": "Mailspur hat auf dieser Website bisher %s zugestellte E-Mails protokolliert. Wenn es dir Zeit spart, würde mir eine kurze Bewertung auf WordPress.org viel bedeuten – sie hilft anderen, das Plugin zu finden, und hält es kostenlos.", + "Mailspur is made by %1$s. Enjoying it? %2$s": "Mailspur wird von %1$s entwickelt. Gefällt es dir? %2$s", + "Mailspur – Email Log": "Mailspur – E-Mail-Log", + "Mask password-reset, activation and access keys in logged links": "Passwort-Reset-, Aktivierungs- und Zugriffsschlüssel in protokollierten Links maskieren", + "Maybe later": "Vielleicht später", + "Menu position": "Menüposition", + "Next email": "Nächste E-Mail", + "Next email (j)": "Nächste E-Mail (j)", + "Next page": "Nächste Seite", + "No emails found.": "Noch keine E-Mails protokolliert.", + "No emails match these filters.": "Keine E-Mails passen zu diesen Filtern.", "No log of another mail logging plugin was found on this site.": "Auf dieser Website wurde kein Protokoll eines anderen Mail-Log-Plugins gefunden.", "No log of this plugin was found on this site.": "Auf dieser Website wurde kein Protokoll dieses Plugins gefunden.", + "Only administrators can empty the log.": "Nur Administratoren können das Protokoll leeren.", + "Own top-level menu item": "Eigener Hauptmenüpunkt", + "Pagination": "Seitennavigation", + "Per page": "Pro Seite", "Plugin": "Plugin", + "Preview": "Vorschau", + "Previous email": "Vorherige E-Mail", + "Previous email (k)": "Vorherige E-Mail (k)", + "Previous page": "Vorherige Seite", + "Privacy & security": "Datenschutz & Sicherheit", + "Rate Mailspur on WordPress.org": "Mailspur auf WordPress.org bewerten", + "Rate Mailspur ★★★★★": "Mailspur bewerten ★★★★★", + "Recipient": "Empfänger", + "Recommended. Otherwise anyone with log access could use a logged reset link to take over an account. Resending such an email sends the masked version.": "Empfohlen. Sonst könnte jeder mit Zugriff auf das Protokoll einen gespeicherten Reset-Link nutzen, um ein Konto zu übernehmen. Wird eine solche E-Mail erneut gesendet, geht die maskierte Fassung raus.", + "Redact secrets": "Geheimnisse schwärzen", + "Remote content": "Externe Inhalte", + "Remote content is loaded.": "Externe Inhalte werden geladen.", + "Remote images and fonts are blocked so senders cannot track when you open this entry.": "Externe Bilder und Schriften sind blockiert, damit niemand verfolgen kann, wann du diesen Eintrag öffnest.", "Remove all entries imported from %s? The data in the other plugin is not affected.": "Alle aus %s importierten Einträge entfernen? Die Daten im anderen Plugin bleiben unberührt.", "Remove imported entries": "Importierte Einträge entfernen", + "Request failed: %s": "Anfrage fehlgeschlagen: %s", + "Resend": "Erneut senden", + "Resent from log": "Erneut gesendet", + "Reset filters": "Filter zurücksetzen", + "Retention": "Aufbewahrung", + "Search recipient or subject": "Empfänger oder Betreff suchen", + "Search recipient or subject …": "Empfänger oder Betreff suchen …", + "Select all": "Alle auswählen", + "Send this email again to %s?": "Diese E-Mail erneut an %s senden?", + "Sending failed – see the new log entry for details.": "Senden fehlgeschlagen – Details im neuen Protokolleintrag.", + "Sent": "Gesendet", + "Settings": "Einstellungen", + "Shop managers and above": "Shop-Manager und höher", + "Sorry, you are not allowed to access this page.": "Du hast leider keine Berechtigung, auf diese Seite zuzugreifen.", + "Source": "Quelle", + "Status": "Status", + "Subject": "Betreff", "Supported: %s.": "Unterstützt: %s.", + "The mail log requires JavaScript.": "Das Mail-Log benötigt JavaScript.", + "This entry was anonymised; its content can no longer be sent.": "Dieser Eintrag wurde anonymisiert; sein Inhalt kann nicht mehr gesendet werden.", "This import is already running in another tab.": "Dieser Import läuft bereits in einem anderen Tab.", - "%1$s imported, %2$s duplicates, %3$s too old": "%1$s importiert, %2$s Duplikate, %3$s zu alt", - "Done: %1$s imported, %2$s duplicates, %3$s too old.": "Fertig: %1$s importiert, %2$s Duplikate, %3$s zu alt.", - "Emails that are already in the log – logged by Mailspur itself or imported from another plugin – are recognized by recipients, subject and send time and skipped as duplicates.": "E-Mails, die bereits im Protokoll stehen – von Mailspur selbst protokolliert oder aus einem anderen Plugin importiert –, werden an Empfängern, Betreff und Versandzeit erkannt und als Duplikat übersprungen.", - "Held": "Zurückgehalten", - "This entry was anonymised; its content can no longer be sent.": "Dieser Eintrag wurde anonymisiert; sein Inhalt kann nicht mehr gesendet werden." + "This site keeps a log of emails it sends (recipient, subject, content and delivery status) to verify delivery and troubleshoot problems. Log entries are deleted automatically after the configured retention period.": "Diese Website protokolliert die von ihr versendeten E-Mails (Empfänger, Betreff, Inhalt und Zustellstatus), um die Zustellung zu prüfen und Fehler zu beheben. Protokolleinträge werden nach der eingestellten Aufbewahrungsdauer automatisch gelöscht.", + "To": "An", + "To date": "Bis Datum", + "Under Tools": "Unter Werkzeuge", + "Uninstall": "Deinstallation", + "Unknown": "Unbekannt", + "View": "Ansehen", + "When off, tracking pixels cannot tell when you open an entry. You can still load remote content for a single email. Scripts and forms are always blocked.": "Ist das aus, können Tracking-Pixel nicht erkennen, wann du einen Eintrag öffnest. Für einzelne E-Mails kannst du externe Inhalte trotzdem laden. Skripte und Formulare sind immer blockiert.", + "Who can view the log": "Wer darf das Protokoll sehen", + "WordPress": "WordPress", + "days": "Tagen", + "entries": "Einträge", + "of %s": "von %s" } diff --git a/i18n/de_DE/insights.json b/i18n/de_DE/insights.json index 70530e4..7bc282d 100644 --- a/i18n/de_DE/insights.json +++ b/i18n/de_DE/insights.json @@ -66,7 +66,7 @@ "Numbers are ignored, so “Order #123” and “Order #124” count together.": "Zahlen werden ignoriert, „Bestellung #123“ und „Bestellung #124“ zählen also zusammen.", "Only alerts when the last 14 days show that emails are normally sent in this time window (on at least 10 of 14 days, including the same weekday), so quiet nights or weekends do not trigger it.": "Benachrichtigt nur, wenn die letzten 14 Tage zeigen, dass in diesem Zeitfenster normalerweise E-Mails gesendet werden (an mindestens 10 von 14 Tagen, einschließlich desselben Wochentags) – ruhige Nächte oder Wochenenden lösen also nichts aus.", "Open the mail log": "Mail-Log öffnen", - "Optional and off by default. When enabled, Mailspur checks the log every 15 minutes and notifies you about failure spikes or unusual silence. Alerts go only to the addresses and the webhook you enter here; they contain the site name, the alert text and a link to the log – never email contents.": "Optional und standardmäßig aus. Wenn aktiviert, prüft Mailspur das Protokoll alle 15 Minuten und benachrichtigt dich bei gehäuften Fehlern oder ungewöhnlicher Stille. Benachrichtigungen gehen nur an die Adressen und den Webhook, die du hier einträgst; sie enthalten den Namen der Website, den Hinweistext und einen Link zum Protokoll – niemals E-Mail-Inhalte.", + "Optional and off by default. When enabled, Mailspur checks the log regularly and notifies you about failure spikes, unusual silence or stopped email types. Alerts go only to the addresses and the webhook you enter here; they contain the site name, the alert text (for a stopped email type: its sender and subject pattern) and a link to the log – never email contents or recipients.": "Optional und standardmäßig aus. Wenn aktiviert, prüft Mailspur das Protokoll regelmäßig und benachrichtigt dich bei gehäuften Fehlern, ungewöhnlicher Stille oder ausbleibenden E-Mail-Typen. Benachrichtigungen gehen nur an die Adressen und den Webhook, die du hier einträgst; sie enthalten den Namen der Website, den Hinweistext (bei einem ausbleibenden E-Mail-Typ: Absender und Betreff-Muster) und einen Link zum Protokoll – niemals E-Mail-Inhalte oder Empfänger.", "Optional, https only. Slack and Discord webhook URLs receive a chat message, any other URL a JSON POST request. The request is made by your server to exactly this URL – no other service is involved.": "Optional, nur https. Slack- und Discord-Webhook-URLs erhalten eine Chat-Nachricht, jede andere URL eine JSON-POST-Anfrage. Die Anfrage geht von deinem Server direkt an genau diese URL – kein anderer Dienst ist beteiligt.", "Period": "Zeitraum", "Plugin or theme that sent the email.": "Plugin oder Theme, das die E-Mail gesendet hat.", diff --git a/i18n/de_DE/types.json b/i18n/de_DE/types.json new file mode 100644 index 0000000..3a6d17e --- /dev/null +++ b/i18n/de_DE/types.json @@ -0,0 +1,61 @@ +{ + "%1$s email types from %2$s senders": "%1$s E-Mail-Typen von %2$s Absendern", + "%1$s emails in the last 30 days, %2$s failed": "%1$s E-Mails in den letzten 30 Tagen, %2$s fehlgeschlagen", + "%s ago": "vor %s", + "%s in 30 days": "%s in 30 Tagen", + "Alert when an email type that is sent regularly stops": "Benachrichtigen, wenn ein regelmäßig versendeter E-Mail-Typ ausbleibt", + "All email types look healthy.": "Alle E-Mail-Typen sehen gesund aus.", + "Daily": "Täglich", + "Email type": "E-Mail-Typ", + "Email type is sent again": "E-Mail-Typ wird wieder versendet", + "Email type stopped": "E-Mail-Typ bleibt aus", + "Email types": "E-Mail-Typen", + "Every %s days": "Alle %s Tage", + "Every kind of email your site sends, found automatically in the log: grouped by the plugin that sends it and by subject, with numbers, addresses and names as placeholders. Mailspur learns how often each type is sent and notices when one stops – for example after a plugin update.": "Jede Art von E-Mail, die deine Website versendet – automatisch im Protokoll erkannt: gruppiert nach dem Plugin, das sie sendet, und nach Betreff, mit Zahlen, Adressen und Namen als Platzhalter. Mailspur lernt, wie oft jeder Typ versendet wird, und bemerkt, wenn einer ausbleibt – zum Beispiel nach einem Plugin-Update.", + "Failing": "Fehlerhaft", + "Filter email types": "E-Mail-Typen filtern", + "Ignore": "Ignorieren", + "Ignored": "Ignoriert", + "Irregular": "Unregelmäßig", + "Last 30 days": "Letzte 30 Tage", + "Last sent": "Zuletzt versendet", + "Mailspur learns the rhythm of every email type from the last 8 weeks – a daily order confirmation is overdue after 2 days, a weekly report after 2 weeks. The alert names the type, its sender and the plugins updated since its last email. Uses the channels above; ignored types never alert.": "Mailspur lernt den Rhythmus jedes E-Mail-Typs aus den letzten 8 Wochen – eine tägliche Bestellbestätigung ist nach 2 Tagen überfällig, ein wöchentlicher Bericht nach 2 Wochen. Die Benachrichtigung nennt den Typ, seinen Absender und die seit seiner letzten E-Mail aktualisierten Plugins. Nutzt die Kanäle oben; ignorierte Typen lösen nie aus.", + "Monitor again": "Wieder überwachen", + "New": "Neu", + "No emails logged yet. Email types appear here as soon as your site sends emails.": "Noch keine E-Mails protokolliert. E-Mail-Typen erscheinen hier, sobald deine Website E-Mails versendet.", + "Normally sent at least every %1$s days, now overdue by %2$s.": "Normalerweise mindestens alle %1$s Tage versendet, jetzt seit %2$s überfällig.", + "Notes in the latest email: %s": "Hinweise in der letzten E-Mail: %s", + "Other emails": "Weitere E-Mails", + "Rarely": "Selten", + "Rebuild from the log": "Aus dem Protokoll neu aufbauen", + "Rhythm": "Rhythmus", + "Several of the latest emails of this type failed.": "Mehrere der letzten E-Mails dieses Typs sind fehlgeschlagen.", + "Show emails": "E-Mails anzeigen", + "Sorry, you are not allowed to do that.": "Du darfst diese Aktion leider nicht ausführen.", + "Still sorting %s older emails into types in the background. Reload the page in a minute.": "Sortiere im Hintergrund noch %s ältere E-Mails in Typen ein. Lade die Seite in einer Minute neu.", + "Stopped": "Ausgeblieben", + "Stopped email types": "Ausbleibende E-Mail-Typen", + "The email types are being rebuilt from the log.": "Die E-Mail-Typen werden aus dem Protokoll neu aufgebaut.", + "This email type is ignored now: no status, no alerts.": "Dieser E-Mail-Typ wird jetzt ignoriert: kein Status, keine Benachrichtigungen.", + "This email type is monitored again.": "Dieser E-Mail-Typ wird wieder überwacht.", + "Types are updated hourly and whenever you open this page. Only counters and subject patterns are stored, and they follow the retention period of the log.": "Die Typen werden stündlich und beim Öffnen dieser Seite aktualisiert. Gespeichert werden nur Zähler und Betreff-Muster, und sie folgen der Aufbewahrungsdauer des Protokolls.", + "Updated since the last one:": "Seit der letzten aktualisiert:", + "Updated since then: %s.": "Seitdem aktualisiert: %s.", + "Weekly": "Wöchentlich", + "address": "Adresse", + "code": "Code", + "date": "Datum", + "failing": "fehlerhaft", + "first seen %s": "zuerst gesehen am %s", + "link": "Link", + "name": "Name", + "new this week": "neu diese Woche", + "number": "Zahl", + "stopped": "ausgeblieben", + "stopped email types": "ausbleibenden E-Mail-Typen", + "text": "Text", + "time": "Uhrzeit", + "usually sent: %s": "üblicher Rhythmus: %s", + "“%1$s” (%2$s) is being sent again.": "„%1$s“ (%2$s) wird wieder versendet.", + "“%1$s” (%2$s) was last sent %3$s ago. Until then it was sent at least every %4$s days.": "„%1$s“ (%2$s) wurde zuletzt vor %3$s versendet. Bis dahin kam der Typ mindestens alle %4$s Tage." +} diff --git a/mailspur-email-log/assets/admin.css b/mailspur-email-log/assets/admin.css index edeb248..262c536 100644 --- a/mailspur-email-log/assets/admin.css +++ b/mailspur-email-log/assets/admin.css @@ -1,20 +1,95 @@ -/* Mailspur – Email Log admin styles. Uses WP admin color scheme variables where available. */ +/* + * Mailspur – Email Log admin styles. + * + * Brand: night indigo, violet accent, coral trail, mint for "delivered". The --ms-* tokens are shared with the + * module stylesheets (insights, types, …); everything stays inside .mailspur so other admin screens are untouched. + */ + +.mailspur, +.mailspur-review { + --ms-night: #1b1145; + --ms-indigo: #2a1a6e; + --ms-accent: #5b3ff0; + --ms-accent-strong: #4a2fd6; + --ms-accent-soft: #f1edff; + --ms-accent-ring: rgba(91, 63, 240, 0.28); + --ms-coral: #ff6b4a; + --ms-mint: #2bd9a1; + --ms-ink: #1b1530; + --ms-surface: #fff; + --ms-canvas: #f6f5fb; + --ms-line: #e7e3f3; + --ms-line-soft: #f1eef8; + --ms-shadow: 0 1px 2px rgba(27, 17, 69, 0.06), 0 10px 30px -18px rgba(27, 17, 69, 0.28); + --ob-accent: var(--ms-accent); + --ob-border: var(--ms-line); + --ob-muted: #625c78; + --ob-bg: var(--ms-surface); + --ob-row-hover: #faf8ff; + --ob-sent: #0b8a5f; + --ob-sent-bg: #e3f8ef; + --ob-failed: #c8321f; + --ob-failed-bg: #fff0ec; + --ob-pending: #8a5a00; + --ob-pending-bg: #fff6dc; + --ob-held: #4a2fd6; + --ob-held-bg: #f1edff; + --ob-radius: 10px; + --ms-logo: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cdefs%3E%3CradialGradient id='g' cx='.18' cy='.12' r='.95'%3E%3Cstop offset='0' stop-color='%234a33c8'/%3E%3Cstop offset='.55' stop-color='%232a1a6e'/%3E%3Cstop offset='1' stop-color='%231b1145'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='100' height='100' rx='24' fill='url(%23g)'/%3E%3Cg fill='%23ff6b4a'%3E%3Ccircle cx='13' cy='90' r='4' opacity='.55'/%3E%3Ccircle cx='22' cy='80' r='4.6' opacity='.8'/%3E%3C/g%3E%3Cg transform='translate(56 47) rotate(-14)'%3E%3Crect x='-28' y='-20' width='56' height='40' rx='8' fill='%23fff8f2'/%3E%3Cpath d='M-21 -12 L0 4 L21 -12' fill='none' stroke='%236c4bff' stroke-width='6.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/g%3E%3C/svg%3E"); +} + +/* Mailspur's page gets a slightly tinted canvas. */ +body.toplevel_page_mailspur-email-log, +body.tools_page_mailspur-email-log { + background: #f6f5fb; +} .mailspur { - --ob-accent: var(--wp-admin-theme-color, #2271b1); - --ob-border: #dcdcde; - --ob-muted: #646970; - --ob-bg: #fff; - --ob-row-hover: #f6f7f7; - --ob-sent: #00a32a; - --ob-sent-bg: #edfaef; - --ob-failed: #d63638; - --ob-failed-bg: #fcf0f1; - --ob-pending: #996800; - --ob-pending-bg: #fcf9e8; - --ob-held: #3858e9; - --ob-held-bg: #eff2ff; - --ob-radius: 6px; + color: var(--ms-ink); +} + +.mailspur a { + color: var(--ms-accent); +} + +.mailspur a:hover, +.mailspur a:focus { + color: var(--ms-accent-strong); +} + +.mailspur .button-primary { + border-color: var(--ms-accent); + background: var(--ms-accent); + color: #fff; +} + +.mailspur .button-primary:hover, +.mailspur .button-primary:focus { + border-color: var(--ms-accent-strong); + background: var(--ms-accent-strong); + color: #fff; +} + +.mailspur .button:not(.button-primary):not(.button-link):hover { + border-color: var(--ms-accent); + color: var(--ms-accent-strong); +} + +.mailspur input[type="text"]:focus, +.mailspur input[type="search"]:focus, +.mailspur input[type="email"]:focus, +.mailspur input[type="url"]:focus, +.mailspur input[type="number"]:focus, +.mailspur input[type="date"]:focus, +.mailspur select:focus, +.mailspur textarea:focus, +.mailspur input[type="checkbox"]:focus { + border-color: var(--ms-accent); + box-shadow: 0 0 0 3px var(--ms-accent-ring); +} + +.mailspur :focus-visible { + outline-color: var(--ms-accent); } /* ---------------------------------------------------------------- header */ @@ -23,44 +98,77 @@ display: flex; flex-wrap: wrap; align-items: center; - gap: 8px 24px; - margin-bottom: 12px; + gap: 12px 28px; + margin: 4px 0 18px; + padding: 12px 14px; + border: 1px solid var(--ms-line); + border-radius: 14px; + background: var(--ms-surface); + box-shadow: var(--ms-shadow); } .mailspur .mailspur-title { display: flex; align-items: center; - gap: 6px; + gap: 12px; padding: 0; margin: 0; + color: var(--ms-ink); + font-size: 20px; + font-weight: 700; + letter-spacing: -0.01em; + line-height: 1.15; } -.mailspur-title .dashicons { - width: 26px; - height: 26px; - font-size: 26px; - color: var(--ob-accent); +.mailspur-logo { + flex: 0 0 auto; + width: 40px; + height: 40px; + border-radius: 11px; + background: var(--ms-logo) center / cover no-repeat; + box-shadow: 0 6px 14px -6px rgba(42, 26, 110, 0.6); +} + +.mailspur-title-text { + display: flex; + flex-direction: column; +} + +.mailspur-brand { + color: var(--ms-accent); + font-size: 11px; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; } .mailspur-nav { display: flex; - gap: 4px; + flex-wrap: wrap; + gap: 2px; + padding: 4px; + border-radius: 12px; + background: var(--ms-canvas); } .mailspur-nav a { - padding: 6px 12px; - border-radius: var(--ob-radius); - color: #1d2327; - font-weight: 500; + padding: 7px 14px; + border-radius: 9px; + color: #4b4566; + font-weight: 600; text-decoration: none; + transition: background 0.15s, color 0.15s; } -.mailspur-nav a:hover { - background: #e5e5e5; +.mailspur-nav a:hover, +.mailspur-nav a:focus { + background: #fff; + color: var(--ms-ink); } .mailspur-nav a.is-active { - background: var(--ob-accent); + background: var(--ms-accent); + box-shadow: 0 6px 14px -8px var(--ms-accent); color: #fff; } @@ -86,17 +194,20 @@ align-items: center; gap: 6px; min-height: 32px; - padding: 0 12px; + padding: 0 14px; border: 1px solid var(--ob-border); border-radius: 999px; background: var(--ob-bg); - color: #1d2327; + color: var(--ms-ink); font: inherit; + font-weight: 500; cursor: pointer; + transition: border-color 0.15s, background 0.15s; } .mailspur-chip:hover { - border-color: #8c8f94; + border-color: var(--ms-accent); + background: var(--ms-accent-soft); } .mailspur-chip[aria-pressed="true"] { @@ -271,8 +382,9 @@ .mailspur-table-wrap { overflow: hidden; border: 1px solid var(--ob-border); - border-radius: var(--ob-radius); + border-radius: 14px; background: var(--ob-bg); + box-shadow: var(--ms-shadow); transition: opacity 0.15s; } @@ -288,8 +400,8 @@ .mailspur-table th, .mailspur-table td { - padding: 9px 10px; - border-bottom: 1px solid #f0f0f1; + padding: 11px 12px; + border-bottom: 1px solid var(--ms-line-soft); text-align: left; vertical-align: middle; } @@ -297,10 +409,12 @@ .mailspur-table thead th, .mailspur-table thead td { border-bottom-color: var(--ob-border); - background: #f6f7f7; - color: #1d2327; - font-size: 12px; - font-weight: 600; + background: #fbfaff; + color: #625c78; + font-size: 11px; + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; } .mailspur-table thead button { @@ -309,6 +423,8 @@ background: none; color: inherit; font: inherit; + letter-spacing: inherit; + text-transform: inherit; cursor: pointer; } @@ -396,7 +512,7 @@ padding: 0; border: 0; background: none; - color: #1d2327; + color: var(--ms-ink); font: inherit; text-align: left; cursor: pointer; @@ -437,8 +553,8 @@ .mailspur-row-action:hover, .mailspur-row-action:focus { - background: #dcdcde; - color: #1d2327; + background: var(--ms-accent-soft); + color: var(--ms-accent-strong); } .mailspur-row-action[data-action="delete"]:hover { @@ -454,18 +570,28 @@ } .mailspur-badge { - display: inline-block; - padding: 1px 8px; + display: inline-flex; + align-items: center; + gap: 6px; + padding: 1px 10px 1px 8px; border-radius: 999px; font-size: 12px; - font-weight: 500; + font-weight: 600; line-height: 20px; white-space: nowrap; } +.mailspur-badge::before { + content: ""; + width: 6px; + height: 6px; + border-radius: 50%; + background: currentColor; +} + .mailspur-badge.is-sent { background: var(--ob-sent-bg); - color: #007017; + color: var(--ob-sent); } .mailspur-badge.is-failed { @@ -522,8 +648,8 @@ max-height: none; padding: 0; border: 0; - border-radius: 10px; - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); + border-radius: 16px; + box-shadow: 0 30px 80px -20px rgba(27, 17, 69, 0.55); } .mailspur-dialog[open] { @@ -532,7 +658,8 @@ } .mailspur-dialog::backdrop { - background: rgba(15, 23, 42, 0.55); + background: rgba(27, 17, 69, 0.55); + backdrop-filter: blur(2px); } .mailspur-d-head { @@ -678,9 +805,9 @@ max-width: min(560px, calc(100vw - 32px)); padding: 10px 16px; border-radius: var(--ob-radius); - background: #1d2327; + background: var(--ms-night); color: #fff; - box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25); + box-shadow: 0 10px 30px -10px rgba(27, 17, 69, 0.6); opacity: 0; pointer-events: none; transform: translate(-50%, 12px); @@ -700,6 +827,98 @@ .mailspur-settings h2 { margin-top: 28px; + color: var(--ms-ink); +} + +.mailspur-settings .form-table { + border-radius: 14px; + background: var(--ms-surface); + box-shadow: var(--ms-shadow); +} + +.mailspur-settings .form-table th { + padding-left: 20px; +} + +/* ---------------------------------------------------------------- review */ + +.mailspur-review { + position: relative; + display: flex; + align-items: center; + gap: 20px; + margin: 0 0 18px; + padding: 18px 22px; + overflow: hidden; + border-radius: 14px; + background: + radial-gradient(circle at 8% 0%, rgba(108, 75, 255, 0.55), transparent 45%), + radial-gradient(circle at 100% 120%, rgba(255, 107, 74, 0.35), transparent 45%), + var(--ms-night); + color: #fff; + box-shadow: var(--ms-shadow); +} + +.mailspur-review-mark { + flex: 0 0 auto; + width: 56px; + height: 56px; + border-radius: 15px; + background: var(--ms-logo) center / cover no-repeat; + box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.15); +} + +.mailspur-review h2 { + margin: 0 0 4px; + color: #fff; + font-size: 16px; +} + +.mailspur-review p { + max-width: 720px; + margin: 0; + color: #ddd8ff; +} + +.mailspur-review .mailspur-review-actions { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 8px 12px; + margin-top: 12px; +} + +.mailspur-review .button-primary, +.mailspur .mailspur-review .button-primary { + border-color: var(--ms-coral); + background: var(--ms-coral); + color: #1b1145; + font-weight: 600; +} + +.mailspur-review .button-primary:hover, +.mailspur-review .button-primary:focus { + border-color: #ff8a6e; + background: #ff8a6e; + color: #1b1145; +} + +.mailspur-review .button:not(.button-primary) { + border-color: rgba(255, 255, 255, 0.35); + background: transparent; + color: #fff; +} + +.mailspur-review .button-link, +.mailspur .mailspur-review a.button-link { + color: #ddd8ff; +} + +@media (max-width: 600px) { + .mailspur-review { + flex-direction: column; + align-items: flex-start; + } } .mailspur .mailspur-narrow { diff --git a/mailspur-email-log/assets/insights.css b/mailspur-email-log/assets/insights.css index de8c416..1dd50fb 100644 --- a/mailspur-email-log/assets/insights.css +++ b/mailspur-email-log/assets/insights.css @@ -2,19 +2,20 @@ .mailspur-insights, .msi-widget { - --msi-accent: var(--wp-admin-theme-color, #2271b1); + --msi-accent: var(--ms-accent, #5b3ff0); --msi-surface: #fff; - --msi-border: #dcdcde; - --msi-ink: #1d2327; + --msi-border: var(--ms-line, #dcdcde); + --msi-ink: var(--ms-ink, #1d2327); --msi-ink-2: #50575e; --msi-muted: #646970; --msi-grid: #ebebea; --msi-axis: #c3c4c7; --msi-good: #007017; --msi-bad: #b32d2e; - --msi-series: #2a78d6; - --msi-failed: #d03b3b; - --msi-radius: 6px; + --msi-series: var(--ms-accent, #5b3ff0); + --msi-failed: #e0442b; + --msi-radius: 14px; + --msi-shadow: var(--ms-shadow, none); } .mailspur-insights { @@ -103,6 +104,7 @@ border: 1px solid var(--msi-border); border-radius: var(--msi-radius); background: var(--msi-surface); + box-shadow: var(--msi-shadow); min-width: 0; } @@ -172,6 +174,7 @@ border: 1px solid var(--msi-border); border-radius: var(--msi-radius); background: var(--msi-surface); + box-shadow: var(--msi-shadow); min-width: 0; } diff --git a/mailspur-email-log/assets/insights.js b/mailspur-email-log/assets/insights.js index e7ec4e3..7adb807 100644 --- a/mailspur-email-log/assets/insights.js +++ b/mailspur-email-log/assets/insights.js @@ -21,9 +21,9 @@ } )(); const STATUSES = [ 'sent', 'failed', 'held', 'pending' ]; // Validated categorical slots (light surface); order = stack order bottom → top. - const COLORS = { sent: '#2a78d6', failed: '#d03b3b', held: '#4a3aa7', pending: '#eda100' }; - // Sequential blue ramp for the heatmap, light → dark; zero gets a neutral gray. - const RAMP = [ '#cde2fb', '#86b6ef', '#3987e5', '#256abf', '#184f95' ]; + const COLORS = { sent: '#5b3ff0', failed: '#e0442b', held: '#b4a6ff', pending: '#eda100' }; + // Sequential violet ramp (brand) for the heatmap, light → dark; zero gets a neutral gray. + const RAMP = [ '#e9e4ff', '#c4b6ff', '#9781ff', '#6c4bff', '#3f24c4' ]; const ZERO = '#f0f0f1'; const locale = cfg.locale || undefined; diff --git a/mailspur-email-log/assets/types.css b/mailspur-email-log/assets/types.css new file mode 100644 index 0000000..d929ad2 --- /dev/null +++ b/mailspur-email-log/assets/types.css @@ -0,0 +1,274 @@ +/* Mailspur – Email Log: "Email types" tab and the type line in the log dialog. */ + +.mailspur-types, +.mailspur-type-dd { + --mst-surface: #fff; + --mst-border: var(--ms-line, #dcdcde); + --mst-ink: var(--ms-ink, #1d2327); + --mst-muted: #646970; + --mst-bar: var(--ms-accent, #5b3ff0); + --mst-held: #a7aaad; + --mst-failed: #d03b3b; + --mst-base: #dcdcde; + --mst-radius: 10px; +} + +.mailspur-types { + max-width: 1280px; + color: var(--mst-ink); +} + +.mst-intro { + max-width: 760px; + color: var(--mst-muted); +} + +/* ---------------------------------------------------------------- summary + views */ + +.mst-summary { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin: 16px 0 12px; + padding: 0; + list-style: none; +} + +.mst-summary li { + margin: 0; + padding: 6px 12px; + border: 1px solid var(--mst-border); + border-radius: var(--mst-radius); + background: var(--mst-surface); +} + +.mst-summary .is-silent { + border-color: #e6a23c; + background: #fcf9e8; +} + +.mst-summary .is-failing { + border-color: #e4a0a0; + background: #fcf0f1; +} + +.mst-summary .is-new { + border-color: #9ec2e6; + background: #f0f6fc; +} + +.mst-views { + display: flex; + gap: 16px; + margin-bottom: 8px; +} + +.mst-views a[aria-current="page"] { + color: var(--mst-ink); + font-weight: 600; + text-decoration: none; +} + +/* ---------------------------------------------------------------- groups + table */ + +.mst-group { + margin: 24px 0 0; +} + +.mst-group h2 { + display: flex; + align-items: center; + gap: 8px; + margin: 0 0 8px; + font-size: 1.15em; +} + +.mst-count { + padding: 0 8px; + border-radius: 10px; + background: #f0f0f1; + color: var(--mst-muted); + font-size: 12px; + font-weight: 400; + line-height: 20px; +} + +.mst-table-wrap { + overflow-x: auto; +} + +.mst-table { + overflow: hidden; + border-color: var(--ms-line, #dcdcde); + border-radius: 14px; + box-shadow: var(--ms-shadow, none); +} + +.mailspur-types .mst-table thead th { + color: #625c78; + font-size: 11px; + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; +} + +.mst-table td { + vertical-align: middle; +} + +.mst-col-type { + width: 34%; + min-width: 220px; +} + +.mst-col-volume { + min-width: 160px; +} + +.mst-col-state { + min-width: 180px; +} + +.mst-row.is-silent { + box-shadow: inset 3px 0 0 #dba617; +} + +.mst-row.is-failing { + box-shadow: inset 3px 0 0 var(--mst-failed); +} + +.mst-row.is-muted { + opacity: 0.65; +} + +.mst-pattern { + display: block; + font-weight: 600; + overflow-wrap: anywhere; +} + +.mst-ph, +.mst-other { + display: inline-block; + margin: 0 1px; + padding: 0 6px; + border-radius: 4px; + background: #f0f0f1; + color: var(--mst-muted); + font-size: 12px; + font-weight: 400; + line-height: 18px; +} + +.mst-other { + margin: 0; + font-style: italic; +} + +.mst-meta, +.mst-volume, +.mst-why { + display: block; + margin-top: 2px; + color: var(--mst-muted); + font-size: 12px; +} + +.mst-notes { + color: #996800; +} + +.mst-failed { + color: var(--mst-failed); +} + +/* ---------------------------------------------------------------- sparkline */ + +.mst-spark { + display: block; +} + +.mst-spark .mst-bar { + fill: var(--mst-bar); +} + +.mst-spark .mst-bar-held { + fill: var(--mst-held); +} + +.mst-spark .mst-bar-failed { + fill: var(--mst-failed); +} + +.mst-spark .mst-bar-base { + fill: var(--mst-base); +} + +/* ---------------------------------------------------------------- state badges */ + +.mst-state { + display: inline-block; + padding: 1px 8px; + border-radius: 10px; + background: #edfaef; + color: #00450c; + font-size: 12px; + font-weight: 600; + line-height: 18px; +} + +.mst-state.is-silent { + background: #fcf9e8; + color: #614200; +} + +.mst-state.is-failing { + background: #fcf0f1; + color: #8a2424; +} + +.mst-state.is-new { + background: #f0f6fc; + color: #0a4b78; +} + +.mst-state.is-muted { + background: #f0f0f1; + color: var(--mst-muted); +} + +.mst-actions, +.mst-col-last { + white-space: nowrap; +} + +.mst-actions form { + display: inline; + margin-left: 8px; +} + +.mst-empty { + padding: 24px; + border: 1px dashed var(--mst-border); + border-radius: var(--mst-radius); + background: var(--mst-surface); + text-align: center; +} + +.mst-rebuild { + margin-top: 24px; +} + +/* ---------------------------------------------------------------- log dialog */ + +.mailspur-type-rhythm { + display: block; + color: var(--mst-muted); + font-size: 12px; +} + +@media (max-width: 782px) { + .mst-col-type { + min-width: 180px; + } +} diff --git a/mailspur-email-log/assets/types.js b/mailspur-email-log/assets/types.js new file mode 100644 index 0000000..04d5e07 --- /dev/null +++ b/mailspur-email-log/assets/types.js @@ -0,0 +1,34 @@ +/** + * Mailspur – email types module (log tab). + * + * Dialog: an "Email type" line linking to the type on the "Email types" tab, with its rhythm. + * + * Uses the window.mailspur module API; all text is inserted via textContent. + */ +( function () { + 'use strict'; + + const m = window.mailspur; + const cfg = window.mailspurTypes; + if ( ! m || ! cfg ) { + return; + } + + const t = cfg.i18n; + + m.registerDetail( ( dl, mail ) => { + const type = mail.mailtype; + if ( ! type || ! type.label ) { + return; + } + const dd = m.node( 'dd', 'mailspur-type-dd' ); + const link = m.node( 'a', '', type.label ); + link.href = type.url; + dd.append( link ); + if ( 'silent' === type.state ) { + dd.append( ' ', m.node( 'span', 'mst-state is-silent', t.stopped ) ); + } + dd.append( m.node( 'span', 'mailspur-type-rhythm', m.fmt( t.rhythm, type.rhythm ) ) ); + dl.append( m.node( 'dt', '', t.type ), dd ); + } ); +}() ); diff --git a/mailspur-email-log/languages/mailspur-email-log-de_DE.l10n.php b/mailspur-email-log/languages/mailspur-email-log-de_DE.l10n.php index 3d471e5..6d27510 100644 --- a/mailspur-email-log/languages/mailspur-email-log-de_DE.l10n.php +++ b/mailspur-email-log/languages/mailspur-email-log-de_DE.l10n.php @@ -6,8 +6,10 @@ 'language' => 'de_DE', 'messages' => array( '"Download .eml" rebuilds the message from the logged, redacted data (without attachments).' => '„.eml herunterladen“ baut die Nachricht aus den protokollierten, geschwärzten Daten neu auf (ohne Anhänge).', + '%1$s email types from %2$s senders' => '%1$s E-Mail-Typen von %2$s Absendern', '%1$s emails failed within the last %2$s minutes.' => '%1$s E-Mails sind in den letzten %2$s Minuten fehlgeschlagen.', '%1$s emails in %2$s days' => '%1$s E-Mails in %2$s Tagen', + '%1$s emails in the last 30 days, %2$s failed' => '%1$s E-Mails in den letzten 30 Tagen, %2$s fehlgeschlagen', '%1$s entries, %2$s' => '%1$s Einträge, %2$s', '%1$s imported, %2$s duplicates, %3$s too old' => '%1$s importiert, %2$s Duplikate, %3$s zu alt', '%1$s of %2$s entries processed …' => '%1$s von %2$s Einträgen verarbeitet …', @@ -16,9 +18,11 @@ '%1$s, %2$s' => '%1$s, %2$s', '%s (must-use plugin)' => '%s (Must-Use-Plugin)', '%s (theme)' => '%s (Theme)', + '%s ago' => 'vor %s', '%s entries' => '%s Einträge', '%s failed' => '%s fehlgeschlagen', '%s imported entries removed.' => '%s importierte Einträge entfernt.', + '%s in 30 days' => '%s in 30 Tagen', '%s of all emails' => '%s aller E-Mails', '%s selected' => '%s ausgewählt', '(no subject)' => '(kein Betreff)', @@ -46,11 +50,13 @@ 'Aggregate reports go to %s.' => 'Sammelberichte gehen an %s.', 'Ajax' => 'Ajax', 'Alert' => 'Benachrichtigung', + 'Alert when an email type that is sent regularly stops' => 'Benachrichtigen, wenn ein regelmäßig versendeter E-Mail-Typ ausbleibt', 'Alert when emails fail repeatedly' => 'Benachrichtigen, wenn E-Mails wiederholt fehlschlagen', 'Alert when the site unexpectedly stops sending emails' => 'Benachrichtigen, wenn die Website unerwartet keine E-Mails mehr sendet', 'Alerts are enabled but have no channel: enter an email address or a webhook URL.' => 'Benachrichtigungen sind aktiviert, haben aber keinen Kanal: Gib eine E-Mail-Adresse oder eine Webhook-URL ein.', 'Alerts are off.' => 'Benachrichtigungen sind aus.', 'All' => 'Alle', + 'All email types look healthy.' => 'Alle E-Mail-Typen sehen gesund aus.', 'All emails are redirected to test addresses.' => 'Alle E-Mails werden an Testadressen umgeleitet.', 'All sources' => 'Alle Quellen', 'Also remove the subject when anonymising' => 'Beim Anonymisieren auch den Betreff entfernen', @@ -130,6 +136,7 @@ 'DNS lookup failed or timed out. Try again later.' => 'DNS-Abfrage fehlgeschlagen oder abgelaufen. Versuche es später erneut.', 'DNS lookups are not available on this server (dns_get_record() is disabled), so the sender check cannot run here.' => 'DNS-Abfragen sind auf diesem Server nicht verfügbar (dns_get_record() ist deaktiviert), daher kann die Absenderprüfung hier nicht laufen.', 'DNS lookups needed: about %1$s of %2$s allowed.' => 'Benötigte DNS-Abfragen: etwa %1$s von %2$s erlaubten.', + 'Daily' => 'Täglich', 'Date' => 'Datum', 'Default sender' => 'Standard-Absender', 'Delete' => 'Löschen', @@ -155,6 +162,10 @@ 'Email log' => 'E-Mail-Protokoll', 'Email sent again.' => 'E-Mail wurde erneut gesendet.', 'Email sent to %s.' => 'E-Mail an %s gesendet.', + 'Email type' => 'E-Mail-Typ', + 'Email type is sent again' => 'E-Mail-Typ wird wieder versendet', + 'Email type stopped' => 'E-Mail-Typ bleibt aus', + 'Email types' => 'E-Mail-Typen', 'Email: failed' => 'E-Mail: fehlgeschlagen', 'Email: failed – see the log' => 'E-Mail: fehlgeschlagen – siehe Protokoll', 'Email: sent' => 'E-Mail: gesendet', @@ -186,16 +197,20 @@ 'Entries older than %s days are skipped because the retention setting would delete them anyway. Change the retention above first to import everything.' => 'Einträge, die älter als %s Tage sind, werden übersprungen, weil die Aufbewahrungseinstellung sie ohnehin löschen würde. Passe die Aufbewahrung oben zuerst an, um alles zu importieren.', 'Error' => 'Fehler', 'Errors' => 'Fehler', + 'Every %s days' => 'Alle %s Tage', 'Every 15 minutes (Mailspur alerts)' => 'Alle 15 Minuten (Mailspur-Benachrichtigungen)', + 'Every kind of email your site sends, found automatically in the log: grouped by the plugin that sends it and by subject, with numbers, addresses and names as placeholders. Mailspur learns how often each type is sent and notices when one stops – for example after a plugin update.' => 'Jede Art von E-Mail, die deine Website versendet – automatisch im Protokoll erkannt: gruppiert nach dem Plugin, das sie sendet, und nach Betreff, mit Zahlen, Adressen und Namen als Platzhalter. Mailspur lernt, wie oft jeder Typ versendet wird, und bemerkt, wenn einer ausbleibt – zum Beispiel nach einem Plugin-Update.', 'Export' => 'Exportieren', 'Export started – your download begins shortly.' => 'Export gestartet – dein Download beginnt gleich.', 'Failed' => 'Fehlgeschlagen', 'Failed (%s %%)' => 'Fehlgeschlagen (%s %%)', + 'Failing' => 'Fehlerhaft', 'Failure rate' => 'Fehlerquote', 'Failure spike' => 'Fehlerhäufung', 'Fewer' => 'Weniger', 'File' => 'Datei', 'Filter by status' => 'Nach Status filtern', + 'Filter email types' => 'E-Mail-Typen filtern', 'First page' => 'Erste Seite', 'For large attachments the timeout can also be hit during the transfer – send smaller files or links.' => 'Bei großen Anhängen kann das Zeitlimit auch während der Übertragung erreicht werden – sende kleinere Dateien oder Links.', 'For staging and development copies of a site: make sure customers never get emails from the copy. Every email is still logged.' => 'Für Staging- und Entwicklungskopien einer Website: So bekommen Kunden niemals E-Mails von der Kopie. Jede E-Mail wird weiterhin protokolliert.', @@ -222,12 +237,15 @@ 'Hooks' => 'Hooks', 'Hours' => 'Stunden', 'How to fix:' => 'So behebst du es:', + 'I already did' => 'Hab ich schon', 'I understand that the raw source is NOT redacted and roughly doubles the storage per email' => 'Mir ist klar, dass der Rohquelltext NICHT geschwärzt wird und den Speicherbedarf pro E-Mail etwa verdoppelt', 'If it happens often, check the sending limits of your mail provider.' => 'Wenn das oft passiert, prüfe die Versandlimits deines Mailanbieters.', 'If it keeps happening, send fewer emails at once or through a mail service with a queue.' => 'Wenn das häufiger passiert, sende weniger E-Mails auf einmal oder über einen Maildienst mit Warteschlange.', 'If security defaults block it, use your SMTP plugin\'s Microsoft (OAuth / Graph API) connection instead.' => 'Wenn die Sicherheitsstandards das blockieren, nutze stattdessen die Microsoft-Verbindung (OAuth / Graph API) deines SMTP-Plugins.', 'If several recipients failed, the server reply after the address names the reason.' => 'Wenn mehrere Empfänger fehlgeschlagen sind, nennt die Serverantwort hinter der Adresse den Grund.', 'If the account uses two-factor authentication, create an app password and use it instead.' => 'Wenn das Konto Zwei-Faktor-Authentifizierung nutzt, erstelle ein App-Passwort und verwende es stattdessen.', + 'Ignore' => 'Ignorieren', + 'Ignored' => 'Ignoriert', 'Ignored notes' => 'Ignorierte Hinweise', 'Ignored notes are no longer recorded for new emails and are hidden for existing entries.' => 'Ignorierte Hinweise werden für neue E-Mails nicht mehr erfasst und bei bestehenden Einträgen ausgeblendet.', 'Images without alt text (%1$s)' => 'Bilder ohne Alternativtext (%1$s)', @@ -247,10 +265,15 @@ 'Invalid email address' => 'Ungültige E-Mail-Adresse', 'Invalid email address: %s' => 'Ungültige E-Mail-Adresse: %s', 'Invalid sender address: %1$s' => 'Ungültige Absenderadresse: %1$s', + 'Irregular' => 'Unregelmäßig', + 'Is Mailspur helping you?' => 'Hilft dir Mailspur?', 'JSON' => 'JSON', 'Keep at most' => 'Höchstens behalten', 'Key figures' => 'Kennzahlen', + 'Last 30 days' => 'Letzte 30 Tage', 'Last page' => 'Letzte Seite', + 'Last sent' => 'Zuletzt versendet', + 'Leave a ★★★★★ review' => 'Gib eine ★★★★★-Bewertung ab', 'Link text shows %1$s but leads to %2$s' => 'Linktext zeigt %1$s, führt aber zu %2$s', 'Link to a development address: %1$s' => 'Link auf eine Entwicklungsadresse: %1$s', 'Links and images starting with "/" only work on the website. In a mail client there is no website address to complete them, so images stay empty and links lead nowhere.' => 'Links und Bilder, die mit „/“ beginnen, funktionieren nur auf der Website. Im Mailprogramm fehlt die Website-Adresse zum Ergänzen – Bilder bleiben leer und Links führen ins Leere.', @@ -269,6 +292,9 @@ 'Mail servers for replies and bounces are set up.' => 'Mailserver für Antworten und Bounces sind eingerichtet.', 'Mailer' => 'Versandart', 'Mailspur alerts' => 'Mailspur-Benachrichtigungen', + 'Mailspur has logged %s delivered emails on this site so far. If it saves you time, a short review on WordPress.org would mean a lot – it helps others find the plugin and keeps it free.' => 'Mailspur hat auf dieser Website bisher %s zugestellte E-Mails protokolliert. Wenn es dir Zeit spart, würde mir eine kurze Bewertung auf WordPress.org viel bedeuten – sie hilft anderen, das Plugin zu finden, und hält es kostenlos.', + 'Mailspur is made by %1$s. Enjoying it? %2$s' => 'Mailspur wird von %1$s entwickelt. Gefällt es dir? %2$s', + 'Mailspur learns the rhythm of every email type from the last 8 weeks – a daily order confirmation is overdue after 2 days, a weekly report after 2 weeks. The alert names the type, its sender and the plugins updated since its last email. Uses the channels above; ignored types never alert.' => 'Mailspur lernt den Rhythmus jedes E-Mail-Typs aus den letzten 8 Wochen – eine tägliche Bestellbestätigung ist nach 2 Tagen überfällig, ein wöchentlicher Bericht nach 2 Wochen. Die Benachrichtigung nennt den Typ, seinen Absender und die seit seiner letzten E-Mail aktualisierten Plugins. Nutzt die Kanäle oben; ignorierte Typen lösen nie aus.', 'Mailspur – Email Log' => 'Mailspur – E-Mail-Log', 'Mailspur: staging mode' => 'Mailspur: Staging-Modus', 'Make sure the From address in the mailer plugin matches the verified domain.' => 'Stell sicher, dass die Absenderadresse im Mailer-Plugin zur verifizierten Domain passt.', @@ -276,12 +302,14 @@ 'Make sure the encryption setting matches the port.' => 'Stell sicher, dass die Verschlüsselung zum Port passt.', 'Many mail clients block images until the reader allows them. Without alt text the reader only sees empty boxes; screen readers announce nothing useful.' => 'Viele Mailprogramme blockieren Bilder, bis der Leser sie erlaubt. Ohne Alternativtext sieht er nur leere Kästen; Screenreader lesen nichts Sinnvolles vor.', 'Mask password-reset, activation and access keys in logged links' => 'Passwort-Reset-, Aktivierungs- und Zugriffsschlüssel in protokollierten Links maskieren', + 'Maybe later' => 'Vielleicht später', 'Menu position' => 'Menüposition', 'Message' => 'Nachricht', 'Method' => 'Methode', 'Microsoft 365 / Exchange Online blocks SMTP login (basic authentication) for this mailbox or the whole organization.' => 'Microsoft 365 / Exchange Online blockiert die SMTP-Anmeldung (Standardauthentifizierung) für dieses Postfach oder die ganze Organisation.', 'Minutes' => 'Minuten', 'Monday' => 'Montag', + 'Monitor again' => 'Wieder überwachen', 'Monitoring alerts' => 'Überwachung & Benachrichtigungen', 'More' => 'Mehr', 'More filters' => 'Weitere Filter', @@ -290,6 +318,7 @@ 'Multiple SPF records found. Receivers treat this as an error (PermError) – merge them into one record.' => 'Mehrere SPF-Einträge gefunden. Empfänger werten das als Fehler (PermError) – fasse sie zu einem Eintrag zusammen.', 'Needs attention' => 'Prüfen', 'Neither a From header nor a sender was recorded. The mailer falls back to its default, often wordpress@yourdomain.' => 'Weder ein From-Header noch ein Absender wurde erfasst. Der Mailer nutzt seine Voreinstellung, oft wordpress@deinedomain.', + 'New' => 'Neu', 'Next email' => 'Nächste E-Mail', 'Next email (j)' => 'Nächste E-Mail (j)', 'Next page' => 'Nächste Seite', @@ -305,6 +334,7 @@ 'No emails' => 'Keine E-Mails', 'No emails found.' => 'Noch keine E-Mails protokolliert.', 'No emails in this period.' => 'Keine E-Mails in diesem Zeitraum.', + 'No emails logged yet. Email types appear here as soon as your site sends emails.' => 'Noch keine E-Mails protokolliert. E-Mail-Typen erscheinen hier, sobald deine Website E-Mails versendet.', 'No emails match these filters.' => 'Keine E-Mails passen zu diesen Filtern.', 'No emails sent' => 'Keine E-Mails gesendet', 'No log of another mail logging plugin was found on this site.' => 'Auf dieser Website wurde kein Protokoll eines anderen Mail-Log-Plugins gefunden.', @@ -315,12 +345,14 @@ 'No sender address recorded' => 'Keine Absenderadresse erfasst', 'No trace is available for this entry. It was logged before the trace existed or by a version without it.' => 'Für diesen Eintrag ist keine Spur vorhanden. Er wurde protokolliert, bevor es die Spur gab, oder von einer Version ohne sie.', 'None' => 'Keine', + 'Normally sent at least every %1$s days, now overdue by %2$s.' => 'Normalerweise mindestens alle %1$s Tage versendet, jetzt seit %2$s überfällig.', 'Not all selectors could be checked in time.' => 'Nicht alle Selektoren konnten rechtzeitig geprüft werden.', 'Not recorded: another plugin had SMTP debugging switched on.' => 'Nicht aufgezeichnet: Ein anderes Plugin hatte das SMTP-Debugging eingeschaltet.', 'Not recorded: the SMTP transcript is switched off in the settings.' => 'Nicht aufgezeichnet: Das SMTP-Protokoll ist in den Einstellungen ausgeschaltet.', 'Not recorded: this email was not sent via SMTP.' => 'Nicht aufgezeichnet: Diese E-Mail wurde nicht per SMTP verschickt.', 'Not stored: transcripts are only kept for failed emails.' => 'Nicht gespeichert: Protokolle werden nur für fehlgeschlagene E-Mails behalten.', 'Notes' => 'Hinweise', + 'Notes in the latest email: %s' => 'Hinweise in der letzten E-Mail: %s', 'Notes: %1$s. %2$s' => 'Hinweise: %1$s. %2$s', 'Number of failed emails' => 'Anzahl fehlgeschlagener E-Mails', 'Numbers are ignored, so “Order #123” and “Order #124” count together.' => 'Zahlen werden ignoriert, „Bestellung #123“ und „Bestellung #124“ zählen also zusammen.', @@ -335,13 +367,14 @@ 'Only held emails can be released.' => 'Nur zurückgehaltene E-Mails können freigegeben werden.', 'Open the log or debug view of your mailer plugin for the exact error.' => 'Öffne das Protokoll oder die Debug-Ansicht deines Mailer-Plugins, um den genauen Fehler zu sehen.', 'Open the mail log' => 'Mail-Log öffnen', - 'Optional and off by default. When enabled, Mailspur checks the log every 15 minutes and notifies you about failure spikes or unusual silence. Alerts go only to the addresses and the webhook you enter here; they contain the site name, the alert text and a link to the log – never email contents.' => 'Optional und standardmäßig aus. Wenn aktiviert, prüft Mailspur das Protokoll alle 15 Minuten und benachrichtigt dich bei gehäuften Fehlern oder ungewöhnlicher Stille. Benachrichtigungen gehen nur an die Adressen und den Webhook, die du hier einträgst; sie enthalten den Namen der Website, den Hinweistext und einen Link zum Protokoll – niemals E-Mail-Inhalte.', + 'Optional and off by default. When enabled, Mailspur checks the log regularly and notifies you about failure spikes, unusual silence or stopped email types. Alerts go only to the addresses and the webhook you enter here; they contain the site name, the alert text (for a stopped email type: its sender and subject pattern) and a link to the log – never email contents or recipients.' => 'Optional und standardmäßig aus. Wenn aktiviert, prüft Mailspur das Protokoll regelmäßig und benachrichtigt dich bei gehäuften Fehlern, ungewöhnlicher Stille oder ausbleibenden E-Mail-Typen. Benachrichtigungen gehen nur an die Adressen und den Webhook, die du hier einträgst; sie enthalten den Namen der Website, den Hinweistext (bei einem ausbleibenden E-Mail-Typ: Absender und Betreff-Muster) und einen Link zum Protokoll – niemals E-Mail-Inhalte oder Empfänger.', 'Optional, https only. Slack and Discord webhook URLs receive a chat message, any other URL a JSON POST request. The request is made by your server to exactly this URL – no other service is involved.' => 'Optional, nur https. Slack- und Discord-Webhook-URLs erhalten eine Chat-Nachricht, jede andere URL eine JSON-POST-Anfrage. Die Anfrage geht von deinem Server direkt an genau diese URL – kein anderer Dienst ist beteiligt.', 'Or add the address as an alias / "send as" permission at your mail provider.' => 'Oder richte die Adresse bei deinem Mailanbieter als Alias bzw. „Senden als“-Berechtigung ein.', 'Origin' => 'Herkunft', 'Original Bcc' => 'Ursprüngliches Bcc', 'Original Cc' => 'Ursprüngliches Cc', 'Original recipients' => 'Ursprüngliche Empfänger', + 'Other emails' => 'Weitere E-Mails', 'Own top-level menu item' => 'Eigener Hauptmenüpunkt', 'PHP extension openssl is missing' => 'PHP-Erweiterung openssl fehlt', 'PHPMailer ready (phpmailer_init)' => 'PHPMailer bereit (phpmailer_init)', @@ -367,7 +400,11 @@ 'Put the important information first and keep the subject under about 80 characters.' => 'Stell das Wichtigste an den Anfang und halte den Betreff unter etwa 80 Zeichen.', 'REST API' => 'REST-API', 'REST route' => 'REST-Route', + 'Rarely' => 'Selten', + 'Rate Mailspur on WordPress.org' => 'Mailspur auf WordPress.org bewerten', + 'Rate Mailspur ★★★★★' => 'Mailspur bewerten ★★★★★', 'Raw source' => 'Rohquelltext', + 'Rebuild from the log' => 'Aus dem Protokoll neu aufbauen', 'Recipient' => 'Empfänger', 'Recipient domain cannot receive email: %1$s' => 'Empfängerdomain kann keine E-Mails empfangen: %1$s', 'Recipient domain does not accept email: %1$s' => 'Empfängerdomain nimmt keine E-Mails an: %1$s', @@ -404,6 +441,7 @@ 'Retention' => 'Aufbewahrung', 'Review the notes of this email (links, sender, placeholders).' => 'Sieh dir die Hinweise zu dieser E-Mail an (Links, Absender, Platzhalter).', 'Revoked keys (empty p=): %s.' => 'Widerrufene Schlüssel (leeres p=): %s.', + 'Rhythm' => 'Rhythmus', 'Run a search & replace of the old domain in the database and check hard-coded URLs in email templates and plugin settings.' => 'Führe ein Suchen & Ersetzen der alten Domain in der Datenbank aus und prüfe fest eingetragene URLs in E-Mail-Templates und Plugin-Einstellungen.', 'SMTP AUTH is disabled in Microsoft 365' => 'SMTP AUTH ist in Microsoft 365 deaktiviert', 'SMTP host' => 'SMTP-Server', @@ -451,14 +489,17 @@ 'Set the From address in your SMTP plugin to the mailbox you log in with and enable "force From address".' => 'Setze die Absenderadresse in deinem SMTP-Plugin auf das Postfach, mit dem du dich anmeldest, und aktiviere „Absenderadresse erzwingen“.', 'Set up staging mode' => 'Staging-Modus einrichten', 'Settings' => 'Einstellungen', + 'Several of the latest emails of this type failed.' => 'Mehrere der letzten E-Mails dieses Typs sind fehlgeschlagen.', 'Share of failed emails per day (per week for long periods).' => 'Anteil fehlgeschlagener E-Mails pro Tag (bei langen Zeiträumen pro Woche).', 'Shop managers and above' => 'Shop-Manager und höher', 'Show data as table' => 'Daten als Tabelle anzeigen', + 'Show emails' => 'E-Mails anzeigen', 'Show emails for %s in the log' => 'E-Mails für %s im Protokoll anzeigen', 'Silence' => 'Stille', 'Since 2024 Gmail and Yahoo require a one-click unsubscribe (List-Unsubscribe header) for bulk mail. Without it newsletters are more likely to be rejected or filtered.' => 'Seit 2024 verlangen Gmail und Yahoo für Massen-E-Mails eine Ein-Klick-Abmeldung (Header List-Unsubscribe). Ohne sie werden Newsletter eher abgelehnt oder aussortiert.', 'Some lookups were skipped because DNS answered too slowly.' => 'Einige Abfragen wurden übersprungen, weil DNS zu langsam geantwortet hat.', 'Sorry, you are not allowed to access this page.' => 'Du hast leider keine Berechtigung, auf diese Seite zuzugreifen.', + 'Sorry, you are not allowed to do that.' => 'Du darfst diese Aktion leider nicht ausführen.', 'Sorry, you are not allowed to export the mail log.' => 'Du darfst das Mail-Log leider nicht exportieren.', 'Source' => 'Quelle', 'Staging' => 'Staging', @@ -469,6 +510,9 @@ 'Start with p=none to receive reports, then tighten to quarantine or reject once SPF and DKIM pass.' => 'Beginne mit p=none, um Berichte zu erhalten, und verschärfe auf quarantine oder reject, sobald SPF und DKIM bestehen.', 'Statistics' => 'Statistik', 'Status' => 'Status', + 'Still sorting %s older emails into types in the background. Reload the page in a minute.' => 'Sortiere im Hintergrund noch %s ältere E-Mails in Typen ein. Lade die Seite in einer Minute neu.', + 'Stopped' => 'Ausgeblieben', + 'Stopped email types' => 'Ausbleibende E-Mail-Typen', 'Store the exact raw MIME source of every email' => 'Den exakten MIME-Rohquelltext jeder E-Mail speichern', 'Subject' => 'Betreff', 'Subjects often contain names or order numbers.' => 'Betreffzeilen enthalten oft Namen oder Bestellnummern.', @@ -493,6 +537,7 @@ 'The email contains template variables that were not filled in. Recipients see them literally.' => 'Die E-Mail enthält Template-Variablen, die nicht ausgefüllt wurden. Empfänger sehen sie wörtlich.', 'The email is too large' => 'Die E-Mail ist zu groß', 'The email links to WordPress files on a related host. This typically happens on a staging copy that still contains URLs of the live site – or the other way round.' => 'Die E-Mail verlinkt WordPress-Dateien auf einem verwandten Host. Das passiert typischerweise auf einer Staging-Kopie, die noch URLs der Live-Website enthält – oder umgekehrt.', + 'The email types are being rebuilt from the log.' => 'Die E-Mail-Typen werden aus dem Protokoll neu aufgebaut.', 'The exact raw source is stored – "Download .eml" returns it unchanged (not redacted).' => 'Der exakte Rohquelltext ist gespeichert – „.eml herunterladen“ liefert ihn unverändert (nicht geschwärzt).', 'The mail log requires JavaScript.' => 'Das Mail-Log benötigt JavaScript.', 'The mail server did not answer in time' => 'Der Mailserver hat nicht rechtzeitig geantwortet', @@ -522,6 +567,8 @@ 'The statistics require JavaScript.' => 'Die Statistik benötigt JavaScript.', 'The user name is usually the full email address. Watch for spaces copied along with the password.' => 'Der Benutzername ist meist die vollständige E-Mail-Adresse. Achte auf mitkopierte Leerzeichen beim Passwort.', 'The webhook URL was removed: only valid https URLs are allowed.' => 'Die Webhook-URL wurde entfernt: Nur gültige https-URLs sind erlaubt.', + 'This email type is ignored now: no status, no alerts.' => 'Dieser E-Mail-Typ wird jetzt ignoriert: kein Status, keine Benachrichtigungen.', + 'This email type is monitored again.' => 'Dieser E-Mail-Typ wird wieder überwacht.', 'This entry was anonymised; its content can no longer be sent.' => 'Dieser Eintrag wurde anonymisiert; sein Inhalt kann nicht mehr gesendet werden.', 'This import is already running in another tab.' => 'Dieser Import läuft bereits in einem anderen Tab.', 'This is a test alert. Your alert channels work.' => 'Dies ist eine Test-Benachrichtigung. Deine Benachrichtigungskanäle funktionieren.', @@ -543,6 +590,7 @@ 'Transport' => 'Transport', 'Tuesday' => 'Dienstag', 'Type' => 'Art', + 'Types are updated hourly and whenever you open this page. Only counters and subject patterns are stored, and they follow the retention period of the log.' => 'Die Typen werden stündlich und beim Öffnen dieser Seite aktualisiert. Gespeichert werden nur Zähler und Betreff-Muster, und sie folgen der Aufbewahrungsdauer des Protokolls.', 'Typo in recipient domain? %1$s → %2$s' => 'Tippfehler in der Empfängerdomain? %1$s → %2$s', 'Umlauts or quotes appear as garbled characters such as "ä" or "’". UTF-8 text was read as a different character set somewhere on the way – in a template, an import or the database.' => 'Umlaute oder Anführungszeichen erscheinen als Zeichensalat wie „ä“ oder „’“. UTF-8-Text wurde unterwegs mit einem anderen Zeichensatz gelesen – in einem Template, einem Import oder der Datenbank.', 'Under Tools' => 'Unter Werkzeuge', @@ -552,6 +600,8 @@ 'Unreplaced placeholders: %1$s' => 'Nicht ersetzte Platzhalter: %1$s', 'Up to 10 addresses, separated by commas. Cc and Bcc are removed and the subject shows the original recipients. Without a valid address, emails are held instead.' => 'Bis zu 10 Adressen, durch Kommas getrennt. Cc und Bcc werden entfernt und der Betreff zeigt die ursprünglichen Empfänger. Ohne gültige Adresse werden E-Mails stattdessen zurückgehalten.', 'Up to 5 addresses, separated by commas. Alert emails appear in the log with the source “Mailspur alerts” and never trigger alerts themselves.' => 'Bis zu 5 Adressen, durch Kommas getrennt. Benachrichtigungs-E-Mails erscheinen im Protokoll mit der Quelle „Mailspur-Benachrichtigungen“ und lösen selbst nie Benachrichtigungen aus.', + 'Updated since the last one:' => 'Seit der letzten aktualisiert:', + 'Updated since then: %s.' => 'Seitdem aktualisiert: %s.', 'Use TLS on port 587 or SSL on port 465.' => 'Nutze TLS auf Port 587 oder SSL auf Port 465.', 'Use a descriptive link text (e.g. "View order") or show the address the link really leads to.' => 'Verwende einen beschreibenden Linktext (z. B. „Bestellung ansehen“) oder zeig die Adresse, zu der der Link wirklich führt.', 'Use a sender address on your own domain and put the free address in Reply-To. Only if you really send through that provider\'s own SMTP server with its login is this fine.' => 'Nutze eine Absenderadresse deiner eigenen Domain und setz die Freemail-Adresse als Reply-To. Nur wenn du wirklich über den SMTP-Server dieses Anbieters mit dessen Zugangsdaten sendest, ist das in Ordnung.', @@ -575,6 +625,7 @@ 'Week' => 'Woche', 'Week of %s' => 'Woche ab %s', 'Weekday' => 'Wochentag', + 'Weekly' => 'Wöchentlich', 'What to do' => 'Was tun?', 'When emails are sent' => 'Wann E-Mails gesendet werden', 'When off, tracking pixels cannot tell when you open an entry. You can still load remote content for a single email. Scripts and forms are always blocked.' => 'Ist das aus, können Tracking-Pixel nicht erkennen, wann du einen Eintrag öffnest. Für einzelne E-Mails kannst du externe Inhalte trotzdem laden. Skripte und Formulare sind immer blockiert.', @@ -586,17 +637,33 @@ 'XML-RPC' => 'XML-RPC', 'You receive this email because monitoring alerts are enabled in the Mailspur settings of this site.' => 'Du erhältst diese E-Mail, weil in den Mailspur-Einstellungen dieser Website Benachrichtigungen aktiviert sind.', 'Your DKIM selector (optional)' => 'Dein DKIM-Selektor (optional)', + 'address' => 'Adresse', + 'code' => 'Code', + 'date' => 'Datum', 'days' => 'Tagen', 'entries' => 'Einträge', + 'failing' => 'fehlerhaft', 'failure spikes' => 'Fehlerhäufungen', + 'first seen %s' => 'zuerst gesehen am %s', + 'link' => 'Link', 'minutes' => 'Minuten', + 'name' => 'Name', + 'new this week' => 'neu diese Woche', 'no' => 'nein', 'none' => 'keine', 'none in %1$s – %2$s' => 'keine in %1$s – %2$s', + 'number' => 'Zahl', 'of %s' => 'von %s', + 'stopped' => 'ausgeblieben', + 'stopped email types' => 'ausbleibenden E-Mail-Typen', + 'text' => 'Text', + 'time' => 'Uhrzeit', 'unchanged' => 'unverändert', 'unusual silence' => 'ungewöhnlicher Stille', + 'usually sent: %s' => 'üblicher Rhythmus: %s', 'wp_mail() called' => 'wp_mail() aufgerufen', 'yes' => 'ja', + '“%1$s” (%2$s) is being sent again.' => '„%1$s“ (%2$s) wird wieder versendet.', + '“%1$s” (%2$s) was last sent %3$s ago. Until then it was sent at least every %4$s days.' => '„%1$s“ (%2$s) wurde zuletzt vor %3$s versendet. Bis dahin kam der Typ mindestens alle %4$s Tage.', ), ); diff --git a/mailspur-email-log/languages/mailspur-email-log-de_DE.po b/mailspur-email-log/languages/mailspur-email-log-de_DE.po index 100976d..54e245b 100644 --- a/mailspur-email-log/languages/mailspur-email-log-de_DE.po +++ b/mailspur-email-log/languages/mailspur-email-log-de_DE.po @@ -8,12 +8,18 @@ msgstr "" msgid "\"Download .eml\" rebuilds the message from the logged, redacted data (without attachments)." msgstr "„.eml herunterladen“ baut die Nachricht aus den protokollierten, geschwärzten Daten neu auf (ohne Anhänge)." +msgid "%1$s email types from %2$s senders" +msgstr "%1$s E-Mail-Typen von %2$s Absendern" + msgid "%1$s emails failed within the last %2$s minutes." msgstr "%1$s E-Mails sind in den letzten %2$s Minuten fehlgeschlagen." msgid "%1$s emails in %2$s days" msgstr "%1$s E-Mails in %2$s Tagen" +msgid "%1$s emails in the last 30 days, %2$s failed" +msgstr "%1$s E-Mails in den letzten 30 Tagen, %2$s fehlgeschlagen" + msgid "%1$s entries, %2$s" msgstr "%1$s Einträge, %2$s" @@ -38,6 +44,9 @@ msgstr "%s (Must-Use-Plugin)" msgid "%s (theme)" msgstr "%s (Theme)" +msgid "%s ago" +msgstr "vor %s" + msgid "%s entries" msgstr "%s Einträge" @@ -47,6 +56,9 @@ msgstr "%s fehlgeschlagen" msgid "%s imported entries removed." msgstr "%s importierte Einträge entfernt." +msgid "%s in 30 days" +msgstr "%s in 30 Tagen" + msgid "%s of all emails" msgstr "%s aller E-Mails" @@ -128,6 +140,9 @@ msgstr "Ajax" msgid "Alert" msgstr "Benachrichtigung" +msgid "Alert when an email type that is sent regularly stops" +msgstr "Benachrichtigen, wenn ein regelmäßig versendeter E-Mail-Typ ausbleibt" + msgid "Alert when emails fail repeatedly" msgstr "Benachrichtigen, wenn E-Mails wiederholt fehlschlagen" @@ -143,6 +158,9 @@ msgstr "Benachrichtigungen sind aus." msgid "All" msgstr "Alle" +msgid "All email types look healthy." +msgstr "Alle E-Mail-Typen sehen gesund aus." + msgid "All emails are redirected to test addresses." msgstr "Alle E-Mails werden an Testadressen umgeleitet." @@ -380,6 +398,9 @@ msgstr "DNS-Abfragen sind auf diesem Server nicht verfügbar (dns_get_record() i msgid "DNS lookups needed: about %1$s of %2$s allowed." msgstr "Benötigte DNS-Abfragen: etwa %1$s von %2$s erlaubten." +msgid "Daily" +msgstr "Täglich" + msgid "Date" msgstr "Datum" @@ -455,6 +476,18 @@ msgstr "E-Mail wurde erneut gesendet." msgid "Email sent to %s." msgstr "E-Mail an %s gesendet." +msgid "Email type" +msgstr "E-Mail-Typ" + +msgid "Email type is sent again" +msgstr "E-Mail-Typ wird wieder versendet" + +msgid "Email type stopped" +msgstr "E-Mail-Typ bleibt aus" + +msgid "Email types" +msgstr "E-Mail-Typen" + msgid "Email: failed" msgstr "E-Mail: fehlgeschlagen" @@ -548,9 +581,15 @@ msgstr "Fehler" msgid "Errors" msgstr "Fehler" +msgid "Every %s days" +msgstr "Alle %s Tage" + msgid "Every 15 minutes (Mailspur alerts)" msgstr "Alle 15 Minuten (Mailspur-Benachrichtigungen)" +msgid "Every kind of email your site sends, found automatically in the log: grouped by the plugin that sends it and by subject, with numbers, addresses and names as placeholders. Mailspur learns how often each type is sent and notices when one stops – for example after a plugin update." +msgstr "Jede Art von E-Mail, die deine Website versendet – automatisch im Protokoll erkannt: gruppiert nach dem Plugin, das sie sendet, und nach Betreff, mit Zahlen, Adressen und Namen als Platzhalter. Mailspur lernt, wie oft jeder Typ versendet wird, und bemerkt, wenn einer ausbleibt – zum Beispiel nach einem Plugin-Update." + msgid "Export" msgstr "Exportieren" @@ -563,6 +602,9 @@ msgstr "Fehlgeschlagen" msgid "Failed (%s %%)" msgstr "Fehlgeschlagen (%s %%)" +msgid "Failing" +msgstr "Fehlerhaft" + msgid "Failure rate" msgstr "Fehlerquote" @@ -578,6 +620,9 @@ msgstr "Datei" msgid "Filter by status" msgstr "Nach Status filtern" +msgid "Filter email types" +msgstr "E-Mail-Typen filtern" + msgid "First page" msgstr "Erste Seite" @@ -656,6 +701,9 @@ msgstr "Stunden" msgid "How to fix:" msgstr "So behebst du es:" +msgid "I already did" +msgstr "Hab ich schon" + msgid "I understand that the raw source is NOT redacted and roughly doubles the storage per email" msgstr "Mir ist klar, dass der Rohquelltext NICHT geschwärzt wird und den Speicherbedarf pro E-Mail etwa verdoppelt" @@ -674,6 +722,12 @@ msgstr "Wenn mehrere Empfänger fehlgeschlagen sind, nennt die Serverantwort hin msgid "If the account uses two-factor authentication, create an app password and use it instead." msgstr "Wenn das Konto Zwei-Faktor-Authentifizierung nutzt, erstelle ein App-Passwort und verwende es stattdessen." +msgid "Ignore" +msgstr "Ignorieren" + +msgid "Ignored" +msgstr "Ignoriert" + msgid "Ignored notes" msgstr "Ignorierte Hinweise" @@ -731,6 +785,12 @@ msgstr "Ungültige E-Mail-Adresse: %s" msgid "Invalid sender address: %1$s" msgstr "Ungültige Absenderadresse: %1$s" +msgid "Irregular" +msgstr "Unregelmäßig" + +msgid "Is Mailspur helping you?" +msgstr "Hilft dir Mailspur?" + msgid "JSON" msgstr "JSON" @@ -740,9 +800,18 @@ msgstr "Höchstens behalten" msgid "Key figures" msgstr "Kennzahlen" +msgid "Last 30 days" +msgstr "Letzte 30 Tage" + msgid "Last page" msgstr "Letzte Seite" +msgid "Last sent" +msgstr "Zuletzt versendet" + +msgid "Leave a ★★★★★ review" +msgstr "Gib eine ★★★★★-Bewertung ab" + msgid "Link text shows %1$s but leads to %2$s" msgstr "Linktext zeigt %1$s, führt aber zu %2$s" @@ -797,6 +866,15 @@ msgstr "Versandart" msgid "Mailspur alerts" msgstr "Mailspur-Benachrichtigungen" +msgid "Mailspur has logged %s delivered emails on this site so far. If it saves you time, a short review on WordPress.org would mean a lot – it helps others find the plugin and keeps it free." +msgstr "Mailspur hat auf dieser Website bisher %s zugestellte E-Mails protokolliert. Wenn es dir Zeit spart, würde mir eine kurze Bewertung auf WordPress.org viel bedeuten – sie hilft anderen, das Plugin zu finden, und hält es kostenlos." + +msgid "Mailspur is made by %1$s. Enjoying it? %2$s" +msgstr "Mailspur wird von %1$s entwickelt. Gefällt es dir? %2$s" + +msgid "Mailspur learns the rhythm of every email type from the last 8 weeks – a daily order confirmation is overdue after 2 days, a weekly report after 2 weeks. The alert names the type, its sender and the plugins updated since its last email. Uses the channels above; ignored types never alert." +msgstr "Mailspur lernt den Rhythmus jedes E-Mail-Typs aus den letzten 8 Wochen – eine tägliche Bestellbestätigung ist nach 2 Tagen überfällig, ein wöchentlicher Bericht nach 2 Wochen. Die Benachrichtigung nennt den Typ, seinen Absender und die seit seiner letzten E-Mail aktualisierten Plugins. Nutzt die Kanäle oben; ignorierte Typen lösen nie aus." + msgid "Mailspur – Email Log" msgstr "Mailspur – E-Mail-Log" @@ -818,6 +896,9 @@ msgstr "Viele Mailprogramme blockieren Bilder, bis der Leser sie erlaubt. Ohne A msgid "Mask password-reset, activation and access keys in logged links" msgstr "Passwort-Reset-, Aktivierungs- und Zugriffsschlüssel in protokollierten Links maskieren" +msgid "Maybe later" +msgstr "Vielleicht später" + msgid "Menu position" msgstr "Menüposition" @@ -836,6 +917,9 @@ msgstr "Minuten" msgid "Monday" msgstr "Montag" +msgid "Monitor again" +msgstr "Wieder überwachen" + msgid "Monitoring alerts" msgstr "Überwachung & Benachrichtigungen" @@ -860,6 +944,9 @@ msgstr "Prüfen" msgid "Neither a From header nor a sender was recorded. The mailer falls back to its default, often wordpress@yourdomain." msgstr "Weder ein From-Header noch ein Absender wurde erfasst. Der Mailer nutzt seine Voreinstellung, oft wordpress@deinedomain." +msgid "New" +msgstr "Neu" + msgid "Next email" msgstr "Nächste E-Mail" @@ -905,6 +992,9 @@ msgstr "Noch keine E-Mails protokolliert." msgid "No emails in this period." msgstr "Keine E-Mails in diesem Zeitraum." +msgid "No emails logged yet. Email types appear here as soon as your site sends emails." +msgstr "Noch keine E-Mails protokolliert. E-Mail-Typen erscheinen hier, sobald deine Website E-Mails versendet." + msgid "No emails match these filters." msgstr "Keine E-Mails passen zu diesen Filtern." @@ -935,6 +1025,9 @@ msgstr "Für diesen Eintrag ist keine Spur vorhanden. Er wurde protokolliert, be msgid "None" msgstr "Keine" +msgid "Normally sent at least every %1$s days, now overdue by %2$s." +msgstr "Normalerweise mindestens alle %1$s Tage versendet, jetzt seit %2$s überfällig." + msgid "Not all selectors could be checked in time." msgstr "Nicht alle Selektoren konnten rechtzeitig geprüft werden." @@ -953,6 +1046,9 @@ msgstr "Nicht gespeichert: Protokolle werden nur für fehlgeschlagene E-Mails be msgid "Notes" msgstr "Hinweise" +msgid "Notes in the latest email: %s" +msgstr "Hinweise in der letzten E-Mail: %s" + msgid "Notes: %1$s. %2$s" msgstr "Hinweise: %1$s. %2$s" @@ -995,8 +1091,8 @@ msgstr "Öffne das Protokoll oder die Debug-Ansicht deines Mailer-Plugins, um de msgid "Open the mail log" msgstr "Mail-Log öffnen" -msgid "Optional and off by default. When enabled, Mailspur checks the log every 15 minutes and notifies you about failure spikes or unusual silence. Alerts go only to the addresses and the webhook you enter here; they contain the site name, the alert text and a link to the log – never email contents." -msgstr "Optional und standardmäßig aus. Wenn aktiviert, prüft Mailspur das Protokoll alle 15 Minuten und benachrichtigt dich bei gehäuften Fehlern oder ungewöhnlicher Stille. Benachrichtigungen gehen nur an die Adressen und den Webhook, die du hier einträgst; sie enthalten den Namen der Website, den Hinweistext und einen Link zum Protokoll – niemals E-Mail-Inhalte." +msgid "Optional and off by default. When enabled, Mailspur checks the log regularly and notifies you about failure spikes, unusual silence or stopped email types. Alerts go only to the addresses and the webhook you enter here; they contain the site name, the alert text (for a stopped email type: its sender and subject pattern) and a link to the log – never email contents or recipients." +msgstr "Optional und standardmäßig aus. Wenn aktiviert, prüft Mailspur das Protokoll regelmäßig und benachrichtigt dich bei gehäuften Fehlern, ungewöhnlicher Stille oder ausbleibenden E-Mail-Typen. Benachrichtigungen gehen nur an die Adressen und den Webhook, die du hier einträgst; sie enthalten den Namen der Website, den Hinweistext (bei einem ausbleibenden E-Mail-Typ: Absender und Betreff-Muster) und einen Link zum Protokoll – niemals E-Mail-Inhalte oder Empfänger." msgid "Optional, https only. Slack and Discord webhook URLs receive a chat message, any other URL a JSON POST request. The request is made by your server to exactly this URL – no other service is involved." msgstr "Optional, nur https. Slack- und Discord-Webhook-URLs erhalten eine Chat-Nachricht, jede andere URL eine JSON-POST-Anfrage. Die Anfrage geht von deinem Server direkt an genau diese URL – kein anderer Dienst ist beteiligt." @@ -1016,6 +1112,9 @@ msgstr "Ursprüngliches Cc" msgid "Original recipients" msgstr "Ursprüngliche Empfänger" +msgid "Other emails" +msgstr "Weitere E-Mails" + msgid "Own top-level menu item" msgstr "Eigener Hauptmenüpunkt" @@ -1091,9 +1190,21 @@ msgstr "REST-API" msgid "REST route" msgstr "REST-Route" +msgid "Rarely" +msgstr "Selten" + +msgid "Rate Mailspur on WordPress.org" +msgstr "Mailspur auf WordPress.org bewerten" + +msgid "Rate Mailspur ★★★★★" +msgstr "Mailspur bewerten ★★★★★" + msgid "Raw source" msgstr "Rohquelltext" +msgid "Rebuild from the log" +msgstr "Aus dem Protokoll neu aufbauen" + msgid "Recipient" msgstr "Empfänger" @@ -1202,6 +1313,9 @@ msgstr "Sieh dir die Hinweise zu dieser E-Mail an (Links, Absender, Platzhalter) msgid "Revoked keys (empty p=): %s." msgstr "Widerrufene Schlüssel (leeres p=): %s." +msgid "Rhythm" +msgstr "Rhythmus" + msgid "Run a search & replace of the old domain in the database and check hard-coded URLs in email templates and plugin settings." msgstr "Führe ein Suchen & Ersetzen der alten Domain in der Datenbank aus und prüfe fest eingetragene URLs in E-Mail-Templates und Plugin-Einstellungen." @@ -1343,6 +1457,9 @@ msgstr "Staging-Modus einrichten" msgid "Settings" msgstr "Einstellungen" +msgid "Several of the latest emails of this type failed." +msgstr "Mehrere der letzten E-Mails dieses Typs sind fehlgeschlagen." + msgid "Share of failed emails per day (per week for long periods)." msgstr "Anteil fehlgeschlagener E-Mails pro Tag (bei langen Zeiträumen pro Woche)." @@ -1352,6 +1469,9 @@ msgstr "Shop-Manager und höher" msgid "Show data as table" msgstr "Daten als Tabelle anzeigen" +msgid "Show emails" +msgstr "E-Mails anzeigen" + msgid "Show emails for %s in the log" msgstr "E-Mails für %s im Protokoll anzeigen" @@ -1367,6 +1487,9 @@ msgstr "Einige Abfragen wurden übersprungen, weil DNS zu langsam geantwortet ha msgid "Sorry, you are not allowed to access this page." msgstr "Du hast leider keine Berechtigung, auf diese Seite zuzugreifen." +msgid "Sorry, you are not allowed to do that." +msgstr "Du darfst diese Aktion leider nicht ausführen." + msgid "Sorry, you are not allowed to export the mail log." msgstr "Du darfst das Mail-Log leider nicht exportieren." @@ -1397,6 +1520,15 @@ msgstr "Statistik" msgid "Status" msgstr "Status" +msgid "Still sorting %s older emails into types in the background. Reload the page in a minute." +msgstr "Sortiere im Hintergrund noch %s ältere E-Mails in Typen ein. Lade die Seite in einer Minute neu." + +msgid "Stopped" +msgstr "Ausgeblieben" + +msgid "Stopped email types" +msgstr "Ausbleibende E-Mail-Typen" + msgid "Store the exact raw MIME source of every email" msgstr "Den exakten MIME-Rohquelltext jeder E-Mail speichern" @@ -1469,6 +1601,9 @@ msgstr "Die E-Mail ist zu groß" msgid "The email links to WordPress files on a related host. This typically happens on a staging copy that still contains URLs of the live site – or the other way round." msgstr "Die E-Mail verlinkt WordPress-Dateien auf einem verwandten Host. Das passiert typischerweise auf einer Staging-Kopie, die noch URLs der Live-Website enthält – oder umgekehrt." +msgid "The email types are being rebuilt from the log." +msgstr "Die E-Mail-Typen werden aus dem Protokoll neu aufgebaut." + msgid "The exact raw source is stored – \"Download .eml\" returns it unchanged (not redacted)." msgstr "Der exakte Rohquelltext ist gespeichert – „.eml herunterladen“ liefert ihn unverändert (nicht geschwärzt)." @@ -1556,6 +1691,12 @@ msgstr "Der Benutzername ist meist die vollständige E-Mail-Adresse. Achte auf m msgid "The webhook URL was removed: only valid https URLs are allowed." msgstr "Die Webhook-URL wurde entfernt: Nur gültige https-URLs sind erlaubt." +msgid "This email type is ignored now: no status, no alerts." +msgstr "Dieser E-Mail-Typ wird jetzt ignoriert: kein Status, keine Benachrichtigungen." + +msgid "This email type is monitored again." +msgstr "Dieser E-Mail-Typ wird wieder überwacht." + msgid "This entry was anonymised; its content can no longer be sent." msgstr "Dieser Eintrag wurde anonymisiert; sein Inhalt kann nicht mehr gesendet werden." @@ -1619,6 +1760,9 @@ msgstr "Dienstag" msgid "Type" msgstr "Art" +msgid "Types are updated hourly and whenever you open this page. Only counters and subject patterns are stored, and they follow the retention period of the log." +msgstr "Die Typen werden stündlich und beim Öffnen dieser Seite aktualisiert. Gespeichert werden nur Zähler und Betreff-Muster, und sie folgen der Aufbewahrungsdauer des Protokolls." + msgid "Typo in recipient domain? %1$s → %2$s" msgstr "Tippfehler in der Empfängerdomain? %1$s → %2$s" @@ -1646,6 +1790,12 @@ msgstr "Bis zu 10 Adressen, durch Kommas getrennt. Cc und Bcc werden entfernt un msgid "Up to 5 addresses, separated by commas. Alert emails appear in the log with the source “Mailspur alerts” and never trigger alerts themselves." msgstr "Bis zu 5 Adressen, durch Kommas getrennt. Benachrichtigungs-E-Mails erscheinen im Protokoll mit der Quelle „Mailspur-Benachrichtigungen“ und lösen selbst nie Benachrichtigungen aus." +msgid "Updated since the last one:" +msgstr "Seit der letzten aktualisiert:" + +msgid "Updated since then: %s." +msgstr "Seitdem aktualisiert: %s." + msgid "Use TLS on port 587 or SSL on port 465." msgstr "Nutze TLS auf Port 587 oder SSL auf Port 465." @@ -1715,6 +1865,9 @@ msgstr "Woche ab %s" msgid "Weekday" msgstr "Wochentag" +msgid "Weekly" +msgstr "Wöchentlich" + msgid "What to do" msgstr "Was tun?" @@ -1748,18 +1901,42 @@ msgstr "Du erhältst diese E-Mail, weil in den Mailspur-Einstellungen dieser Web msgid "Your DKIM selector (optional)" msgstr "Dein DKIM-Selektor (optional)" +msgid "address" +msgstr "Adresse" + +msgid "code" +msgstr "Code" + +msgid "date" +msgstr "Datum" + msgid "days" msgstr "Tagen" msgid "entries" msgstr "Einträge" +msgid "failing" +msgstr "fehlerhaft" + msgid "failure spikes" msgstr "Fehlerhäufungen" +msgid "first seen %s" +msgstr "zuerst gesehen am %s" + +msgid "link" +msgstr "Link" + msgid "minutes" msgstr "Minuten" +msgid "name" +msgstr "Name" + +msgid "new this week" +msgstr "neu diese Woche" + msgid "no" msgstr "nein" @@ -1769,17 +1946,41 @@ msgstr "keine" msgid "none in %1$s – %2$s" msgstr "keine in %1$s – %2$s" +msgid "number" +msgstr "Zahl" + msgid "of %s" msgstr "von %s" +msgid "stopped" +msgstr "ausgeblieben" + +msgid "stopped email types" +msgstr "ausbleibenden E-Mail-Typen" + +msgid "text" +msgstr "Text" + +msgid "time" +msgstr "Uhrzeit" + msgid "unchanged" msgstr "unverändert" msgid "unusual silence" msgstr "ungewöhnlicher Stille" +msgid "usually sent: %s" +msgstr "üblicher Rhythmus: %s" + msgid "wp_mail() called" msgstr "wp_mail() aufgerufen" msgid "yes" msgstr "ja" + +msgid "“%1$s” (%2$s) is being sent again." +msgstr "„%1$s“ (%2$s) wird wieder versendet." + +msgid "“%1$s” (%2$s) was last sent %3$s ago. Until then it was sent at least every %4$s days." +msgstr "„%1$s“ (%2$s) wurde zuletzt vor %3$s versendet. Bis dahin kam der Typ mindestens alle %4$s Tage." diff --git a/mailspur-email-log/mailspur-email-log.php b/mailspur-email-log/mailspur-email-log.php index 5792c02..1ce5af0 100644 --- a/mailspur-email-log/mailspur-email-log.php +++ b/mailspur-email-log/mailspur-email-log.php @@ -2,11 +2,12 @@ /** * Plugin Name: Mailspur – Email Log * Plugin URI: https://github.com/lcswll/wordpress-mails - * Description: Logs every outgoing email and lets you search, filter and safely inspect it. A modern, lightweight replacement for classic mail logging plugins. + * Description: Logs every outgoing email, maps every type of email your site sends and alerts you when one stops. Safe preview, delivery diagnostics, statistics. * Version: 1.0.0 * Requires at least: 6.5 * Requires PHP: 7.4 - * Author: Lucas + * Author: Lucas Wille + * Author URI: https://lucaswille.de/ * License: GPLv2 or later * License URI: https://www.gnu.org/licenses/gpl-2.0.html * Text Domain: mailspur-email-log diff --git a/mailspur-email-log/readme.txt b/mailspur-email-log/readme.txt index 905dcf7..bce2078 100644 --- a/mailspur-email-log/readme.txt +++ b/mailspur-email-log/readme.txt @@ -8,7 +8,7 @@ Stable tag: 1.0.0 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html -Logs every email WordPress sends – with search, safe preview, delivery diagnostics, charts and alerts. Private and lightweight. +Logs every email WordPress sends, knows every type of email your site sends and alerts you when one stops. Safe preview, diagnostics, private. == Description == @@ -16,12 +16,22 @@ Did the order confirmation go out? Why did the password reset never arrive? Mail = What makes it different = +* **It knows every email your site sends – and notices when one stops.** Mailspur builds a map of all email types on its own (order confirmation, password reset, contact form …), learns how often each one goes out and tells you when a type that normally runs daily or weekly suddenly falls silent – naming the plugin update that happened in between. As far as we know, no other email log plugin does this. * **Logged emails cannot attack you.** HTML emails are shown in a sandboxed frame with an opaque origin: injected scripts, phishing forms and tracking pixels in a logged email stay inert, and remote content is not even requested until you allow it. * **The log cannot be used to take over accounts.** One-time secrets in links (password resets, activation keys, order keys) are masked *before* they are written to the database. * **It explains problems instead of just listing them.** Every email is checked for issues that keep it from arriving or displaying correctly, and failed emails come with a plain-language explanation and concrete steps. * **It records what was actually sent** – the final body after template plugins, the real sender, the SMTP server or API plugin that delivered it, and the exact code that called `wp_mail()`. * **Built for large logs:** an indexed table, live search, two small queries per email. No upsells, no external services, no tracking. += Email types: the map of your site's emails = + +Most email problems are not failures but emails that are never triggered: a plugin update breaks the order confirmation, a cron job dies, a form stops sending. A log of the emails that *were* sent cannot show what is missing. Mailspur's "Email types" tab can: + +* **Every kind of email, found automatically.** Grouped by the plugin that sends it and by subject – order numbers, dates, addresses and even customer names become placeholders, so "Welcome, Anna!" and "Welcome, Ben!" are one type, while "Your order is complete" and "Your order is cancelled" stay two. +* **Health per type:** emails and failures of the last 30 days as a small chart, the rhythm ("daily", "every 3 days", "weekly"), when it was last sent and notes found in its latest email. +* **"This email type stopped":** Mailspur learns each type's rhythm from its own last 8 weeks – a daily order confirmation is overdue after 2 days, one that pauses on weekends after 4, a weekly report after 2 weeks. Overdue types are marked, and with alerts enabled you get one email or webhook message – including the plugins, themes or WordPress updates installed since the type was last sent – and another one when it is back. +* **Built for privacy and speed:** sorting happens afterwards (hourly and when you open the tab), never while an email is sent. Only counters and subject patterns are stored – never recipients or contents – and they follow the retention period of the log. Types you do not care about can be ignored. + = Find any email in seconds = * Live search over recipient and subject, optionally also the content. @@ -64,17 +74,30 @@ The log contains personal data (recipients and content of emails). Mailspur: * deletes entries automatically after a configurable retention period (default: 90 days) and/or above a maximum number of entries – or anonymises them first, keeping only what the statistics need, * integrates with the WordPress personal data export and erasure tools, * suggests a paragraph for your privacy policy, -* contacts no external service. The only exception is a webhook URL you enter yourself for monitoring alerts (off by default), which receives a short alert text – never email contents. +* contacts no external service. The only exception is a webhook URL you enter yourself for monitoring alerts (off by default), which receives a short alert text – never email contents or recipients. + += External services = + +Mailspur works without any external service. There is exactly one optional exception: + +* **Alert webhook (off by default).** If you enable monitoring alerts and enter a webhook URL, your site sends a short JSON POST to exactly that URL when an alert fires (or when you click "Send test alert"): site name, site URL, the alert text, a link to the log and a timestamp – never email contents or recipient addresses. For a stopped email type the alert text names the sending plugin, the subject pattern with placeholders (e.g. "Your order #… has been received") and recently updated plugins. Where the data goes depends on the URL you enter. For Slack see the [terms](https://slack.com/terms-of-service) and [privacy policy](https://slack.com/privacy-policy), for Discord the [terms](https://discord.com/terms) and [privacy policy](https://discord.com/privacy). + +The sender check (SPF/DKIM/DMARC/MX) and the recipient-domain check only ask your server's own DNS resolver, on demand, and contact no third-party service. = For developers = * WP-CLI: `wp mailspur list|show|resend|stats|purge|export|import`. +* REST: `GET /wp-json/mailspur-email-log/v1/types` lists every email type with its health. * Filters: `mailspur_should_log` (skip logging an email), `mailspur_redact_params` (masked URL parameters), `mailspur_import_duplicate_window` (seconds), `mailspur_note_rules` and `mailspur_note_texts` (own checks), `mailspur_staging_subject`. = Source code = Development happens on GitHub: https://github.com/lcswll/wordpress-mails – issues and pull requests are welcome. += About the author = + +Mailspur is made by [Lucas Wille](https://lucaswille.de/), web designer and developer from Magdeburg, Germany. If Mailspur saves you time, a [review on WordPress.org](https://wordpress.org/support/plugin/mailspur-email-log/reviews/#new-post) helps a lot. + == Installation == 1. Install the plugin via Plugins → Add New (search for "Mailspur Email Log") or upload the ZIP file. @@ -123,6 +146,14 @@ No. It only asks your server's own DNS resolver for the SPF, DMARC, DKIM and MX It only alerts when the last 14 days show that your site normally sends emails in that time window (on at least 10 of 14 days, including the same weekday one and two weeks ago). += How does Mailspur know that an email type stopped? = + +From the type's own history, without any setting to tune: a type sent on at least 6 of the last 56 days is "regular", and it is overdue once the time since its last email exceeds twice its typical gap or its longest gap so far plus one day. Rare or irregular types never alert. Turn the alert on under Settings → "Stopped email types"; it uses the email addresses and webhook of the monitoring alerts. + += Why are two of my emails shown as one type, or one email as two types? = + +Numbers, dates, addresses, links and quoted text are always placeholders. Other words only merge when they look like names (capitalised in a normally written subject) and most of the subject stays the same – so different wording always stays apart. If a sender produces more than 150 different subjects, the rest is collected as "Other emails" of that sender. + = Can I keep my history when switching from WP Mail Logging or another log plugin? = Yes. Under Mail Log → Settings → "Import from other plugins" Mailspur lists every supported log it finds on the site (also from deactivated plugins) and imports it with one click. Entries older than your retention period are skipped, so raise the retention first if you want the complete history. @@ -159,6 +190,7 @@ Yes. Each site keeps its own log. 4. Notes and explained errors for a failed email. 5. Statistics: emails over time, failure rate, heatmap and top lists. 6. Settings: access, privacy, retention, staging mode and alerts. +7. Email types: every kind of email the site sends, with volume, rhythm and status – here a renewal email that stopped after a plugin update. == Changelog == diff --git a/mailspur-email-log/src/Admin.php b/mailspur-email-log/src/Admin.php index 0ffecde..35e5ab2 100644 --- a/mailspur-email-log/src/Admin.php +++ b/mailspur-email-log/src/Admin.php @@ -16,6 +16,9 @@ final class Admin { const SLUG = 'mailspur-email-log'; + /** Menu icon: envelope with its trail (monochrome SVG, recoloured by WordPress to match the admin colour scheme). */ + const MENU_ICON = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+PHBhdGggZmlsbD0iYmxhY2siIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTcuNSA0LjVoOS41YTIgMiAwIDAgMSAyIDJ2N2EyIDIgMCAwIDEtMiAySDcuNWEyIDIgMCAwIDEtMi0ydi03YTIgMiAwIDAgMSAyLTJ6TTcuNiA2LjlsNC42NSAzLjUgNC42NS0zLjV2MS42bC00LjY1IDMuNS00LjY1LTMuNXoiLz48Y2lyY2xlIGZpbGw9ImJsYWNrIiBjeD0iMy42IiBjeT0iMTYuNCIgcj0iMS4yNSIvPjxjaXJjbGUgZmlsbD0iYmxhY2siIGN4PSIxLjQiIGN5PSIxOC43IiByPSIwLjkiLz48L3N2Zz4='; + /** @var Repository */ private $repository; @@ -40,7 +43,7 @@ public function menu(): void { if ( 'tools' === Settings::get( 'menu_location' ) ) { $this->hook = (string) add_management_page( $title, $title, $cap, self::SLUG, array( $this, 'render' ) ); } else { - $this->hook = (string) add_menu_page( $title, $title, $cap, self::SLUG, array( $this, 'render' ), 'dashicons-email-alt', 81 ); + $this->hook = (string) add_menu_page( $title, $title, $cap, self::SLUG, array( $this, 'render' ), self::MENU_ICON, 81 ); } } @@ -219,7 +222,7 @@ public function render(): void { ?>