فهرست منبع

feat: add entry filters at the feed level

Frédéric Guillot 10 ماه پیش
والد
کامیت
2a9d91c783
37فایلهای تغییر یافته به همراه513 افزوده شده و 350 حذف شده
  1. 9 0
      client/model.go
  2. 9 0
      internal/database/migrations.go
  3. 14 12
      internal/locale/translations/de_DE.json
  4. 16 14
      internal/locale/translations/el_EL.json
  5. 13 11
      internal/locale/translations/en_US.json
  6. 16 14
      internal/locale/translations/es_ES.json
  7. 22 20
      internal/locale/translations/fi_FI.json
  8. 13 11
      internal/locale/translations/fr_FR.json
  9. 20 18
      internal/locale/translations/hi_IN.json
  10. 13 11
      internal/locale/translations/id_ID.json
  11. 19 17
      internal/locale/translations/it_IT.json
  12. 18 16
      internal/locale/translations/ja_JP.json
  13. 12 10
      internal/locale/translations/nan_Latn_pehoeji.json
  14. 15 13
      internal/locale/translations/nl_NL.json
  15. 14 12
      internal/locale/translations/pl_PL.json
  16. 22 20
      internal/locale/translations/pt_BR.json
  17. 15 13
      internal/locale/translations/ro_RO.json
  18. 14 12
      internal/locale/translations/ru_RU.json
  19. 13 11
      internal/locale/translations/tr_TR.json
  20. 23 21
      internal/locale/translations/uk_UA.json
  21. 13 11
      internal/locale/translations/zh_CN.json
  22. 15 13
      internal/locale/translations/zh_TW.json
  23. 19 5
      internal/model/feed.go
  24. 17 11
      internal/reader/filter/filter.go
  25. 2 0
      internal/reader/filter/filter_test.go
  26. 5 1
      internal/reader/handler/handler.go
  27. 33 25
      internal/storage/feed.go
  28. 6 2
      internal/storage/feed_query_builder.go
  29. 27 4
      internal/template/templates/views/add_subscription.html
  30. 3 1
      internal/template/templates/views/choose_subscription.html
  31. 27 4
      internal/template/templates/views/edit_feed.html
  32. 9 8
      internal/template/templates/views/settings.html
  33. 3 1
      internal/ui/feed_edit.go
  34. 9 3
      internal/ui/form/feed.go
  35. 6 2
      internal/ui/form/subscription.go
  36. 3 1
      internal/ui/subscription_choose.go
  37. 6 2
      internal/ui/subscription_submit.go

+ 9 - 0
client/model.go

@@ -160,8 +160,11 @@ type Feed struct {
 	FetchViaProxy               bool      `json:"fetch_via_proxy"`
 	ScraperRules                string    `json:"scraper_rules"`
 	RewriteRules                string    `json:"rewrite_rules"`
+	UrlRewriteRules             string    `json:"urlrewrite_rules"`
 	BlocklistRules              string    `json:"blocklist_rules"`
 	KeeplistRules               string    `json:"keeplist_rules"`
+	BlockFilterEntryRules       string    `json:"block_filter_entry_rules"`
+	KeepFilterEntryRules        string    `json:"keep_filter_entry_rules"`
 	Crawler                     bool      `json:"crawler"`
 	UserAgent                   string    `json:"user_agent"`
 	Cookie                      string    `json:"cookie"`
@@ -188,8 +191,11 @@ type FeedCreationRequest struct {
 	FetchViaProxy               bool   `json:"fetch_via_proxy"`
 	ScraperRules                string `json:"scraper_rules"`
 	RewriteRules                string `json:"rewrite_rules"`
+	UrlRewriteRules             string `json:"urlrewrite_rules"`
 	BlocklistRules              string `json:"blocklist_rules"`
 	KeeplistRules               string `json:"keeplist_rules"`
+	BlockFilterEntryRules       string `json:"block_filter_entry_rules"`
+	KeepFilterEntryRules        string `json:"keep_filter_entry_rules"`
 	HideGlobally                bool   `json:"hide_globally"`
 	DisableHTTP2                bool   `json:"disable_http2"`
 	ProxyURL                    string `json:"proxy_url"`
@@ -202,8 +208,11 @@ type FeedModificationRequest struct {
 	Title                       *string `json:"title"`
 	ScraperRules                *string `json:"scraper_rules"`
 	RewriteRules                *string `json:"rewrite_rules"`
+	UrlRewriteRules             *string `json:"urlrewrite_rules"`
 	BlocklistRules              *string `json:"blocklist_rules"`
 	KeeplistRules               *string `json:"keeplist_rules"`
+	BlockFilterEntryRules       *string `json:"block_filter_entry_rules"`
+	KeepFilterEntryRules        *string `json:"keep_filter_entry_rules"`
 	Crawler                     *bool   `json:"crawler"`
 	UserAgent                   *string `json:"user_agent"`
 	Cookie                      *string `json:"cookie"`

+ 9 - 0
internal/database/migrations.go

@@ -1132,4 +1132,13 @@ var migrations = []func(tx *sql.Tx, driver string) error{
 		_, err = tx.Exec(sql)
 		return err
 	},
+	func(tx *sql.Tx, _ string) (err error) {
+		sql := `
+			ALTER TABLE feeds
+				ADD COLUMN block_filter_entry_rules text not null default '',
+				ADD COLUMN keep_filter_entry_rules text not null default ''
+		`
+		_, err = tx.Exec(sql)
+		return err
+	},
 }

+ 14 - 12
internal/locale/translations/de_DE.json

@@ -169,7 +169,8 @@
     "form.feed.fieldset.rules": "Regeln",
     "form.feed.label.allow_self_signed_certificates": "Erlaube selbstsignierte oder ungültige Zertifikate",
     "form.feed.label.apprise_service_urls": "Kommaseparierte Liste der Apprise-Service-URLs",
-    "form.feed.label.blocklist_rules": "Blockierregeln",
+    "form.feed.label.block_filter_entry_rules": "Eintrags-Sperrregeln",
+    "form.feed.label.blocklist_rules": "Regex-basierte Sperrfilter",
     "form.feed.label.category": "Kategorie",
     "form.feed.label.cookie": "Cookies setzen",
     "form.feed.label.crawler": "Originalinhalt herunterladen",
@@ -182,7 +183,8 @@
     "form.feed.label.fetch_via_proxy": "Den auf Anwendungsebene konfigurierten Proxy verwenden",
     "form.feed.label.hide_globally": "Einträge in der globalen Ungelesen-Liste ausblenden",
     "form.feed.label.ignore_http_cache": "Ignoriere HTTP-Cache",
-    "form.feed.label.keeplist_rules": "Erlaubnisregeln",
+    "form.feed.label.keep_filter_entry_rules": "Eintrags-Erlaubnisregeln",
+    "form.feed.label.keeplist_rules": "Regex-basierte Behalte-Filter",
     "form.feed.label.no_media_player": "Kein Media-Player (Audio/Video)",
     "form.feed.label.ntfy_activate": "Einträge zu ntfy pushen",
     "form.feed.label.ntfy_default_priority": "Normale Ntfy-Priorität",
@@ -200,7 +202,7 @@
     "form.feed.label.pushover_max_priority": "Höchste Pushoverpriorität",
     "form.feed.label.pushover_min_priority": "Niedrigste Pushoverpriorität",
     "form.feed.label.pushover_priority": "Pushover-Nachrichtenpriorität",
-    "form.feed.label.rewrite_rules": "Umschreiberegeln",
+    "form.feed.label.rewrite_rules": "Inhalts-Umschreibregeln",
     "form.feed.label.scraper_rules": "Extraktionsregeln",
     "form.feed.label.site_url": "URL der Webseite",
     "form.feed.label.title": "Titel",
@@ -295,7 +297,7 @@
     "form.integration.readwise_api_key": "Readwise-Reader-Zugangstoken",
     "form.integration.readwise_api_key_link": "Erhalten Sie Ihren Readwise-Zugangstoken",
     "form.integration.rssbridge_activate": "Beim Hinzufügen von Abonnements RSS-Bridge prüfen.",
-    "form.integration.rssbridge_token": "RSS-Bridge authentication token",
+    "form.integration.rssbridge_token": "RSS-Bridge-Authentifizierungs-Token",
     "form.integration.rssbridge_url": "RSS-Bridge-Server-URL",
     "form.integration.shaarli_activate": "Artikel in Shaarli speichern",
     "form.integration.shaarli_api_secret": "Shaarli-API-Geheimnis",
@@ -403,7 +405,7 @@
     "menu.show_only_starred_entries": "Nur markierte Artikel anzeigen",
     "menu.show_only_unread_entries": "Nur ungelesene Artikel anzeigen",
     "menu.starred": "Lesezeichen",
-    "menu.title": "Menu",
+    "menu.title": "Menü",
     "menu.unread": "Ungelesen",
     "menu.users": "Benutzer",
     "page.about.author": "Autor:",
@@ -430,10 +432,6 @@
     "page.api_keys.table.last_used_at": "Zuletzt verwendeten",
     "page.api_keys.table.token": "Zeichen",
     "page.api_keys.title": "API-Schlüssel",
-    "page.categories_count": [
-        "%d Kategorie",
-        "%d Kategorien"
-    ],
     "page.categories.entries": "Artikel",
     "page.categories.feed_count": [
         "Es gibt %d Abonnement.",
@@ -442,6 +440,10 @@
     "page.categories.feeds": "Abonnements",
     "page.categories.no_feed": "Kein Abonnement.",
     "page.categories.title": "Kategorien",
+    "page.categories_count": [
+        "%d Kategorie",
+        "%d Kategorien"
+    ],
     "page.category_label": "Kategorie: %s",
     "page.edit_category.title": "Kategorie bearbeiten: %s",
     "page.edit_feed.etag_header": "ETag-Kopfzeile:",
@@ -547,25 +549,25 @@
     "page.settings.webauthn.passkeys": "Passkeys",
     "page.settings.webauthn.register": "Hauptschlüssel registrieren",
     "page.settings.webauthn.register.error": "Hauptschlüssel kann nicht registriert werden",
+    "page.shared_entries.title": "Geteilte Artikel",
     "page.shared_entries_count": [
         "%d geteilter Artikel",
         "%d geteilte Artikel"
     ],
-    "page.shared_entries.title": "Geteilte Artikel",
+    "page.starred.title": "Lesezeichen",
     "page.starred_entry_count": [
         "%d Lesezeichen",
         "%d Lesezeichen"
     ],
-    "page.starred.title": "Lesezeichen",
     "page.total_entry_count": [
         "%d Artikel insgesamt",
         "%d Artikel insgesamt"
     ],
+    "page.unread.title": "Ungelesen",
     "page.unread_entry_count": [
         "%d ungelesener Artikel",
         "%d ungelesene Artikel"
     ],
-    "page.unread.title": "Ungelesen",
     "page.users.actions": "Aktionen",
     "page.users.admin.no": "Nein",
     "page.users.admin.yes": "Ja",

+ 16 - 14
internal/locale/translations/el_EL.json

@@ -169,7 +169,8 @@
     "form.feed.fieldset.rules": "Κανόνες",
     "form.feed.label.allow_self_signed_certificates": "Να επιτρέπονται αυτο-υπογεγραμμένα ή μη έγκυρα πιστοποιητικά",
     "form.feed.label.apprise_service_urls": "Λίστα διευθύνσεων URL υπηρεσιών Apprise διαχωρισμένων με κόμμα",
-    "form.feed.label.blocklist_rules": "Κανόνες Αποκλεισμού",
+    "form.feed.label.block_filter_entry_rules": "Κανόνες Αποκλεισμού Καταχωρήσεων",
+    "form.feed.label.blocklist_rules": "Φίλτρα Αποκλεισμού Βασισμένα σε Regex",
     "form.feed.label.category": "Κατηγορία",
     "form.feed.label.cookie": "Ορισμός Cookies",
     "form.feed.label.crawler": "Λήψη αρχικού περιεχομένου",
@@ -182,7 +183,8 @@
     "form.feed.label.fetch_via_proxy": "Χρησιμοποιήστε τον διακομιστή μεσολάβησης που έχει ρυθμιστεί σε επίπεδο εφαρμογής",
     "form.feed.label.hide_globally": "Απόκρυψη καταχωρήσεων σε γενική λίστα μη αναγνωσμένων",
     "form.feed.label.ignore_http_cache": "Αγνοήστε την προσωρινή μνήμη HTTP",
-    "form.feed.label.keeplist_rules": "Κρατήστε Κανόνες",
+    "form.feed.label.keep_filter_entry_rules": "Κανόνες Επιτρεπόμενων Καταχωρήσεων",
+    "form.feed.label.keeplist_rules": "Φίλτρα Διατήρησης Βασισμένα σε Regex",
     "form.feed.label.no_media_player": "Χωρίς πρόγραμμα αναπαραγωγής πολυμέσων (ήχος/βίντεο)",
     "form.feed.label.ntfy_activate": "Προώθηση καταχωρήσεων στο ntfy",
     "form.feed.label.ntfy_default_priority": "Προεπιλεγμένη προτεραιότητα Ntfy",
@@ -200,7 +202,7 @@
     "form.feed.label.pushover_max_priority": "Μέγιστη προτεραιότητα Pushover",
     "form.feed.label.pushover_min_priority": "Ελάχιστη προτεραιότητα Pushover",
     "form.feed.label.pushover_priority": "Προτεραιότητα μηνύματος Pushover",
-    "form.feed.label.rewrite_rules": "Κανόνες Μετατροπής",
+    "form.feed.label.rewrite_rules": "Κανόνες Επανασύνταξης Περιεχομένου",
     "form.feed.label.scraper_rules": "Κανόνες Scraper",
     "form.feed.label.site_url": "Διεύθυνση URL ιστότοπου",
     "form.feed.label.title": "Τίτλος",
@@ -247,7 +249,7 @@
     "form.integration.linkding_api_key": "Κλειδί API Linkding",
     "form.integration.linkding_bookmark": "Σημείωση του σελιδοδείκτη ως μη αναγνωσμένου",
     "form.integration.linkding_endpoint": "Τελικό σημείο Linkding API",
-    "form.integration.linkding_tags": "Linkding Tags",
+    "form.integration.linkding_tags": "Ετικέτες Linkding",
     "form.integration.linkwarden_activate": "Αποθήκευση άρθρων στο Linkwarden",
     "form.integration.linkwarden_api_key": "Κλειδί API Linkwarden",
     "form.integration.linkwarden_endpoint": "Τελικό σημείο Linkwarden API",
@@ -276,7 +278,7 @@
     "form.integration.pinboard_activate": "Αποθήκευση άρθρων στο Pinboard",
     "form.integration.pinboard_bookmark": "Σημείωση του σελιδοδείκτη ως μη αναγνωσμένου",
     "form.integration.pinboard_tags": "Ετικέτες Pinboard",
-    "form.integration.pinboard_token": "Pinboard API Token",
+    "form.integration.pinboard_token": "Διακριτικό API Pinboard",
     "form.integration.pushover_activate": "Προώθηση καταχωρήσεων στο Pushover",
     "form.integration.pushover_device": "Συσκευή Pushover (προαιρετικό)",
     "form.integration.pushover_prefix": "Πρόθεμα διεύθυνσης URL Pushover (προαιρετικό)",
@@ -289,7 +291,7 @@
     "form.integration.readeck_activate": "Αποθήκευση άρθρων στο Readeck",
     "form.integration.readeck_api_key": "Κλειδί API Readeck",
     "form.integration.readeck_endpoint": "Τελικό σημείο Readeck API",
-    "form.integration.readeck_labels": "Readeck Labels",
+    "form.integration.readeck_labels": "Ετικέτες Readeck",
     "form.integration.readeck_only_url": "Αποστολή μόνο URL (αντί για πλήρες περιεχόμενο)",
     "form.integration.readwise_activate": "Αποθήκευση καταχωρήσεων στο Readwise Reader",
     "form.integration.readwise_api_key": "Διακριτικό πρόσβασης Readwise Reader",
@@ -410,7 +412,7 @@
     "page.about.build_date": "Ημερομηνία Κατασκευής:",
     "page.about.credits": "Συνεισφέροντες",
     "page.about.db_usage": "Μέγεθος βάσης δεδομένων:",
-    "page.about.git_commit": "Git Commit:",
+    "page.about.git_commit": "Υποβολή Git:",
     "page.about.global_config_options": "Γενικές ρυθμίσεις",
     "page.about.go_version": "Έκδοση Go:",
     "page.about.license": "Άδεια:",
@@ -430,10 +432,6 @@
     "page.api_keys.table.last_used_at": "Τελευταία Χρήση",
     "page.api_keys.table.token": "Token",
     "page.api_keys.title": "Κλειδιά API",
-    "page.categories_count": [
-        "%d κατηγορία",
-        "%d κατηγορίες"
-    ],
     "page.categories.entries": "Άρθρα",
     "page.categories.feed_count": [
         "Υπάρχει μία %d ροή.",
@@ -442,6 +440,10 @@
     "page.categories.feeds": "Συνδρομές",
     "page.categories.no_feed": "Καμία ροή.",
     "page.categories.title": "Κατηγορίες",
+    "page.categories_count": [
+        "%d κατηγορία",
+        "%d κατηγορίες"
+    ],
     "page.category_label": "Κατηγορία: %s",
     "page.edit_category.title": "Επεξεργασία κατηγορίας: % s",
     "page.edit_feed.etag_header": "Κεφαλίδα ETag:",
@@ -547,25 +549,25 @@
     "page.settings.webauthn.passkeys": "Κωδικοί πρόσβασης",
     "page.settings.webauthn.register": "Εγγραφή κωδικού πρόσβασης",
     "page.settings.webauthn.register.error": "Δεν είναι δυνατή η εγγραφή του κωδικού πρόσβασης",
+    "page.shared_entries.title": "Κοινόχρηστες Καταχωρήσεις",
     "page.shared_entries_count": [
         "%d κοινόχρηστη καταχώρηση",
         "%d κοινόχρηστες καταχωρήσεις"
     ],
-    "page.shared_entries.title": "Κοινόχρηστες Καταχωρήσεις",
+    "page.starred.title": "Αγαπημένo",
     "page.starred_entry_count": [
         "%d καταχώρηση με αστέρι",
         "%d καταχωρήσεις με αστέρι"
     ],
-    "page.starred.title": "Αγαπημένo",
     "page.total_entry_count": [
         "%d καταχώρηση συνολικά",
         "%d καταχωρήσεις συνολικά"
     ],
+    "page.unread.title": "Μη αναγνωσμένα",
     "page.unread_entry_count": [
         "%d μη αναγνωσμένη καταχώρηση",
         "%d μη αναγνωσμένες καταχωρήσεις"
     ],
-    "page.unread.title": "Μη αναγνωσμένα",
     "page.users.actions": "Eνέργειες",
     "page.users.admin.no": "Όχι",
     "page.users.admin.yes": "Ναι.",

+ 13 - 11
internal/locale/translations/en_US.json

@@ -169,7 +169,8 @@
     "form.feed.fieldset.rules": "Rules",
     "form.feed.label.allow_self_signed_certificates": "Allow self-signed or invalid certificates",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
-    "form.feed.label.blocklist_rules": "Block Rules",
+    "form.feed.label.block_filter_entry_rules": "Entry Blocking Rules",
+    "form.feed.label.blocklist_rules": "Regex-Based Blocking Filters",
     "form.feed.label.category": "Category",
     "form.feed.label.cookie": "Set Cookies",
     "form.feed.label.crawler": "Fetch original content",
@@ -182,7 +183,8 @@
     "form.feed.label.fetch_via_proxy": "Use the proxy configured at the application level",
     "form.feed.label.hide_globally": "Hide entries in global unread list",
     "form.feed.label.ignore_http_cache": "Ignore HTTP cache",
-    "form.feed.label.keeplist_rules": "Keep Rules",
+    "form.feed.label.keep_filter_entry_rules": "Entry Allow Rules",
+    "form.feed.label.keeplist_rules": "Regex-Based Keep Filters",
     "form.feed.label.no_media_player": "No media player (audio/video)",
     "form.feed.label.ntfy_activate": "Push entries to ntfy",
     "form.feed.label.ntfy_default_priority": "Ntfy default priority",
@@ -200,7 +202,7 @@
     "form.feed.label.pushover_max_priority": "Max priority",
     "form.feed.label.pushover_min_priority": "Minimal priority",
     "form.feed.label.pushover_priority": "Pushover message priority",
-    "form.feed.label.rewrite_rules": "Rewrite Rules",
+    "form.feed.label.rewrite_rules": "Content Rewrite Rules",
     "form.feed.label.scraper_rules": "Scraper Rules",
     "form.feed.label.site_url": "Site URL",
     "form.feed.label.title": "Title",
@@ -430,10 +432,6 @@
     "page.api_keys.table.last_used_at": "Last Used",
     "page.api_keys.table.token": "Token",
     "page.api_keys.title": "API Keys",
-    "page.categories_count": [
-        "%d category",
-        "%d categories"
-    ],
     "page.categories.entries": "Entries",
     "page.categories.feed_count": [
         "There is %d feed.",
@@ -442,6 +440,10 @@
     "page.categories.feeds": "Feeds",
     "page.categories.no_feed": "No feed.",
     "page.categories.title": "Categories",
+    "page.categories_count": [
+        "%d category",
+        "%d categories"
+    ],
     "page.category_label": "Category: %s",
     "page.edit_category.title": "Edit Category: %s",
     "page.edit_feed.etag_header": "ETag header:",
@@ -547,25 +549,25 @@
     "page.settings.webauthn.passkeys": "Passkeys",
     "page.settings.webauthn.register": "Register passkey",
     "page.settings.webauthn.register.error": "Unable to register passkey",
+    "page.shared_entries.title": "Shared entries",
     "page.shared_entries_count": [
         "%d shared entry",
         "%d shared entries"
     ],
-    "page.shared_entries.title": "Shared entries",
+    "page.starred.title": "Starred",
     "page.starred_entry_count": [
         "%d starred entry",
         "%d starred entries"
     ],
-    "page.starred.title": "Starred",
     "page.total_entry_count": [
         "%d entry in total",
         "%d entries in total"
     ],
+    "page.unread.title": "Unread",
     "page.unread_entry_count": [
         "%d unread entry",
         "%d unread entries"
     ],
-    "page.unread.title": "Unread",
     "page.users.actions": "Actions",
     "page.users.admin.no": "No",
     "page.users.admin.yes": "Yes",
@@ -612,4 +614,4 @@
     "time_elapsed.yesterday": "yesterday",
     "tooltip.keyboard_shortcuts": "Keyboard Shortcut: %s",
     "tooltip.logged_user": "Logged in as %s"
-}
+}

+ 16 - 14
internal/locale/translations/es_ES.json

@@ -122,7 +122,7 @@
     "error.invalid_display_mode": "Modo de visualización de la aplicación web no válido.",
     "error.invalid_entry_direction": "Dirección de artículo no válida.",
     "error.invalid_entry_order": "Orden de artículo no válido.",
-    "error.invalid_feed_proxy_url": "Invalid proxy URL.",
+    "error.invalid_feed_proxy_url": "URL de proxy inválida.",
     "error.invalid_feed_url": "URL de feed no válida.",
     "error.invalid_gesture_nav": "Navegación por gestos no válida.",
     "error.invalid_language": "Idioma no válido.",
@@ -132,12 +132,12 @@
     "error.network_operation": "Miniflux no puede acceder a este sitio web debido a un error de red: %v.",
     "error.network_timeout": "Este sitio web es demasiado lento y se agotó el tiempo de espera de la solicitud: %v",
     "error.password_min_length": "La contraseña debería tener al menos 6 caracteres.",
-    "error.proxy_url_not_empty": "The proxy URL cannot be empty.",
+    "error.proxy_url_not_empty": "La URL del proxy no puede estar vacía.",
     "error.settings_block_rule_fieldname_invalid": "Regla de bloqueo no válida: a la regla #%d le falta un nombre de campo válido (Opciones: %s)",
     "error.settings_block_rule_invalid_regex": "Regla de bloqueo no válida: el patrón de la regla #%d no es una expresión regular válida",
     "error.settings_block_rule_regex_required": "Regla de bloqueo no válida: no se ha proporcionado el patrón de la regla #%d",
     "error.settings_block_rule_separator_required": "Regla de bloqueo no válida: el patrón de la regla #%d debe estar separado por un '='",
-    "error.settings_invalid_domain_list": "Invalid domain list. Please provide a space separated list of domains.",
+    "error.settings_invalid_domain_list": "Lista de dominios inválida. Por favor proporcione una lista de dominios separados por espacios.",
     "error.settings_keep_rule_fieldname_invalid": "Regla de mantenimiento no válida: a la regla #%d le falta un nombre de campo válido (Opciones: %s)",
     "error.settings_keep_rule_invalid_regex": "Regla de mantenimiento no válida: el patrón de la regla #%d no es una expresión regular válida",
     "error.settings_keep_rule_regex_required": "Regla de conservación no válida: no se ha proporcionado la regla #%d patrón",
@@ -169,7 +169,8 @@
     "form.feed.fieldset.rules": "Reglas",
     "form.feed.label.allow_self_signed_certificates": "Permitir certificados autofirmados o no válidos",
     "form.feed.label.apprise_service_urls": "Lista separada por comas de las URL del servicio Apprise",
-    "form.feed.label.blocklist_rules": "Reglas de Filtrado (Bloquear)",
+    "form.feed.label.block_filter_entry_rules": "Reglas de Bloqueo de Entradas",
+    "form.feed.label.blocklist_rules": "Filtros de Bloqueo Basados en Regex",
     "form.feed.label.category": "Categoría",
     "form.feed.label.cookie": "Configurar las cookies",
     "form.feed.label.crawler": "Obtener rastreador original",
@@ -182,7 +183,8 @@
     "form.feed.label.fetch_via_proxy": "Usar el proxy configurado a nivel de la aplicación",
     "form.feed.label.hide_globally": "Ocultar artículos en la lista global de no leídos",
     "form.feed.label.ignore_http_cache": "Ignorar caché HTTP",
-    "form.feed.label.keeplist_rules": "Reglas de Filtrado (Permitir)",
+    "form.feed.label.keep_filter_entry_rules": "Reglas de Permitir Entradas",
+    "form.feed.label.keeplist_rules": "Filtros de Mantener Basados en Regex",
     "form.feed.label.no_media_player": "Sin reproductor multimedia (audio/video)",
     "form.feed.label.ntfy_activate": "Enviar entradas a ntfy",
     "form.feed.label.ntfy_default_priority": "Prioridad predeterminada a Ntfy",
@@ -192,7 +194,7 @@
     "form.feed.label.ntfy_min_priority": "Prioridad mínima a Ntfy",
     "form.feed.label.ntfy_priority": "Prioridad Ntfy",
     "form.feed.label.ntfy_topic": "Tema Ntfy (opcional)",
-    "form.feed.label.proxy_url": "Proxy URL",
+    "form.feed.label.proxy_url": "URL del Proxy",
     "form.feed.label.pushover_activate": "Enviar artículos a pushover.net",
     "form.feed.label.pushover_default_priority": "Prioridad predeterminada de Pushover",
     "form.feed.label.pushover_high_priority": "Prioridad alta de Pushover",
@@ -200,7 +202,7 @@
     "form.feed.label.pushover_max_priority": "Prioridad máxima de Pushover",
     "form.feed.label.pushover_min_priority": "Prioridad mínima de Pushover",
     "form.feed.label.pushover_priority": "Prioridad del mensaje de Pushover",
-    "form.feed.label.rewrite_rules": "Reglas de reescribir",
+    "form.feed.label.rewrite_rules": "Reglas de Reescritura de Contenido",
     "form.feed.label.scraper_rules": "Reglas de extracción de información",
     "form.feed.label.site_url": "URL del sitio",
     "form.feed.label.title": "Título",
@@ -430,10 +432,6 @@
     "page.api_keys.table.last_used_at": "Último utilizado",
     "page.api_keys.table.token": "simbólico",
     "page.api_keys.title": "Claves API",
-    "page.categories_count": [
-        "%d categoría",
-        "%d categorías"
-    ],
     "page.categories.entries": "Artículos",
     "page.categories.feed_count": [
         "Hay %d fuente.",
@@ -442,6 +440,10 @@
     "page.categories.feeds": "Fuentes",
     "page.categories.no_feed": "Sin fuente.",
     "page.categories.title": "Categorías",
+    "page.categories_count": [
+        "%d categoría",
+        "%d categorías"
+    ],
     "page.category_label": "Categoría: %s",
     "page.edit_category.title": "Editar categoría: %s",
     "page.edit_feed.etag_header": "Cabecera de ETag:",
@@ -547,25 +549,25 @@
     "page.settings.webauthn.passkeys": "Claves de acceso",
     "page.settings.webauthn.register": "Registrar clave de acceso",
     "page.settings.webauthn.register.error": "No se puede registrar la clave de acceso",
+    "page.shared_entries.title": "Artículos compartidos",
     "page.shared_entries_count": [
         "%d artículo compartido",
         "%d artículos compartidos"
     ],
-    "page.shared_entries.title": "Artículos compartidos",
+    "page.starred.title": "Marcadores",
     "page.starred_entry_count": [
         "%d artículo marcado",
         "%d artículos marcados"
     ],
-    "page.starred.title": "Marcadores",
     "page.total_entry_count": [
         "%d artículo en total",
         "%d artículos en total"
     ],
+    "page.unread.title": "No leídos",
     "page.unread_entry_count": [
         "%d artículo no leído",
         "%d artículos no leídos"
     ],
-    "page.unread.title": "No leídos",
     "page.users.actions": "Acciones",
     "page.users.admin.no": "No",
     "page.users.admin.yes": "Sí",

+ 22 - 20
internal/locale/translations/fi_FI.json

@@ -84,26 +84,26 @@
     "error.api_key_already_exists": "API-avain on jo olemassa.",
     "error.bad_credentials": "Virheellinen käyttäjänimi tai salasana.",
     "error.category_already_exists": "Kategoria on jo olemassa. ",
-    "error.category_not_found": "This category does not exist or does not belong to this user.",
-    "error.database_error": "Database error: %v.",
+    "error.category_not_found": "Tämä kategoria ei ole olemassa tai se ei kuulu tälle käyttäjälle.",
+    "error.database_error": "Tietokantavirhe: %v.",
     "error.different_passwords": "Salasanat eivät ole samat.",
-    "error.duplicate_fever_username": "There is already someone else with the same Fever username!",
+    "error.duplicate_fever_username": "Joku muu käyttää jo samaa Fever-käyttäjänimeä!",
     "error.duplicate_googlereader_username": "On jo joku muu, jolla on sama Google-syötteenlukijan käyttäjätunnus!",
-    "error.duplicate_linked_account": "There is already someone associated with this provider!",
-    "error.duplicated_feed": "This feed already exists.",
+    "error.duplicate_linked_account": "Joku on jo yhdistetty tähän palveluntarjoajaan!",
+    "error.duplicated_feed": "Tämä syöte on jo olemassa.",
     "error.empty_file": "Tiedosto on tyhjä.",
     "error.entries_per_page_invalid": "Artikkelien määrä sivulla ei kelpaa.",
     "error.feed_already_exists": "Tämä syöte on jo olemassa.",
     "error.feed_category_not_found": "Tätä kategoriaa ei ole olemassa tai se ei kuulu tälle käyttäjälle.",
-    "error.feed_format_not_detected": "Unable to detect feed format: %v.",
-    "error.feed_invalid_blocklist_rule": "The block list rule is invalid.",
-    "error.feed_invalid_keeplist_rule": "The keep list rule is invalid.",
+    "error.feed_format_not_detected": "Syötteen muotoa ei voitu tunnistaa: %v.",
+    "error.feed_invalid_blocklist_rule": "Estolistan sääntö on virheellinen.",
+    "error.feed_invalid_keeplist_rule": "Säilytettävien listan sääntö on virheellinen.",
     "error.feed_mandatory_fields": "URL-osoite ja kategoria ovat pakollisia.",
-    "error.feed_not_found": "This feed does not exist or does not belong to this user.",
+    "error.feed_not_found": "Tämä syöte ei ole olemassa tai se ei kuulu tälle käyttäjälle.",
     "error.feed_title_not_empty": "Syötteen otsikko ei voi olla tyhjä.",
     "error.feed_url_not_empty": "Syötteen URL-osoite ei voi olla tyhjä.",
     "error.fields_mandatory": "Kaikki kentät ovat pakollisia.",
-    "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.",
+    "error.http_bad_gateway": "Verkkosivusto ei ole tällä hetkellä saatavilla huonon yhdyskäytävän virheen vuoksi. Ongelma ei ole Miniflux-puolella. Yritä uudelleen myöhemmin.",
     "error.http_body_read": "Unable to read the HTTP body: %v.",
     "error.http_client_error": "HTTP client error: %v.",
     "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?",
@@ -169,7 +169,8 @@
     "form.feed.fieldset.rules": "Rules",
     "form.feed.label.allow_self_signed_certificates": "Salli itseallekirjoitetut tai virheelliset varmenteet",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
-    "form.feed.label.blocklist_rules": "Block-säännöt",
+    "form.feed.label.block_filter_entry_rules": "Merkinnän estosäännöt",
+    "form.feed.label.blocklist_rules": "Regex-pohjaiset estosuodattimet",
     "form.feed.label.category": "Kategoria",
     "form.feed.label.cookie": "Aseta evästeet",
     "form.feed.label.crawler": "Nouda alkuperäinen sisältö",
@@ -182,7 +183,8 @@
     "form.feed.label.fetch_via_proxy": "Käytä sovellustasolla määritettyä välityspalvelinta",
     "form.feed.label.hide_globally": "Piilota artikkelit lukemattomien listassa",
     "form.feed.label.ignore_http_cache": "Ohita HTTP-välimuisti",
-    "form.feed.label.keeplist_rules": "Keep-säännöt",
+    "form.feed.label.keep_filter_entry_rules": "Merkinnän sallimissäännöt",
+    "form.feed.label.keeplist_rules": "Regex-pohjaiset säilytyssuodattimet",
     "form.feed.label.no_media_player": "No media player (audio/video)",
     "form.feed.label.ntfy_activate": "Push entries to ntfy",
     "form.feed.label.ntfy_default_priority": "Ntfy default priority",
@@ -200,7 +202,7 @@
     "form.feed.label.pushover_max_priority": "Pushover max priority",
     "form.feed.label.pushover_min_priority": "Pushover min priority",
     "form.feed.label.pushover_priority": "Pushover message priority",
-    "form.feed.label.rewrite_rules": "Rewrite-säännöt",
+    "form.feed.label.rewrite_rules": "Sisällön uudelleenkirjoitussäännöt",
     "form.feed.label.scraper_rules": "Scraper-säännöt",
     "form.feed.label.site_url": "Sivuston URL-osoite",
     "form.feed.label.title": "Otsikko",
@@ -430,10 +432,6 @@
     "page.api_keys.table.last_used_at": "Viimeksi käytetty",
     "page.api_keys.table.token": "Tunnus",
     "page.api_keys.title": "API-avaimet",
-    "page.categories_count": [
-        "%d category",
-        "%d categories"
-    ],
     "page.categories.entries": "Artikkelit",
     "page.categories.feed_count": [
         "On %d syöte.",
@@ -442,6 +440,10 @@
     "page.categories.feeds": "Tilaukset",
     "page.categories.no_feed": "Ei syötettä.",
     "page.categories.title": "Kategoriat",
+    "page.categories_count": [
+        "%d category",
+        "%d categories"
+    ],
     "page.category_label": "Category: %s",
     "page.edit_category.title": "Muokkaa kategoria: %s",
     "page.edit_feed.etag_header": "ETag-otsikko:",
@@ -547,25 +549,25 @@
     "page.settings.webauthn.passkeys": "Passkeys",
     "page.settings.webauthn.register": "Rekisteröi salasana",
     "page.settings.webauthn.register.error": "Salasanaa ei voi rekisteröidä",
+    "page.shared_entries.title": "Jaetut artikkelit",
     "page.shared_entries_count": [
         "%d shared entry",
         "%d shared entries"
     ],
-    "page.shared_entries.title": "Jaetut artikkelit",
+    "page.starred.title": "Suosikit",
     "page.starred_entry_count": [
         "%d starred entry",
         "%d starred entries"
     ],
-    "page.starred.title": "Suosikit",
     "page.total_entry_count": [
         "%d entry in total",
         "%d entries in total"
     ],
+    "page.unread.title": "Lukemattomat",
     "page.unread_entry_count": [
         "%d unread entry",
         "%d unread entries"
     ],
-    "page.unread.title": "Lukemattomat",
     "page.users.actions": "Toiminnot",
     "page.users.admin.no": "Ei",
     "page.users.admin.yes": "Kyllä",

+ 13 - 11
internal/locale/translations/fr_FR.json

@@ -169,7 +169,8 @@
     "form.feed.fieldset.rules": "Règles",
     "form.feed.label.allow_self_signed_certificates": "Autoriser les certificats auto-signés ou non valides",
     "form.feed.label.apprise_service_urls": "Liste séparée par des virgules des URL du service Apprise",
-    "form.feed.label.blocklist_rules": "Règles de blocage",
+    "form.feed.label.block_filter_entry_rules": "Règles de blocage des entrées",
+    "form.feed.label.blocklist_rules": "Filtres de blocage basés sur des expressions régulières",
     "form.feed.label.category": "Catégorie",
     "form.feed.label.cookie": "Définir les cookies",
     "form.feed.label.crawler": "Récupérer le contenu original",
@@ -182,7 +183,8 @@
     "form.feed.label.fetch_via_proxy": "Utiliser le proxy configuré au niveau de l'application",
     "form.feed.label.hide_globally": "Masquer les entrées dans la liste globale non lue",
     "form.feed.label.ignore_http_cache": "Ignorer le cache HTTP",
-    "form.feed.label.keeplist_rules": "Règles d'autorisation",
+    "form.feed.label.keep_filter_entry_rules": "Règles d'autorisation des entrées",
+    "form.feed.label.keeplist_rules": "Filtres de conservation basés sur des expressions régulières",
     "form.feed.label.no_media_player": "Pas de lecteur multimedia (audio/vidéo)",
     "form.feed.label.ntfy_activate": "Activer les notifications",
     "form.feed.label.ntfy_default_priority": "Priorité par défaut de notification",
@@ -200,7 +202,7 @@
     "form.feed.label.pushover_max_priority": "Priorité maximale",
     "form.feed.label.pushover_min_priority": "Priorité minimale",
     "form.feed.label.pushover_priority": "Priorité des notifications Pushover",
-    "form.feed.label.rewrite_rules": "Règles de réécriture",
+    "form.feed.label.rewrite_rules": "Règles de réécriture du contenu",
     "form.feed.label.scraper_rules": "Règles pour récupérer le contenu original",
     "form.feed.label.site_url": "URL du site web",
     "form.feed.label.title": "Titre",
@@ -289,7 +291,7 @@
     "form.integration.readeck_activate": "Sauvegarder les articles vers Readeck",
     "form.integration.readeck_api_key": "Clé d'API de Readeck",
     "form.integration.readeck_endpoint": "URL de l'API de Readeck",
-    "form.integration.readeck_labels": "Readeck Labels",
+    "form.integration.readeck_labels": "Libellés Readeck",
     "form.integration.readeck_only_url": "Envoyer uniquement l'URL (au lieu du contenu complet)",
     "form.integration.readwise_activate": "Enregistrer les entrées vers Readwise Reader",
     "form.integration.readwise_api_key": "Jeton d'accès au lecteur Readwise",
@@ -430,10 +432,6 @@
     "page.api_keys.table.last_used_at": "Dernière utilisation",
     "page.api_keys.table.token": "Jeton",
     "page.api_keys.title": "Clés d'API",
-    "page.categories_count": [
-        "%d catégorie",
-        "%d catégories"
-    ],
     "page.categories.entries": "Articles",
     "page.categories.feed_count": [
         "Il y a %d abonnement.",
@@ -442,6 +440,10 @@
     "page.categories.feeds": "Abonnements",
     "page.categories.no_feed": "Aucun abonnement.",
     "page.categories.title": "Catégories",
+    "page.categories_count": [
+        "%d catégorie",
+        "%d catégories"
+    ],
     "page.category_label": "Catégorie : %s",
     "page.edit_category.title": "Modification de la catégorie : %s",
     "page.edit_feed.etag_header": "En-tête ETag :",
@@ -547,25 +549,25 @@
     "page.settings.webauthn.passkeys": "Clés d’accès",
     "page.settings.webauthn.register": "Enregistrer une nouvelle clé d’accès",
     "page.settings.webauthn.register.error": "Impossible d'enregistrer la clé d’accès",
+    "page.shared_entries.title": "Articles partagés",
     "page.shared_entries_count": [
         "%d article partagé",
         "%d articles partagés"
     ],
-    "page.shared_entries.title": "Articles partagés",
+    "page.starred.title": "Favoris",
     "page.starred_entry_count": [
         "%d favori",
         "%d favoris"
     ],
-    "page.starred.title": "Favoris",
     "page.total_entry_count": [
         "%d article au total",
         "%d articles au total"
     ],
+    "page.unread.title": "Non lus",
     "page.unread_entry_count": [
         "%d article non lu",
         "%d articles non lus"
     ],
-    "page.unread.title": "Non lus",
     "page.users.actions": "Actions",
     "page.users.admin.no": "Non",
     "page.users.admin.yes": "Oui",

+ 20 - 18
internal/locale/translations/hi_IN.json

@@ -85,7 +85,7 @@
     "error.bad_credentials": "अमान्य उपयोगकर्ता नाम या पासवर्ड।",
     "error.category_already_exists": "यह श्रेणी पहले से मौजूद है।",
     "error.category_not_found": "यह श्रेणी मौजूद नहीं है या इस उपयोगकर्ता से संबंधित नहीं है।",
-    "error.database_error": "Database error: %v.",
+    "error.database_error": "डेटाबेस त्रुटि: %v।",
     "error.different_passwords": "पासवर्ड एक जैसे नहीं हैं।",
     "error.duplicate_fever_username": "पहले से ही समान फीवर उपयोगकर्ता नाम वाला कोई और है!",
     "error.duplicate_googlereader_username": "समान गूगल रीडर उपयोगकर्ता नाम वाला कोई और पहले से मौजूद है!",
@@ -95,7 +95,7 @@
     "error.entries_per_page_invalid": "प्रति पृष्ठ प्रविष्टियों की संख्या मान्य नहीं है।",
     "error.feed_already_exists": "यह फ़ीड पहले से मौजूद है.",
     "error.feed_category_not_found": "यह श्रेणी मौजूद नहीं है या इस उपयोगकर्ता से संबंधित नहीं है।",
-    "error.feed_format_not_detected": "Unable to detect feed format: %v.",
+    "error.feed_format_not_detected": "फ़ीड प्रारूप का पता नहीं लगा सकते: %v।",
     "error.feed_invalid_blocklist_rule": "ब्लॉक सूची नियम अमान्य है।",
     "error.feed_invalid_keeplist_rule": "सूची रखें नियम अमान्य है।",
     "error.feed_mandatory_fields": "URL और श्रेणी अनिवार्य हैं।",
@@ -103,12 +103,12 @@
     "error.feed_title_not_empty": "फ़ीड शीर्षक खाली नहीं हो सकता.",
     "error.feed_url_not_empty": "फ़ीड यूआरएल खाली नहीं हो सकता.",
     "error.fields_mandatory": "सभी फील्ड अनिवार्य।",
-    "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.",
-    "error.http_body_read": "Unable to read the HTTP body: %v.",
-    "error.http_client_error": "HTTP client error: %v.",
-    "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?",
-    "error.http_empty_response_body": "The HTTP response body is empty.",
-    "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?",
+    "error.http_bad_gateway": "खराब गेटवे त्रुटि के कारण वेबसाइट फिलहाल उपलब्ध नहीं है। समस्या Miniflux की तरफ नहीं है। कृपया बाद में फिर से कोशिश करें।",
+    "error.http_body_read": "HTTP बॉडी पढ़ने में असमर्थ: %v।",
+    "error.http_client_error": "HTTP क्लाइंट त्रुटि: %v।",
+    "error.http_empty_response": "HTTP प्रतिक्रिया खाली है। शायद यह वेबसाइट बॉट सुरक्षा तंत्र का उपयोग कर रही है?",
+    "error.http_empty_response_body": "HTTP प्रतिक्रिया बॉडी खाली है।",
+    "error.http_forbidden": "इस वेबसाइट तक पहुंच वर्जित है। शायद इस वेबसाइट में बॉट सुरक्षा तंत्र है?",
     "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.",
     "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.",
     "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.",
@@ -169,7 +169,8 @@
     "form.feed.fieldset.rules": "Rules",
     "form.feed.label.allow_self_signed_certificates": "स्व-हस्ताक्षरित या अमान्य प्रमाणपत्रों की अनुमति दें",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
-    "form.feed.label.blocklist_rules": "ब्लॉक नियम",
+    "form.feed.label.block_filter_entry_rules": "प्रविष्टि अवरोधन नियम",
+    "form.feed.label.blocklist_rules": "रेगेक्स-आधारित अवरोधन फिल्टर",
     "form.feed.label.category": "श्रेणी",
     "form.feed.label.cookie": "कुकीज़ सेट करें",
     "form.feed.label.crawler": "मूल सामग्री प्राप्त करें",
@@ -182,7 +183,8 @@
     "form.feed.label.fetch_via_proxy": "एप्लिकेशन स्तर पर कॉन्फ़िगर किए गए प्रॉक्सी का उपयोग करें",
     "form.feed.label.hide_globally": "वैश्विक अपठित सूची में प्रविष्टियां छिपाएं",
     "form.feed.label.ignore_http_cache": "एचटीटीपी कैश पर ध्यान न दें",
-    "form.feed.label.keeplist_rules": "नियम बनाए रखें",
+    "form.feed.label.keep_filter_entry_rules": "प्रविष्टि अनुमति नियम",
+    "form.feed.label.keeplist_rules": "रेगेक्स-आधारित रखने वाले फिल्टर",
     "form.feed.label.no_media_player": "No media player (audio/video)",
     "form.feed.label.ntfy_activate": "Push entries to ntfy",
     "form.feed.label.ntfy_default_priority": "Ntfy default priority",
@@ -200,7 +202,7 @@
     "form.feed.label.pushover_max_priority": "Pushover max priority",
     "form.feed.label.pushover_min_priority": "Pushover min priority",
     "form.feed.label.pushover_priority": "Pushover message priority",
-    "form.feed.label.rewrite_rules": "नियम फिर से लिखें",
+    "form.feed.label.rewrite_rules": "सामग्री पुनर्लेखन नियम",
     "form.feed.label.scraper_rules": "खुरचनी नियम",
     "form.feed.label.site_url": "साइट यूआरएल",
     "form.feed.label.title": "शीर्षक",
@@ -430,10 +432,6 @@
     "page.api_keys.table.last_used_at": "आखरी इस्त्तमाल किया गया",
     "page.api_keys.table.token": "टोकन",
     "page.api_keys.title": "एपीआई कुंजी",
-    "page.categories_count": [
-        "%d category",
-        "%d categories"
-    ],
     "page.categories.entries": "विषयवस्तुया",
     "page.categories.feed_count": [
         "%d फ़ीड बाकी है।",
@@ -442,6 +440,10 @@
     "page.categories.feeds": "सदस्यता ले",
     "page.categories.no_feed": "कोई फ़ीड नहीं है।",
     "page.categories.title": "श्रेणियाँ",
+    "page.categories_count": [
+        "%d category",
+        "%d categories"
+    ],
     "page.category_label": "Category: %s",
     "page.edit_category.title": "%s श्रेणी संपाद करे",
     "page.edit_feed.etag_header": "ईटाग हैडर:",
@@ -547,25 +549,25 @@
     "page.settings.webauthn.passkeys": "Passkeys",
     "page.settings.webauthn.register": "रजिस्टर पासकी",
     "page.settings.webauthn.register.error": "पासकी पंजीकृत करने में असमर्थ",
+    "page.shared_entries.title": "साझा किया हुआ प्रविष्टि",
     "page.shared_entries_count": [
         "%d shared entry",
         "%d shared entries"
     ],
-    "page.shared_entries.title": "साझा किया हुआ प्रविष्टि",
+    "page.starred.title": "तारांकित",
     "page.starred_entry_count": [
         "%d starred entry",
         "%d starred entries"
     ],
-    "page.starred.title": "तारांकित",
     "page.total_entry_count": [
         "%d entry in total",
         "%d entries in total"
     ],
+    "page.unread.title": "अपठित",
     "page.unread_entry_count": [
         "%d unread entry",
         "%d unread entries"
     ],
-    "page.unread.title": "अपठित",
     "page.users.actions": "कार्रवाई",
     "page.users.admin.no": "नहीं",
     "page.users.admin.yes": "हां",

+ 13 - 11
internal/locale/translations/id_ID.json

@@ -163,10 +163,11 @@
     "form.feed.fieldset.general": "Umum",
     "form.feed.fieldset.integration": "Pengaturan Pihak Ketiga",
     "form.feed.fieldset.network_settings": "Pengaturan Jaringan",
-    "form.feed.fieldset.rules": "Rules",
+    "form.feed.fieldset.rules": "Aturan",
     "form.feed.label.allow_self_signed_certificates": "Perbolehkan sertifikat web tidak valid atau sertifikasi sendiri",
     "form.feed.label.apprise_service_urls": "Daftar yang dipisahkan koma untuk URL layanan Apprise",
-    "form.feed.label.blocklist_rules": "Aturan Blokir",
+    "form.feed.label.block_filter_entry_rules": "Aturan Pemblokiran Entri",
+    "form.feed.label.blocklist_rules": "Filter Pemblokiran Berbasis Regex",
     "form.feed.label.category": "Kategori",
     "form.feed.label.cookie": "Atur Kuki",
     "form.feed.label.crawler": "Ambil konten asli",
@@ -179,8 +180,9 @@
     "form.feed.label.fetch_via_proxy": "Gunakan proksi yang dikonfigurasi di tingkat aplikasi",
     "form.feed.label.hide_globally": "Sembunyikan entri di daftar belum dibaca global",
     "form.feed.label.ignore_http_cache": "Abaikan Tembolok HTTP",
-    "form.feed.label.keeplist_rules": "Aturan Simpan",
-    "form.feed.label.no_media_player": "No media player (audio/video)",
+    "form.feed.label.keep_filter_entry_rules": "Aturan Izin Entri",
+    "form.feed.label.keeplist_rules": "Filter Simpan Berbasis Regex",
+    "form.feed.label.no_media_player": "Tidak ada pemutar media (audio/video)",
     "form.feed.label.ntfy_activate": "Kirim artikel ke ntfy",
     "form.feed.label.ntfy_default_priority": "Prioritas baku Ntfy",
     "form.feed.label.ntfy_high_priority": "Priroritas tinggi Ntfy",
@@ -197,7 +199,7 @@
     "form.feed.label.pushover_max_priority": "Prioritas maksimal Pushover",
     "form.feed.label.pushover_min_priority": "Prioritas minimal Pushover",
     "form.feed.label.pushover_priority": "Prioritas pesan Pushover",
-    "form.feed.label.rewrite_rules": "Aturan Tulis Ulang",
+    "form.feed.label.rewrite_rules": "Aturan Penulisan Ulang Konten",
     "form.feed.label.scraper_rules": "Aturan Pengambil Data",
     "form.feed.label.site_url": "URL Situs",
     "form.feed.label.title": "Judul",
@@ -427,9 +429,6 @@
     "page.api_keys.table.last_used_at": "Terakhir Digunakan",
     "page.api_keys.table.token": "Token",
     "page.api_keys.title": "Kunci API",
-    "page.categories_count": [
-        "%d kategori"
-    ],
     "page.categories.entries": "Artikel",
     "page.categories.feed_count": [
         "Ada %d umpan."
@@ -437,6 +436,9 @@
     "page.categories.feeds": "Langganan",
     "page.categories.no_feed": "Tidak ada umpan.",
     "page.categories.title": "Kategori",
+    "page.categories_count": [
+        "%d kategori"
+    ],
     "page.category_label": "Category: %s",
     "page.edit_category.title": "Sunting Kategori: %s",
     "page.edit_feed.etag_header": "Tajuk ETag:",
@@ -539,21 +541,21 @@
     "page.settings.webauthn.passkeys": "Passkey",
     "page.settings.webauthn.register": "Daftar passkey",
     "page.settings.webauthn.register.error": "Tidak dapat mendaftarkan passkey",
+    "page.shared_entries.title": "Entri yang Dibagikan",
     "page.shared_entries_count": [
         "%d entri yang dibagikan"
     ],
-    "page.shared_entries.title": "Entri yang Dibagikan",
+    "page.starred.title": "Markah",
     "page.starred_entry_count": [
         "%d entri dimarkahi"
     ],
-    "page.starred.title": "Markah",
     "page.total_entry_count": [
         "%d entri secara total"
     ],
+    "page.unread.title": "Belum Dibaca",
     "page.unread_entry_count": [
         "%d entri belum dibaca"
     ],
-    "page.unread.title": "Belum Dibaca",
     "page.users.actions": "Tindakan",
     "page.users.admin.no": "Tidak",
     "page.users.admin.yes": "Ya",

+ 19 - 17
internal/locale/translations/it_IT.json

@@ -85,7 +85,7 @@
     "error.bad_credentials": "Nome utente o password non validi.",
     "error.category_already_exists": "Questa categoria esiste già.",
     "error.category_not_found": "Questa categoria non esiste o non appartiene a questo utente.",
-    "error.database_error": "Database error: %v.",
+    "error.database_error": "Errore del database: %v.",
     "error.different_passwords": "Le password non coincidono.",
     "error.duplicate_fever_username": "Esiste già un account Fever con lo stesso nome utente!",
     "error.duplicate_googlereader_username": "Esiste già un account Google Reader con lo stesso nome utente!",
@@ -103,12 +103,12 @@
     "error.feed_title_not_empty": "Il titolo del feed non può essere vuoto.",
     "error.feed_url_not_empty": "L'URL del feed non può essere vuoto.",
     "error.fields_mandatory": "Tutti i campi sono obbligatori.",
-    "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.",
-    "error.http_body_read": "Unable to read the HTTP body: %v.",
-    "error.http_client_error": "HTTP client error: %v.",
-    "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?",
-    "error.http_empty_response_body": "The HTTP response body is empty.",
-    "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?",
+    "error.http_bad_gateway": "Il sito web non è disponibile al momento a causa di un errore di gateway. Il problema non è dal lato di Miniflux. Per favore, riprova più tardi.",
+    "error.http_body_read": "Impossibile leggere il corpo HTTP: %v.",
+    "error.http_client_error": "Errore del client HTTP: %v.",
+    "error.http_empty_response": "La risposta HTTP è vuota. Forse questo sito web utilizza un meccanismo di protezione dai bot?",
+    "error.http_empty_response_body": "Il corpo della risposta HTTP è vuoto.",
+    "error.http_forbidden": "L'accesso a questo sito web è vietato. Forse questo sito web ha un meccanismo di protezione dai bot?",
     "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.",
     "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.",
     "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.",
@@ -169,7 +169,8 @@
     "form.feed.fieldset.rules": "Rules",
     "form.feed.label.allow_self_signed_certificates": "Consenti certificati autofirmati o non validi",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
-    "form.feed.label.blocklist_rules": "Regole di blocco",
+    "form.feed.label.block_filter_entry_rules": "Regole di Blocco delle Voci",
+    "form.feed.label.blocklist_rules": "Filtri di Blocco Basati su Regex",
     "form.feed.label.category": "Categoria",
     "form.feed.label.cookie": "Installare i cookies",
     "form.feed.label.crawler": "Scarica il contenuto integrale",
@@ -182,7 +183,8 @@
     "form.feed.label.fetch_via_proxy": "Usa il proxy configurato a livello di applicazione",
     "form.feed.label.hide_globally": "Nascondere le voci nella lista globale dei non letti",
     "form.feed.label.ignore_http_cache": "Ignora cache HTTP",
-    "form.feed.label.keeplist_rules": "Regole di autorizzazione",
+    "form.feed.label.keep_filter_entry_rules": "Regole di Permesso delle Voci",
+    "form.feed.label.keeplist_rules": "Filtri di Mantenimento Basati su Regex",
     "form.feed.label.no_media_player": "No media player (audio/video)",
     "form.feed.label.ntfy_activate": "Push entries to ntfy",
     "form.feed.label.ntfy_default_priority": "Ntfy default priority",
@@ -200,7 +202,7 @@
     "form.feed.label.pushover_max_priority": "Pushover max priority",
     "form.feed.label.pushover_min_priority": "Pushover min priority",
     "form.feed.label.pushover_priority": "Pushover message priority",
-    "form.feed.label.rewrite_rules": "Regole di impaginazione del contenuto",
+    "form.feed.label.rewrite_rules": "Regole di Riscrittura del Contenuto",
     "form.feed.label.scraper_rules": "Regole di estrazione del contenuto",
     "form.feed.label.site_url": "URL del sito",
     "form.feed.label.title": "Titolo",
@@ -430,10 +432,6 @@
     "page.api_keys.table.last_used_at": "Ultimo uso",
     "page.api_keys.table.token": "Gettone",
     "page.api_keys.title": "Chiavi API",
-    "page.categories_count": [
-        "%d category",
-        "%d categories"
-    ],
     "page.categories.entries": "Articoli",
     "page.categories.feed_count": [
         "C'è %d feed.",
@@ -442,6 +440,10 @@
     "page.categories.feeds": "Abbonamenti",
     "page.categories.no_feed": "Nessun feed.",
     "page.categories.title": "Categorie",
+    "page.categories_count": [
+        "%d category",
+        "%d categories"
+    ],
     "page.category_label": "Category: %s",
     "page.edit_category.title": "Modifica categoria: %s",
     "page.edit_feed.etag_header": "Header ETag:",
@@ -547,25 +549,25 @@
     "page.settings.webauthn.passkeys": "Passkeys",
     "page.settings.webauthn.register": "Registra la chiave di accesso",
     "page.settings.webauthn.register.error": "Impossibile registrare la passkey",
+    "page.shared_entries.title": "Voci condivise",
     "page.shared_entries_count": [
         "%d shared entry",
         "%d shared entries"
     ],
-    "page.shared_entries.title": "Voci condivise",
+    "page.starred.title": "Preferiti",
     "page.starred_entry_count": [
         "%d starred entry",
         "%d starred entries"
     ],
-    "page.starred.title": "Preferiti",
     "page.total_entry_count": [
         "%d entry in total",
         "%d entries in total"
     ],
+    "page.unread.title": "Da leggere",
     "page.unread_entry_count": [
         "%d unread entry",
         "%d unread entries"
     ],
-    "page.unread.title": "Da leggere",
     "page.users.actions": "Azioni",
     "page.users.admin.no": "No",
     "page.users.admin.yes": "Sì",

+ 18 - 16
internal/locale/translations/ja_JP.json

@@ -82,7 +82,7 @@
     "error.bad_credentials": "ユーザー名かパスワードが間違っています。",
     "error.category_already_exists": "このカテゴリは既に存在します。",
     "error.category_not_found": "このカテゴリは存在しないか、このユーザーに属していません。",
-    "error.database_error": "Database error: %v.",
+    "error.database_error": "データベースエラー: %v。",
     "error.different_passwords": "パスワードが一致しません。",
     "error.duplicate_fever_username": "既に同じ名前の Fever ユーザー名が使われています!",
     "error.duplicate_googlereader_username": "既に同じ名前の Google Reader ユーザー名が使われています!",
@@ -100,12 +100,12 @@
     "error.feed_title_not_empty": "フィードのタイトルを空にすることはできません。",
     "error.feed_url_not_empty": "フィード URL を空にすることはできません。",
     "error.fields_mandatory": "すべての項目が必要です。",
-    "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.",
-    "error.http_body_read": "Unable to read the HTTP body: %v.",
-    "error.http_client_error": "HTTP client error: %v.",
-    "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?",
-    "error.http_empty_response_body": "The HTTP response body is empty.",
-    "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?",
+    "error.http_bad_gateway": "ウェブサイトは、不正なゲートウェイエラーのため現在利用できません。問題はMiniflux側にはありません。後でもう一度お試しください。",
+    "error.http_body_read": "HTTP本文を読み取れません: %v。",
+    "error.http_client_error": "HTTPクライアントエラー: %v。",
+    "error.http_empty_response": "HTTP応答が空です。おそらく、このウェブサイトはボット保護メカニズムを使用していますか?",
+    "error.http_empty_response_body": "HTTP応答本文が空です。",
+    "error.http_forbidden": "このウェブサイトへのアクセスは禁止されています。おそらく、このウェブサイトはボット保護メカニズムを持っていますか?",
     "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.",
     "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.",
     "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.",
@@ -166,7 +166,8 @@
     "form.feed.fieldset.rules": "Rules",
     "form.feed.label.allow_self_signed_certificates": "自己署名証明書または無効な証明書を許可する",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
-    "form.feed.label.blocklist_rules": "Block ルール",
+    "form.feed.label.block_filter_entry_rules": "エントリブロッキングルール",
+    "form.feed.label.blocklist_rules": "正規表現ベースのブロッキングフィルター",
     "form.feed.label.category": "カテゴリ",
     "form.feed.label.cookie": "Cookie の設定",
     "form.feed.label.crawler": "オリジナルの内容を取得",
@@ -179,7 +180,8 @@
     "form.feed.label.fetch_via_proxy": "アプリケーションレベルで設定されたプロキシを使用する",
     "form.feed.label.hide_globally": "未読一覧に記事を表示しない",
     "form.feed.label.ignore_http_cache": "HTTPキャッシュを無視",
-    "form.feed.label.keeplist_rules": "Keep ルール",
+    "form.feed.label.keep_filter_entry_rules": "エントリ許可ルール",
+    "form.feed.label.keeplist_rules": "正規表現ベースのキープフィルター",
     "form.feed.label.no_media_player": "No media player (audio/video)",
     "form.feed.label.ntfy_activate": "Push entries to ntfy",
     "form.feed.label.ntfy_default_priority": "Ntfy default priority",
@@ -197,7 +199,7 @@
     "form.feed.label.pushover_max_priority": "Pushover max priority",
     "form.feed.label.pushover_min_priority": "Pushover min priority",
     "form.feed.label.pushover_priority": "Pushover message priority",
-    "form.feed.label.rewrite_rules": "Rewrite ルール",
+    "form.feed.label.rewrite_rules": "コンテンツ書き換えルール",
     "form.feed.label.scraper_rules": "Scraper ルール",
     "form.feed.label.site_url": "サイト URL",
     "form.feed.label.title": "タイトル",
@@ -427,9 +429,6 @@
     "page.api_keys.table.last_used_at": "最終使用",
     "page.api_keys.table.token": "トークン",
     "page.api_keys.title": "API キー",
-    "page.categories_count": [
-        "%d 件のカテゴリ"
-    ],
     "page.categories.entries": "記事一覧",
     "page.categories.feed_count": [
         "%d 件のフィードがあります。"
@@ -437,6 +436,9 @@
     "page.categories.feeds": "フィード一覧",
     "page.categories.no_feed": "フィードはありません。",
     "page.categories.title": "カテゴリ",
+    "page.categories_count": [
+        "%d 件のカテゴリ"
+    ],
     "page.category_label": "Category: %s",
     "page.edit_category.title": "カテゴリを編集: %s",
     "page.edit_feed.etag_header": "ETag ヘッダー:",
@@ -539,21 +541,21 @@
     "page.settings.webauthn.passkeys": "Passkeys",
     "page.settings.webauthn.register": "パスキーを登録する",
     "page.settings.webauthn.register.error": "パスキーを登録できません",
+    "page.shared_entries.title": "共有エントリ",
     "page.shared_entries_count": [
         "%d 件の共有エントリ"
     ],
-    "page.shared_entries.title": "共有エントリ",
+    "page.starred.title": "星付き",
     "page.starred_entry_count": [
         "%d 件の星付きエントリ"
     ],
-    "page.starred.title": "星付き",
     "page.total_entry_count": [
         "合計 %d 件のエントリ"
     ],
+    "page.unread.title": "未読",
     "page.unread_entry_count": [
         "%d 件の未読エントリ"
     ],
-    "page.unread.title": "未読",
     "page.users.actions": "アクション",
     "page.users.admin.no": "非管理者",
     "page.users.admin.yes": "管理者",

+ 12 - 10
internal/locale/translations/nan_Latn_pehoeji.json

@@ -166,7 +166,8 @@
     "form.feed.fieldset.rules": "Kui-chek",
     "form.feed.label.allow_self_signed_certificates": "ún-chún chū chhiam ah-sī bô-hāu ê pîn-chèng",
     "form.feed.label.apprise_service_urls": "Sú-iōng tō͘-tiám keh khui ê Apprise ho̍k-bū bāng-chí lia̍t-pió",
-    "form.feed.label.blocklist_rules": "Hong-só kui-chek",
+    "form.feed.label.block_filter_entry_rules": "Entry Blocking Rules",
+    "form.feed.label.blocklist_rules": "Regex-Based Blocking Filters",
     "form.feed.label.category": "lūi-pia̍t",
     "form.feed.label.cookie": "Siat-tēng Cookies",
     "form.feed.label.crawler": "Lia̍h goân-tóe lōe-iông",
@@ -179,7 +180,8 @@
     "form.feed.label.fetch_via_proxy": "Iōng tī su-hāu-khì siat-tēng ê proxy",
     "form.feed.label.hide_globally": "Tī choân-he̍k ah-bōe tha̍k--ê lia̍t-pió am-khàm siau-sit",
     "form.feed.label.ignore_http_cache": "Pàng-ba̍k HTTP cache",
-    "form.feed.label.keeplist_rules": "Pó-liû kui-chek",
+    "form.feed.label.keep_filter_entry_rules": "Entry Allow Rules",
+    "form.feed.label.keeplist_rules": "Regex-Based Keep Filters",
     "form.feed.label.no_media_player": "Bô mûi-thé hòng-sàng khì (im-sìn, sī-sìn)",
     "form.feed.label.ntfy_activate": "Thui-sàng siau-sit khì ntfy",
     "form.feed.label.ntfy_default_priority": "Ntfy ū-siat iu-sian sūn-sū",
@@ -197,7 +199,7 @@
     "form.feed.label.pushover_max_priority": "Pushover siōng koân iu-sian sūn-sū",
     "form.feed.label.pushover_min_priority": "Pushover siōng kē iu-sian sūn-sū",
     "form.feed.label.pushover_priority": "Pushover siau-sit iu-sian sūn-sū",
-    "form.feed.label.rewrite_rules": "Têng siá kui-chek",
+    "form.feed.label.rewrite_rules": "Content Rewrite Rules",
     "form.feed.label.scraper_rules": "Lia̍h ê kui-chek",
     "form.feed.label.site_url": "Bāng-chām bāng-chí",
     "form.feed.label.title": "Piau-tôe",
@@ -427,9 +429,6 @@
     "page.api_keys.table.last_used_at": "Siōng-bóe pái sú-iōng",
     "page.api_keys.table.token": "Só-sî",
     "page.api_keys.title": "API só-sî",
-    "page.categories_count": [
-        "%d ê lūi-pia̍t"
-    ],
     "page.categories.entries": "Siau-sit",
     "page.categories.feed_count": [
         "Ū %d ê Siau-sit lâi-goân"
@@ -437,6 +436,9 @@
     "page.categories.feeds": "Siau-sit lâi-goân",
     "page.categories.no_feed": "Ah-bô siau-sit lâi-goân",
     "page.categories.title": "Lūi-pia̍t",
+    "page.categories_count": [
+        "%d ê lūi-pia̍t"
+    ],
     "page.category_label": "Lūi-pia̍t: %s",
     "page.edit_category.title": "Pian-chi̍p lūi-pia̍t: %s",
     "page.edit_feed.etag_header": "ETag piau-thâu:",
@@ -539,21 +541,21 @@
     "page.settings.webauthn.passkeys": "Passkeys",
     "page.settings.webauthn.register": "Chù-chheh Passkey",
     "page.settings.webauthn.register.error": "Bô-hoat-tō͘ chù-chheh Passkey",
+    "page.shared_entries.title": "Hun-hióng kè ê siau-sit",
     "page.shared_entries_count": [
         "Í-keng hun-hióng %d ê siau-sit"
     ],
-    "page.shared_entries.title": "Hun-hióng kè ê siau-sit",
+    "page.starred.title": "Siu-chông",
     "page.starred_entry_count": [
         "%d ê siu-chông ê siau-sit"
     ],
-    "page.starred.title": "Siu-chông",
     "page.total_entry_count": [
         "Lóng-chóng %d ê siau-sit"
     ],
+    "page.unread.title": "Ah-bōe tha̍k",
     "page.unread_entry_count": [
         "%d ê siau-sit ah-bōe tha̍k"
     ],
-    "page.unread.title": "Ah-bōe tha̍k",
     "page.users.actions": "chhau-chok",
     "page.users.admin.no": "Hóⁿ",
     "page.users.admin.yes": "Sī",
@@ -594,4 +596,4 @@
     "time_elapsed.yesterday": "cha-hng",
     "tooltip.keyboard_shortcuts": "Khoài-sok khí:%s",
     "tooltip.logged_user": "Chit-má teng-lo̍k--ê:  %s"
-}
+}

+ 15 - 13
internal/locale/translations/nl_NL.json

@@ -1,6 +1,6 @@
 {
     "action.cancel": "annuleren",
-    "action.download": "Download",
+    "action.download": "Downloaden",
     "action.edit": "Bewerken",
     "action.home_screen": "Toevoegen aan startscherm",
     "action.import": "Importeren",
@@ -42,7 +42,7 @@
     "enclosure_media_controls.speed": "Snelheid:",
     "enclosure_media_controls.speed.faster": "Versnel",
     "enclosure_media_controls.speed.faster.title": "Versnel met %sx",
-    "enclosure_media_controls.speed.reset": "Reset",
+    "enclosure_media_controls.speed.reset": "Resetten",
     "enclosure_media_controls.speed.reset.title": "Reset snelheid naar 1x",
     "enclosure_media_controls.speed.slower": "Vertraag",
     "enclosure_media_controls.speed.slower.title": "Vertraag met %sx",
@@ -169,7 +169,8 @@
     "form.feed.fieldset.rules": "Regels",
     "form.feed.label.allow_self_signed_certificates": "Zelfondertekende of ongeldige certificaten toestaan",
     "form.feed.label.apprise_service_urls": "Door komma's gescheiden lijst van Apprise service URL's",
-    "form.feed.label.blocklist_rules": "Blokkeerregels",
+    "form.feed.label.block_filter_entry_rules": "Blokkeerregels voor Items",
+    "form.feed.label.blocklist_rules": "Regex-gebaseerde Blokkeerfilters",
     "form.feed.label.category": "Categorie",
     "form.feed.label.cookie": "Cookies instellen",
     "form.feed.label.crawler": "Download originele inhoud",
@@ -182,7 +183,8 @@
     "form.feed.label.fetch_via_proxy": "Gebruik de proxy die op applicatieniveau is geconfigureerd",
     "form.feed.label.hide_globally": "Verberg artikelen in de globale ongelezen lijst",
     "form.feed.label.ignore_http_cache": "Negeer HTTP-cache",
-    "form.feed.label.keeplist_rules": "Bewaarregels",
+    "form.feed.label.keep_filter_entry_rules": "Toestaan Regels voor Items",
+    "form.feed.label.keeplist_rules": "Regex-gebaseerde Bewaarfilters",
     "form.feed.label.no_media_player": "Geen mediaspeler (audio/video)",
     "form.feed.label.ntfy_activate": "Artikelen naar ntfy sturen",
     "form.feed.label.ntfy_default_priority": "Ntfy standaard prioriteit",
@@ -191,7 +193,7 @@
     "form.feed.label.ntfy_max_priority": "Ntfy maximale prioriteit",
     "form.feed.label.ntfy_min_priority": "Ntfy minimale prioriteit",
     "form.feed.label.ntfy_priority": "Ntfy prioriteit",
-    "form.feed.label.ntfy_topic": "Ntfy topic (optional)",
+    "form.feed.label.ntfy_topic": "Ntfy onderwerp (optioneel)",
     "form.feed.label.proxy_url": "Proxy URL",
     "form.feed.label.pushover_activate": "Stuur artikelen naar pushover.net",
     "form.feed.label.pushover_default_priority": "Pushover standaard prioriteit",
@@ -200,7 +202,7 @@
     "form.feed.label.pushover_max_priority": "Pushover maximale prioriteit",
     "form.feed.label.pushover_min_priority": "Pushover minimale prioriteit",
     "form.feed.label.pushover_priority": "Pushover berichtprioriteit",
-    "form.feed.label.rewrite_rules": "Herschrijfregels",
+    "form.feed.label.rewrite_rules": "Inhoud Herschrijfregels",
     "form.feed.label.scraper_rules": "Extractieregels",
     "form.feed.label.site_url": "Website URL",
     "form.feed.label.title": "Titel",
@@ -430,10 +432,6 @@
     "page.api_keys.table.last_used_at": "Laatst gebruikt",
     "page.api_keys.table.token": "Token",
     "page.api_keys.title": "API-sleutels",
-    "page.categories_count": [
-        "%d categorie",
-        "%d categorieën"
-    ],
     "page.categories.entries": "Artikelen",
     "page.categories.feed_count": [
         "Er is %d feed.",
@@ -442,6 +440,10 @@
     "page.categories.feeds": "Feeds",
     "page.categories.no_feed": "Geen feed.",
     "page.categories.title": "Categorieën",
+    "page.categories_count": [
+        "%d categorie",
+        "%d categorieën"
+    ],
     "page.category_label": "Categorie: %s",
     "page.edit_category.title": "Bewerk categorie: %s",
     "page.edit_feed.etag_header": "ETAG header:",
@@ -547,25 +549,25 @@
     "page.settings.webauthn.passkeys": "Passkeys",
     "page.settings.webauthn.register": "Passkey registreren",
     "page.settings.webauthn.register.error": "Kan passkey niet registreren",
+    "page.shared_entries.title": "Gedeelde artikelen",
     "page.shared_entries_count": [
         "%d gedeeld artikel",
         "%d gedeelde artikelen"
     ],
-    "page.shared_entries.title": "Gedeelde artikelen",
+    "page.starred.title": "Favorieten",
     "page.starred_entry_count": [
         "%d favoriet artikel",
         "%d favoriete artikelen"
     ],
-    "page.starred.title": "Favorieten",
     "page.total_entry_count": [
         "%d artikel totaal",
         "%d artikelen totaal"
     ],
+    "page.unread.title": "Ongelezen",
     "page.unread_entry_count": [
         "%d ongelezen artikel",
         "%d ongelezen artikelen"
     ],
-    "page.unread.title": "Ongelezen",
     "page.users.actions": "Acties",
     "page.users.admin.no": "Nee",
     "page.users.admin.yes": "Ja",

+ 14 - 12
internal/locale/translations/pl_PL.json

@@ -172,7 +172,8 @@
     "form.feed.fieldset.rules": "Reguły",
     "form.feed.label.allow_self_signed_certificates": "Zezwalaj na samopodpisane lub nieprawidłowe certyfikaty",
     "form.feed.label.apprise_service_urls": "Rozdzielana przecinkami lista adresów URL usług Appprise",
-    "form.feed.label.blocklist_rules": "Reguły blokowania",
+    "form.feed.label.block_filter_entry_rules": "Reguły Blokowania Wpisów",
+    "form.feed.label.blocklist_rules": "Filtry Blokujące Oparte na Regex",
     "form.feed.label.category": "Kategoria",
     "form.feed.label.cookie": "Ustaw ciasteczka",
     "form.feed.label.crawler": "Pobierz oryginalną treść",
@@ -185,7 +186,8 @@
     "form.feed.label.fetch_via_proxy": "Użyj serwera proxy skonfigurowanego na poziomie aplikacji",
     "form.feed.label.hide_globally": "Ukryj wpisy na globalnej liście nieprzeczytanych",
     "form.feed.label.ignore_http_cache": "Zignoruj pamięć podręczną HTTP",
-    "form.feed.label.keeplist_rules": "Reguły utrzymywania",
+    "form.feed.label.keep_filter_entry_rules": "Reguły Zezwalania na Wpisy",
+    "form.feed.label.keeplist_rules": "Filtry Zachowywania Oparte na Regex",
     "form.feed.label.no_media_player": "Brak odtwarzacza multimedialnego (audio i wideo)",
     "form.feed.label.ntfy_activate": "Prześlij wpisy do ntfy",
     "form.feed.label.ntfy_default_priority": "Domyślny priorytet ntfy",
@@ -203,7 +205,7 @@
     "form.feed.label.pushover_max_priority": "Maksymalny priorytet Pushover",
     "form.feed.label.pushover_min_priority": "Minimalny priorytet Pushover",
     "form.feed.label.pushover_priority": "Priorytet wiadomości Pushover",
-    "form.feed.label.rewrite_rules": "Reguły zapisu",
+    "form.feed.label.rewrite_rules": "Reguły Przepisywania Treści",
     "form.feed.label.scraper_rules": "Reguły ekstrakcji",
     "form.feed.label.site_url": "Adres URL strony",
     "form.feed.label.title": "Tytuł",
@@ -308,7 +310,7 @@
     "form.integration.shiori_password": "Hasło do Shiori",
     "form.integration.shiori_username": "Login do Shiori",
     "form.integration.slack_activate": "Przesyłaj wpisy do Slack",
-    "form.integration.slack_webhook_link": "Slack Webhook link",
+    "form.integration.slack_webhook_link": "Link Webhook Slack",
     "form.integration.telegram_bot_activate": "Przesyłaj nowe wpisy do czatu Telegram",
     "form.integration.telegram_bot_disable_buttons": "Wyłącz przyciski",
     "form.integration.telegram_bot_disable_notification": "Wyłącz powiadomienie",
@@ -433,11 +435,6 @@
     "page.api_keys.table.last_used_at": "Ostatnio używane",
     "page.api_keys.table.token": "Token",
     "page.api_keys.title": "Klucze API",
-    "page.categories_count": [
-        "%d kategoria",
-        "%d kategorie",
-        "%d kategorii"
-    ],
     "page.categories.entries": "Wpisy",
     "page.categories.feed_count": [
         "Jest %d kanał.",
@@ -447,6 +444,11 @@
     "page.categories.feeds": "Kanały",
     "page.categories.no_feed": "Brak kanałów.",
     "page.categories.title": "Kategorie",
+    "page.categories_count": [
+        "%d kategoria",
+        "%d kategorie",
+        "%d kategorii"
+    ],
     "page.category_label": "Kategoria: %s",
     "page.edit_category.title": "Edytuj kategorię: %s",
     "page.edit_feed.etag_header": "Nagłówek ETag:",
@@ -555,29 +557,29 @@
     "page.settings.webauthn.passkeys": "Klucze dostępu",
     "page.settings.webauthn.register": "Zarejestruj klucz dostępu",
     "page.settings.webauthn.register.error": "Nie można zarejestrować klucza dostępu",
+    "page.shared_entries.title": "Udostępnione wpisy",
     "page.shared_entries_count": [
         "%d udostępniony wpis",
         "%d udostępnione wpisy",
         "%d udostępnionych wpisów"
     ],
-    "page.shared_entries.title": "Udostępnione wpisy",
+    "page.starred.title": "Ulubione",
     "page.starred_entry_count": [
         "%d ulubiony wpis",
         "%d ulubione wpisy",
         "%d ulubionych wpisów"
     ],
-    "page.starred.title": "Ulubione",
     "page.total_entry_count": [
         "%d wpis łącznie",
         "%d wpisy łącznie",
         "%d wpisów łącznie"
     ],
+    "page.unread.title": "Nieprzeczytane",
     "page.unread_entry_count": [
         "%d nieprzeczytany wpis",
         "%d nieprzeczytane wpisy",
         "%d nieprzeczytanych wpisów"
     ],
-    "page.unread.title": "Nieprzeczytane",
     "page.users.actions": "Działania",
     "page.users.admin.no": "Nie",
     "page.users.admin.yes": "Tak",

+ 22 - 20
internal/locale/translations/pt_BR.json

@@ -37,15 +37,15 @@
     "confirm.question": "Tem certeza?",
     "confirm.question.refresh": "Você deseja forçar a atualização?",
     "confirm.yes": "Sim",
-    "enclosure_media_controls.seek": "Seek:",
-    "enclosure_media_controls.seek.title": "Seek %s seconds",
-    "enclosure_media_controls.speed": "Speed:",
-    "enclosure_media_controls.speed.faster": "Faster",
-    "enclosure_media_controls.speed.faster.title": "Faster by %sx",
-    "enclosure_media_controls.speed.reset": "Reset",
-    "enclosure_media_controls.speed.reset.title": "Reset speed to 1x",
-    "enclosure_media_controls.speed.slower": "Slower",
-    "enclosure_media_controls.speed.slower.title": "Slower by %sx",
+    "enclosure_media_controls.seek": "Procurar:",
+    "enclosure_media_controls.seek.title": "Procurar %s segundos",
+    "enclosure_media_controls.speed": "Velocidade:",
+    "enclosure_media_controls.speed.faster": "Mais Rápido",
+    "enclosure_media_controls.speed.faster.title": "Mais rápido em %sx",
+    "enclosure_media_controls.speed.reset": "Resetar",
+    "enclosure_media_controls.speed.reset.title": "Resetar velocidade para 1x",
+    "enclosure_media_controls.speed.slower": "Mais Lento",
+    "enclosure_media_controls.speed.slower.title": "Mais lento em %sx",
     "entry.bookmark.toast.off": "Desfavoritado",
     "entry.bookmark.toast.on": "Favoritado",
     "entry.bookmark.toggle.off": "Remover dos Favoritos",
@@ -148,7 +148,7 @@
     "error.site_url_not_empty": "O URL do site não pode estar vazio.",
     "error.subscription_not_found": "Não foi possível encontrar uma inscrição.",
     "error.title_required": "O título é obrigatório.",
-    "error.tls_error": "TLS error: %q. You could disable TLS verification in the feed settings if you would like.",
+    "error.tls_error": "Erro TLS: %q. Você pode desabilitar a verificação TLS nas configurações do feed se desejar.",
     "error.unable_to_create_api_key": "Não foi possível criar uma chave de API.",
     "error.unable_to_create_category": "Não foi possível criar essa categoria.",
     "error.unable_to_create_user": "Não foi possível criar esse usuário.",
@@ -169,7 +169,8 @@
     "form.feed.fieldset.rules": "Regras",
     "form.feed.label.allow_self_signed_certificates": "Permitir certificados autoassinados ou inválidos",
     "form.feed.label.apprise_service_urls": "Lista de URLs de serviços Apprise separadas por vírgula",
-    "form.feed.label.blocklist_rules": "Regras de bloqueio",
+    "form.feed.label.block_filter_entry_rules": "Regras de Bloqueio de Entradas",
+    "form.feed.label.blocklist_rules": "Filtros de Bloqueio Baseados em Regex",
     "form.feed.label.category": "Categoria",
     "form.feed.label.cookie": "Definir Cookies",
     "form.feed.label.crawler": "Obter conteúdo original",
@@ -182,7 +183,8 @@
     "form.feed.label.fetch_via_proxy": "Usar o proxy configurado no nível da aplicação",
     "form.feed.label.hide_globally": "Ocultar entradas na lista global não lida",
     "form.feed.label.ignore_http_cache": "Ignorar cache HTTP",
-    "form.feed.label.keeplist_rules": "Regras de permissão",
+    "form.feed.label.keep_filter_entry_rules": "Regras de Permissão de Entradas",
+    "form.feed.label.keeplist_rules": "Filtros de Manutenção Baseados em Regex",
     "form.feed.label.no_media_player": "Sem reprodutor de mídia (áudio/vídeo)",
     "form.feed.label.ntfy_activate": "Enviar itens para o ntfy",
     "form.feed.label.ntfy_default_priority": "Prioridade padrão do ntfy",
@@ -200,7 +202,7 @@
     "form.feed.label.pushover_max_priority": "Prioridade máxima do Pushover",
     "form.feed.label.pushover_min_priority": "Prioridade mínima do Pushover",
     "form.feed.label.pushover_priority": "Prioridade da mensagem do Pushover",
-    "form.feed.label.rewrite_rules": "Regras para o Rewrite",
+    "form.feed.label.rewrite_rules": "Regras de Reescrita de Conteúdo",
     "form.feed.label.scraper_rules": "Regras do scraper",
     "form.feed.label.site_url": "URL do site",
     "form.feed.label.title": "Título",
@@ -430,10 +432,6 @@
     "page.api_keys.table.last_used_at": "Ultima utilização",
     "page.api_keys.table.token": "Token",
     "page.api_keys.title": "Chaves de API",
-    "page.categories_count": [
-        "%d categoria",
-        "%d categorias"
-    ],
     "page.categories.entries": "Itens",
     "page.categories.feed_count": [
         "Existe %d fonte.",
@@ -442,6 +440,10 @@
     "page.categories.feeds": "Inscrições",
     "page.categories.no_feed": "Sem fonte.",
     "page.categories.title": "Categorias",
+    "page.categories_count": [
+        "%d categoria",
+        "%d categorias"
+    ],
     "page.category_label": "Categoria: %s",
     "page.edit_category.title": "Editar categoria: %s",
     "page.edit_feed.etag_header": "Cabeçalho 'ETag':",
@@ -547,25 +549,25 @@
     "page.settings.webauthn.passkeys": "Senhas",
     "page.settings.webauthn.register": "Registrar senha",
     "page.settings.webauthn.register.error": "Não foi possível registrar a senha",
+    "page.shared_entries.title": "Itens compartilhados",
     "page.shared_entries_count": [
         "%d item compartilhado",
         "%d itens compartilhados"
     ],
-    "page.shared_entries.title": "Itens compartilhados",
+    "page.starred.title": "Favoritos",
     "page.starred_entry_count": [
         "%d item favorito",
         "%d itens favoritos"
     ],
-    "page.starred.title": "Favoritos",
     "page.total_entry_count": [
         "%d item no total",
         "%d itens no total"
     ],
+    "page.unread.title": "Não lidos",
     "page.unread_entry_count": [
         "%d item não lido",
         "%d itens não lidos"
     ],
-    "page.unread.title": "Não lidos",
     "page.users.actions": "Ações",
     "page.users.admin.no": "Não",
     "page.users.admin.yes": "Sim",

+ 15 - 13
internal/locale/translations/ro_RO.json

@@ -172,7 +172,8 @@
     "form.feed.fieldset.rules": "Reguli",
     "form.feed.label.allow_self_signed_certificates": "Permite certificatele auto-semnate sau invalide",
     "form.feed.label.apprise_service_urls": "Lista de URL-uri ale serviciilor Apprise separate prin virgule",
-    "form.feed.label.blocklist_rules": "Reguli de Blocare",
+    "form.feed.label.block_filter_entry_rules": "Reguli de Blocare a Intrărilor",
+    "form.feed.label.blocklist_rules": "Filtre de Blocare Bazate pe Regex",
     "form.feed.label.category": "Categorie",
     "form.feed.label.cookie": "Setare Cookie-uri",
     "form.feed.label.crawler": "Aduce conținutul original",
@@ -185,7 +186,8 @@
     "form.feed.label.fetch_via_proxy": "Utilizați proxy-ul configurat la nivelul aplicației",
     "form.feed.label.hide_globally": "Ascunde intrările în lista globală de articole necitite",
     "form.feed.label.ignore_http_cache": "Ignoră cache HTTP",
-    "form.feed.label.keeplist_rules": "Reguli de Păstrare",
+    "form.feed.label.keep_filter_entry_rules": "Reguli de Permitere a Intrărilor",
+    "form.feed.label.keeplist_rules": "Filtre de Păstrare Bazate pe Regex",
     "form.feed.label.no_media_player": "Nu există player media (audio/video)",
     "form.feed.label.ntfy_activate": "Împinge intrările la ntfy",
     "form.feed.label.ntfy_default_priority": "Prioritate predefinită Ntfy",
@@ -195,7 +197,7 @@
     "form.feed.label.ntfy_min_priority": "Prioritate minimă Ntfy",
     "form.feed.label.ntfy_priority": "Prioritate Ntfy",
     "form.feed.label.ntfy_topic": "Subiect Ntfy (opțional)",
-    "form.feed.label.proxy_url": "Proxy URL",
+    "form.feed.label.proxy_url": "URL Proxy",
     "form.feed.label.pushover_activate": "Activează Pushover",
     "form.feed.label.pushover_default_priority": "Prioritate implicită Pushover",
     "form.feed.label.pushover_high_priority": "Prioritate ridicată Pushover",
@@ -203,7 +205,7 @@
     "form.feed.label.pushover_max_priority": "Prioritate maximă Pushover",
     "form.feed.label.pushover_min_priority": "Prioritate minimă Pushover",
     "form.feed.label.pushover_priority": "Prioritate Pushover",
-    "form.feed.label.rewrite_rules": "Rescrie Regulile",
+    "form.feed.label.rewrite_rules": "Reguli de Rescriere a Conținutului",
     "form.feed.label.scraper_rules": "Reguli de Eliminare",
     "form.feed.label.site_url": "Adresă URL",
     "form.feed.label.title": "Titlu",
@@ -222,7 +224,7 @@
     "form.integration.cubox_api_link": "Link APi Cubox",
     "form.integration.discord_activate": "Împinge intrările pe Discord",
     "form.integration.discord_webhook_link": "Link Webhook Discord",
-    "form.integration.espial_activate": "Save entries to Espial",
+    "form.integration.espial_activate": "Salvează intrările în Espial",
     "form.integration.espial_api_key": "Cheie API Espial",
     "form.integration.espial_endpoint": "Punct acces API Espial",
     "form.integration.espial_tags": "Etichete Espial",
@@ -433,11 +435,6 @@
     "page.api_keys.table.last_used_at": "Utilizat ultima dată",
     "page.api_keys.table.token": "Token",
     "page.api_keys.title": "Chei API",
-    "page.categories_count": [
-        "%d categorie",
-        "%d categorii",
-        "%d categorie găsită"
-    ],
     "page.categories.entries": "Intrări",
     "page.categories.feed_count": [
         "Este %d flux.",
@@ -447,6 +444,11 @@
     "page.categories.feeds": "Fluxuri",
     "page.categories.no_feed": "Nici un flux.",
     "page.categories.title": "Categorii",
+    "page.categories_count": [
+        "%d categorie",
+        "%d categorii",
+        "%d categorie găsită"
+    ],
     "page.category_label": "Categorie: %s",
     "page.edit_category.title": "Editare Categorie: %s",
     "page.edit_feed.etag_header": "Antet ETag:",
@@ -555,29 +557,29 @@
     "page.settings.webauthn.passkeys": "Chei Acces",
     "page.settings.webauthn.register": "Înregistrare cheie acces",
     "page.settings.webauthn.register.error": "Eroare la înregistrarea cheii de acces",
+    "page.shared_entries.title": "Înregistrări partajate",
     "page.shared_entries_count": [
         "%d înregistrare partajată",
         "%d înregistrări partajate",
         "%d înregistrări partajate"
     ],
-    "page.shared_entries.title": "Înregistrări partajate",
+    "page.starred.title": "Marcate",
     "page.starred_entry_count": [
         "%d înregistrare marcată",
         "%d Înregistrări marcate",
         "%d Înregistrări marcate"
     ],
-    "page.starred.title": "Marcate",
     "page.total_entry_count": [
         "%d intrare în total",
         "%d intrări în total",
         "%d intrări în total"
     ],
+    "page.unread.title": "Necitite",
     "page.unread_entry_count": [
         "%d înregistrare necitită",
         "%d înregistrări necitite",
         "%d înregistrări necitite"
     ],
-    "page.unread.title": "Necitite",
     "page.users.actions": "Acțiuni",
     "page.users.admin.no": "Nu",
     "page.users.admin.yes": "Da",

+ 14 - 12
internal/locale/translations/ru_RU.json

@@ -172,7 +172,8 @@
     "form.feed.fieldset.rules": "Правила",
     "form.feed.label.allow_self_signed_certificates": "Разрешить самоподписанные или недействительные сертификаты",
     "form.feed.label.apprise_service_urls": "Список ссылок сервисов Apprise, разделенный запятой",
-    "form.feed.label.blocklist_rules": "Правила черного списка",
+    "form.feed.label.block_filter_entry_rules": "Правила блокировки записей",
+    "form.feed.label.blocklist_rules": "Фильтры блокировки на основе регулярных выражений",
     "form.feed.label.category": "Категория",
     "form.feed.label.cookie": "Установить куки",
     "form.feed.label.crawler": "Извлечь оригинальное содержимое",
@@ -185,7 +186,8 @@
     "form.feed.label.fetch_via_proxy": "Использовать прокси, настроенный на уровне приложения",
     "form.feed.label.hide_globally": "Скрыть записи в глобальном списке непрочитанных",
     "form.feed.label.ignore_http_cache": "Игнорировать HTTP кеш",
-    "form.feed.label.keeplist_rules": "Правила белого списка",
+    "form.feed.label.keep_filter_entry_rules": "Правила разрешения записей",
+    "form.feed.label.keeplist_rules": "Фильтры сохранения на основе регулярных выражений",
     "form.feed.label.no_media_player": "Отключить медиаплеер (аудио и видео)",
     "form.feed.label.ntfy_activate": "Отправлять статьи в ntfy",
     "form.feed.label.ntfy_default_priority": "По умолчанию",
@@ -203,7 +205,7 @@
     "form.feed.label.pushover_max_priority": "Высший",
     "form.feed.label.pushover_min_priority": "Минимальный",
     "form.feed.label.pushover_priority": "Приоритет сообщений Pushover",
-    "form.feed.label.rewrite_rules": "Правила перезаписи",
+    "form.feed.label.rewrite_rules": "Правила переписывания содержимого",
     "form.feed.label.scraper_rules": "Правила сборщика",
     "form.feed.label.site_url": "Адрес сайта",
     "form.feed.label.title": "Название",
@@ -433,11 +435,6 @@
     "page.api_keys.table.last_used_at": "Последнее использование",
     "page.api_keys.table.token": "Токен",
     "page.api_keys.title": "API-ключи",
-    "page.categories_count": [
-        "%d категория",
-        "%d категории",
-        "%d категорий"
-    ],
     "page.categories.entries": "Статьи",
     "page.categories.feed_count": [
         "Есть %d подписка.",
@@ -447,6 +444,11 @@
     "page.categories.feeds": "Подписки",
     "page.categories.no_feed": "Нет подписок.",
     "page.categories.title": "Категории",
+    "page.categories_count": [
+        "%d категория",
+        "%d категории",
+        "%d категорий"
+    ],
     "page.category_label": "Категории: %s",
     "page.edit_category.title": "Изменить категорию: %s",
     "page.edit_feed.etag_header": "Заголовок ETag:",
@@ -472,7 +474,7 @@
     "page.integration.bookmarklet.help": "Эта специальная ссылка позволит вам подписаться на сайт, используя обыкновенную закладку в вашем браузере.",
     "page.integration.bookmarklet.instructions": "Перетащите эту ссылку в ваши закладки.",
     "page.integration.bookmarklet.name": "Добавить в Miniflux",
-    "page.integration.miniflux_api": "Miniflux API",
+    "page.integration.miniflux_api": "API Miniflux",
     "page.integration.miniflux_api_endpoint": "Конечная точка API",
     "page.integration.miniflux_api_password": "Пароль",
     "page.integration.miniflux_api_password_value": "Пароль вашего аккаунта",
@@ -555,29 +557,29 @@
     "page.settings.webauthn.passkeys": "Ключи доступа",
     "page.settings.webauthn.register": "Зарегистрировать пароль",
     "page.settings.webauthn.register.error": "Не удается зарегистрировать пароль",
+    "page.shared_entries.title": "Общедоступные статьи",
     "page.shared_entries_count": [
         "%d общедоступная статья",
         "%d общедоступных статьи",
         "%d общедоступных статей"
     ],
-    "page.shared_entries.title": "Общедоступные статьи",
+    "page.starred.title": "Избранное",
     "page.starred_entry_count": [
         "%d избранная статья",
         "%d избранные статьи",
         "%d избранных статей"
     ],
-    "page.starred.title": "Избранное",
     "page.total_entry_count": [
         "%d статья всего",
         "%d статьи всего",
         "%d статей всего"
     ],
+    "page.unread.title": "Непрочитанное",
     "page.unread_entry_count": [
         "%d непрочитанная статья",
         "%d непрочитанных статьи",
         "%d непрочитанных статей"
     ],
-    "page.unread.title": "Непрочитанное",
     "page.users.actions": "Действия",
     "page.users.admin.no": "Нет",
     "page.users.admin.yes": "Да",

+ 13 - 11
internal/locale/translations/tr_TR.json

@@ -169,7 +169,8 @@
     "form.feed.fieldset.rules": "Kurallar",
     "form.feed.label.allow_self_signed_certificates": "Kendinden imzalı veya geçersiz sertifikalara izin ver",
     "form.feed.label.apprise_service_urls": "Apprise hizmet URL'lerinin virgülle ayrılmış listesi",
-    "form.feed.label.blocklist_rules": "Engelleme Kuralları",
+    "form.feed.label.block_filter_entry_rules": "Giriş Engelleme Kuralları",
+    "form.feed.label.blocklist_rules": "Regex Tabanlı Engelleme Filtreleri",
     "form.feed.label.category": "Kategori",
     "form.feed.label.cookie": "Çerezleri Ayarla",
     "form.feed.label.crawler": "Orijinal içeriği çek",
@@ -182,7 +183,8 @@
     "form.feed.label.fetch_via_proxy": "Uygulama düzeyinde yapılandırılmış proxy'yi kullan",
     "form.feed.label.hide_globally": "Genel okunmamış listesindeki girişleri gizle",
     "form.feed.label.ignore_http_cache": "HTTP önbelleğini yoksay",
-    "form.feed.label.keeplist_rules": "Saklama Kuralları",
+    "form.feed.label.keep_filter_entry_rules": "Giriş İzin Kuralları",
+    "form.feed.label.keeplist_rules": "Regex Tabanlı Tutma Filtreleri",
     "form.feed.label.no_media_player": "Medya oynatıcı yok (ses/video)",
     "form.feed.label.ntfy_activate": "Makaleleri ntfy'ye gönder",
     "form.feed.label.ntfy_default_priority": "Ntfy varsayılan öncelik",
@@ -200,13 +202,13 @@
     "form.feed.label.pushover_max_priority": "Pushover maksimum öncelik",
     "form.feed.label.pushover_min_priority": "Pushover minimum öncelik",
     "form.feed.label.pushover_priority": "Pushover mesaj önceliği",
-    "form.feed.label.rewrite_rules": "Yeniden Yazma Kuralları",
+    "form.feed.label.rewrite_rules": "İçerik Yeniden Yazma Kuralları",
     "form.feed.label.scraper_rules": "Scrapper Kuralları",
     "form.feed.label.site_url": "Site URL'si",
     "form.feed.label.title": "Başlık",
     "form.feed.label.urlrewrite_rules": "URL Yeniden Yazma Kuralları",
     "form.feed.label.user_agent": "Varsayılan User Agent'i Geçersiz Kıl",
-    "form.feed.label.webhook_url": "Override webhook url",
+    "form.feed.label.webhook_url": "Webhook URL'sini geçersiz kıl",
     "form.import.label.file": "OPML dosyası",
     "form.import.label.url": "URL",
     "form.integration.apprise_activate": "Makaleleri Apprise'a gönder",
@@ -430,10 +432,6 @@
     "page.api_keys.table.last_used_at": "Son Kullanılma",
     "page.api_keys.table.token": "Token",
     "page.api_keys.title": "API Anahtarları",
-    "page.categories_count": [
-        "%d kategori",
-        "%d kategori"
-    ],
     "page.categories.entries": "Makaleler",
     "page.categories.feed_count": [
         "%d besleme var.",
@@ -442,6 +440,10 @@
     "page.categories.feeds": "Beslemeler",
     "page.categories.no_feed": "Besleme yok.",
     "page.categories.title": "Kategoriler",
+    "page.categories_count": [
+        "%d kategori",
+        "%d kategori"
+    ],
     "page.category_label": "Kategori: %s",
     "page.edit_category.title": "Kategoriyi Düzenle: %s",
     "page.edit_feed.etag_header": "ETag başlığı:",
@@ -547,25 +549,25 @@
     "page.settings.webauthn.passkeys": "Passkeyler",
     "page.settings.webauthn.register": "Passkey'i kaydet",
     "page.settings.webauthn.register.error": "Passkey kaydedilemiyor",
+    "page.shared_entries.title": "Paylaşılan makaleler",
     "page.shared_entries_count": [
         "%d paylaşılan makaleler",
         "%d paylaşılan makaleler"
     ],
-    "page.shared_entries.title": "Paylaşılan makaleler",
+    "page.starred.title": "Yıldızlı",
     "page.starred_entry_count": [
         "%d yıldızlanmış makale",
         "%d yıldızlanmış makale"
     ],
-    "page.starred.title": "Yıldızlı",
     "page.total_entry_count": [
         "Toplamda %d makale",
         "Toplamda %d makale"
     ],
+    "page.unread.title": "Okunmadı",
     "page.unread_entry_count": [
         "Toplamda %d okunmamış makale",
         "Toplamda %d okunmamış makale"
     ],
-    "page.unread.title": "Okunmadı",
     "page.users.actions": "Eylemler",
     "page.users.admin.no": "Hayır",
     "page.users.admin.yes": "Evet",

+ 23 - 21
internal/locale/translations/uk_UA.json

@@ -38,15 +38,15 @@
     "confirm.question": "Ви впевнені?",
     "confirm.question.refresh": "Ви хочете змусити оновити?",
     "confirm.yes": "так",
-    "enclosure_media_controls.seek": "Seek:",
-    "enclosure_media_controls.seek.title": "Seek %s seconds",
-    "enclosure_media_controls.speed": "Speed:",
-    "enclosure_media_controls.speed.faster": "Faster",
-    "enclosure_media_controls.speed.faster.title": "Faster by %sx",
-    "enclosure_media_controls.speed.reset": "Reset",
-    "enclosure_media_controls.speed.reset.title": "Reset speed to 1x",
-    "enclosure_media_controls.speed.slower": "Slower",
-    "enclosure_media_controls.speed.slower.title": "Slower by %sx",
+    "enclosure_media_controls.seek": "Пошук:",
+    "enclosure_media_controls.seek.title": "Пошук %s секунд",
+    "enclosure_media_controls.speed": "Швидкість:",
+    "enclosure_media_controls.speed.faster": "Швидше",
+    "enclosure_media_controls.speed.faster.title": "Швидше на %sx",
+    "enclosure_media_controls.speed.reset": "Скинути",
+    "enclosure_media_controls.speed.reset.title": "Скинути швидкість до 1x",
+    "enclosure_media_controls.speed.slower": "Повільніше",
+    "enclosure_media_controls.speed.slower.title": "Повільніше на %sx",
     "entry.bookmark.toast.off": "Без зірочки",
     "entry.bookmark.toast.on": "З зірочкою",
     "entry.bookmark.toggle.off": "Прибрати зірочку",
@@ -151,7 +151,7 @@
     "error.site_url_not_empty": "URL-адреса сайту не може бути порожньою.",
     "error.subscription_not_found": "Не знайшлося жодної підписки.",
     "error.title_required": "Назва є обов’язковою.",
-    "error.tls_error": "TLS error: %q. You could disable TLS verification in the feed settings if you would like.",
+    "error.tls_error": "Помилка TLS: %q. Ви можете відключити перевірку TLS в налаштуваннях фіду, якщо хочете.",
     "error.unable_to_create_api_key": "Не вдається створити такий ключ API",
     "error.unable_to_create_category": "Не вдається сворити категорію.",
     "error.unable_to_create_user": "Не вдається створити користувача.",
@@ -172,7 +172,8 @@
     "form.feed.fieldset.rules": "Правила",
     "form.feed.label.allow_self_signed_certificates": "Дозволити сертифікати з власним підписом або недійсні",
     "form.feed.label.apprise_service_urls": "Список URL сервісів Apprise, розділених комами",
-    "form.feed.label.blocklist_rules": "Правила блокування",
+    "form.feed.label.block_filter_entry_rules": "Правила блокування записів",
+    "form.feed.label.blocklist_rules": "Фільтри блокування на основі регулярних виразів",
     "form.feed.label.category": "Категорія",
     "form.feed.label.cookie": "Встановити кукі",
     "form.feed.label.crawler": "Завантажувати оригінальний вміст",
@@ -185,7 +186,8 @@
     "form.feed.label.fetch_via_proxy": "Використовувати проксі, налаштований на рівні програми",
     "form.feed.label.hide_globally": "Приховати записи в глобальному списку непрочитаного",
     "form.feed.label.ignore_http_cache": "Ігнорувати кеш HTTP",
-    "form.feed.label.keeplist_rules": "Правила дозволення",
+    "form.feed.label.keep_filter_entry_rules": "Правила дозволу записів",
+    "form.feed.label.keeplist_rules": "Фільтри збереження на основі регулярних виразів",
     "form.feed.label.no_media_player": "Немає медіаплеєра (аудіо/відео)",
     "form.feed.label.ntfy_activate": "Надсилати записи у ntfy",
     "form.feed.label.ntfy_default_priority": "Стандартний пріоритет ntfy",
@@ -203,7 +205,7 @@
     "form.feed.label.pushover_max_priority": "Максимальний пріоритет Pushover",
     "form.feed.label.pushover_min_priority": "Мінімальний пріоритет Pushover",
     "form.feed.label.pushover_priority": "Пріоритет повідомлення Pushover",
-    "form.feed.label.rewrite_rules": "Правила Rewrite",
+    "form.feed.label.rewrite_rules": "Правила перезапису вмісту",
     "form.feed.label.scraper_rules": "Правила Scraper",
     "form.feed.label.site_url": "URL-адреса сайту",
     "form.feed.label.title": "Назва",
@@ -433,11 +435,6 @@
     "page.api_keys.table.last_used_at": "Дата останнього використання",
     "page.api_keys.table.token": "Токен",
     "page.api_keys.title": "Ключі API",
-    "page.categories_count": [
-        "%d category",
-        "%d categories",
-        "%d categories"
-    ],
     "page.categories.entries": "Статті",
     "page.categories.feed_count": [
         "Містить %d стрічку.",
@@ -447,6 +444,11 @@
     "page.categories.feeds": "Підписки",
     "page.categories.no_feed": "Немає стрічки.",
     "page.categories.title": "Категорії",
+    "page.categories_count": [
+        "%d category",
+        "%d categories",
+        "%d categories"
+    ],
     "page.category_label": "Категорія: %s",
     "page.edit_category.title": "Редагування категорії: %s",
     "page.edit_feed.etag_header": "Заголовок ETag:",
@@ -555,29 +557,29 @@
     "page.settings.webauthn.passkeys": "Passkeys",
     "page.settings.webauthn.register": "Зареєструвати пароль",
     "page.settings.webauthn.register.error": "Не вдалося зареєструвати ключ доступу",
+    "page.shared_entries.title": "Спільні записи",
     "page.shared_entries_count": [
         "%d shared entry",
         "%d shared entries",
         "%d shared entries"
     ],
-    "page.shared_entries.title": "Спільні записи",
+    "page.starred.title": "З зірочкою",
     "page.starred_entry_count": [
         "%d starred entry",
         "%d starred entries",
         "%d starred entries"
     ],
-    "page.starred.title": "З зірочкою",
     "page.total_entry_count": [
         "%d entry in total",
         "%d entries in total",
         "%d entries in total"
     ],
+    "page.unread.title": "Непрочитане",
     "page.unread_entry_count": [
         "%d unread entry",
         "%d unread entries",
         "%d unread entries"
     ],
-    "page.unread.title": "Непрочитане",
     "page.users.actions": "Дії",
     "page.users.admin.no": "Ні",
     "page.users.admin.yes": "Так",

+ 13 - 11
internal/locale/translations/zh_CN.json

@@ -166,7 +166,8 @@
     "form.feed.fieldset.rules": "规则",
     "form.feed.label.allow_self_signed_certificates": "允许自签名证书或无效证书",
     "form.feed.label.apprise_service_urls": "使用逗号分隔的 Apprise 服务 URL 列表",
-    "form.feed.label.blocklist_rules": "阻止规则",
+    "form.feed.label.block_filter_entry_rules": "条目屏蔽规则",
+    "form.feed.label.blocklist_rules": "基于正则表达式的屏蔽过滤器",
     "form.feed.label.category": "类别",
     "form.feed.label.cookie": "设置 Cookies",
     "form.feed.label.crawler": "抓取全文内容",
@@ -179,7 +180,8 @@
     "form.feed.label.fetch_via_proxy": "使用在应用程序级别配置的代理",
     "form.feed.label.hide_globally": "隐藏全局未读列表中的文章",
     "form.feed.label.ignore_http_cache": "忽略 HTTP 缓存",
-    "form.feed.label.keeplist_rules": "保留规则",
+    "form.feed.label.keep_filter_entry_rules": "条目允许规则",
+    "form.feed.label.keeplist_rules": "基于正则表达式的保留过滤器",
     "form.feed.label.no_media_player": "没有媒体播放器(音频/视频)",
     "form.feed.label.ntfy_activate": "推送条目到ntfy",
     "form.feed.label.ntfy_default_priority": "Ntfy 默认优先级",
@@ -197,7 +199,7 @@
     "form.feed.label.pushover_max_priority": "Pushover 最高优先级",
     "form.feed.label.pushover_min_priority": "Pushover 最低优先级",
     "form.feed.label.pushover_priority": "Pushover 消息优先级",
-    "form.feed.label.rewrite_rules": "重写规则",
+    "form.feed.label.rewrite_rules": "内容重写规则",
     "form.feed.label.scraper_rules": "抓取规则",
     "form.feed.label.site_url": "源网站 URL",
     "form.feed.label.title": "标题",
@@ -309,7 +311,7 @@
     "form.integration.telegram_bot_disable_web_page_preview": "禁用网页预览",
     "form.integration.telegram_bot_token": "机器人令牌",
     "form.integration.telegram_chat_id": "聊天 ID",
-    "form.integration.telegram_topic_id": "Topic ID",
+    "form.integration.telegram_topic_id": "主题ID",
     "form.integration.wallabag_activate": "保存文章到 Wallabag",
     "form.integration.wallabag_client_id": "Wallabag 客户端 ID",
     "form.integration.wallabag_client_secret": "Wallabag 客户端 密钥",
@@ -407,7 +409,7 @@
     "page.about.build_date": "构建日期:",
     "page.about.credits": "版权",
     "page.about.db_usage": "数据库容量",
-    "page.about.git_commit": "Git Commit:",
+    "page.about.git_commit": "Git提交:",
     "page.about.global_config_options": "全局配置选项",
     "page.about.go_version": "Go 版本号:",
     "page.about.license": "协议:",
@@ -427,9 +429,6 @@
     "page.api_keys.table.last_used_at": "最后使用",
     "page.api_keys.table.token": "令牌",
     "page.api_keys.title": "API 密钥",
-    "page.categories_count": [
-        "%d 分类"
-    ],
     "page.categories.entries": "查看内容",
     "page.categories.feed_count": [
         "有 %d 个源"
@@ -437,6 +436,9 @@
     "page.categories.feeds": "查看源",
     "page.categories.no_feed": "没有源",
     "page.categories.title": "分类",
+    "page.categories_count": [
+        "%d 分类"
+    ],
     "page.category_label": "分类: %s",
     "page.edit_category.title": "编辑分类 : %s",
     "page.edit_feed.etag_header": "ETag 标题:",
@@ -539,21 +541,21 @@
     "page.settings.webauthn.passkeys": "通行密钥列表",
     "page.settings.webauthn.register": "注册通行密钥",
     "page.settings.webauthn.register.error": "无法注册通行密钥",
+    "page.shared_entries.title": "已分享的文章",
     "page.shared_entries_count": [
         "%d 已分享的文章"
     ],
-    "page.shared_entries.title": "已分享的文章",
+    "page.starred.title": "收藏",
     "page.starred_entry_count": [
         "%d 收藏的文章"
     ],
-    "page.starred.title": "收藏",
     "page.total_entry_count": [
         "%d 文章总数"
     ],
+    "page.unread.title": "未读",
     "page.unread_entry_count": [
         "%d 未读的文章"
     ],
-    "page.unread.title": "未读",
     "page.users.actions": "操作",
     "page.users.admin.no": "否",
     "page.users.admin.yes": "是",

+ 15 - 13
internal/locale/translations/zh_TW.json

@@ -166,7 +166,8 @@
     "form.feed.fieldset.rules": "規則",
     "form.feed.label.allow_self_signed_certificates": "允許自簽或無效的憑證",
     "form.feed.label.apprise_service_urls": "使用逗號分隔的 Apprise 服務網址列表",
-    "form.feed.label.blocklist_rules": "過濾規則",
+    "form.feed.label.block_filter_entry_rules": "條目封鎖規則",
+    "form.feed.label.blocklist_rules": "基於正則表達式的封鎖過濾器",
     "form.feed.label.category": "類別",
     "form.feed.label.cookie": "設定 Cookies",
     "form.feed.label.crawler": "下載原文內容",
@@ -179,7 +180,8 @@
     "form.feed.label.fetch_via_proxy": "使用應用程式層級設定的代理",
     "form.feed.label.hide_globally": "在全域未讀列表中隱藏文章",
     "form.feed.label.ignore_http_cache": "忽略 HTTP 快取",
-    "form.feed.label.keeplist_rules": "保留規則",
+    "form.feed.label.keep_filter_entry_rules": "條目允許規則",
+    "form.feed.label.keeplist_rules": "基於正則表達式的保留過濾器",
     "form.feed.label.no_media_player": "無媒體播放器 (音訊/視訊)",
     "form.feed.label.ntfy_activate": "推送文章到 ntfy",
     "form.feed.label.ntfy_default_priority": "Ntfy 預設優先順序",
@@ -189,28 +191,28 @@
     "form.feed.label.ntfy_min_priority": "Ntfy 最低優先順序",
     "form.feed.label.ntfy_priority": "Ntfy 優先順序",
     "form.feed.label.ntfy_topic": "Ntfy topic (選填)",
-    "form.feed.label.proxy_url": "Proxy URL",
+    "form.feed.label.proxy_url": "代理URL",
     "form.feed.label.pushover_activate": "Push entries to pushover.net",
     "form.feed.label.pushover_default_priority": "Pushover default priority",
     "form.feed.label.pushover_high_priority": "Pushover high priority",
     "form.feed.label.pushover_low_priority": "Pushover low priority",
     "form.feed.label.pushover_max_priority": "Pushover max priority",
     "form.feed.label.pushover_min_priority": "Pushover min priority",
-    "form.feed.label.pushover_priority": "Pushover message priority",
-    "form.feed.label.rewrite_rules": "重寫規則",
+    "form.feed.label.pushover_priority": "Pushover消息優先級",
+    "form.feed.label.rewrite_rules": "內容重寫規則",
     "form.feed.label.scraper_rules": "抓取規則",
     "form.feed.label.site_url": "網站網址",
     "form.feed.label.title": "標題",
     "form.feed.label.urlrewrite_rules": "網址重寫規則",
     "form.feed.label.user_agent": "覆蓋預設的使用者代理",
-    "form.feed.label.webhook_url": "Override webhook url",
+    "form.feed.label.webhook_url": "覆蓋webhook URL",
     "form.import.label.file": "OPML 檔案",
     "form.import.label.url": "URL",
     "form.integration.apprise_activate": "推送文章到 Apprise",
     "form.integration.apprise_services_url": "使用逗號分隔的 Apprise 服務網址列表",
     "form.integration.apprise_url": "Apprise API 網址",
     "form.integration.betula_activate": "儲存文章到 Betula",
-    "form.integration.betula_token": "Betula Token",
+    "form.integration.betula_token": "Betula令牌",
     "form.integration.betula_url": "Betula 伺服器網址",
     "form.integration.cubox_activate": "儲存文章到 Cubox",
     "form.integration.cubox_api_link": "Cubox API 連結",
@@ -427,9 +429,6 @@
     "page.api_keys.table.last_used_at": "最後使用",
     "page.api_keys.table.token": "金鑰",
     "page.api_keys.title": "API 金鑰",
-    "page.categories_count": [
-        "%d 個分類"
-    ],
     "page.categories.entries": "檢視內容",
     "page.categories.feed_count": [
         "有 %d 個 Feed"
@@ -437,6 +436,9 @@
     "page.categories.feeds": "檢視 Feeds",
     "page.categories.no_feed": "沒有 Feed",
     "page.categories.title": "分類",
+    "page.categories_count": [
+        "%d 個分類"
+    ],
     "page.category_label": "分類:%s",
     "page.edit_category.title": "編輯分類 : %s",
     "page.edit_feed.etag_header": "ETag 標頭:",
@@ -539,21 +541,21 @@
     "page.settings.webauthn.passkeys": "Passkeys",
     "page.settings.webauthn.register": "註冊 Passkey",
     "page.settings.webauthn.register.error": "無法註冊 Passkey",
+    "page.shared_entries.title": "已分享的文章",
     "page.shared_entries_count": [
         "已分享 %d 篇文章"
     ],
-    "page.shared_entries.title": "已分享的文章",
+    "page.starred.title": "收藏",
     "page.starred_entry_count": [
         "%d 篇收藏文章"
     ],
-    "page.starred.title": "收藏",
     "page.total_entry_count": [
         "總共 %d 篇文章"
     ],
+    "page.unread.title": "未讀",
     "page.unread_entry_count": [
         "%d 篇未讀文章"
     ],
-    "page.unread.title": "未讀",
     "page.users.actions": "操作",
     "page.users.admin.no": "否",
     "page.users.admin.yes": "是",

+ 19 - 5
internal/model/feed.go

@@ -40,6 +40,8 @@ type Feed struct {
 	Crawler                     bool      `json:"crawler"`
 	BlocklistRules              string    `json:"blocklist_rules"`
 	KeeplistRules               string    `json:"keeplist_rules"`
+	BlockFilterEntryRules       string    `json:"block_filter_entry_rules"`
+	KeepFilterEntryRules        string    `json:"keep_filter_entry_rules"`
 	UrlRewriteRules             string    `json:"urlrewrite_rules"`
 	UserAgent                   string    `json:"user_agent"`
 	Cookie                      string    `json:"cookie"`
@@ -166,6 +168,8 @@ type FeedCreationRequest struct {
 	RewriteRules                string `json:"rewrite_rules"`
 	BlocklistRules              string `json:"blocklist_rules"`
 	KeeplistRules               string `json:"keeplist_rules"`
+	BlockFilterEntryRules       string `json:"block_filter_entry_rules"`
+	KeepFilterEntryRules        string `json:"keep_filter_entry_rules"`
 	HideGlobally                bool   `json:"hide_globally"`
 	UrlRewriteRules             string `json:"urlrewrite_rules"`
 	DisableHTTP2                bool   `json:"disable_http2"`
@@ -189,8 +193,10 @@ type FeedModificationRequest struct {
 	ScraperRules                *string `json:"scraper_rules"`
 	RewriteRules                *string `json:"rewrite_rules"`
 	BlocklistRules              *string `json:"blocklist_rules"`
-	KeeplistRules               *string `json:"keeplist_rules"`
 	UrlRewriteRules             *string `json:"urlrewrite_rules"`
+	KeeplistRules               *string `json:"keeplist_rules"`
+	BlockFilterEntryRules       *string `json:"block_filter_entry_rules"`
+	KeepFilterEntryRules        *string `json:"keep_filter_entry_rules"`
 	Crawler                     *bool   `json:"crawler"`
 	UserAgent                   *string `json:"user_agent"`
 	Cookie                      *string `json:"cookie"`
@@ -233,18 +239,26 @@ func (f *FeedModificationRequest) Patch(feed *Feed) {
 		feed.RewriteRules = *f.RewriteRules
 	}
 
-	if f.KeeplistRules != nil {
-		feed.KeeplistRules = *f.KeeplistRules
-	}
-
 	if f.UrlRewriteRules != nil {
 		feed.UrlRewriteRules = *f.UrlRewriteRules
 	}
 
+	if f.KeeplistRules != nil {
+		feed.KeeplistRules = *f.KeeplistRules
+	}
+
 	if f.BlocklistRules != nil {
 		feed.BlocklistRules = *f.BlocklistRules
 	}
 
+	if f.BlockFilterEntryRules != nil {
+		feed.BlockFilterEntryRules = *f.BlockFilterEntryRules
+	}
+
+	if f.KeepFilterEntryRules != nil {
+		feed.KeepFilterEntryRules = *f.KeepFilterEntryRules
+	}
+
 	if f.Crawler != nil {
 		feed.Crawler = *f.Crawler
 	}

+ 17 - 11
internal/reader/filter/filter.go

@@ -21,36 +21,42 @@ const (
 )
 
 func IsBlockedEntry(feed *model.Feed, entry *model.Entry, user *model.User) bool {
-	// Check user-defined block rules first
 	if user.BlockFilterEntryRules != "" {
-		if matchesUserRules(user.BlockFilterEntryRules, entry, feed, filterActionBlock) {
+		if matchesEntryFilterRules(user.BlockFilterEntryRules, entry, feed, filterActionBlock) {
+			return true
+		}
+	}
+
+	if feed.BlockFilterEntryRules != "" {
+		if matchesEntryFilterRules(feed.BlockFilterEntryRules, entry, feed, filterActionBlock) {
 			return true
 		}
 	}
 
-	// Check feed-level blocklist rules
 	if feed.BlocklistRules == "" {
 		return false
 	}
 
-	return matchesFeedRules(feed.BlocklistRules, entry, feed, filterActionBlock)
+	return matchesEntryRegexRules(feed.BlocklistRules, entry, feed, filterActionBlock)
 }
 
 func IsAllowedEntry(feed *model.Feed, entry *model.Entry, user *model.User) bool {
-	// Check user-defined keep rules first
 	if user.KeepFilterEntryRules != "" {
-		return matchesUserRules(user.KeepFilterEntryRules, entry, feed, filterActionAllow)
+		return matchesEntryFilterRules(user.KeepFilterEntryRules, entry, feed, filterActionAllow)
+	}
+
+	if feed.KeepFilterEntryRules != "" {
+		return matchesEntryFilterRules(feed.KeepFilterEntryRules, entry, feed, filterActionAllow)
 	}
 
-	// Check feed-level keeplist rules
 	if feed.KeeplistRules == "" {
 		return true
 	}
 
-	return matchesFeedRules(feed.KeeplistRules, entry, feed, filterActionAllow)
+	return matchesEntryRegexRules(feed.KeeplistRules, entry, feed, filterActionAllow)
 }
 
-func matchesUserRules(rules string, entry *model.Entry, feed *model.Feed, filterAction filterActionType) bool {
+func matchesEntryFilterRules(rules string, entry *model.Entry, feed *model.Feed, filterAction filterActionType) bool {
 	for rule := range strings.SplitSeq(rules, "\n") {
 		if matchesRule(rule, entry) {
 			logFilterAction(entry, feed, rule, filterAction)
@@ -60,10 +66,10 @@ func matchesUserRules(rules string, entry *model.Entry, feed *model.Feed, filter
 	return false
 }
 
-func matchesFeedRules(rules string, entry *model.Entry, feed *model.Feed, filterAction filterActionType) bool {
+func matchesEntryRegexRules(rules string, entry *model.Entry, feed *model.Feed, filterAction filterActionType) bool {
 	compiledRegex, err := regexp.Compile(rules)
 	if err != nil {
-		slog.Debug("Failed on regexp compilation",
+		slog.Warn("Failed on regexp compilation",
 			slog.String("pattern", rules),
 			slog.Any("error", err),
 		)

+ 2 - 0
internal/reader/filter/filter_test.go

@@ -41,6 +41,7 @@ func TestBlockingEntries(t *testing.T) {
 		{&model.Feed{ID: 1}, &model.Entry{Author: "Different", Tags: []string{"example", "test"}}, &model.User{BlockFilterEntryRules: "EntryAuthor\nEntryTag=(?i)Test"}, true},
 		{&model.Feed{ID: 1}, &model.Entry{Date: time.Date(2024, 3, 14, 0, 0, 0, 0, time.UTC)}, &model.User{BlockFilterEntryRules: "EntryDate=before:2024-03-15"}, true},
 		{&model.Feed{ID: 1}, &model.Entry{Date: time.Date(2024, 3, 14, 0, 0, 0, 0, time.UTC)}, &model.User{BlockFilterEntryRules: "UnknownRuleType=test"}, false},
+		{&model.Feed{ID: 1, BlockFilterEntryRules: "EntryURL=(?i)example\nEntryTitle=(?i)Test"}, &model.Entry{URL: "https://example.com", Title: "Some Example"}, &model.User{}, true},
 	}
 
 	for _, tc := range scenarios {
@@ -93,6 +94,7 @@ func TestAllowEntries(t *testing.T) {
 		{&model.Feed{ID: 1}, &model.Entry{Date: time.Date(2024, 2, 28, 0, 0, 0, 0, time.UTC)}, &model.User{KeepFilterEntryRules: "EntryDate=between:2024-03-15"}, false},              // missing second date in range
 		{&model.Feed{ID: 1}, &model.Entry{Date: time.Date(2024, 2, 28, 0, 0, 0, 0, time.UTC)}, &model.User{KeepFilterEntryRules: "EntryDate=abcd"}, false},                            // no colon in rule value
 		{&model.Feed{ID: 1}, &model.Entry{Date: time.Date(2024, 2, 28, 0, 0, 0, 0, time.UTC)}, &model.User{KeepFilterEntryRules: "EntryDate=unknown:2024-03-15"}, false},              // unknown rule type
+		{&model.Feed{ID: 1, KeepFilterEntryRules: "EntryURL=(?i)example\nEntryTitle=(?i)Test"}, &model.Entry{URL: "https://example.com", Title: "Some Example"}, &model.User{}, true},
 	}
 
 	for _, tc := range scenarios {

+ 5 - 1
internal/reader/handler/handler.go

@@ -61,6 +61,8 @@ func CreateFeedFromSubscriptionDiscovery(store *storage.Storage, userID int64, f
 	subscription.BlocklistRules = feedCreationRequest.BlocklistRules
 	subscription.KeeplistRules = feedCreationRequest.KeeplistRules
 	subscription.UrlRewriteRules = feedCreationRequest.UrlRewriteRules
+	subscription.BlockFilterEntryRules = feedCreationRequest.BlockFilterEntryRules
+	subscription.KeepFilterEntryRules = feedCreationRequest.KeepFilterEntryRules
 	subscription.EtagHeader = feedCreationRequest.ETag
 	subscription.LastModifiedHeader = feedCreationRequest.LastModified
 	subscription.FeedURL = feedCreationRequest.FeedURL
@@ -158,9 +160,11 @@ func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model
 	subscription.FetchViaProxy = feedCreationRequest.FetchViaProxy
 	subscription.ScraperRules = feedCreationRequest.ScraperRules
 	subscription.RewriteRules = feedCreationRequest.RewriteRules
+	subscription.UrlRewriteRules = feedCreationRequest.UrlRewriteRules
 	subscription.BlocklistRules = feedCreationRequest.BlocklistRules
 	subscription.KeeplistRules = feedCreationRequest.KeeplistRules
-	subscription.UrlRewriteRules = feedCreationRequest.UrlRewriteRules
+	subscription.BlockFilterEntryRules = feedCreationRequest.BlockFilterEntryRules
+	subscription.KeepFilterEntryRules = feedCreationRequest.KeepFilterEntryRules
 	subscription.HideGlobally = feedCreationRequest.HideGlobally
 	subscription.EtagHeader = responseHandler.ETag()
 	subscription.LastModifiedHeader = responseHandler.LastModified()

+ 33 - 25
internal/storage/feed.go

@@ -239,6 +239,8 @@ func (s *Storage) CreateFeed(feed *model.Feed) error {
 			rewrite_rules,
 			blocklist_rules,
 			keeplist_rules,
+			block_filter_entry_rules,
+			keep_filter_entry_rules,
 			ignore_http_cache,
 			allow_self_signed_certificates,
 			fetch_via_proxy,
@@ -252,7 +254,7 @@ func (s *Storage) CreateFeed(feed *model.Feed) error {
 			proxy_url
 		)
 		VALUES
-			($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)
+			($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30)
 		RETURNING
 			id
 	`
@@ -275,6 +277,8 @@ func (s *Storage) CreateFeed(feed *model.Feed) error {
 		feed.RewriteRules,
 		feed.BlocklistRules,
 		feed.KeeplistRules,
+		feed.BlockFilterEntryRules,
+		feed.KeepFilterEntryRules,
 		feed.IgnoreHTTPCache,
 		feed.AllowSelfSignedCertificates,
 		feed.FetchViaProxy,
@@ -344,31 +348,33 @@ func (s *Storage) UpdateFeed(feed *model.Feed) (err error) {
 			rewrite_rules=$11,
 			blocklist_rules=$12,
 			keeplist_rules=$13,
-			crawler=$14,
-			user_agent=$15,
-			cookie=$16,
-			username=$17,
-			password=$18,
-			disabled=$19,
-			next_check_at=$20,
-			ignore_http_cache=$21,
-			allow_self_signed_certificates=$22,
-			fetch_via_proxy=$23,
-			hide_globally=$24,
-			url_rewrite_rules=$25,
-			no_media_player=$26,
-			apprise_service_urls=$27,
-			webhook_url=$28,
-			disable_http2=$29,
-			description=$30,
-			ntfy_enabled=$31,
-			ntfy_priority=$32,
-			ntfy_topic=$33,
-			pushover_enabled=$34,
-			pushover_priority=$35,
-			proxy_url=$36
+			block_filter_entry_rules=$14,
+			keep_filter_entry_rules=$15,
+			crawler=$16,
+			user_agent=$17,
+			cookie=$18,
+			username=$19,
+			password=$20,
+			disabled=$21,
+			next_check_at=$22,
+			ignore_http_cache=$23,
+			allow_self_signed_certificates=$24,
+			fetch_via_proxy=$25,
+			hide_globally=$26,
+			url_rewrite_rules=$27,
+			no_media_player=$28,
+			apprise_service_urls=$29,
+			webhook_url=$30,
+			disable_http2=$31,
+			description=$32,
+			ntfy_enabled=$33,
+			ntfy_priority=$34,
+			ntfy_topic=$35,
+			pushover_enabled=$36,
+			pushover_priority=$37,
+			proxy_url=$38
 		WHERE
-			id=$37 AND user_id=$38
+			id=$39 AND user_id=$40
 	`
 	_, err = s.db.Exec(query,
 		feed.FeedURL,
@@ -384,6 +390,8 @@ func (s *Storage) UpdateFeed(feed *model.Feed) (err error) {
 		feed.RewriteRules,
 		feed.BlocklistRules,
 		feed.KeeplistRules,
+		feed.BlockFilterEntryRules,
+		feed.KeepFilterEntryRules,
 		feed.Crawler,
 		feed.UserAgent,
 		feed.Cookie,

+ 6 - 2
internal/storage/feed_query_builder.go

@@ -146,9 +146,11 @@ func (f *FeedQueryBuilder) GetFeeds() (model.Feeds, error) {
 			f.parsing_error_msg,
 			f.scraper_rules,
 			f.rewrite_rules,
+			f.url_rewrite_rules,
 			f.blocklist_rules,
 			f.keeplist_rules,
-			f.url_rewrite_rules,
+			f.block_filter_entry_rules,
+			f.keep_filter_entry_rules,
 			f.crawler,
 			f.user_agent,
 			f.cookie,
@@ -225,9 +227,11 @@ func (f *FeedQueryBuilder) GetFeeds() (model.Feeds, error) {
 			&feed.ParsingErrorMsg,
 			&feed.ScraperRules,
 			&feed.RewriteRules,
+			&feed.UrlRewriteRules,
 			&feed.BlocklistRules,
 			&feed.KeeplistRules,
-			&feed.UrlRewriteRules,
+			&feed.BlockFilterEntryRules,
+			&feed.KeepFilterEntryRules,
 			&feed.Crawler,
 			&feed.UserAgent,
 			&feed.Cookie,

+ 27 - 4
internal/template/templates/views/add_subscription.html

@@ -82,6 +82,18 @@
                     </a>
                 </div>
                 <input type="text" name="rewrite_rules" id="form-rewrite-rules" value="{{ .form.RewriteRules }}" spellcheck="false">
+
+                <div class="form-label-row">
+                    <label for="form-urlrewrite-rules">
+                        {{ t "form.feed.label.urlrewrite_rules" }}
+                    </label>
+                    &nbsp;
+                    <a href=" https://miniflux.app/docs/rules.html#rewriteurl-rules" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>
+                        {{ icon "external-link" }}
+                    </a>
+                </div>
+                <input type="text" name="urlrewrite_rules" id="form-urlrewrite-rules" value="{{ .form.UrlRewriteRules }}" spellcheck="false">
+
                 <div class="form-label-row">
                     <label for="form-blocklist-rules">
                         {{ t "form.feed.label.blocklist_rules" }}
@@ -105,15 +117,26 @@
                 <input type="text" name="keeplist_rules" id="form-keeplist-rules" value="{{ .form.KeeplistRules }}" spellcheck="false">
 
                 <div class="form-label-row">
-                    <label for="form-urlrewrite-rules">
-                        {{ t "form.feed.label.urlrewrite_rules" }}
+                    <label for="form-block-filter-rules">
+                        {{ t "form.feed.label.block_filter_entry_rules" }}
                     </label>
                     &nbsp;
-                    <a href=" https://miniflux.app/docs/rules.html#rewriteurl-rules" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>
+                    <a href=" https://miniflux.app/docs/rules.html#filtering-rules" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>
                         {{ icon "external-link" }}
                     </a>
                 </div>
-                <input type="text" name="urlrewrite_rules" id="form-urlrewrite-rules" value="{{ .form.UrlRewriteRules }}" spellcheck="false">
+                <textarea id="form-block-filter-rules" name="block_filter_entry_rules" cols="40" rows="10" spellcheck="false">{{ .form.BlockFilterEntryRules }}</textarea>
+
+                <div class="form-label-row">
+                    <label for="form-keep-filter-rules">
+                        {{ t "form.feed.label.keep_filter_entry_rules" }}
+                    </label>
+                    &nbsp;
+                    <a href=" https://miniflux.app/docs/rules.html#filtering-rules" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>
+                        {{ icon "external-link" }}
+                    </a>
+                </div>
+                <textarea id="form-keep-filter-rules" name="keep_filter_entry_rules" cols="40" rows="10" spellcheck="false">{{ .form.KeepFilterEntryRules }}</textarea>
             </div>
         </details>
 

+ 3 - 1
internal/template/templates/views/choose_subscription.html

@@ -17,9 +17,11 @@
     <input type="hidden" name="feed_password" value="{{ .form.Password }}">
     <input type="hidden" name="scraper_rules" value="{{ .form.ScraperRules }}">
     <input type="hidden" name="rewrite_rules" value="{{ .form.RewriteRules }}">
+    <input type="hidden" name="urlrewrite_rules" value="{{ .form.UrlRewriteRules }}">
     <input type="hidden" name="blocklist_rules" value="{{ .form.BlocklistRules }}">
     <input type="hidden" name="keeplist_rules" value="{{ .form.KeeplistRules }}">
-    <input type="hidden" name="urlrewrite_rules" value="{{ .form.UrlRewriteRules }}">
+    <input type="hidden" name="block_filter_entry_rules" value="{{ .form.BlockFilterEntryRules }}">
+    <input type="hidden" name="keep_filter_entry_rules" value="{{ .form.KeepFilterEntryRules }}">
     <input type="hidden" name="proxy_url" value="{{ .form.ProxyURL }}">
     {{ if .form.FetchViaProxy }}
     <input type="hidden" name="fetch_via_proxy" value="1">

+ 27 - 4
internal/template/templates/views/edit_feed.html

@@ -140,6 +140,18 @@
                 </a>
             </div>
             <input type="text" name="rewrite_rules" id="form-rewrite-rules" value="{{ .form.RewriteRules }}" spellcheck="false">
+
+            <div class="form-label-row">
+                <label for="form-urlrewrite-rules">
+                    {{ t "form.feed.label.urlrewrite_rules" }}
+                </label>
+                &nbsp;
+                <a href="https://miniflux.app/docs/rules.html#rewriteurl-rules" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>
+                    {{ icon "external-link" }}
+                </a>
+            </div>
+            <input type="text" name="urlrewrite_rules" id="form-urlrewrite-rules" value="{{ .form.UrlRewriteRules }}" spellcheck="false">
+
             <div class="form-label-row">
                 <label for="form-blocklist-rules">
                     {{ t "form.feed.label.blocklist_rules" }}
@@ -163,15 +175,26 @@
             <input type="text" name="keeplist_rules" id="form-keeplist-rules" value="{{ .form.KeeplistRules }}" spellcheck="false">
 
             <div class="form-label-row">
-                <label for="form-urlrewrite-rules">
-                    {{ t "form.feed.label.urlrewrite_rules" }}
+                <label for="form-block-filter-rules">
+                    {{ t "form.feed.label.block_filter_entry_rules" }}
                 </label>
                 &nbsp;
-                <a href="https://miniflux.app/docs/rules.html#rewriteurl-rules" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>
+                <a href=" https://miniflux.app/docs/rules.html#filtering-rules" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>
                     {{ icon "external-link" }}
                 </a>
             </div>
-            <input type="text" name="urlrewrite_rules" id="form-urlrewrite-rules" value="{{ .form.UrlRewriteRules }}" spellcheck="false">
+            <textarea id="form-block-filter-rules" name="block_filter_entry_rules" cols="40" rows="10" spellcheck="false">{{ .form.BlockFilterEntryRules }}</textarea>
+
+            <div class="form-label-row">
+                <label for="form-keep-filter-rules">
+                    {{ t "form.feed.label.keep_filter_entry_rules" }}
+                </label>
+                &nbsp;
+                <a href=" https://miniflux.app/docs/rules.html#filtering-rules" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>
+                    {{ icon "external-link" }}
+                </a>
+            </div>
+            <textarea id="form-keep-filter-rules" name="keep_filter_entry_rules" cols="40" rows="10" spellcheck="false">{{ .form.KeepFilterEntryRules }}</textarea>
 
             <div class="buttons">
                 <button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>

+ 9 - 8
internal/template/templates/views/settings.html

@@ -229,25 +229,26 @@
     <fieldset>
         <legend>{{ t "form.prefs.fieldset.global_feed_settings" }}</legend>
         <div class="form-label-row">
-            <label for="form-blocklist-rules">
-                {{ t "form.feed.label.blocklist_rules" }}
+            <label for="form-block-filter-rules">
+                {{ t "form.feed.label.block_filter_entry_rules" }}
             </label>
             &nbsp;
-            <a href=" https://miniflux.app/docs/rules.html#global-filtering-rules" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>
+            <a href=" https://miniflux.app/docs/rules.html#filtering-rules" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>
                 {{ icon "external-link" }}
             </a>
         </div>
-        <textarea id="form-blocklist-rules" name="block_filter_entry_rules" cols="40" rows="10" spellcheck="false">{{ .form.BlockFilterEntryRules }}</textarea>
+        <textarea id="form-block-filter-rules" name="block_filter_entry_rules" cols="40" rows="10" spellcheck="false">{{ .form.BlockFilterEntryRules }}</textarea>
 
         <div class="form-label-row">
-            <label for="form-keeplist-rules">
-                {{ t "form.feed.label.keeplist_rules" }}
+            <label for="form-keep-filter-rules">
+                {{ t "form.feed.label.keep_filter_entry_rules" }}
             </label>
-            <a href=" https://miniflux.app/docs/rules.html#global-filtering-rules" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>
+            &nbsp;
+            <a href=" https://miniflux.app/docs/rules.html#filtering-rules" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>
                 {{ icon "external-link" }}
             </a>
         </div>
-        <textarea id="form-keeplist-rules" name="keep_filter_entry_rules" cols="40" rows="10" spellcheck="false">{{ .form.KeepFilterEntryRules }}</textarea>
+        <textarea id="form-keep-filter-rules" name="keep_filter_entry_rules" cols="40" rows="10" spellcheck="false">{{ .form.KeepFilterEntryRules }}</textarea>
 
         <div class="buttons">
             <button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>

+ 3 - 1
internal/ui/feed_edit.go

@@ -46,9 +46,11 @@ func (h *handler) showEditFeedPage(w http.ResponseWriter, r *http.Request) {
 		Description:                 feed.Description,
 		ScraperRules:                feed.ScraperRules,
 		RewriteRules:                feed.RewriteRules,
+		UrlRewriteRules:             feed.UrlRewriteRules,
 		BlocklistRules:              feed.BlocklistRules,
 		KeeplistRules:               feed.KeeplistRules,
-		UrlRewriteRules:             feed.UrlRewriteRules,
+		BlockFilterEntryRules:       feed.BlockFilterEntryRules,
+		KeepFilterEntryRules:        feed.KeepFilterEntryRules,
 		Crawler:                     feed.Crawler,
 		UserAgent:                   feed.UserAgent,
 		Cookie:                      feed.Cookie,

+ 9 - 3
internal/ui/form/feed.go

@@ -18,9 +18,11 @@ type FeedForm struct {
 	Description                 string
 	ScraperRules                string
 	RewriteRules                string
+	UrlRewriteRules             string
 	BlocklistRules              string
 	KeeplistRules               string
-	UrlRewriteRules             string
+	BlockFilterEntryRules       string
+	KeepFilterEntryRules        string
 	Crawler                     bool
 	UserAgent                   string
 	Cookie                      string
@@ -54,9 +56,11 @@ func (f FeedForm) Merge(feed *model.Feed) *model.Feed {
 	feed.Description = f.Description
 	feed.ScraperRules = f.ScraperRules
 	feed.RewriteRules = f.RewriteRules
+	feed.UrlRewriteRules = f.UrlRewriteRules
 	feed.BlocklistRules = f.BlocklistRules
 	feed.KeeplistRules = f.KeeplistRules
-	feed.UrlRewriteRules = f.UrlRewriteRules
+	feed.BlockFilterEntryRules = f.BlockFilterEntryRules
+	feed.KeepFilterEntryRules = f.KeepFilterEntryRules
 	feed.Crawler = f.Crawler
 	feed.UserAgent = f.UserAgent
 	feed.Cookie = f.Cookie
@@ -108,9 +112,11 @@ func NewFeedForm(r *http.Request) *FeedForm {
 		UserAgent:                   r.FormValue("user_agent"),
 		Cookie:                      r.FormValue("cookie"),
 		RewriteRules:                r.FormValue("rewrite_rules"),
+		UrlRewriteRules:             r.FormValue("urlrewrite_rules"),
 		BlocklistRules:              r.FormValue("blocklist_rules"),
 		KeeplistRules:               r.FormValue("keeplist_rules"),
-		UrlRewriteRules:             r.FormValue("urlrewrite_rules"),
+		BlockFilterEntryRules:       r.FormValue("block_filter_entry_rules"),
+		KeepFilterEntryRules:        r.FormValue("keep_filter_entry_rules"),
 		Crawler:                     r.FormValue("crawler") == "1",
 		CategoryID:                  int64(categoryID),
 		Username:                    r.FormValue("feed_username"),

+ 6 - 2
internal/ui/form/subscription.go

@@ -24,9 +24,11 @@ type SubscriptionForm struct {
 	Password                    string
 	ScraperRules                string
 	RewriteRules                string
+	UrlRewriteRules             string
 	BlocklistRules              string
 	KeeplistRules               string
-	UrlRewriteRules             string
+	BlockFilterEntryRules       string
+	KeepFilterEntryRules        string
 	DisableHTTP2                bool
 	ProxyURL                    string
 }
@@ -79,9 +81,11 @@ func NewSubscriptionForm(r *http.Request) *SubscriptionForm {
 		Password:                    r.FormValue("feed_password"),
 		ScraperRules:                r.FormValue("scraper_rules"),
 		RewriteRules:                r.FormValue("rewrite_rules"),
+		UrlRewriteRules:             r.FormValue("urlrewrite_rules"),
 		BlocklistRules:              r.FormValue("blocklist_rules"),
 		KeeplistRules:               r.FormValue("keeplist_rules"),
-		UrlRewriteRules:             r.FormValue("urlrewrite_rules"),
+		KeepFilterEntryRules:        r.FormValue("keep_filter_entry_rules"),
+		BlockFilterEntryRules:       r.FormValue("block_filter_entry_rules"),
 		DisableHTTP2:                r.FormValue("disable_http2") == "1",
 		ProxyURL:                    r.FormValue("proxy_url"),
 	}

+ 3 - 1
internal/ui/subscription_choose.go

@@ -58,9 +58,11 @@ func (h *handler) showChooseSubscriptionPage(w http.ResponseWriter, r *http.Requ
 		Password:                    subscriptionForm.Password,
 		ScraperRules:                subscriptionForm.ScraperRules,
 		RewriteRules:                subscriptionForm.RewriteRules,
+		UrlRewriteRules:             subscriptionForm.UrlRewriteRules,
 		BlocklistRules:              subscriptionForm.BlocklistRules,
 		KeeplistRules:               subscriptionForm.KeeplistRules,
-		UrlRewriteRules:             subscriptionForm.UrlRewriteRules,
+		KeepFilterEntryRules:        subscriptionForm.KeepFilterEntryRules,
+		BlockFilterEntryRules:       subscriptionForm.BlockFilterEntryRules,
 		FetchViaProxy:               subscriptionForm.FetchViaProxy,
 		DisableHTTP2:                subscriptionForm.DisableHTTP2,
 		ProxyURL:                    subscriptionForm.ProxyURL,

+ 6 - 2
internal/ui/subscription_submit.go

@@ -106,9 +106,11 @@ func (h *handler) submitSubscription(w http.ResponseWriter, r *http.Request) {
 				Password:                    subscriptionForm.Password,
 				ScraperRules:                subscriptionForm.ScraperRules,
 				RewriteRules:                subscriptionForm.RewriteRules,
+				UrlRewriteRules:             subscriptionForm.UrlRewriteRules,
 				BlocklistRules:              subscriptionForm.BlocklistRules,
 				KeeplistRules:               subscriptionForm.KeeplistRules,
-				UrlRewriteRules:             subscriptionForm.UrlRewriteRules,
+				KeepFilterEntryRules:        subscriptionForm.KeepFilterEntryRules,
+				BlockFilterEntryRules:       subscriptionForm.BlockFilterEntryRules,
 				FetchViaProxy:               subscriptionForm.FetchViaProxy,
 				DisableHTTP2:                subscriptionForm.DisableHTTP2,
 				ProxyURL:                    subscriptionForm.ProxyURL,
@@ -134,9 +136,11 @@ func (h *handler) submitSubscription(w http.ResponseWriter, r *http.Request) {
 			Password:                    subscriptionForm.Password,
 			ScraperRules:                subscriptionForm.ScraperRules,
 			RewriteRules:                subscriptionForm.RewriteRules,
+			UrlRewriteRules:             subscriptionForm.UrlRewriteRules,
 			BlocklistRules:              subscriptionForm.BlocklistRules,
 			KeeplistRules:               subscriptionForm.KeeplistRules,
-			UrlRewriteRules:             subscriptionForm.UrlRewriteRules,
+			KeepFilterEntryRules:        subscriptionForm.KeepFilterEntryRules,
+			BlockFilterEntryRules:       subscriptionForm.BlockFilterEntryRules,
 			FetchViaProxy:               subscriptionForm.FetchViaProxy,
 			DisableHTTP2:                subscriptionForm.DisableHTTP2,
 			ProxyURL:                    subscriptionForm.ProxyURL,