diff --git a/client/model.go b/client/model.go index 0a6cd4d1..8f257e6a 100644 --- a/client/model.go +++ b/client/model.go @@ -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. diff --git a/internal/api/subscription.go b/internal/api/subscription.go index e5099528..63eeba73 100644 --- a/internal/api/subscription.go +++ b/internal/api/subscription.go @@ -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()) diff --git a/internal/database/migrations.go b/internal/database/migrations.go index 73da902c..4f553e9c 100644 --- a/internal/database/migrations.go +++ b/internal/database/migrations.go @@ -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 + }, } diff --git a/internal/googlereader/handler.go b/internal/googlereader/handler.go index 9764edbf..c5e6e537 100644 --- a/internal/googlereader/handler.go +++ b/internal/googlereader/handler.go @@ -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 diff --git a/internal/locale/translations/de_DE.json b/internal/locale/translations/de_DE.json index ba68e9a6..214c987e 100644 --- a/internal/locale/translations/de_DE.json +++ b/internal/locale/translations/de_DE.json @@ -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", @@ -603,4 +606,4 @@ "time_elapsed.yesterday": "gestern", "tooltip.keyboard_shortcuts": "Tastenkürzel: %s", "tooltip.logged_user": "Angemeldet als %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/el_EL.json b/internal/locale/translations/el_EL.json index 0463d3b6..42d07e3a 100644 --- a/internal/locale/translations/el_EL.json +++ b/internal/locale/translations/el_EL.json @@ -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": "Ναι.", @@ -603,4 +606,4 @@ "time_elapsed.yesterday": "χθες", "tooltip.keyboard_shortcuts": "Συντόμευση πληκτρολογίου: % s", "tooltip.logged_user": "Συνδεδεμένος/η ως %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/en_US.json b/internal/locale/translations/en_US.json index cb516358..2b85ccfd 100644 --- a/internal/locale/translations/en_US.json +++ b/internal/locale/translations/en_US.json @@ -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", diff --git a/internal/locale/translations/es_ES.json b/internal/locale/translations/es_ES.json index 8507b5ab..494e004c 100644 --- a/internal/locale/translations/es_ES.json +++ b/internal/locale/translations/es_ES.json @@ -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í", @@ -603,4 +606,4 @@ "time_elapsed.yesterday": "ayer", "tooltip.keyboard_shortcuts": "Atajo de teclado: %s", "tooltip.logged_user": "Registrado como %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/fi_FI.json b/internal/locale/translations/fi_FI.json index 294b35b7..65dc3ace 100644 --- a/internal/locale/translations/fi_FI.json +++ b/internal/locale/translations/fi_FI.json @@ -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ä", @@ -603,4 +606,4 @@ "time_elapsed.yesterday": "eilen", "tooltip.keyboard_shortcuts": "Pikanäppäin: %s", "tooltip.logged_user": "Kirjautunut %s-käyttäjänä" -} +} \ No newline at end of file diff --git a/internal/locale/translations/fr_FR.json b/internal/locale/translations/fr_FR.json index 9293cbe0..60b39407 100644 --- a/internal/locale/translations/fr_FR.json +++ b/internal/locale/translations/fr_FR.json @@ -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 d’accès", "page.settings.webauthn.register": "Enregister une nouvelle clé d’accès", "page.settings.webauthn.register.error": "Impossible d'enregistrer la clé d’accès", - "page.shared_entries.title": "Articles partagés", "page.shared_entries_count": [ "%d article partagé", "%d articles partagés" ], - "page.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", @@ -603,4 +606,4 @@ "time_elapsed.yesterday": "hier", "tooltip.keyboard_shortcuts": "Raccourci clavier : %s", "tooltip.logged_user": "Connecté en tant que %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/hi_IN.json b/internal/locale/translations/hi_IN.json index dc323d11..cd90cd5e 100644 --- a/internal/locale/translations/hi_IN.json +++ b/internal/locale/translations/hi_IN.json @@ -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": "हां", @@ -603,4 +606,4 @@ "time_elapsed.yesterday": "कल", "tooltip.keyboard_shortcuts": "कुंजीपटल संक्षिप्त रीति: %s", "tooltip.logged_user": "%s के रूप में लॉग इन किया" -} +} \ No newline at end of file diff --git a/internal/locale/translations/id_ID.json b/internal/locale/translations/id_ID.json index e38c291f..998fc598 100644 --- a/internal/locale/translations/id_ID.json +++ b/internal/locale/translations/id_ID.json @@ -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", @@ -586,4 +589,4 @@ "time_elapsed.yesterday": "kemarin", "tooltip.keyboard_shortcuts": "Pintasan Papan Tik: %s", "tooltip.logged_user": "Masuk sebagai %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/it_IT.json b/internal/locale/translations/it_IT.json index 479bf48b..2ea4a3e7 100644 --- a/internal/locale/translations/it_IT.json +++ b/internal/locale/translations/it_IT.json @@ -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ì", @@ -603,4 +606,4 @@ "time_elapsed.yesterday": "ieri", "tooltip.keyboard_shortcuts": "Scorciatoia da tastiera: %s", "tooltip.logged_user": "Autenticato come %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/ja_JP.json b/internal/locale/translations/ja_JP.json index 78963d92..cbd4b47c 100644 --- a/internal/locale/translations/ja_JP.json +++ b/internal/locale/translations/ja_JP.json @@ -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": "管理者", @@ -586,4 +589,4 @@ "time_elapsed.yesterday": "昨日", "tooltip.keyboard_shortcuts": "キーボードショートカット: %s", "tooltip.logged_user": "%s としてログイン中" -} +} \ No newline at end of file diff --git a/internal/locale/translations/nan_Latn_pehoeji.json b/internal/locale/translations/nan_Latn_pehoeji.json index d4f5046f..e70a0993 100644 --- a/internal/locale/translations/nan_Latn_pehoeji.json +++ b/internal/locale/translations/nan_Latn_pehoeji.json @@ -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ī", @@ -586,4 +589,4 @@ "time_elapsed.yesterday": "cha-hng", "tooltip.keyboard_shortcuts": "Khoài-sok khí:%s", "tooltip.logged_user": "Chit-má teng-lo̍k--ê: %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/nl_NL.json b/internal/locale/translations/nl_NL.json index 5ddfea97..d2ca2322 100644 --- a/internal/locale/translations/nl_NL.json +++ b/internal/locale/translations/nl_NL.json @@ -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", @@ -603,4 +606,4 @@ "time_elapsed.yesterday": "gisteren", "tooltip.keyboard_shortcuts": "Sneltoets: %s", "tooltip.logged_user": "Ingelogd als %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/pl_PL.json b/internal/locale/translations/pl_PL.json index 6f01087d..4219b8ed 100644 --- a/internal/locale/translations/pl_PL.json +++ b/internal/locale/translations/pl_PL.json @@ -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", @@ -620,4 +623,4 @@ "time_elapsed.yesterday": "wczoraj", "tooltip.keyboard_shortcuts": "Skróty klawiszowe: %s", "tooltip.logged_user": "Zalogowany jako %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/pt_BR.json b/internal/locale/translations/pt_BR.json index 40d9796b..196396ad 100644 --- a/internal/locale/translations/pt_BR.json +++ b/internal/locale/translations/pt_BR.json @@ -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", @@ -603,4 +606,4 @@ "time_elapsed.yesterday": "ontem", "tooltip.keyboard_shortcuts": "Atalho do teclado: %s", "tooltip.logged_user": "Autenticado como %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/ro_RO.json b/internal/locale/translations/ro_RO.json index 7f981ba5..5fb95831 100644 --- a/internal/locale/translations/ro_RO.json +++ b/internal/locale/translations/ro_RO.json @@ -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", diff --git a/internal/locale/translations/ru_RU.json b/internal/locale/translations/ru_RU.json index eee84940..a95c6f68 100644 --- a/internal/locale/translations/ru_RU.json +++ b/internal/locale/translations/ru_RU.json @@ -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": "Да", @@ -620,4 +623,4 @@ "time_elapsed.yesterday": "вчера", "tooltip.keyboard_shortcuts": "Сочетания клавиш: %s", "tooltip.logged_user": "Авторизован как %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/tr_TR.json b/internal/locale/translations/tr_TR.json index 067f8401..0132ef16 100644 --- a/internal/locale/translations/tr_TR.json +++ b/internal/locale/translations/tr_TR.json @@ -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", @@ -603,4 +606,4 @@ "time_elapsed.yesterday": "dün", "tooltip.keyboard_shortcuts": "Klavye Kısayolu: %s", "tooltip.logged_user": "%s olarak giriş yapıldı" -} +} \ No newline at end of file diff --git a/internal/locale/translations/uk_UA.json b/internal/locale/translations/uk_UA.json index 822f653a..ef914630 100644 --- a/internal/locale/translations/uk_UA.json +++ b/internal/locale/translations/uk_UA.json @@ -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": "Так", @@ -620,4 +623,4 @@ "time_elapsed.yesterday": "вчора", "tooltip.keyboard_shortcuts": "Комбінація клавіш: %s", "tooltip.logged_user": "Здійснено вхід як %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/zh_CN.json b/internal/locale/translations/zh_CN.json index b8769361..e7a79866 100644 --- a/internal/locale/translations/zh_CN.json +++ b/internal/locale/translations/zh_CN.json @@ -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 高优先级", @@ -586,4 +589,4 @@ "time_elapsed.yesterday": "昨天", "tooltip.keyboard_shortcuts": "快捷键: %s", "tooltip.logged_user": "当前登录 %s" -} +} \ No newline at end of file diff --git a/internal/locale/translations/zh_TW.json b/internal/locale/translations/zh_TW.json index 7b3e5c19..c009ea3b 100644 --- a/internal/locale/translations/zh_TW.json +++ b/internal/locale/translations/zh_TW.json @@ -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": "是", @@ -586,4 +589,4 @@ "time_elapsed.yesterday": "昨天", "tooltip.keyboard_shortcuts": "快捷鍵:%s", "tooltip.logged_user": "目前登入 %s" -} +} \ No newline at end of file diff --git a/internal/model/feed.go b/internal/model/feed.go index 585365d3..7f022bed 100644 --- a/internal/model/feed.go +++ b/internal/model/feed.go @@ -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 diff --git a/internal/model/subscription.go b/internal/model/subscription.go index faed2b99..c8a45c71 100644 --- a/internal/model/subscription.go +++ b/internal/model/subscription.go @@ -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"` diff --git a/internal/reader/fetcher/request_builder.go b/internal/reader/fetcher/request_builder.go index a71ea1a4..b46ed568 100644 --- a/internal/reader/fetcher/request_builder.go +++ b/internal/reader/fetcher/request_builder.go @@ -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() } diff --git a/internal/reader/handler/handler.go b/internal/reader/handler/handler.go index 4745b7c1..15301a7a 100644 --- a/internal/reader/handler/handler.go +++ b/internal/reader/handler/handler.go @@ -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) diff --git a/internal/reader/icon/checker.go b/internal/reader/icon/checker.go index 45a1b519..287a3d99 100644 --- a/internal/reader/icon/checker.go +++ b/internal/reader/icon/checker.go @@ -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) diff --git a/internal/reader/processor/bilibili.go b/internal/reader/processor/bilibili.go index fffc5bd3..315bba81 100644 --- a/internal/reader/processor/bilibili.go +++ b/internal/reader/processor/bilibili.go @@ -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 { diff --git a/internal/reader/processor/nebula.go b/internal/reader/processor/nebula.go index 9193b50f..0759f6fe 100644 --- a/internal/reader/processor/nebula.go +++ b/internal/reader/processor/nebula.go @@ -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() diff --git a/internal/reader/processor/odysee.go b/internal/reader/processor/odysee.go index 4e4a82b4..132d2926 100644 --- a/internal/reader/processor/odysee.go +++ b/internal/reader/processor/odysee.go @@ -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() diff --git a/internal/reader/processor/processor.go b/internal/reader/processor/processor.go index 2c433728..7c5bb40f 100644 --- a/internal/reader/processor/processor.go +++ b/internal/reader/processor/processor.go @@ -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) diff --git a/internal/reader/processor/youtube.go b/internal/reader/processor/youtube.go index fcb07d4b..72c9ce15 100644 --- a/internal/reader/processor/youtube.go +++ b/internal/reader/processor/youtube.go @@ -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() diff --git a/internal/storage/feed.go b/internal/storage/feed.go index 835bcd3f..a3f21fa9 100644 --- a/internal/storage/feed.go +++ b/internal/storage/feed.go @@ -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, ) diff --git a/internal/storage/feed_query_builder.go b/internal/storage/feed_query_builder.go index b8a9eee0..82e6594f 100644 --- a/internal/storage/feed_query_builder.go +++ b/internal/storage/feed_query_builder.go @@ -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 { diff --git a/internal/template/templates/views/add_subscription.html b/internal/template/templates/views/add_subscription.html index 4619fd53..28ef4882 100644 --- a/internal/template/templates/views/add_subscription.html +++ b/internal/template/templates/views/add_subscription.html @@ -39,6 +39,9 @@ {{ end }} + + + diff --git a/internal/template/templates/views/choose_subscription.html b/internal/template/templates/views/choose_subscription.html index 3b347f07..c8034a2b 100644 --- a/internal/template/templates/views/choose_subscription.html +++ b/internal/template/templates/views/choose_subscription.html @@ -20,6 +20,7 @@ + {{ if .form.FetchViaProxy }} {{ end }} diff --git a/internal/template/templates/views/edit_feed.html b/internal/template/templates/views/edit_feed.html index 8daa9f3b..b55ad754 100644 --- a/internal/template/templates/views/edit_feed.html +++ b/internal/template/templates/views/edit_feed.html @@ -97,6 +97,9 @@ + + + diff --git a/internal/ui/feed_edit.go b/internal/ui/feed_edit.go index d3ade628..d1dcdc6f 100644 --- a/internal/ui/feed_edit.go +++ b/internal/ui/feed_edit.go @@ -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)) diff --git a/internal/ui/feed_update.go b/internal/ui/feed_update.go index 5a6fd625..ea1e70ff 100644 --- a/internal/ui/feed_update.go +++ b/internal/ui/feed_update.go @@ -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 { diff --git a/internal/ui/form/feed.go b/internal/ui/form/feed.go index e30d9318..fdb94b8e 100644 --- a/internal/ui/form/feed.go +++ b/internal/ui/form/feed.go @@ -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"), } } diff --git a/internal/ui/form/subscription.go b/internal/ui/form/subscription.go index ab46ce65..8ead956c 100644 --- a/internal/ui/form/subscription.go +++ b/internal/ui/form/subscription.go @@ -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"), } } diff --git a/internal/ui/opml_upload.go b/internal/ui/opml_upload.go index 6dd58410..c31b6e88 100644 --- a/internal/ui/opml_upload.go +++ b/internal/ui/opml_upload.go @@ -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() diff --git a/internal/ui/subscription_choose.go b/internal/ui/subscription_choose.go index af355d34..de6a4b5d 100644 --- a/internal/ui/subscription_choose.go +++ b/internal/ui/subscription_choose.go @@ -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) diff --git a/internal/ui/subscription_submit.go b/internal/ui/subscription_submit.go index 4ba9f8c1..16a9c3f0 100644 --- a/internal/ui/subscription_submit.go +++ b/internal/ui/subscription_submit.go @@ -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) diff --git a/internal/validator/feed.go b/internal/validator/feed.go index 6a353892..b3227726 100644 --- a/internal/validator/feed.go +++ b/internal/validator/feed.go @@ -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 } diff --git a/internal/validator/subscription.go b/internal/validator/subscription.go index 516f679d..ff167e92 100644 --- a/internal/validator/subscription.go +++ b/internal/validator/subscription.go @@ -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 }