1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-06-27 16:36:00 +00:00

feat: implement proxy URL per feed

This commit is contained in:
Frédéric Guillot 2025-04-06 18:04:50 -07:00
parent 7b344de846
commit ef22e95f8b
48 changed files with 333 additions and 192 deletions

View file

@ -151,6 +151,7 @@ type Feed struct {
Category *Category `json:"category,omitempty"`
HideGlobally bool `json:"hide_globally"`
DisableHTTP2 bool `json:"disable_http2"`
ProxyURL string `json:"proxy_url"`
}
// FeedCreationRequest represents the request to create a feed.
@ -172,6 +173,7 @@ type FeedCreationRequest struct {
KeeplistRules string `json:"keeplist_rules"`
HideGlobally bool `json:"hide_globally"`
DisableHTTP2 bool `json:"disable_http2"`
ProxyURL string `json:"proxy_url"`
}
// FeedModificationRequest represents the request to update a feed.
@ -195,6 +197,7 @@ type FeedModificationRequest struct {
FetchViaProxy *bool `json:"fetch_via_proxy"`
HideGlobally *bool `json:"hide_globally"`
DisableHTTP2 *bool `json:"disable_http2"`
ProxyURL *string `json:"proxy_url"`
}
// FeedIcon represents the feed icon.

View file

@ -38,6 +38,7 @@ func (h *handler) discoverSubscriptions(w http.ResponseWriter, r *http.Request)
requestBuilder := fetcher.NewRequestBuilder()
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomFeedProxyURL(subscriptionDiscoveryRequest.ProxyURL)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
requestBuilder.UseCustomApplicationProxyURL(subscriptionDiscoveryRequest.FetchViaProxy)
requestBuilder.WithUserAgent(subscriptionDiscoveryRequest.UserAgent, config.Opts.HTTPClientUserAgent())

View file

@ -1062,4 +1062,8 @@ var migrations = []func(tx *sql.Tx, driver string) error{
return nil
},
func(tx *sql.Tx, _ string) (err error) {
_, err = tx.Exec(`ALTER TABLE feeds ADD COLUMN proxy_url text default ''`)
return err
},
}

View file

@ -684,7 +684,6 @@ func (h *handler) quickAddHandler(w http.ResponseWriter, r *http.Request) {
requestBuilder := fetcher.NewRequestBuilder()
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
var rssBridgeURL string

View file

@ -72,10 +72,10 @@
"entry.state.loading": "Lade...",
"entry.state.saving": "Speichern...",
"entry.status.mark_as_read": "Als gelesen markieren",
"entry.status.mark_as_unread": "Als ungelesen markieren",
"entry.status.title": "Status des Artikels ändern",
"entry.status.toast.read": "Als gelesen markiert",
"entry.status.toast.unread": "Als ungelesen markiert",
"entry.status.mark_as_unread": "Als ungelesen markieren",
"entry.tags.label": "Stichworte:",
"entry.unshare.label": "Nicht teilen",
"error.api_key_already_exists": "Dieser API-Schlüssel ist bereits vorhanden.",
@ -117,6 +117,7 @@
"error.invalid_default_home_page": "Ungültige Standard-Startseite!",
"error.invalid_display_mode": "Progressive-Web-App- (PWA-)Anzeigemodus",
"error.invalid_entry_direction": "Ungültige Sortierreihenfolge.",
"error.invalid_feed_proxy_url": "Ungültige Proxy-URL.",
"error.invalid_feed_url": "Ungültiger Feed-URL.",
"error.invalid_gesture_nav": "Ungültige Gestennavigation.",
"error.invalid_language": "Ungültige Sprache.",
@ -128,6 +129,7 @@
"error.password_min_length": "Wenigstens 6 Zeichen müssen genutzt werden.",
"error.pocket_access_token": "Zugriffstoken konnte nicht von Pocket abgerufen werden!",
"error.pocket_request_token": "Anfrage-Token konnte nicht von Pocket abgerufen werden!",
"error.proxy_url_not_empty": "Die Proxy-URL darf nicht leer sein.",
"error.settings_block_rule_fieldname_invalid": "Ungültige Blockierregel: Regel #%d hat keinen gültigen Feldnamen (Optionen: %s)",
"error.settings_block_rule_invalid_regex": "Ungültige Blockierregel: Das Muster für Regel #%d ist kein zulässiger regulärer Ausdruck",
"error.settings_block_rule_regex_required": "Ungültige Blockierregel: Regel #%d hat kein Muster",
@ -174,7 +176,7 @@
"form.feed.label.feed_password": "Passwort des Abonnements",
"form.feed.label.feed_url": "URL des Abonnements",
"form.feed.label.feed_username": "Benutzername des Abonnements",
"form.feed.label.fetch_via_proxy": "Über Proxy abrufen",
"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",
@ -187,6 +189,7 @@
"form.feed.label.ntfy_min_priority": "Niedrigste Ntfy-Priorität",
"form.feed.label.ntfy_priority": "Ntfy-Priorität",
"form.feed.label.ntfy_topic": "Ntfy-Thema (optional)",
"form.feed.label.proxy_url": "Proxy-URL",
"form.feed.label.pushover_activate": "Einträge an pushover.net senden",
"form.feed.label.pushover_default_priority": "Pushover-Standardpriorität",
"form.feed.label.pushover_high_priority": "Hohe Pushoverpriorität",
@ -421,6 +424,10 @@
"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.",
@ -429,10 +436,6 @@
"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:",
@ -538,25 +541,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.starred.title": "Lesezeichen",
"page.shared_entries.title": "Geteilte Artikel",
"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",

View file

@ -72,10 +72,10 @@
"entry.state.loading": "Φόρτωση...",
"entry.state.saving": "Aποθήκευση...",
"entry.status.mark_as_read": "Επισήμανση ως αναγνωσμένο",
"entry.status.mark_as_unread": "Επισήμανση ως μη αναγνωσμένο",
"entry.status.title": "Αλλαγή κατάστασης καταχώρησης",
"entry.status.toast.read": "Επισήμανση ως αναγνωσμένο",
"entry.status.toast.unread": "Επισήμανση ως μη αναγνωσμένο",
"entry.status.mark_as_unread": "Επισήμανση ως μη αναγνωσμένο",
"entry.tags.label": "Ετικέτες:",
"entry.unshare.label": "Aναίρεση Διαμοιρασμού",
"error.api_key_already_exists": "Αυτό το κλειδί API υπάρχει ήδη.",
@ -117,6 +117,7 @@
"error.invalid_default_home_page": "Μη έγκυρη προεπιλεγμένη αρχική σελίδα!",
"error.invalid_display_mode": "Μη έγκυρη λειτουργία εμφάνισης εφαρμογών ιστού.",
"error.invalid_entry_direction": "Μη έγκυρη κατεύθυνση ταξινόμησης άρθρων.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "Μη έγκυρη διεύθυνση URL ροής.",
"error.invalid_gesture_nav": "Μη έγκυρη πλοήγηση με χειρονομίες.",
"error.invalid_language": "Μη έγκυρη γλώσσα.",
@ -128,6 +129,7 @@
"error.password_min_length": "Ο κωδικός πρόσβασης πρέπει να έχει τουλάχιστον 6 χαρακτήρες.",
"error.pocket_access_token": "Δεν είναι δυνατή η λήψη του access token από το Pocket!",
"error.pocket_request_token": "Δεν είναι δυνατή η λήψη του request token από το Pocket!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Invalid Block rule: rule #%d is missing a valid field name (Options: %s)",
"error.settings_block_rule_invalid_regex": "Invalid Block rule: rule #%d's pattern is not a valid regex",
"error.settings_block_rule_regex_required": "Invalid Block rule: rule #%d's pattern is not provided",
@ -174,7 +176,7 @@
"form.feed.label.feed_password": "Κωδικός Πρόσβασης ροής",
"form.feed.label.feed_url": "Διεύθυνση URL ροής",
"form.feed.label.feed_username": "Όνομα Χρήστη ροής",
"form.feed.label.fetch_via_proxy": "Λήψη μέσω διακομιστή μεσολάβησης",
"form.feed.label.fetch_via_proxy": "Χρησιμοποιήστε τον διακομιστή μεσολάβησης που έχει ρυθμιστεί σε επίπεδο εφαρμογής",
"form.feed.label.hide_globally": "Απόκρυψη καταχωρήσεων σε γενική λίστα μη αναγνωσμένων",
"form.feed.label.ignore_http_cache": "Αγνοήστε την προσωρινή μνήμη HTTP",
"form.feed.label.keeplist_rules": "Κρατήστε Κανόνες",
@ -187,6 +189,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.feed.label.ntfy_priority": "Ntfy priority",
"form.feed.label.ntfy_topic": "Ntfy topic (optional)",
"form.feed.label.proxy_url": "Proxy 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",
@ -421,6 +424,10 @@
"page.api_keys.table.last_used_at": "Τελευταία Χρήση",
"page.api_keys.table.token": "Token",
"page.api_keys.title": "Κλειδιά API",
"page.categories_count": [
"%d category",
"%d categories"
],
"page.categories.entries": "Άρθρα",
"page.categories.feed_count": [
"Υπάρχει μία %d ροή.",
@ -429,10 +436,6 @@
"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": "Κεφαλίδα ETag:",
@ -538,25 +541,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.starred.title": "Αγαπημένo",
"page.shared_entries.title": "Κοινόχρηστες Καταχωρήσεις",
"page.starred_entry_count": [
"%d starred entry",
"%d starred entries"
],
"page.starred.title": "Αγαπημένo",
"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": "Eνέργειες",
"page.users.admin.no": "Όχι",
"page.users.admin.yes": "Ναι.",

View file

@ -72,10 +72,10 @@
"entry.state.loading": "Loading…",
"entry.state.saving": "Saving…",
"entry.status.mark_as_read": "Mark as read",
"entry.status.mark_as_unread": "Mark as unread",
"entry.status.title": "Change entry status",
"entry.status.toast.read": "Marked as read",
"entry.status.toast.unread": "Marked as unread",
"entry.status.mark_as_unread": "Mark as unread",
"entry.tags.label": "Tags:",
"entry.unshare.label": "Unshare",
"error.api_key_already_exists": "This API Key already exists.",
@ -117,6 +117,7 @@
"error.invalid_default_home_page": "Invalid default homepage!",
"error.invalid_display_mode": "Invalid web app display mode.",
"error.invalid_entry_direction": "Invalid entry direction.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "Invalid feed URL.",
"error.invalid_gesture_nav": "Invalid gesture navigation.",
"error.invalid_language": "Invalid language.",
@ -128,6 +129,7 @@
"error.password_min_length": "The password must have at least 6 characters.",
"error.pocket_access_token": "Unable to fetch access token from Pocket!",
"error.pocket_request_token": "Unable to fetch request token from Pocket!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Invalid Block rule: rule #%d is missing a valid field name (Options: %s)",
"error.settings_block_rule_invalid_regex": "Invalid Block rule: rule #%d's pattern is not a valid regex",
"error.settings_block_rule_regex_required": "Invalid Block rule: rule #%d's pattern is not provided",
@ -174,7 +176,7 @@
"form.feed.label.feed_password": "Feed Password",
"form.feed.label.feed_url": "Feed URL",
"form.feed.label.feed_username": "Feed Username",
"form.feed.label.fetch_via_proxy": "Fetch via proxy",
"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",
@ -187,6 +189,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.feed.label.ntfy_priority": "Ntfy priority",
"form.feed.label.ntfy_topic": "Ntfy topic (optional)",
"form.feed.label.proxy_url": "Proxy URL",
"form.feed.label.pushover_activate": "Push entries to Pushover",
"form.feed.label.pushover_default_priority": "Default priority",
"form.feed.label.pushover_high_priority": "High priority",

View file

@ -72,10 +72,10 @@
"entry.state.loading": "Cargando...",
"entry.state.saving": "Guardando...",
"entry.status.mark_as_read": "Marcar como leído",
"entry.status.mark_as_unread": "Marcar como no leído",
"entry.status.title": "Cambiar estado del artículo",
"entry.status.toast.read": "Marcado como leído",
"entry.status.toast.unread": "Marcado como no leído",
"entry.status.mark_as_unread": "Marcar como no leído",
"entry.tags.label": "Etiquetas:",
"entry.unshare.label": "No compartir",
"error.api_key_already_exists": "Esta clave API ya existe.",
@ -117,6 +117,7 @@
"error.invalid_default_home_page": "¡Página de inicio por defecto no válida!",
"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_feed_proxy_url": "Invalid proxy URL.",
"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.",
@ -128,6 +129,7 @@
"error.password_min_length": "La contraseña debería tener al menos 6 caracteres.",
"error.pocket_access_token": "Incapaz de obtener un token de acceso de Pocket!",
"error.pocket_request_token": "Incapaz de obtener un token de solicitud de Pocket!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"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",
@ -174,7 +176,7 @@
"form.feed.label.feed_password": "Contraseña de la fuente",
"form.feed.label.feed_url": "URL de la fuente",
"form.feed.label.feed_username": "Nombre de usuario de la fuente",
"form.feed.label.fetch_via_proxy": "Buscar a través de proxy",
"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)",
@ -187,6 +189,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.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",
@ -421,6 +424,10 @@
"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.",
@ -429,10 +436,6 @@
"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:",
@ -538,25 +541,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.starred.title": "Marcadores",
"page.shared_entries.title": "Artículos compartidos",
"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í",

View file

@ -72,10 +72,10 @@
"entry.state.loading": "Ladataan...",
"entry.state.saving": "Tallennetaan...",
"entry.status.mark_as_read": "Merkitse luetuksi",
"entry.status.mark_as_unread": "Merkitse lukemattomaksi",
"entry.status.title": "Vaihda artikkelin tilaa",
"entry.status.toast.read": "Merkitty luetuksi",
"entry.status.toast.unread": "Merkitty lukemattomaksi",
"entry.status.mark_as_unread": "Merkitse lukemattomaksi",
"entry.tags.label": "Tags:",
"entry.unshare.label": "Poista jako",
"error.api_key_already_exists": "API-avain on jo olemassa.",
@ -117,6 +117,7 @@
"error.invalid_default_home_page": "Väärä oletusarvoinen kotisivu!",
"error.invalid_display_mode": "Virheellinen verkkosovelluksen näyttötila.",
"error.invalid_entry_direction": "Invalid entry direction.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "Virheellinen syötteen URL-osoite.",
"error.invalid_gesture_nav": "Virheellinen ele-navigointi.",
"error.invalid_language": "Virheellinen kieli.",
@ -128,6 +129,7 @@
"error.password_min_length": "Salasanassa on oltava vähintään 6 merkkiä.",
"error.pocket_access_token": "Unable to fetch access token from Pocket!",
"error.pocket_request_token": "Unable to fetch request token from Pocket!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Invalid Block rule: rule #%d is missing a valid field name (Options: %s)",
"error.settings_block_rule_invalid_regex": "Invalid Block rule: rule #%d's pattern is not a valid regex",
"error.settings_block_rule_regex_required": "Invalid Block rule: rule #%d's pattern is not provided",
@ -174,7 +176,7 @@
"form.feed.label.feed_password": "Syötteen salasana",
"form.feed.label.feed_url": "Syötteen URL-osoite",
"form.feed.label.feed_username": "Syötteen käyttäjätunnus",
"form.feed.label.fetch_via_proxy": "Nouda välityspalvelimen kautta",
"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",
@ -187,6 +189,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.feed.label.ntfy_priority": "Ntfy priority",
"form.feed.label.ntfy_topic": "Ntfy topic (optional)",
"form.feed.label.proxy_url": "Proxy 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",
@ -421,6 +424,10 @@
"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.",
@ -429,10 +436,6 @@
"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:",
@ -538,25 +541,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.starred.title": "Suosikit",
"page.shared_entries.title": "Jaetut artikkelit",
"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ä",

View file

@ -72,10 +72,10 @@
"entry.state.loading": "Chargement...",
"entry.state.saving": "Sauvegarde en cours...",
"entry.status.mark_as_read": "Marquer comme lu",
"entry.status.mark_as_unread": "Marquer comme non lu",
"entry.status.title": "Changer le statut de l'entrée",
"entry.status.toast.read": "Marqué comme lu",
"entry.status.toast.unread": "Marqué comme non lu",
"entry.status.mark_as_unread": "Marquer comme non lu",
"entry.tags.label": "Libellés :",
"entry.unshare.label": "Enlever le partage",
"error.api_key_already_exists": "Cette clé d'API existe déjà.",
@ -117,6 +117,7 @@
"error.invalid_default_home_page": "Page d'accueil par défaut invalide !",
"error.invalid_display_mode": "Mode d'affichage de l'application web non valide.",
"error.invalid_entry_direction": "Ordre de trie non valide.",
"error.invalid_feed_proxy_url": "L'URL du proxy n'est pas valide.",
"error.invalid_feed_url": "URL de flux non valide.",
"error.invalid_gesture_nav": "Navigation gestuelle non valide.",
"error.invalid_language": "Langue non valide.",
@ -128,6 +129,7 @@
"error.password_min_length": "Vous devez utiliser au moins 6 caractères pour le mot de passe.",
"error.pocket_access_token": "Impossible de récupérer le jeton d'accès depuis Pocket !",
"error.pocket_request_token": "Impossible de récupérer le jeton d'accès depuis Pocket !",
"error.proxy_url_not_empty": "L'URL du proxy ne peut pas être vide.",
"error.settings_block_rule_fieldname_invalid": "Règle de blocage invalide : la règle n°%d ne contient pas un nom de champ valide (Options : %s)",
"error.settings_block_rule_invalid_regex": "Règle de blocage invalide : le motif de la règle n°%d n'est pas une expression régulière valide",
"error.settings_block_rule_regex_required": "Règle de blocage invalide : le motif de la règle n°%d n'est pas fourni",
@ -174,7 +176,7 @@
"form.feed.label.feed_password": "Mot de passe du flux",
"form.feed.label.feed_url": "URL du flux",
"form.feed.label.feed_username": "Nom d'utilisateur du flux",
"form.feed.label.fetch_via_proxy": "Récupérer via proxy",
"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",
@ -187,6 +189,7 @@
"form.feed.label.ntfy_min_priority": "Priorité minimale de notification",
"form.feed.label.ntfy_priority": "Priorité de notification",
"form.feed.label.ntfy_topic": "Sujet Ntfy (facultatif)",
"form.feed.label.proxy_url": "URL du proxy",
"form.feed.label.pushover_activate": "Activer les notifications vers Pushover",
"form.feed.label.pushover_default_priority": "Priorité par défaut",
"form.feed.label.pushover_high_priority": "Priorité élevée",
@ -421,6 +424,10 @@
"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.",
@ -429,10 +436,6 @@
"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 :",
@ -538,25 +541,25 @@
"page.settings.webauthn.passkeys": "Clés daccès",
"page.settings.webauthn.register": "Enregister une nouvelle clé daccès",
"page.settings.webauthn.register.error": "Impossible d'enregistrer la clé daccès",
"page.shared_entries.title": "Articles partagés",
"page.shared_entries_count": [
"%d article partagé",
"%d articles partagés"
],
"page.starred.title": "Favoris",
"page.shared_entries.title": "Articles partagés",
"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",

View file

@ -72,10 +72,10 @@
"entry.state.loading": "लोड हो रहा है...",
"entry.state.saving": "सहेजा जा रहा है...",
"entry.status.mark_as_read": "पढ़े हुए का चिह्न",
"entry.status.mark_as_unread": "अपठित के रूप में चिह्नित करें",
"entry.status.title": "प्रविष्टि स्थिति बदलें",
"entry.status.toast.read": "पढ़ा हुआ चिह्नित करे",
"entry.status.toast.unread": "अपठित के रूप में चिह्नित",
"entry.status.mark_as_unread": "अपठित के रूप में चिह्नित करें",
"entry.tags.label": "टैग:",
"entry.unshare.label": "न साझा कारें",
"error.api_key_already_exists": "यह एपीआई कुंजी पहले से मौजूद है।",
@ -117,6 +117,7 @@
"error.invalid_default_home_page": "अमान्य डिफ़ॉल्ट मुखपृष्ठ!",
"error.invalid_display_mode": "अमान्य वेब ऐप्लिकेशन प्रदर्शन मोड.",
"error.invalid_entry_direction": "अमान्य प्रवेश दिशा।",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "दृष्टिकोण यूआरएल.",
"error.invalid_gesture_nav": "अमान्य इशारा नेविगेशन।",
"error.invalid_language": "अमान्य भाषा.",
@ -128,6 +129,7 @@
"error.password_min_length": "पासवर्ड में कम से कम 6 अक्षर होने चाहिए।",
"error.pocket_access_token": "पॉकेट से एक्सेस टोकन प्राप्त करने में असमर्थ!",
"error.pocket_request_token": "पॉकेट से अनुरोध टोकन लाने में असमर्थ!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Invalid Block rule: rule #%d is missing a valid field name (Options: %s)",
"error.settings_block_rule_invalid_regex": "Invalid Block rule: rule #%d's pattern is not a valid regex",
"error.settings_block_rule_regex_required": "Invalid Block rule: rule #%d's pattern is not provided",
@ -174,7 +176,7 @@
"form.feed.label.feed_password": "फ़ीड पासवर्ड",
"form.feed.label.feed_url": "फ़ीड यूआरएल",
"form.feed.label.feed_username": "फ़ीड उपयोगकर्ता नाम",
"form.feed.label.fetch_via_proxy": "प्रॉक्सी के माध्यम से प्राप्त करें",
"form.feed.label.fetch_via_proxy": "एप्लिकेशन स्तर पर कॉन्फ़िगर किए गए प्रॉक्सी का उपयोग करें",
"form.feed.label.hide_globally": "वैश्विक अपठित सूची में प्रविष्टियां छिपाएं",
"form.feed.label.ignore_http_cache": "एचटीटीपी कैश पर ध्यान न दें",
"form.feed.label.keeplist_rules": "नियम बनाए रखें",
@ -187,6 +189,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.feed.label.ntfy_priority": "Ntfy priority",
"form.feed.label.ntfy_topic": "Ntfy topic (optional)",
"form.feed.label.proxy_url": "Proxy 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",
@ -421,6 +424,10 @@
"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 फ़ीड बाकी है।",
@ -429,10 +436,6 @@
"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": "ईटाग हैडर:",
@ -538,25 +541,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.starred.title": "तारांकित",
"page.shared_entries.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": "हां",

View file

@ -70,10 +70,10 @@
"entry.state.loading": "Memuat...",
"entry.state.saving": "Menyimpan...",
"entry.status.mark_as_read": "Telah dibaca",
"entry.status.mark_as_unread": "Belum dibaca",
"entry.status.title": "Ubah status entri",
"entry.status.toast.read": "Ditandai sebagai telah dibaca",
"entry.status.toast.unread": "Ditandai sebagai belum dibaca",
"entry.status.mark_as_unread": "Belum dibaca",
"entry.tags.label": "Tanda:",
"entry.unshare.label": "Batal bagikan",
"error.api_key_already_exists": "Kunci API ini sudah ada.",
@ -115,6 +115,7 @@
"error.invalid_default_home_page": "Beranda baku tidak valid!",
"error.invalid_display_mode": "Mode tampilan aplikasi web tidak valid.",
"error.invalid_entry_direction": "Urutan entri tidak valid.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "URL umpan tidak valid.",
"error.invalid_gesture_nav": "Navigasi gestur tidak valid.",
"error.invalid_language": "Bahasa tidak valid.",
@ -126,6 +127,7 @@
"error.password_min_length": "Kata sandi harus memiliki setidaknya 6 karakter.",
"error.pocket_access_token": "Tidak bisa mendapatkan token akses dari Pocket!",
"error.pocket_request_token": "Tidak bisa mendapatkan token permintaan dari Pocket!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Invalid Block rule: rule #%d is missing a valid field name (Options: %s)",
"error.settings_block_rule_invalid_regex": "Invalid Block rule: rule #%d's pattern is not a valid regex",
"error.settings_block_rule_regex_required": "Invalid Block rule: rule #%d's pattern is not provided",
@ -172,7 +174,7 @@
"form.feed.label.feed_password": "Kata Sandi Umpan",
"form.feed.label.feed_url": "URL Umpan",
"form.feed.label.feed_username": "Nama Pengguna Umpan",
"form.feed.label.fetch_via_proxy": "Ambil via Proksi",
"form.feed.label.fetch_via_proxy": "Gunakan proxy 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",
@ -185,6 +187,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.feed.label.ntfy_priority": "Ntfy priority",
"form.feed.label.ntfy_topic": "Ntfy topic (optional)",
"form.feed.label.proxy_url": "Proxy 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",
@ -419,6 +422,9 @@
"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 category"
],
"page.categories.entries": "Artikel",
"page.categories.feed_count": [
"Ada %d umpan."
@ -426,9 +432,6 @@
"page.categories.feeds": "Langganan",
"page.categories.no_feed": "Tidak ada umpan.",
"page.categories.title": "Kategori",
"page.categories_count": [
"%d category"
],
"page.category_label": "Category: %s",
"page.edit_category.title": "Sunting Kategori: %s",
"page.edit_feed.etag_header": "Tajuk ETag:",
@ -531,21 +534,21 @@
"page.settings.webauthn.passkeys": "Passkeys",
"page.settings.webauthn.register": "Register passkey",
"page.settings.webauthn.register.error": "Unable to register passkey",
"page.shared_entries.title": "Entri yang Dibagikan",
"page.shared_entries_count": [
"%d shared entry"
],
"page.starred.title": "Markah",
"page.shared_entries.title": "Entri yang Dibagikan",
"page.starred_entry_count": [
"%d starred entry"
],
"page.starred.title": "Markah",
"page.total_entry_count": [
"%d entry in total"
],
"page.unread.title": "Belum Dibaca",
"page.unread_entry_count": [
"%d unread entry"
],
"page.unread.title": "Belum Dibaca",
"page.users.actions": "Tindakan",
"page.users.admin.no": "Tidak",
"page.users.admin.yes": "Ya",

View file

@ -72,10 +72,10 @@
"entry.state.loading": "Caricamento in corso...",
"entry.state.saving": "Salvataggio in corso...",
"entry.status.mark_as_read": "Segna come letto",
"entry.status.mark_as_unread": "Segna come non letto",
"entry.status.title": "Cambia lo stato dell'articolo",
"entry.status.toast.read": "Contrassegnato come letto",
"entry.status.toast.unread": "Contrassegnato come non letto",
"entry.status.mark_as_unread": "Segna come non letto",
"entry.tags.label": "Tag:",
"entry.unshare.label": "Unshare",
"error.api_key_already_exists": "Questa chiave API esiste già.",
@ -117,6 +117,7 @@
"error.invalid_default_home_page": "Pagina iniziale predefinita non valida!",
"error.invalid_display_mode": "Modalità di visualizzazione web app non valida.",
"error.invalid_entry_direction": "Ordinamento non valido.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "URL del feed non valido.",
"error.invalid_gesture_nav": "Navigazione gestuale non valida.",
"error.invalid_language": "Lingua non valida.",
@ -128,6 +129,7 @@
"error.password_min_length": "La password deve contenere almeno 6 caratteri.",
"error.pocket_access_token": "Non sono riuscito ad ottenere l'access token da Pocket!",
"error.pocket_request_token": "Non sono riuscito ad ottenere il request token da Pocket!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Invalid Block rule: rule #%d is missing a valid field name (Options: %s)",
"error.settings_block_rule_invalid_regex": "Invalid Block rule: rule #%d's pattern is not a valid regex",
"error.settings_block_rule_regex_required": "Invalid Block rule: rule #%d's pattern is not provided",
@ -174,7 +176,7 @@
"form.feed.label.feed_password": "Password del feed",
"form.feed.label.feed_url": "URL del feed",
"form.feed.label.feed_username": "Nome utente del feed",
"form.feed.label.fetch_via_proxy": "Recuperare tramite proxy",
"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",
@ -187,6 +189,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.feed.label.ntfy_priority": "Ntfy priority",
"form.feed.label.ntfy_topic": "Ntfy topic (optional)",
"form.feed.label.proxy_url": "Proxy 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",
@ -421,6 +424,10 @@
"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.",
@ -429,10 +436,6 @@
"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:",
@ -538,25 +541,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.starred.title": "Preferiti",
"page.shared_entries.title": "Voci condivise",
"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ì",

View file

@ -70,10 +70,10 @@
"entry.state.loading": "読み込み中…",
"entry.state.saving": "保存中…",
"entry.status.mark_as_read": "既読にする",
"entry.status.mark_as_unread": "未読に戻す",
"entry.status.title": "記事の状態を変更",
"entry.status.toast.read": "既読にしました",
"entry.status.toast.unread": "未読にしました",
"entry.status.mark_as_unread": "未読に戻す",
"entry.tags.label": "タグ:",
"entry.unshare.label": "共有を解除",
"error.api_key_already_exists": "この API キーは既に存在します。",
@ -115,6 +115,7 @@
"error.invalid_default_home_page": "デフォルトのトップページが無効です",
"error.invalid_display_mode": "Web アプリの表示モードが無効です。",
"error.invalid_entry_direction": "記事の表示順が無効です。",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "フィード URL が無効です。",
"error.invalid_gesture_nav": "ジェスチャー ナビゲーションが無効です。",
"error.invalid_language": "言語が無効です。",
@ -126,6 +127,7 @@
"error.password_min_length": "パスワードは6文字以上である必要があります。",
"error.pocket_access_token": "Pocket の access token が取得できません!",
"error.pocket_request_token": "Pocket の request token が取得できません!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Invalid Block rule: rule #%d is missing a valid field name (Options: %s)",
"error.settings_block_rule_invalid_regex": "Invalid Block rule: rule #%d's pattern is not a valid regex",
"error.settings_block_rule_regex_required": "Invalid Block rule: rule #%d's pattern is not provided",
@ -172,7 +174,7 @@
"form.feed.label.feed_password": "フィードのパスワード",
"form.feed.label.feed_url": "フィード URL",
"form.feed.label.feed_username": "フィードのユーザー名",
"form.feed.label.fetch_via_proxy": "プロキシ経由で取得",
"form.feed.label.fetch_via_proxy": "アプリケーションレベルで設定されたプロキシを使用する",
"form.feed.label.hide_globally": "未読一覧に記事を表示しない",
"form.feed.label.ignore_http_cache": "HTTPキャッシュを無視",
"form.feed.label.keeplist_rules": "Keep ルール",
@ -185,6 +187,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.feed.label.ntfy_priority": "Ntfy priority",
"form.feed.label.ntfy_topic": "Ntfy topic (optional)",
"form.feed.label.proxy_url": "Proxy 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",
@ -419,6 +422,9 @@
"page.api_keys.table.last_used_at": "最終使用",
"page.api_keys.table.token": "トークン",
"page.api_keys.title": "API キー",
"page.categories_count": [
"%d category"
],
"page.categories.entries": "記事一覧",
"page.categories.feed_count": [
"%d 件のフィードがあります。"
@ -426,9 +432,6 @@
"page.categories.feeds": "フィード一覧",
"page.categories.no_feed": "フィードはありません。",
"page.categories.title": "カテゴリ",
"page.categories_count": [
"%d category"
],
"page.category_label": "Category: %s",
"page.edit_category.title": "カテゴリを編集: %s",
"page.edit_feed.etag_header": "ETag ヘッダー:",
@ -531,21 +534,21 @@
"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"
],
"page.starred.title": "星付き",
"page.shared_entries.title": "共有エントリ",
"page.starred_entry_count": [
"%d starred entry"
],
"page.starred.title": "星付き",
"page.total_entry_count": [
"%d entry in total"
],
"page.unread.title": "未読",
"page.unread_entry_count": [
"%d unread entry"
],
"page.unread.title": "未読",
"page.users.actions": "アクション",
"page.users.admin.no": "非管理者",
"page.users.admin.yes": "管理者",

View file

@ -70,10 +70,10 @@
"entry.state.loading": "Tng leh chip-hêng…",
"entry.state.saving": "Tng leh pó-chûn…",
"entry.status.mark_as_read": "Chù chòe tha̍k kè",
"entry.status.mark_as_unread": "Chù chòe ah-bōe tha̍k",
"entry.status.title": "Kái chōng-thài",
"entry.status.toast.read": "Chù chòe tha̍k kè chòe soah",
"entry.status.toast.unread": "Chù chòe ah-bōe tha̍k chòe soah",
"entry.status.mark_as_unread": "Chù chòe ah-bōe tha̍k",
"entry.tags.label": "Khan-á:",
"entry.unshare.label": "Chhú-siau hun-hióng",
"error.api_key_already_exists": "Chit ê API só-sî í-keng chûn-chāi",
@ -115,6 +115,7 @@
"error.invalid_default_home_page": "Ū-siat chú-ia̍h ū būn-tôe!",
"error.invalid_display_mode": "Ū būn-tôe ê su-li̍p bô͘-sek.",
"error.invalid_entry_direction": "Ū būn-tôe ê su-li̍p hong-hiòng.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "Beh tēng ê siau-sit lâi-goân ê bāng-chí ū būn-tôe.",
"error.invalid_gesture_nav": "Chhiú-sè tō-lám ū būn-tôe.",
"error.invalid_language": "Ū būn-tôe ê gú-giân.",
@ -126,6 +127,7 @@
"error.password_min_length": "Chhiáⁿ chì-chió ài su-li̍p la̍k ê lī goân.",
"error.pocket_access_token": "Bô-hoat-tō͘ ùi Pocket thê tio̍h access token",
"error.pocket_request_token": "Bô-hoat-tō͘ ùi Pocket thê tio̍h request token",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Bô-hāu ê hong-só kui-chek: kui-chek #%d khiàm ū-hāu ê lân-ūi miâ (e-sai ê soán-hāng: %s)",
"error.settings_block_rule_invalid_regex": "Bô-hāu ê hong-só kui-chek: kui-chek #%d ê bô͘-sek m̄ sī ha̍p-hoat ê chiàⁿ-kui piáu-ta̍t sek",
"error.settings_block_rule_regex_required": "Bô-hāu ê hong-só kui-chek: kui-chek #%d bô thê-kiong chiàⁿ-kui piáu-ta̍t sek",
@ -172,7 +174,7 @@
"form.feed.label.feed_password": "Siau-sit lâi-goân bi̍t-bé",
"form.feed.label.feed_url": "Siau-sit lâi-goân bāng-chí",
"form.feed.label.feed_username": "Siau-sit lâi-goân kháu-chō miâ",
"form.feed.label.fetch_via_proxy": "Thàu-kè tāi-lí lia̍h",
"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",
@ -185,6 +187,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy siōng kē iu-sian sūn-sū",
"form.feed.label.ntfy_priority": "Ntfy iu-sian sūn-sū",
"form.feed.label.ntfy_topic": "Ntfy topic (soán thiⁿ)",
"form.feed.label.proxy_url": "Proxy URL",
"form.feed.label.pushover_activate": "Push entries to Pushover",
"form.feed.label.pushover_default_priority": "Default priority",
"form.feed.label.pushover_high_priority": "High priority",
@ -419,6 +422,9 @@
"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"
@ -426,9 +432,6 @@
"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:",
@ -531,21 +534,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.starred.title": "Siu-chông",
"page.shared_entries.title": "Hun-hióng kè ê siau-sit",
"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ī",

View file

@ -72,10 +72,10 @@
"entry.state.loading": "Laden...",
"entry.state.saving": "Opslaan...",
"entry.status.mark_as_read": "Markeren als gelezen",
"entry.status.mark_as_unread": "Markeren als ongelezen",
"entry.status.title": "Verander artikelstatus",
"entry.status.toast.read": "Gemarkeerd als gelezen",
"entry.status.toast.unread": "Gemarkeerd als ongelezen",
"entry.status.mark_as_unread": "Markeren als ongelezen",
"entry.tags.label": "Tags:",
"entry.unshare.label": "Delen ongedaan maken",
"error.api_key_already_exists": "Deze API-sleutel bestaat al.",
@ -117,6 +117,7 @@
"error.invalid_default_home_page": "Ongeldige startpagina!",
"error.invalid_display_mode": "Ongeldige weergavemodus voor de webapp.",
"error.invalid_entry_direction": "Ongeldige sorteervolgorde.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "Ongeldige feed URL.",
"error.invalid_gesture_nav": "Ongeldige gebarennavigatie.",
"error.invalid_language": "Ongeldige taal.",
@ -128,6 +129,7 @@
"error.password_min_length": "Minimaal 6 tekens gebruiken.",
"error.pocket_access_token": "Kon geen toegangstoken ophalen van Pocket!",
"error.pocket_request_token": "Kon geen aanvraagtoken ophalen van Pocket!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Ongeldige blokkeerregel: regel #%d mist een geldige veldnaam (Opties: %s)",
"error.settings_block_rule_invalid_regex": "Ongeldige blokkeerregel: het patroon van regel #%d is geen geldige regex",
"error.settings_block_rule_regex_required": "Ongeldige blokkeerregel: het patroon van regel #%d is niet opgegeven",
@ -174,7 +176,7 @@
"form.feed.label.feed_password": "Feed wachtwoord",
"form.feed.label.feed_url": "Feed URL",
"form.feed.label.feed_username": "Feed gebruikersnaam",
"form.feed.label.fetch_via_proxy": "Ophalen via proxy",
"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",
@ -187,6 +189,7 @@
"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.proxy_url": "Proxy 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",
@ -421,6 +424,10 @@
"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.",
@ -429,10 +436,6 @@
"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:",
@ -538,25 +541,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.starred.title": "Favorieten",
"page.shared_entries.title": "Gedeelde artikelen",
"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",

View file

@ -74,10 +74,10 @@
"entry.state.loading": "Ładowanie…",
"entry.state.saving": "Zapisywanie…",
"entry.status.mark_as_read": "Oznacz jako przeczytany",
"entry.status.mark_as_unread": "Oznacz jako nieprzeczytany",
"entry.status.title": "Zmień status wpisu",
"entry.status.toast.read": "Oznaczono jako przeczytany",
"entry.status.toast.unread": "Oznaczono jako nieprzeczytany",
"entry.status.mark_as_unread": "Oznacz jako nieprzeczytany",
"entry.tags.label": "Znaczniki:",
"entry.unshare.label": "Cofnij udostępnianie",
"error.api_key_already_exists": "Ten klucz API już istnieje.",
@ -119,6 +119,7 @@
"error.invalid_default_home_page": "Nieprawidłowa domyślna strona główna!",
"error.invalid_display_mode": "Nieprawidłowy tryb wyświetlania aplikacji sieciowej.",
"error.invalid_entry_direction": "Nieprawidłowa kolejność sortowania.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "Nieprawidłowy adres URL kanału.",
"error.invalid_gesture_nav": "Nieprawidłowa nawigacja gestami.",
"error.invalid_language": "Nieprawidłowy język.",
@ -130,6 +131,7 @@
"error.password_min_length": "Musisz użyć co najmniej 6 znaków.",
"error.pocket_access_token": "Nie można pobrać tokena dostępu z Pocket!",
"error.pocket_request_token": "Nie można pobrać tokena żądania z Pocket!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Nieprawidłowa reguła blokowania: w regule #%d brakuje prawidłowej nazwy pola (opcje: %s)",
"error.settings_block_rule_invalid_regex": "Nieprawidłowa reguła blokowania: wzór reguły #%d nie jest prawidłowym wyrażeniem regularnym",
"error.settings_block_rule_regex_required": "Nieprawidłowa reguła blokowania: nie podano wzorca reguły #%d",
@ -176,7 +178,7 @@
"form.feed.label.feed_password": "Hasło do subskrypcji",
"form.feed.label.feed_url": "Adres URL kanału",
"form.feed.label.feed_username": "Nazwa użytkownika subskrypcji",
"form.feed.label.fetch_via_proxy": "Pobierz przez proxy",
"form.feed.label.fetch_via_proxy": "Użyj 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",
@ -189,6 +191,7 @@
"form.feed.label.ntfy_min_priority": "Minimalny priorytet ntfy",
"form.feed.label.ntfy_priority": "Priorytet ntfy",
"form.feed.label.ntfy_topic": "Temat ntfy (opcjonalny)",
"form.feed.label.proxy_url": "Proxy URL",
"form.feed.label.pushover_activate": "Prześlij wpisy do pushover.net",
"form.feed.label.pushover_default_priority": "Domyślny priorytet Pushover",
"form.feed.label.pushover_high_priority": "Wysoki priorytet Pushover",
@ -423,6 +426,11 @@
"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ł.",
@ -432,11 +440,6 @@
"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:",
@ -545,29 +548,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.starred.title": "Ulubione",
"page.shared_entries.title": "Udostępnione wpisy",
"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",

View file

@ -72,10 +72,10 @@
"entry.state.loading": "Carregando...",
"entry.state.saving": "Salvando...",
"entry.status.mark_as_read": "Marcar como lido",
"entry.status.mark_as_unread": "Marcar como não lido",
"entry.status.title": "Modificar estado deste item",
"entry.status.toast.read": "Marcado como lido",
"entry.status.toast.unread": "Marcado como não lido",
"entry.status.mark_as_unread": "Marcar como não lido",
"entry.tags.label": "Etiquetas:",
"entry.unshare.label": "Descompartilhar",
"error.api_key_already_exists": "Essa chave de API já existe.",
@ -117,6 +117,7 @@
"error.invalid_default_home_page": "Página inicial por defeito inválida!",
"error.invalid_display_mode": "Modo de exibição de aplicativo inválido da web.",
"error.invalid_entry_direction": "Direção de entrada inválida.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "URL de feed inválido.",
"error.invalid_gesture_nav": "Navegação por gestos inválida.",
"error.invalid_language": "Idioma inválido.",
@ -128,6 +129,7 @@
"error.password_min_length": "A senha deve ter no mínimo 6 caracteres.",
"error.pocket_access_token": "Não foi possível obter um token de acesso no Pocket!",
"error.pocket_request_token": "Não foi possível obter um pedido de token no Pocket!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Invalid Block rule: rule #%d is missing a valid field name (Options: %s)",
"error.settings_block_rule_invalid_regex": "Invalid Block rule: rule #%d's pattern is not a valid regex",
"error.settings_block_rule_regex_required": "Invalid Block rule: rule #%d's pattern is not provided",
@ -174,7 +176,7 @@
"form.feed.label.feed_password": "Senha da fonte",
"form.feed.label.feed_url": "URL da fonte",
"form.feed.label.feed_username": "Nome de usuário da fonte",
"form.feed.label.fetch_via_proxy": "Buscar via proxy",
"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",
@ -187,6 +189,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.feed.label.ntfy_priority": "Ntfy priority",
"form.feed.label.ntfy_topic": "Ntfy topic (optional)",
"form.feed.label.proxy_url": "Proxy 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",
@ -421,6 +424,10 @@
"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 category",
"%d categories"
],
"page.categories.entries": "Itens",
"page.categories.feed_count": [
"Existe %d fonte.",
@ -429,10 +436,6 @@
"page.categories.feeds": "Inscrições",
"page.categories.no_feed": "Sem fonte.",
"page.categories.title": "Categorias",
"page.categories_count": [
"%d category",
"%d categories"
],
"page.category_label": "Category: %s",
"page.edit_category.title": "Editar categoria: %s",
"page.edit_feed.etag_header": "Cabeçalho 'ETag':",
@ -538,25 +541,25 @@
"page.settings.webauthn.passkeys": "Passkeys",
"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 shared entry",
"%d shared entries"
],
"page.starred.title": "Favoritos",
"page.shared_entries.title": "Itens compartilhados",
"page.starred_entry_count": [
"%d starred entry",
"%d starred entries"
],
"page.starred.title": "Favoritos",
"page.total_entry_count": [
"%d entry in total",
"%d entries in total"
],
"page.unread.title": "Não lidos",
"page.unread_entry_count": [
"%d unread entry",
"%d unread entries"
],
"page.unread.title": "Não lidos",
"page.users.actions": "Ações",
"page.users.admin.no": "Não",
"page.users.admin.yes": "Sim",

View file

@ -74,10 +74,10 @@
"entry.state.loading": "Încarc…",
"entry.state.saving": "Salvez…",
"entry.status.mark_as_read": "Marcați ca citit",
"entry.status.mark_as_unread": "Marcați ca necitit",
"entry.status.title": "Modifică starea intrării",
"entry.status.toast.read": "Marcat ca citit",
"entry.status.toast.unread": "Marcat ca necitit",
"entry.status.mark_as_unread": "Marcați ca necitit",
"entry.tags.label": "Etichete:",
"entry.unshare.label": "Elimină partajarea",
"error.api_key_already_exists": "Această cheie API există deja.",
@ -119,6 +119,7 @@
"error.invalid_default_home_page": "Pagină de start invalidă!",
"error.invalid_display_mode": "Mod invalid de afișare în aplicația web.",
"error.invalid_entry_direction": "Direcție invalidă ăn intrare.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "Adresa URL a fluxului este invalidă.",
"error.invalid_gesture_nav": "Gest de navigare invalid.",
"error.invalid_language": "Limbă invalidă.",
@ -130,6 +131,7 @@
"error.password_min_length": "Parola trebuie să aibă cel puțin 6 caractere.",
"error.pocket_access_token": "Nu poate obține token-ul de acces de la Pocket!",
"error.pocket_request_token": "Nu poate obține token-ul solicitat de la Pocket!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Regulă de bloc invalidă: regulii #%d îi lipsește un nume valid de câmp (Opțiuni: %s)",
"error.settings_block_rule_invalid_regex": "Regulă de bloc invalidă: modelul regulii #%d's nu este regex valid",
"error.settings_block_rule_regex_required": "Regulă de bloc invalidă: modelul regulii #%d's nu este furnizat",
@ -176,7 +178,7 @@
"form.feed.label.feed_password": "Parolă Flux",
"form.feed.label.feed_url": "Flux URL",
"form.feed.label.feed_username": "Nume user Flux",
"form.feed.label.fetch_via_proxy": "Actualizare prin proxy",
"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",
@ -189,6 +191,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.pushover_activate": "Activează Pushover",
"form.feed.label.pushover_default_priority": "Prioritate implicită Pushover",
"form.feed.label.pushover_high_priority": "Prioritate ridicată Pushover",

View file

@ -74,10 +74,10 @@
"entry.state.loading": "Загрузка…",
"entry.state.saving": "Сохранение…",
"entry.status.mark_as_read": "Отметить как прочитанное",
"entry.status.mark_as_unread": "Пометить как непрочитанное",
"entry.status.title": "Изменить статус записи",
"entry.status.toast.read": "Помечено как прочитанное",
"entry.status.toast.unread": "Помечено как непрочитанное",
"entry.status.mark_as_unread": "Пометить как непрочитанное",
"entry.tags.label": "Теги:",
"entry.unshare.label": "Удалить из общедоступных",
"error.api_key_already_exists": "Этот API-ключ уже существует.",
@ -119,6 +119,7 @@
"error.invalid_default_home_page": "Недопустимая домашняя страница по умолчанию!",
"error.invalid_display_mode": "Недопустимый режим отображения веб-приложения.",
"error.invalid_entry_direction": "Недопустимая сортировка записей.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "Недействительная ссылка подписки.",
"error.invalid_gesture_nav": "Недопустимая навигация жестами.",
"error.invalid_language": "Недопустимый язык.",
@ -130,6 +131,7 @@
"error.password_min_length": "Вы должны использовать минимум 6 символов.",
"error.pocket_access_token": "Не удалось получить ключ доступа от Pocket!",
"error.pocket_request_token": "Не удалось получить request token от Pocket!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Invalid Block rule: rule #%d is missing a valid field name (Options: %s)",
"error.settings_block_rule_invalid_regex": "Invalid Block rule: rule #%d's pattern is not a valid regex",
"error.settings_block_rule_regex_required": "Invalid Block rule: rule #%d's pattern is not provided",
@ -176,7 +178,7 @@
"form.feed.label.feed_password": "Пароль подписки",
"form.feed.label.feed_url": "Адрес подписки",
"form.feed.label.feed_username": "Имя пользователя подписки",
"form.feed.label.fetch_via_proxy": "Использовать прокси",
"form.feed.label.fetch_via_proxy": "Использовать прокси, настроенный на уровне приложения",
"form.feed.label.hide_globally": "Скрыть записи в глобальном списке непрочитанных",
"form.feed.label.ignore_http_cache": "Игнорировать HTTP кеш",
"form.feed.label.keeplist_rules": "Правила белого списка",
@ -189,6 +191,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.feed.label.ntfy_priority": "Ntfy priority",
"form.feed.label.ntfy_topic": "Ntfy topic (optional)",
"form.feed.label.proxy_url": "Proxy 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",
@ -423,6 +426,11 @@
"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": "Cтатьи",
"page.categories.feed_count": [
"Есть %d подписка.",
@ -432,11 +440,6 @@
"page.categories.feeds": "Подписки",
"page.categories.no_feed": "Нет подписок.",
"page.categories.title": "Категории",
"page.categories_count": [
"%d category",
"%d categories",
"%d categories"
],
"page.category_label": "Category: %s",
"page.edit_category.title": "Изменить категорию: %s",
"page.edit_feed.etag_header": "Заголовок ETag:",
@ -545,29 +548,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.starred.title": "Избранное",
"page.shared_entries.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": "Да",

View file

@ -72,10 +72,10 @@
"entry.state.loading": "Yükleniyor...",
"entry.state.saving": "Kaydediliyor...",
"entry.status.mark_as_read": "Okundu olarak işaretle",
"entry.status.mark_as_unread": "Okunmadı olarak işaretle",
"entry.status.title": "Makele okundu durumunu değiştir",
"entry.status.toast.read": "Okundu olarak işaretlendi",
"entry.status.toast.unread": "Okunmamış olarak işaretlendi",
"entry.status.mark_as_unread": "Okunmadı olarak işaretle",
"entry.tags.label": "Etiketler:",
"entry.unshare.label": "Paylaşma",
"error.api_key_already_exists": "Bu API anahtarı zaten mevcut.",
@ -117,6 +117,7 @@
"error.invalid_default_home_page": "Geçersiz varsayılan ana sayfa!",
"error.invalid_display_mode": "Geçersiz web uygulaması görüntüleme modu.",
"error.invalid_entry_direction": "Geçersiz makele sıralaması.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "Geçersiz besleme URL'si.",
"error.invalid_gesture_nav": "Hareketle gezinme geçersiz.",
"error.invalid_language": "Geçersiz dil.",
@ -128,6 +129,7 @@
"error.password_min_length": "Parola en az 6 karakter içermeli.",
"error.pocket_access_token": "Pocket'tan access tokeni alınamıyor!",
"error.pocket_request_token": "Pocket'tan request tokeni alınamıyor!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Geçersiz Engelleme kuralı: #%d kuralında geçerli bir alan adı eksik (Seçenekler: %s)",
"error.settings_block_rule_invalid_regex": "Geçersiz Engelleme kuralı: #%d kuralı modeli geçerli bir düzenli ifade değil",
"error.settings_block_rule_regex_required": "Geçersiz Engelleme kuralı: #%d kuralı modeli sağlanmadı",
@ -174,7 +176,7 @@
"form.feed.label.feed_password": "Besleme Parolası",
"form.feed.label.feed_url": "Besleme URL'si",
"form.feed.label.feed_username": "Besleme Kullanıcı Adı",
"form.feed.label.fetch_via_proxy": "Proxy ile çek",
"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ı",
@ -187,6 +189,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.feed.label.ntfy_priority": "Ntfy priority",
"form.feed.label.ntfy_topic": "Ntfy topic (optional)",
"form.feed.label.proxy_url": "Proxy 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",
@ -421,6 +424,10 @@
"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.",
@ -429,10 +436,6 @@
"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ığı:",
@ -538,25 +541,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.starred.title": "Yıldızlı",
"page.shared_entries.title": "Paylaşılan makaleler",
"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",

View file

@ -74,10 +74,10 @@
"entry.state.loading": "Завантаження...",
"entry.state.saving": "Зберігаю...",
"entry.status.mark_as_read": "Позначити як прочитане",
"entry.status.mark_as_unread": "Позначити як непрочитане",
"entry.status.title": "Змінити стан запису",
"entry.status.toast.read": "Відмічено прочитаним",
"entry.status.toast.unread": "Відмічено непрочитаним",
"entry.status.mark_as_unread": "Позначити як непрочитане",
"entry.tags.label": "Теги:",
"entry.unshare.label": "Не ділитися",
"error.api_key_already_exists": "Такий ключ API вже існує.",
@ -119,6 +119,7 @@
"error.invalid_default_home_page": "Недійсна домашня сторінка за замовчуванням!",
"error.invalid_display_mode": "Недійсний режим відображення.",
"error.invalid_entry_direction": "Недійсний напрямок запису.",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "Недійсна URL-адреса стрічки.",
"error.invalid_gesture_nav": "Недійсна навігація жестами.",
"error.invalid_language": "Недійсна мова.",
@ -130,6 +131,7 @@
"error.password_min_length": "Пароль має складати щонайменше 6 символів.",
"error.pocket_access_token": "Не вдалося отримати токен доступу з Pocket!",
"error.pocket_request_token": "Не вдалося отримати токен доступу з Pocket!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "Invalid Block rule: rule #%d is missing a valid field name (Options: %s)",
"error.settings_block_rule_invalid_regex": "Invalid Block rule: rule #%d's pattern is not a valid regex",
"error.settings_block_rule_regex_required": "Invalid Block rule: rule #%d's pattern is not provided",
@ -176,7 +178,7 @@
"form.feed.label.feed_password": "Пароль для завантаження",
"form.feed.label.feed_url": "URL-адреса стрічки",
"form.feed.label.feed_username": "Ім’я користувача для завантаження",
"form.feed.label.fetch_via_proxy": "Використати проксі-сервер",
"form.feed.label.fetch_via_proxy": "Використовувати проксі, налаштований на рівні програми",
"form.feed.label.hide_globally": "Приховати записи в глобальному списку непрочитаного",
"form.feed.label.ignore_http_cache": "Ігнорувати кеш HTTP",
"form.feed.label.keeplist_rules": "Правила дозволення",
@ -189,6 +191,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.feed.label.ntfy_priority": "Ntfy priority",
"form.feed.label.ntfy_topic": "Ntfy topic (optional)",
"form.feed.label.proxy_url": "Proxy 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",
@ -423,6 +426,11 @@
"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 стрічку.",
@ -432,11 +440,6 @@
"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:",
@ -545,29 +548,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.starred.title": "З зірочкою",
"page.shared_entries.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": "Так",

View file

@ -70,10 +70,10 @@
"entry.state.loading": "载入中…",
"entry.state.saving": "保存中…",
"entry.status.mark_as_read": "标为已读",
"entry.status.mark_as_unread": "标为未读",
"entry.status.title": "更改状态",
"entry.status.toast.read": "已标为已读",
"entry.status.toast.unread": "已标为未读",
"entry.status.mark_as_unread": "标为未读",
"entry.tags.label": "标签:",
"entry.unshare.label": "取消分享",
"error.api_key_already_exists": "此 API 密钥已存在。",
@ -115,6 +115,7 @@
"error.invalid_default_home_page": "无效的默认主页!",
"error.invalid_display_mode": "无效的网页应用显示模式。",
"error.invalid_entry_direction": "无效的输入方向。",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "订阅源的网址无效。",
"error.invalid_gesture_nav": "手势导航无效。",
"error.invalid_language": "无效的语言。",
@ -126,6 +127,7 @@
"error.password_min_length": "请至少输入 6 个字符",
"error.pocket_access_token": "无法从 Pocket 获取访问令牌!",
"error.pocket_request_token": "无法从 Pocket 获取请求令牌!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "无效的阻止规则: 规则 #%d 缺少合法的字段名 (可选: %s)",
"error.settings_block_rule_invalid_regex": "无效的阻止规则: 规则 #%d 的模式字符不是合法的正则表达式。",
"error.settings_block_rule_regex_required": "无效的阻止规则: 规则 #%d 的模式字符没有提供。",
@ -172,7 +174,7 @@
"form.feed.label.feed_password": "源密码",
"form.feed.label.feed_url": "订阅源 URL",
"form.feed.label.feed_username": "源用户名",
"form.feed.label.fetch_via_proxy": "通过代理获取",
"form.feed.label.fetch_via_proxy": "使用在应用程序级别配置的代理",
"form.feed.label.hide_globally": "隐藏全局未读列表中的文章",
"form.feed.label.ignore_http_cache": "忽略 HTTP 缓存",
"form.feed.label.keeplist_rules": "保留规则",
@ -185,6 +187,7 @@
"form.feed.label.ntfy_min_priority": "Ntfy 最低优先级",
"form.feed.label.ntfy_priority": "Ntfy 优先级",
"form.feed.label.ntfy_topic": "Ntfy 主题(可选)",
"form.feed.label.proxy_url": "Proxy URL",
"form.feed.label.pushover_activate": "将条目推送至 pushover.net",
"form.feed.label.pushover_default_priority": "Pushover 默认优先级",
"form.feed.label.pushover_high_priority": "Pushover 高优先级",

View file

@ -70,10 +70,10 @@
"entry.state.loading": "載入中…",
"entry.state.saving": "儲存中…",
"entry.status.mark_as_read": "標記為已讀",
"entry.status.mark_as_unread": "標記為未讀",
"entry.status.title": "更改狀態",
"entry.status.toast.read": "已標記為已讀",
"entry.status.toast.unread": "已標記為未讀",
"entry.status.mark_as_unread": "標記為未讀",
"entry.tags.label": "標籤:",
"entry.unshare.label": "取消分享",
"error.api_key_already_exists": "此 API 金鑰已存在。",
@ -115,6 +115,7 @@
"error.invalid_default_home_page": "預設主頁無效!",
"error.invalid_display_mode": "無效的顯示模式。",
"error.invalid_entry_direction": "無效的輸入方向。",
"error.invalid_feed_proxy_url": "Invalid proxy URL.",
"error.invalid_feed_url": "訂閱網址無效。",
"error.invalid_gesture_nav": "手勢導覽無效。",
"error.invalid_language": "無效的語言。",
@ -126,6 +127,7 @@
"error.password_min_length": "請至少輸入 6 個字元",
"error.pocket_access_token": "無法從 Pocket 取得存取金鑰!",
"error.pocket_request_token": "無法從 Pocket 取得請求金鑰!",
"error.proxy_url_not_empty": "The proxy URL cannot be empty.",
"error.settings_block_rule_fieldname_invalid": "無效的封鎖規則:規則 #%d 缺少有效的欄位名稱 (可用選項:%s)",
"error.settings_block_rule_invalid_regex": "無效的封鎖規則:規則 #%d 的模式不是合法的正規表示式",
"error.settings_block_rule_regex_required": "無效的封鎖規則:規則 #%d 沒有提供正規表示式",
@ -172,7 +174,7 @@
"form.feed.label.feed_password": "Feed 密碼",
"form.feed.label.feed_url": "Feed 網址",
"form.feed.label.feed_username": "Feed 使用者名稱",
"form.feed.label.fetch_via_proxy": "透過代理取得",
"form.feed.label.fetch_via_proxy": "使用應用程式層級設定的代理",
"form.feed.label.hide_globally": "在全域未讀列表中隱藏文章",
"form.feed.label.ignore_http_cache": "忽略 HTTP 快取",
"form.feed.label.keeplist_rules": "保留規則",
@ -185,6 +187,7 @@
"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.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",
@ -419,6 +422,9 @@
"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"
@ -426,9 +432,6 @@
"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 標頭:",
@ -531,21 +534,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.starred.title": "收藏",
"page.shared_entries.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": "是",

View file

@ -57,8 +57,9 @@ type Feed struct {
NtfyEnabled bool `json:"ntfy_enabled"`
NtfyPriority int `json:"ntfy_priority"`
NtfyTopic string `json:"ntfy_topic"`
PushoverEnabled bool `json:"pushover_enabled,omitempty"`
PushoverPriority int `json:"pushover_priority,omitempty"`
PushoverEnabled bool `json:"pushover_enabled"`
PushoverPriority int `json:"pushover_priority"`
ProxyURL string `json:"proxy_url"`
// Non-persisted attributes
Category *Category `json:"category,omitempty"`
@ -161,6 +162,7 @@ type FeedCreationRequest struct {
HideGlobally bool `json:"hide_globally"`
UrlRewriteRules string `json:"urlrewrite_rules"`
DisableHTTP2 bool `json:"disable_http2"`
ProxyURL string `json:"proxy_url"`
}
type FeedCreationRequestFromSubscriptionDiscovery struct {
@ -195,6 +197,7 @@ type FeedModificationRequest struct {
FetchViaProxy *bool `json:"fetch_via_proxy"`
HideGlobally *bool `json:"hide_globally"`
DisableHTTP2 *bool `json:"disable_http2"`
ProxyURL *string `json:"proxy_url"`
}
// Patch updates a feed with modified values.
@ -286,6 +289,10 @@ func (f *FeedModificationRequest) Patch(feed *Feed) {
if f.DisableHTTP2 != nil {
feed.DisableHTTP2 = *f.DisableHTTP2
}
if f.ProxyURL != nil {
feed.ProxyURL = *f.ProxyURL
}
}
// Feeds is a list of feed

View file

@ -10,6 +10,7 @@ type SubscriptionDiscoveryRequest struct {
Cookie string `json:"cookie"`
Username string `json:"username"`
Password string `json:"password"`
ProxyURL string `json:"proxy_url"`
FetchViaProxy bool `json:"fetch_via_proxy"`
AllowSelfSignedCertificates bool `json:"allow_self_signed_certificates"`
DisableHTTP2 bool `json:"disable_http2"`

View file

@ -6,6 +6,7 @@ package fetcher // import "miniflux.app/v2/internal/reader/fetcher"
import (
"crypto/tls"
"encoding/base64"
"fmt"
"log/slog"
"net"
"net/http"
@ -30,6 +31,7 @@ type RequestBuilder struct {
ignoreTLSErrors bool
disableHTTP2 bool
proxyRotator *proxyrotator.ProxyRotator
feedProxyURL string
}
func NewRequestBuilder() *RequestBuilder {
@ -96,6 +98,11 @@ func (r *RequestBuilder) UseCustomApplicationProxyURL(value bool) *RequestBuilde
return r
}
func (r *RequestBuilder) WithCustomFeedProxyURL(proxyURL string) *RequestBuilder {
r.feedProxyURL = proxyURL
return r
}
func (r *RequestBuilder) WithTimeout(timeout int) *RequestBuilder {
r.clientTimeout = timeout
return r
@ -160,9 +167,17 @@ func (r *RequestBuilder) ExecuteRequest(requestURL string) (*http.Response, erro
}
var clientProxyURL *url.URL
if r.useClientProxy && r.clientProxyURL != nil {
switch {
case r.feedProxyURL != "":
var err error
clientProxyURL, err = url.Parse(r.feedProxyURL)
if err != nil {
return nil, fmt.Errorf(`fetcher: invalid feed proxy URL %q: %w`, r.feedProxyURL, err)
}
case r.useClientProxy && r.clientProxyURL != nil:
clientProxyURL = r.clientProxyURL
} else if r.proxyRotator != nil && r.proxyRotator.HasProxies() {
case r.proxyRotator != nil && r.proxyRotator.HasProxies():
clientProxyURL = r.proxyRotator.GetNextProxy()
}

View file

@ -30,6 +30,7 @@ func CreateFeedFromSubscriptionDiscovery(store *storage.Storage, userID int64, f
slog.Debug("Begin feed creation process from subscription discovery",
slog.Int64("user_id", userID),
slog.String("feed_url", feedCreationRequest.FeedURL),
slog.String("proxy_url", feedCreationRequest.ProxyURL),
)
if !store.CategoryIDExists(userID, feedCreationRequest.CategoryID) {
@ -65,6 +66,7 @@ func CreateFeedFromSubscriptionDiscovery(store *storage.Storage, userID int64, f
subscription.FeedURL = feedCreationRequest.FeedURL
subscription.DisableHTTP2 = feedCreationRequest.DisableHTTP2
subscription.WithCategoryID(feedCreationRequest.CategoryID)
subscription.ProxyURL = feedCreationRequest.ProxyURL
subscription.CheckedNow()
processor.ProcessFeedEntries(store, subscription, userID, true)
@ -85,6 +87,7 @@ func CreateFeedFromSubscriptionDiscovery(store *storage.Storage, userID int64, f
requestBuilder.WithCookie(feedCreationRequest.Cookie)
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomFeedProxyURL(feedCreationRequest.ProxyURL)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
requestBuilder.UseCustomApplicationProxyURL(feedCreationRequest.FetchViaProxy)
requestBuilder.IgnoreTLSErrors(feedCreationRequest.AllowSelfSignedCertificates)
@ -100,6 +103,7 @@ func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model
slog.Debug("Begin feed creation process",
slog.Int64("user_id", userID),
slog.String("feed_url", feedCreationRequest.FeedURL),
slog.String("proxy_url", feedCreationRequest.ProxyURL),
)
if !store.CategoryIDExists(userID, feedCreationRequest.CategoryID) {
@ -112,6 +116,7 @@ func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model
requestBuilder.WithCookie(feedCreationRequest.Cookie)
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomFeedProxyURL(feedCreationRequest.ProxyURL)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
requestBuilder.UseCustomApplicationProxyURL(feedCreationRequest.FetchViaProxy)
requestBuilder.IgnoreTLSErrors(feedCreationRequest.AllowSelfSignedCertificates)
@ -160,6 +165,7 @@ func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model
subscription.EtagHeader = responseHandler.ETag()
subscription.LastModifiedHeader = responseHandler.LastModified()
subscription.FeedURL = responseHandler.EffectiveURL()
subscription.ProxyURL = feedCreationRequest.ProxyURL
subscription.WithCategoryID(feedCreationRequest.CategoryID)
subscription.CheckedNow()
@ -216,6 +222,7 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool
requestBuilder.WithCookie(originalFeed.Cookie)
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomFeedProxyURL(originalFeed.ProxyURL)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
requestBuilder.UseCustomApplicationProxyURL(originalFeed.FetchViaProxy)
requestBuilder.IgnoreTLSErrors(originalFeed.AllowSelfSignedCertificates)

View file

@ -31,6 +31,7 @@ func (c *IconChecker) fetchAndStoreIcon() {
requestBuilder.WithCookie(c.feed.Cookie)
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomFeedProxyURL(c.feed.ProxyURL)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
requestBuilder.UseCustomApplicationProxyURL(c.feed.FetchViaProxy)
requestBuilder.IgnoreTLSErrors(c.feed.AllowSelfSignedCertificates)

View file

@ -47,7 +47,6 @@ func fetchBilibiliWatchTime(websiteURL string) (int, error) {
requestBuilder := fetcher.NewRequestBuilder()
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
idType, videoID, extractErr := extractBilibiliVideoID(websiteURL)
if extractErr != nil {

View file

@ -35,7 +35,6 @@ func fetchNebulaWatchTime(websiteURL string) (int, error) {
requestBuilder := fetcher.NewRequestBuilder()
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(websiteURL))
defer responseHandler.Close()

View file

@ -35,7 +35,6 @@ func fetchOdyseeWatchTime(websiteURL string) (int, error) {
requestBuilder := fetcher.NewRequestBuilder()
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(websiteURL))
defer responseHandler.Close()

View file

@ -80,6 +80,7 @@ func ProcessFeedEntries(store *storage.Storage, feed *model.Feed, userID int64,
requestBuilder.WithCookie(feed.Cookie)
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomFeedProxyURL(feed.ProxyURL)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
requestBuilder.UseCustomApplicationProxyURL(feed.FetchViaProxy)
requestBuilder.IgnoreTLSErrors(feed.AllowSelfSignedCertificates)
@ -148,6 +149,7 @@ func ProcessEntryWebPage(feed *model.Feed, entry *model.Entry, user *model.User)
requestBuilder.WithCookie(feed.Cookie)
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomFeedProxyURL(feed.ProxyURL)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
requestBuilder.UseCustomApplicationProxyURL(feed.FetchViaProxy)
requestBuilder.IgnoreTLSErrors(feed.AllowSelfSignedCertificates)

View file

@ -54,7 +54,6 @@ func fetchYouTubeWatchTimeForSingleEntry(websiteURL string) (int, error) {
requestBuilder := fetcher.NewRequestBuilder()
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(websiteURL))
defer responseHandler.Close()
@ -135,7 +134,6 @@ func fetchYouTubeWatchTimeFromApiInBulk(videoIDs []string) (map[string]time.Dura
requestBuilder := fetcher.NewRequestBuilder()
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(apiURL.String()))
defer responseHandler.Close()

View file

@ -248,10 +248,11 @@ func (s *Storage) CreateFeed(feed *model.Feed) error {
apprise_service_urls,
webhook_url,
disable_http2,
description
description,
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)
($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)
RETURNING
id
`
@ -284,6 +285,7 @@ func (s *Storage) CreateFeed(feed *model.Feed) error {
feed.WebhookURL,
feed.DisableHTTP2,
feed.Description,
feed.ProxyURL,
).Scan(&feed.ID)
if err != nil {
return fmt.Errorf(`store: unable to create feed %q: %v`, feed.FeedURL, err)
@ -363,9 +365,10 @@ func (s *Storage) UpdateFeed(feed *model.Feed) (err error) {
ntfy_priority=$32,
ntfy_topic=$33,
pushover_enabled=$34,
pushover_priority=$35
pushover_priority=$35,
proxy_url=$36
WHERE
id=$36 AND user_id=$37
id=$37 AND user_id=$38
`
_, err = s.db.Exec(query,
feed.FeedURL,
@ -403,6 +406,7 @@ func (s *Storage) UpdateFeed(feed *model.Feed) (err error) {
feed.NtfyTopic,
feed.PushoverEnabled,
feed.PushoverPriority,
feed.ProxyURL,
feed.ID,
feed.UserID,
)

View file

@ -172,7 +172,8 @@ func (f *FeedQueryBuilder) GetFeeds() (model.Feeds, error) {
f.ntfy_priority,
f.ntfy_topic,
f.pushover_enabled,
f.pushover_priority
f.pushover_priority,
f.proxy_url
FROM
feeds f
LEFT JOIN
@ -251,6 +252,7 @@ func (f *FeedQueryBuilder) GetFeeds() (model.Feeds, error) {
&feed.NtfyTopic,
&feed.PushoverEnabled,
&feed.PushoverPriority,
&feed.ProxyURL,
)
if err != nil {

View file

@ -39,6 +39,9 @@
<label><input type="checkbox" name="fetch_via_proxy" value="1" {{ if .form.FetchViaProxy }}checked{{ end }}> {{ t "form.feed.label.fetch_via_proxy" }}</label>
{{ end }}
<label for="form-proxy-url">{{ t "form.feed.label.proxy_url" }}</label>
<input type="url" name="proxy_url" id="form-proxy-url" value="{{ .form.ProxyURL }}" spellcheck="false">
<label for="form-user-agent">{{ t "form.feed.label.user_agent" }}</label>
<input type="text" name="user_agent" id="form-user-agent" placeholder="{{ .defaultUserAgent }}" value="{{ .form.UserAgent }}" spellcheck="false" autocomplete="off">

View file

@ -20,6 +20,7 @@
<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="proxy_url" value="{{ .form.ProxyURL }}">
{{ if .form.FetchViaProxy }}
<input type="hidden" name="fetch_via_proxy" value="1">
{{ end }}

View file

@ -97,6 +97,9 @@
<label for="form-user-agent">{{ t "form.feed.label.user_agent" }}</label>
<input type="text" name="user_agent" id="form-user-agent" placeholder="{{ .defaultUserAgent }}" value="{{ .form.UserAgent }}" spellcheck="false">
<label for="form-proxy-url">{{ t "form.feed.label.proxy_url" }}</label>
<input type="url" name="proxy_url" id="form-proxy-url" value="{{ .form.ProxyURL }}" spellcheck="false">
<label for="form-cookie">{{ t "form.feed.label.cookie" }}</label>
<input type="text" name="cookie" id="form-cookie" value="{{ .form.Cookie }}" spellcheck="false">

View file

@ -70,6 +70,7 @@ func (h *handler) showEditFeedPage(w http.ResponseWriter, r *http.Request) {
NtfyTopic: feed.NtfyTopic,
PushoverEnabled: feed.PushoverEnabled,
PushoverPriority: feed.PushoverPriority,
ProxyURL: feed.ProxyURL,
}
sess := session.New(h.store, request.SessionID(r))

View file

@ -64,6 +64,7 @@ func (h *handler) updateFeed(w http.ResponseWriter, r *http.Request) {
BlocklistRules: model.OptionalString(feedForm.BlocklistRules),
KeeplistRules: model.OptionalString(feedForm.KeeplistRules),
UrlRewriteRules: model.OptionalString(feedForm.UrlRewriteRules),
ProxyURL: model.OptionalString(feedForm.ProxyURL),
}
if validationErr := validator.ValidateFeedModification(h.store, loggedUser.ID, feed.ID, feedModificationRequest); validationErr != nil {

View file

@ -42,6 +42,7 @@ type FeedForm struct {
NtfyTopic string
PushoverEnabled bool
PushoverPriority int
ProxyURL string
}
// Merge updates the fields of the given feed.
@ -77,6 +78,7 @@ func (f FeedForm) Merge(feed *model.Feed) *model.Feed {
feed.NtfyTopic = f.NtfyTopic
feed.PushoverEnabled = f.PushoverEnabled
feed.PushoverPriority = f.PushoverPriority
feed.ProxyURL = f.ProxyURL
return feed
}
@ -86,6 +88,7 @@ func NewFeedForm(r *http.Request) *FeedForm {
if err != nil {
categoryID = 0
}
ntfyPriority, err := strconv.Atoi(r.FormValue("ntfy_priority"))
if err != nil {
ntfyPriority = 0
@ -126,5 +129,6 @@ func NewFeedForm(r *http.Request) *FeedForm {
NtfyTopic: r.FormValue("ntfy_topic"),
PushoverEnabled: r.FormValue("pushover_enabled") == "1",
PushoverPriority: pushoverPriority,
ProxyURL: r.FormValue("proxy_url"),
}
}

View file

@ -28,6 +28,7 @@ type SubscriptionForm struct {
KeeplistRules string
UrlRewriteRules string
DisableHTTP2 bool
ProxyURL string
}
// Validate makes sure the form values locale.are valid.
@ -52,6 +53,10 @@ func (s *SubscriptionForm) Validate() *locale.LocalizedError {
return locale.NewLocalizedError("error.feed_invalid_urlrewrite_rule")
}
if s.ProxyURL != "" && !validator.IsValidURL(s.ProxyURL) {
return locale.NewLocalizedError("error.invalid_feed_proxy_url")
}
return nil
}
@ -78,5 +83,6 @@ func NewSubscriptionForm(r *http.Request) *SubscriptionForm {
KeeplistRules: r.FormValue("keeplist_rules"),
UrlRewriteRules: r.FormValue("urlrewrite_rules"),
DisableHTTP2: r.FormValue("disable_http2") == "1",
ProxyURL: r.FormValue("proxy_url"),
}
}

View file

@ -97,7 +97,6 @@ func (h *handler) fetchOPML(w http.ResponseWriter, r *http.Request) {
requestBuilder := fetcher.NewRequestBuilder()
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(opmlFileURL))
defer responseHandler.Close()

View file

@ -63,6 +63,7 @@ func (h *handler) showChooseSubscriptionPage(w http.ResponseWriter, r *http.Requ
UrlRewriteRules: subscriptionForm.UrlRewriteRules,
FetchViaProxy: subscriptionForm.FetchViaProxy,
DisableHTTP2: subscriptionForm.DisableHTTP2,
ProxyURL: subscriptionForm.ProxyURL,
})
if localizedError != nil {
view.Set("form", subscriptionForm)

View file

@ -60,6 +60,7 @@ func (h *handler) submitSubscription(w http.ResponseWriter, r *http.Request) {
requestBuilder := fetcher.NewRequestBuilder()
requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout())
requestBuilder.WithProxyRotator(proxyrotator.ProxyRotatorInstance)
requestBuilder.WithCustomFeedProxyURL(subscriptionForm.ProxyURL)
requestBuilder.WithCustomApplicationProxyURL(config.Opts.HTTPClientProxyURL())
requestBuilder.UseCustomApplicationProxyURL(subscriptionForm.FetchViaProxy)
requestBuilder.WithUserAgent(subscriptionForm.UserAgent, config.Opts.HTTPClientUserAgent())
@ -107,6 +108,7 @@ func (h *handler) submitSubscription(w http.ResponseWriter, r *http.Request) {
UrlRewriteRules: subscriptionForm.UrlRewriteRules,
FetchViaProxy: subscriptionForm.FetchViaProxy,
DisableHTTP2: subscriptionForm.DisableHTTP2,
ProxyURL: subscriptionForm.ProxyURL,
},
})
if localizedError != nil {
@ -134,6 +136,7 @@ func (h *handler) submitSubscription(w http.ResponseWriter, r *http.Request) {
UrlRewriteRules: subscriptionForm.UrlRewriteRules,
FetchViaProxy: subscriptionForm.FetchViaProxy,
DisableHTTP2: subscriptionForm.DisableHTTP2,
ProxyURL: subscriptionForm.ProxyURL,
})
if localizedError != nil {
v.Set("form", subscriptionForm)

View file

@ -35,6 +35,10 @@ func ValidateFeedCreation(store *storage.Storage, userID int64, request *model.F
return locale.NewLocalizedError("error.feed_invalid_keeplist_rule")
}
if request.ProxyURL != "" && !IsValidURL(request.ProxyURL) {
return locale.NewLocalizedError("error.invalid_feed_proxy_url")
}
return nil
}
@ -88,5 +92,15 @@ func ValidateFeedModification(store *storage.Storage, userID, feedID int64, requ
}
}
if request.ProxyURL != nil {
if *request.ProxyURL == "" {
return locale.NewLocalizedError("error.proxy_url_not_empty")
}
if !IsValidURL(*request.ProxyURL) {
return locale.NewLocalizedError("error.invalid_feed_proxy_url")
}
}
return nil
}

View file

@ -14,5 +14,9 @@ func ValidateSubscriptionDiscovery(request *model.SubscriptionDiscoveryRequest)
return locale.NewLocalizedError("error.invalid_site_url")
}
if request.ProxyURL != "" && !IsValidURL(request.ProxyURL) {
return locale.NewLocalizedError("error.invalid_proxy_url")
}
return nil
}