From 43d302e7681904c7b678b8c6f7cbda9db6b84866 Mon Sep 17 00:00:00 2001 From: Jesse Jaggars Date: Wed, 4 Jun 2025 08:37:11 -0400 Subject: [PATCH] feat: adding support for saving entries to karakeep Signed-off-by: Jesse Jaggars --- internal/database/migrations.go | 9 ++ internal/integration/integration.go | 19 ++++ internal/integration/karakeep/karakeep.go | 89 +++++++++++++++++++ internal/locale/translations/de_DE.json | 5 +- internal/locale/translations/el_EL.json | 5 +- internal/locale/translations/en_US.json | 5 +- internal/locale/translations/es_ES.json | 5 +- internal/locale/translations/fi_FI.json | 5 +- internal/locale/translations/fr_FR.json | 5 +- internal/locale/translations/hi_IN.json | 5 +- internal/locale/translations/id_ID.json | 5 +- internal/locale/translations/it_IT.json | 5 +- internal/locale/translations/ja_JP.json | 5 +- .../locale/translations/nan_Latn_pehoeji.json | 5 +- internal/locale/translations/nl_NL.json | 5 +- internal/locale/translations/pl_PL.json | 5 +- internal/locale/translations/pt_BR.json | 5 +- internal/locale/translations/ro_RO.json | 5 +- internal/locale/translations/ru_RU.json | 5 +- internal/locale/translations/tr_TR.json | 5 +- internal/locale/translations/uk_UA.json | 5 +- internal/locale/translations/zh_CN.json | 5 +- internal/locale/translations/zh_TW.json | 5 +- internal/model/integration.go | 3 + internal/storage/integration.go | 19 +++- .../templates/views/integrations.html | 19 ++++ internal/ui/form/integration.go | 9 ++ internal/ui/integration_show.go | 3 + 28 files changed, 247 insertions(+), 23 deletions(-) create mode 100644 internal/integration/karakeep/karakeep.go diff --git a/internal/database/migrations.go b/internal/database/migrations.go index 327336d5..70c11792 100644 --- a/internal/database/migrations.go +++ b/internal/database/migrations.go @@ -1077,4 +1077,13 @@ var migrations = []func(tx *sql.Tx, driver string) error{ _, err = tx.Exec(`ALTER TABLE users ADD COLUMN always_open_external_links bool default 'f'`) return err }, + func(tx *sql.Tx, _ string) (err error) { + sql := ` + ALTER TABLE integrations ADD COLUMN karakeep_enabled bool default 'f'; + ALTER TABLE integrations ADD COLUMN karakeep_api_key text default ''; + ALTER TABLE integrations ADD COLUMN karakeep_url text default ''; + ` + _, err = tx.Exec(sql) + return + }, } diff --git a/internal/integration/integration.go b/internal/integration/integration.go index fc4c7c64..795d1dc0 100644 --- a/internal/integration/integration.go +++ b/internal/integration/integration.go @@ -13,6 +13,7 @@ import ( "miniflux.app/v2/internal/integration/discord" "miniflux.app/v2/internal/integration/espial" "miniflux.app/v2/internal/integration/instapaper" + "miniflux.app/v2/internal/integration/karakeep" "miniflux.app/v2/internal/integration/linkace" "miniflux.app/v2/internal/integration/linkding" "miniflux.app/v2/internal/integration/linkwarden" @@ -428,6 +429,24 @@ func SendEntry(entry *model.Entry, userIntegrations *model.Integration) { } } + if userIntegrations.KarakeepEnabled { + slog.Debug("Sending entry to Karakeep", + slog.Int64("user_id", userIntegrations.UserID), + slog.Int64("entry_id", entry.ID), + slog.String("entry_url", entry.URL), + ) + + client := karakeep.NewClient(userIntegrations.KarakeepAPIKey, userIntegrations.KarakeepURL) + if err := client.SaveUrl(entry.URL); err != nil { + slog.Error("Unable to send entry to Karakeep", + slog.Int64("user_id", userIntegrations.UserID), + slog.Int64("entry_id", entry.ID), + slog.String("entry_url", entry.URL), + slog.Any("error", err), + ) + } + } + if userIntegrations.RaindropEnabled { slog.Debug("Sending entry to Raindrop", slog.Int64("user_id", userIntegrations.UserID), diff --git a/internal/integration/karakeep/karakeep.go b/internal/integration/karakeep/karakeep.go new file mode 100644 index 00000000..90d8c5bc --- /dev/null +++ b/internal/integration/karakeep/karakeep.go @@ -0,0 +1,89 @@ +// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package karakeep // import "miniflux.app/v2/internal/integration/karakeep" + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "time" + + "miniflux.app/v2/internal/version" +) + +const defaultClientTimeout = 10 * time.Second + +type errorResponse struct { + Code string `json:"code"` + Error string `json:"error"` +} + +type successResponse struct { + CreatedAt string `json:"createdAt"` + Content struct { + Type string `json:"type"` + Url string `json:"url"` + } +} + +type Client interface { + SaveUrl(url string) error +} + +type client struct { + wrapped *http.Client + apiEndpoint string + apiToken string +} + +func NewClient(apiToken string, apiEndpoint string) Client { + return &client{wrapped: &http.Client{Timeout: defaultClientTimeout}, apiEndpoint: apiEndpoint, apiToken: apiToken} +} + +func (c *client) SaveUrl(url string) error { + var payload = map[string]interface{}{ + "type": "link", + "url": url, + } + b, err := json.Marshal(payload) + if err != nil { + return err + } + req, err := http.NewRequest(http.MethodPost, c.apiEndpoint, bytes.NewReader(b)) + if err != nil { + return err + } + + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.apiToken)) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("User-Agent", "Miniflux/"+version.Version) + + resp, err := c.wrapped.Do(req) + if err != nil { + return err + } + + defer resp.Body.Close() + b, err = io.ReadAll(resp.Body) + if err != nil { + return fmt.Errorf("karakeep: failed to parse response: %s", err) + } + + if resp.StatusCode >= 400 { + var errResponse errorResponse + if err = json.Unmarshal(b, &errResponse); err != nil { + return fmt.Errorf("karakeep: failed to save URL: status=%d %s", resp.StatusCode, string(b)) + } + return fmt.Errorf("karakeep: failed to save URL: status=%d errorcode=%s %s", resp.StatusCode, errResponse.Code, errResponse.Error) + } + + var successReponse successResponse + if err = json.Unmarshal(b, &successReponse); err != nil { + return fmt.Errorf("karakeep: failed to parse response, however the request appears successful, is the url correct?: status=%d %s", resp.StatusCode, string(b)) + } + + return nil +} diff --git a/internal/locale/translations/de_DE.json b/internal/locale/translations/de_DE.json index 164df22d..8c0a6316 100644 --- a/internal/locale/translations/de_DE.json +++ b/internal/locale/translations/de_DE.json @@ -233,6 +233,9 @@ "form.integration.instapaper_activate": "Einträge in Instapaper speichern", "form.integration.instapaper_password": "Instapaper-Passwort", "form.integration.instapaper_username": "Instapaper-Benutzername", + "form.integration.karakeep_activate": "Einträge in Karakeep speichern", + "form.integration.karakeep_api_key": "Karakeep-API-Schlüssel", + "form.integration.karakeep_url": "Karakeep-API-Endpunkt", "form.integration.linkace_activate": "Einträge in LinkAce speichern", "form.integration.linkace_api_key": "LinkAce-API-Schlüssel", "form.integration.linkace_check_disabled": "Linkprüfung deaktivieren", @@ -328,6 +331,7 @@ "form.prefs.fieldset.global_feed_settings": "Globale Feedeinstellungen", "form.prefs.fieldset.reader_settings": "Reader-Einstellungen", "form.prefs.help.external_font_hosts": "Per Leerzeichen getrennte Liste externer Schriftarten-Hosts, die erlaubt werden sollen. Beispiel: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Artikel immer mit Öffnen der Links lesen", "form.prefs.label.categories_sorting_order": "Kategorie-Sortierung", "form.prefs.label.cjk_reading_speed": "Lesegeschwindigkeit für Chinesisch, Koreanisch und Japanisch (Zeichen pro Minute)", "form.prefs.label.custom_css": "Benutzerdefiniertes CSS", @@ -348,7 +352,6 @@ "form.prefs.label.mark_read_on_view": "Einträge automatisch als gelesen markieren, wenn sie angezeigt werden", "form.prefs.label.mark_read_on_view_or_media_completion": "Einträge automatisch als gelesen markieren, wenn sie angezeigt werden. Audio/Video bei 90%% Wiedergabe als gelesen markieren", "form.prefs.label.media_playback_rate": "Wiedergabegeschwindigkeit von Audio/Video", - "form.prefs.label.always_open_external_links": "Artikel immer mit Öffnen der Links lesen", "form.prefs.label.show_reading_time": "Geschätzte Lesezeit für Artikel anzeigen", "form.prefs.label.theme": "Thema", "form.prefs.label.timezone": "Zeitzone", diff --git a/internal/locale/translations/el_EL.json b/internal/locale/translations/el_EL.json index 851b4233..b4820b27 100644 --- a/internal/locale/translations/el_EL.json +++ b/internal/locale/translations/el_EL.json @@ -233,6 +233,9 @@ "form.integration.instapaper_activate": "Αποθήκευση άρθρων στο Instapaper", "form.integration.instapaper_password": "Κωδικός Πρόσβασης Instapaper", "form.integration.instapaper_username": "Όνομα Χρήστη Instapaper", + "form.integration.karakeep_activate": "Αποθήκευση άρθρων στο Karakeep", + "form.integration.karakeep_api_key": "Κλειδί API Karakeep", + "form.integration.karakeep_url": "Τελικό σημείο Karakeep API", "form.integration.linkace_activate": "Save entries to LinkAce", "form.integration.linkace_api_key": "LinkAce API key", "form.integration.linkace_check_disabled": "Disable link check", @@ -328,6 +331,7 @@ "form.prefs.fieldset.global_feed_settings": "Global Feed Settings", "form.prefs.fieldset.reader_settings": "Reader Settings", "form.prefs.help.external_font_hosts": "Space separated list of external font hosts to allow. For example: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Ταξινόμηση κατηγοριών", "form.prefs.label.cjk_reading_speed": "Ταχύτητα ανάγνωσης για κινέζικα, κορεάτικα και ιαπωνικά (χαρακτήρες ανά λεπτό)", "form.prefs.label.custom_css": "Προσαρμοσμένο CSS", @@ -348,7 +352,6 @@ "form.prefs.label.mark_read_on_view": "Αυτόματη επισήμανση καταχωρήσεων ως αναγνωσμένων κατά την προβολή", "form.prefs.label.mark_read_on_view_or_media_completion": "Mark entries as read when viewed. For audio/video, mark as read at 90%% completion", "form.prefs.label.media_playback_rate": "Ταχύτητα αναπαραγωγής του ήχου/βίντεο", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Εμφάνιση εκτιμώμενου χρόνου ανάγνωσης για άρθρα", "form.prefs.label.theme": "Θέμα", "form.prefs.label.timezone": "Ζώνη Ώρας", diff --git a/internal/locale/translations/en_US.json b/internal/locale/translations/en_US.json index b8d53339..aa95d1d3 100644 --- a/internal/locale/translations/en_US.json +++ b/internal/locale/translations/en_US.json @@ -233,6 +233,9 @@ "form.integration.instapaper_activate": "Save entries to Instapaper", "form.integration.instapaper_password": "Instapaper Password", "form.integration.instapaper_username": "Instapaper Username", + "form.integration.karakeep_activate": "Save entries to Karakeep", + "form.integration.karakeep_api_key": "Karakeep API key", + "form.integration.karakeep_url": "Karakeep API Endpoint", "form.integration.linkace_activate": "Save entries to LinkAce", "form.integration.linkace_api_key": "LinkAce API key", "form.integration.linkace_check_disabled": "Disable link check", @@ -328,6 +331,7 @@ "form.prefs.fieldset.global_feed_settings": "Global Feed Settings", "form.prefs.fieldset.reader_settings": "Reader Settings", "form.prefs.help.external_font_hosts": "Space separated list of external font hosts to allow. For example: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Categories sorting", "form.prefs.label.cjk_reading_speed": "Reading speed for Chinese, Korean and Japanese (characters per minute)", "form.prefs.label.custom_css": "Custom CSS", @@ -348,7 +352,6 @@ "form.prefs.label.mark_read_on_view": "Automatically mark entries as read when viewed", "form.prefs.label.mark_read_on_view_or_media_completion": "Mark entries as read when viewed. For audio/video, mark as read at 90%% completion", "form.prefs.label.media_playback_rate": "Playback speed of the audio/video", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Show estimated reading time for entries", "form.prefs.label.theme": "Theme", "form.prefs.label.timezone": "Timezone", diff --git a/internal/locale/translations/es_ES.json b/internal/locale/translations/es_ES.json index a9da1bfc..cedf94b9 100644 --- a/internal/locale/translations/es_ES.json +++ b/internal/locale/translations/es_ES.json @@ -233,6 +233,9 @@ "form.integration.instapaper_activate": "Enviar artículos a Instapaper", "form.integration.instapaper_password": "Contraseña de Instapaper", "form.integration.instapaper_username": "Nombre de usuario de Instapaper", + "form.integration.karakeep_activate": "Enviar artículos a Karakeep", + "form.integration.karakeep_api_key": "Clave de API de Karakeep", + "form.integration.karakeep_url": "Acceso API de Karakeep", "form.integration.linkace_activate": "Guardar artículos en LinkAce", "form.integration.linkace_api_key": "Clave API de LinkAce", "form.integration.linkace_check_disabled": "Deshabilitar la comprobación de enlace", @@ -328,6 +331,7 @@ "form.prefs.fieldset.global_feed_settings": "Ajustes globales del feed", "form.prefs.fieldset.reader_settings": "Ajustes del lector", "form.prefs.help.external_font_hosts": "Space separated list of external font hosts to allow. For example: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Clasificación por categorías", "form.prefs.label.cjk_reading_speed": "Velocidad de lectura en chino, coreano y japonés (caracteres por minuto)", "form.prefs.label.custom_css": "CSS personalizado", @@ -348,7 +352,6 @@ "form.prefs.label.mark_read_on_view": "Marcar automáticamente las entradas como leídas cuando se vean", "form.prefs.label.mark_read_on_view_or_media_completion": "Marcar las entradas como leídas cuando se vean. Para audio/video, marcar como leído al 90%% de finalización", "form.prefs.label.media_playback_rate": "Velocidad de reproducción del audio/vídeo", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Mostrar el tiempo estimado de lectura de los artículos", "form.prefs.label.theme": "Tema", "form.prefs.label.timezone": "Zona horaria", diff --git a/internal/locale/translations/fi_FI.json b/internal/locale/translations/fi_FI.json index 778e8dbe..9f760861 100644 --- a/internal/locale/translations/fi_FI.json +++ b/internal/locale/translations/fi_FI.json @@ -233,6 +233,9 @@ "form.integration.instapaper_activate": "Tallenna artikkelit Instapaperiin", "form.integration.instapaper_password": "Instapaper-salasana", "form.integration.instapaper_username": "Instapaper-käyttäjätunnus", + "form.integration.karakeep_activate": "Tallenna artikkelit Karakeepiin", + "form.integration.karakeep_api_key": "Karakeep API-avain", + "form.integration.karakeep_url": "Karakeep API-päätepiste", "form.integration.linkace_activate": "Save entries to LinkAce", "form.integration.linkace_api_key": "LinkAce API key", "form.integration.linkace_check_disabled": "Disable link check", @@ -328,6 +331,7 @@ "form.prefs.fieldset.global_feed_settings": "Global Feed Settings", "form.prefs.fieldset.reader_settings": "Reader Settings", "form.prefs.help.external_font_hosts": "Space separated list of external font hosts to allow. For example: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Kategorioiden lajittelu", "form.prefs.label.cjk_reading_speed": "Kiinan, Korean ja Japanin lukunopeus (merkkejä minuutissa)", "form.prefs.label.custom_css": "Mukautettu CSS", @@ -348,7 +352,6 @@ "form.prefs.label.mark_read_on_view": "Merkitse kohdat automaattisesti luetuiksi, kun niitä tarkastellaan", "form.prefs.label.mark_read_on_view_or_media_completion": "Mark entries as read when viewed. For audio/video, mark as read at 90%% completion", "form.prefs.label.media_playback_rate": "Äänen/videon toistonopeus", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Näytä artikkeleiden arvioitu lukuaika", "form.prefs.label.theme": "Teema", "form.prefs.label.timezone": "Aikavyöhyke", diff --git a/internal/locale/translations/fr_FR.json b/internal/locale/translations/fr_FR.json index e8cf8f27..dd492a5f 100644 --- a/internal/locale/translations/fr_FR.json +++ b/internal/locale/translations/fr_FR.json @@ -233,6 +233,9 @@ "form.integration.instapaper_activate": "Sauvegarder les articles vers Instapaper", "form.integration.instapaper_password": "Mot de passe Instapaper", "form.integration.instapaper_username": "Nom d'utilisateur Instapaper", + "form.integration.karakeep_activate": "Sauvegarder les articles vers Karakeep", + "form.integration.karakeep_api_key": "Clé d'API de Karakeep", + "form.integration.karakeep_url": "URL de l'API de Karakeep", "form.integration.linkace_activate": "Enregistrer les entrées vers LinkAce", "form.integration.linkace_api_key": "Clé d'API LinkAce", "form.integration.linkace_check_disabled": "Désactiver la vérification des liens", @@ -328,6 +331,7 @@ "form.prefs.fieldset.global_feed_settings": "Paramètres globaux des abonnements", "form.prefs.fieldset.reader_settings": "Paramètres du lecteur", "form.prefs.help.external_font_hosts": "Liste de domaine externes autorisés, séparés par des espaces. Par exemple : « fonts.gstatic.com fonts.googleapis.com ».", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Colonne de tri des catégories", "form.prefs.label.cjk_reading_speed": "Vitesse de lecture pour le chinois, le coréen et le japonais (caractères par minute)", "form.prefs.label.custom_css": "Feuille de style personnalisée", @@ -348,7 +352,6 @@ "form.prefs.label.mark_read_on_view": "Marquer automatiquement les entrées comme lues lorsqu'elles sont consultées", "form.prefs.label.mark_read_on_view_or_media_completion": "Marquer automatiquement les entrées comme lues lorsqu'elles sont consultées. Pour l'audio/vidéo, marquer comme lues après 90%%", "form.prefs.label.media_playback_rate": "Vitesse de lecture de l'audio/vidéo", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Afficher le temps de lecture estimé des articles", "form.prefs.label.theme": "Thème", "form.prefs.label.timezone": "Fuseau horaire", diff --git a/internal/locale/translations/hi_IN.json b/internal/locale/translations/hi_IN.json index 49f4b354..8631eb55 100644 --- a/internal/locale/translations/hi_IN.json +++ b/internal/locale/translations/hi_IN.json @@ -233,6 +233,9 @@ "form.integration.instapaper_activate": "विषय-वस्तु को इंस्टापेपर में सहेजें", "form.integration.instapaper_password": "इंस्टापेपर पासवर्ड", "form.integration.instapaper_username": "इंस्टापेपर यूजरनेम", + "form.integration.karakeep_activate": "Save entries to Karakeep", + "form.integration.karakeep_api_key": "Karakeep API key", + "form.integration.karakeep_url": "Karakeep API Endpoint", "form.integration.linkace_activate": "Save entries to LinkAce", "form.integration.linkace_api_key": "LinkAce API key", "form.integration.linkace_check_disabled": "Disable link check", @@ -328,6 +331,7 @@ "form.prefs.fieldset.global_feed_settings": "Global Feed Settings", "form.prefs.fieldset.reader_settings": "Reader Settings", "form.prefs.help.external_font_hosts": "Space separated list of external font hosts to allow. For example: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "श्रेणियाँ छँटाई", "form.prefs.label.cjk_reading_speed": "चीनी, कोरियाई और जापानी के लिए पढ़ने की गति (प्रति मिनट वर्ण)", "form.prefs.label.custom_css": "कस्टम सीएसएस", @@ -348,7 +352,6 @@ "form.prefs.label.mark_read_on_view": "देखे जाने पर स्वचालित रूप से प्रविष्टियों को पढ़ने के रूप में चिह्नित करें", "form.prefs.label.mark_read_on_view_or_media_completion": "Mark entries as read when viewed. For audio/video, mark as read at 90%% completion", "form.prefs.label.media_playback_rate": "ऑडियो/वीडियो की प्लेबैक गति", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "विषय के लिए अनुमानित पढ़ने का समय दिखाएं", "form.prefs.label.theme": "थीम", "form.prefs.label.timezone": "समय क्षेत्र", diff --git a/internal/locale/translations/id_ID.json b/internal/locale/translations/id_ID.json index 4158d435..5e5e2070 100644 --- a/internal/locale/translations/id_ID.json +++ b/internal/locale/translations/id_ID.json @@ -231,6 +231,9 @@ "form.integration.instapaper_activate": "Simpan artikel ke Instapaper", "form.integration.instapaper_password": "Kata Sandi Instapaper", "form.integration.instapaper_username": "Nama Pengguna Instapaper", + "form.integration.karakeep_activate": "Simpan artikel ke Karakeep", + "form.integration.karakeep_api_key": "Kunci API Karakeep", + "form.integration.karakeep_url": "Titik URL API Karakeep", "form.integration.linkace_activate": "Simpan artikel ke LinkAce", "form.integration.linkace_api_key": "Kunci API LinkAce", "form.integration.linkace_check_disabled": "Matikan pemeriksaan tautan", @@ -326,6 +329,7 @@ "form.prefs.fieldset.global_feed_settings": "Pengaturan Umpan Global", "form.prefs.fieldset.reader_settings": "Pengaturan Pembaca", "form.prefs.help.external_font_hosts": "Daftar yang dipisah spasi untuk peladen penyedia fonta eksternal yang diperbolehkan. Seperti: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Baca artikel dengan membuka tautan eksternal", "form.prefs.label.categories_sorting_order": "Pengurutan Kategori", "form.prefs.label.cjk_reading_speed": "Kecepatan membaca untuk bahasa Tiongkok, Korea, dan Jepang (karakter per menit)", "form.prefs.label.custom_css": "Modifikasi CSS", @@ -346,7 +350,6 @@ "form.prefs.label.mark_read_on_view": "Secara otomatis menandai entri sebagai telah dibaca saat dilihat", "form.prefs.label.mark_read_on_view_or_media_completion": "Tandai entri sebagai telah dibaca ketika dilihat. Untuk audio/video, tandai sebagai telah dibaca ketika sudah 90% didengar/ditonton.", "form.prefs.label.media_playback_rate": "Kecepatan pemutaran audio/video", - "form.prefs.label.always_open_external_links": "Baca artikel dengan membuka tautan eksternal", "form.prefs.label.show_reading_time": "Tampilkan perkiraan waktu baca untuk artikel", "form.prefs.label.theme": "Tema", "form.prefs.label.timezone": "Zona Waktu", diff --git a/internal/locale/translations/it_IT.json b/internal/locale/translations/it_IT.json index 503f612b..10d824da 100644 --- a/internal/locale/translations/it_IT.json +++ b/internal/locale/translations/it_IT.json @@ -233,6 +233,9 @@ "form.integration.instapaper_activate": "Salva gli articoli su Instapaper", "form.integration.instapaper_password": "Password dell'account Instapaper", "form.integration.instapaper_username": "Nome utente dell'account Instapaper", + "form.integration.karakeep_activate": "Salva gli articoli su Karakeep", + "form.integration.karakeep_api_key": "API key dell'account Karakeep", + "form.integration.karakeep_url": "Endpoint dell'API di Karakeep", "form.integration.linkace_activate": "Salva gli articoli su LinkAce", "form.integration.linkace_api_key": "API key dell'account LinkAce", "form.integration.linkace_check_disabled": "Disabilita i controlli", @@ -328,6 +331,7 @@ "form.prefs.fieldset.global_feed_settings": "Global Feed Settings", "form.prefs.fieldset.reader_settings": "Reader Settings", "form.prefs.help.external_font_hosts": "Space separated list of external font hosts to allow. For example: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Ordinamento delle categorie", "form.prefs.label.cjk_reading_speed": "Velocità di lettura per cinese, coreano e giapponese (caratteri al minuto)", "form.prefs.label.custom_css": "CSS personalizzati", @@ -348,7 +352,6 @@ "form.prefs.label.mark_read_on_view": "Contrassegna automaticamente le voci come lette quando visualizzate", "form.prefs.label.mark_read_on_view_or_media_completion": "Mark entries as read when viewed. For audio/video, mark as read at 90%% completion", "form.prefs.label.media_playback_rate": "Velocità di riproduzione dell'audio/video", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Mostra il tempo di lettura stimato per gli articoli", "form.prefs.label.theme": "Tema", "form.prefs.label.timezone": "Fuso orario", diff --git a/internal/locale/translations/ja_JP.json b/internal/locale/translations/ja_JP.json index 56b5c85c..ae158bbc 100644 --- a/internal/locale/translations/ja_JP.json +++ b/internal/locale/translations/ja_JP.json @@ -231,6 +231,9 @@ "form.integration.instapaper_activate": "Instapaper に記事を保存する", "form.integration.instapaper_password": "Instapaper のパスワード", "form.integration.instapaper_username": "Instapaper のユーザー名", + "form.integration.karakeep_activate": "Karakeep に記事を保存する", + "form.integration.karakeep_api_key": "Karakeep の API key", + "form.integration.karakeep_url": "Karakeep の API Endpoint", "form.integration.linkace_activate": "Save entries to LinkAce", "form.integration.linkace_api_key": "LinkAce API key", "form.integration.linkace_check_disabled": "Disable link check", @@ -326,6 +329,7 @@ "form.prefs.fieldset.global_feed_settings": "Global Feed Settings", "form.prefs.fieldset.reader_settings": "Reader Settings", "form.prefs.help.external_font_hosts": "Space separated list of external font hosts to allow. For example: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "カテゴリの表示順", "form.prefs.label.cjk_reading_speed": "中国語、韓国語、日本語の読書速度(文字数/分)", "form.prefs.label.custom_css": "カスタム CSS", @@ -346,7 +350,6 @@ "form.prefs.label.mark_read_on_view": "表示時にエントリを自動的に既読としてマークします", "form.prefs.label.mark_read_on_view_or_media_completion": "Mark entries as read when viewed. For audio/video, mark as read at 90%% completion", "form.prefs.label.media_playback_rate": "オーディオ/ビデオの再生速度", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "記事の推定読書時間を表示する", "form.prefs.label.theme": "テーマ", "form.prefs.label.timezone": "タイムゾーン", diff --git a/internal/locale/translations/nan_Latn_pehoeji.json b/internal/locale/translations/nan_Latn_pehoeji.json index 6b4c27e3..ef714c5a 100644 --- a/internal/locale/translations/nan_Latn_pehoeji.json +++ b/internal/locale/translations/nan_Latn_pehoeji.json @@ -231,6 +231,9 @@ "form.integration.instapaper_activate": "Pó-chûn siau-sit kàu Instapaper", "form.integration.instapaper_password": "Instapaper bi̍t-bé", "form.integration.instapaper_username": "Instapaper Kháu-chō miâ", + "form.integration.karakeep_activate": "Pó-chûn siau-sit kàu Karakeep", + "form.integration.karakeep_api_key": "Karakeep API só-sî", + "form.integration.karakeep_url": "Karakeep API thâu", "form.integration.linkace_activate": "Pó-chûn siau-sit kàu LinkAce", "form.integration.linkace_api_key": "LinkAce API só-sî", "form.integration.linkace_check_disabled": "Thêng iōng liân-kiat kiám-cha", @@ -326,6 +329,7 @@ "form.prefs.fieldset.global_feed_settings": "Choân-he̍k siau-sit lâi-goân siat-tēng", "form.prefs.fieldset.reader_settings": "Ia̍t-tha̍k khì siat-tēng", "form.prefs.help.external_font_hosts": "Iōng khang-keh keh khui ún-chún ê gōa-pō͘ lī-hêng lâi-goân. Phì-lû \"fonts.gstatic.com fonts.googleapis.com\"", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Lūi-pia̍t hián-sī sūn-sū", "form.prefs.label.cjk_reading_speed": "Tiong-bûn, Hân-bûn, Li̍t-bûn tha̍k ê sok-tō͘ (múi hun-cheng ē-sái tha̍k kúi ê lī-goân)", "form.prefs.label.custom_css": "Chū tēng ê CSS", @@ -346,7 +350,6 @@ "form.prefs.label.mark_read_on_view": "Phah khui ê sî-chūn sūn-sòa kā siau-sit chù chòe tha̍k kè", "form.prefs.label.mark_read_on_view_or_media_completion": "Phah khui ê sî-chūn sūn-sòa kā siau-sit chù chòe tha̍k kè, m̄-koh nā-sī im-sìn, sī-sìn tio̍h tī hòng-sàng kàu 90%% ê si-chun chiah lâi chù", "form.prefs.label.media_playback_rate": "Im-sìn, sī-sìn pàng ê sok-tō͘", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Hián-sī siau-sit àn-sǹg ài gōa-kú lâi tha̍k", "form.prefs.label.theme": "Chú-tôe", "form.prefs.label.timezone": "Sî-khu", diff --git a/internal/locale/translations/nl_NL.json b/internal/locale/translations/nl_NL.json index ae236e1c..a8d8ef3e 100644 --- a/internal/locale/translations/nl_NL.json +++ b/internal/locale/translations/nl_NL.json @@ -233,6 +233,9 @@ "form.integration.instapaper_activate": "Artikelen opslaan in Instapaper", "form.integration.instapaper_password": "Instapaper wachtwoord", "form.integration.instapaper_username": "Instapaper gebruikersnaam", + "form.integration.karakeep_activate": "Artikelen opslaan in Karakeep", + "form.integration.karakeep_api_key": "Karakeep API-sleutel", + "form.integration.karakeep_url": "Karakeep URL", "form.integration.linkace_activate": "Artikelen opslaan in LinkAce", "form.integration.linkace_api_key": "LinkAce API-sleutel", "form.integration.linkace_check_disabled": "Koppelingcontrole uitschakelen", @@ -328,6 +331,7 @@ "form.prefs.fieldset.global_feed_settings": "Globale Feed Instellingen", "form.prefs.fieldset.reader_settings": "Lees Instellingen", "form.prefs.help.external_font_hosts": "Space separated list of external font hosts to allow. For example: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Volgorde categorieën", "form.prefs.label.cjk_reading_speed": "Leessnelheid voor Chinees, Koreaans en Japans (tekens per minuut)", "form.prefs.label.custom_css": "Aangepaste CSS", @@ -348,7 +352,6 @@ "form.prefs.label.mark_read_on_view": "Markeer artikelen automatisch als gelezen wanneer ze worden bekeken", "form.prefs.label.mark_read_on_view_or_media_completion": "Markeer artikelen als gelezen wanneer ze worden bekeken. Voor audio/video, markeer als gelezen bij 90%% voltooiing", "form.prefs.label.media_playback_rate": "Afspeelsnelheid van de audio/video", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Toon geschatte leestijd van artikelen", "form.prefs.label.theme": "Thema", "form.prefs.label.timezone": "Tijdzone", diff --git a/internal/locale/translations/pl_PL.json b/internal/locale/translations/pl_PL.json index c2663f47..8b88a761 100644 --- a/internal/locale/translations/pl_PL.json +++ b/internal/locale/translations/pl_PL.json @@ -235,6 +235,9 @@ "form.integration.instapaper_activate": "Zapisuj wpisy w Instapaper", "form.integration.instapaper_password": "Hasło do Instapaper", "form.integration.instapaper_username": "Login do Instapaper", + "form.integration.karakeep_activate": "Zapisuj wpisy w Karakeep", + "form.integration.karakeep_api_key": "Klucz API do Karakeep", + "form.integration.karakeep_url": "Punkt końcowy API Karakeep", "form.integration.linkace_activate": "Zapisuj wpisy w LinkAce", "form.integration.linkace_api_key": "Klucz API do LinkAce", "form.integration.linkace_check_disabled": "Wyłącz sprawdzanie łączy", @@ -330,6 +333,7 @@ "form.prefs.fieldset.global_feed_settings": "Globalne ustawienia kanałów", "form.prefs.fieldset.reader_settings": "Ustawienia czytnika", "form.prefs.help.external_font_hosts": "Lista hostów zewnętrznych czcionek, na które należy zezwolić, rozdzielona spacjami. Na przykład: „fonts.gstatic.com fonts.googleapis.com”.", + "form.prefs.label.always_open_external_links": "Czytaj artykuły, otwierając łącza zewnętrzne", "form.prefs.label.categories_sorting_order": "Sortowanie kategorii", "form.prefs.label.cjk_reading_speed": "Szybkość czytania w języku chińskim, koreańskim i japońskim (znaki na minutę)", "form.prefs.label.custom_css": "Niestandardowy CSS", @@ -350,7 +354,6 @@ "form.prefs.label.mark_read_on_view": "Automatycznie oznacz wpisy jako przeczytane podczas przeglądania", "form.prefs.label.mark_read_on_view_or_media_completion": "Oznacz wpisy jako przeczytane po wyświetleniu. W przypadku audio i wideo oznacz jako przeczytane po ukończeniu 90%%", "form.prefs.label.media_playback_rate": "Szybkość odtwarzania audio i wideo", - "form.prefs.label.always_open_external_links": "Czytaj artykuły, otwierając łącza zewnętrzne", "form.prefs.label.show_reading_time": "Pokaż szacowany czas czytania wpisów", "form.prefs.label.theme": "Wygląd", "form.prefs.label.timezone": "Strefa czasowa", diff --git a/internal/locale/translations/pt_BR.json b/internal/locale/translations/pt_BR.json index fb588649..86a3e346 100644 --- a/internal/locale/translations/pt_BR.json +++ b/internal/locale/translations/pt_BR.json @@ -233,6 +233,9 @@ "form.integration.instapaper_activate": "Salvar itens no Instapaper", "form.integration.instapaper_password": "Senha do Instapaper", "form.integration.instapaper_username": "Nome do usuário do Instapaper", + "form.integration.karakeep_activate": "Salvar itens no Karakeep", + "form.integration.karakeep_api_key": "Chave de API do Karakeep", + "form.integration.karakeep_url": "Endpoint de API do Karakeep", "form.integration.linkace_activate": "Save entries to LinkAce", "form.integration.linkace_api_key": "LinkAce API key", "form.integration.linkace_check_disabled": "Disable link check", @@ -328,6 +331,7 @@ "form.prefs.fieldset.global_feed_settings": "Global Feed Settings", "form.prefs.fieldset.reader_settings": "Reader Settings", "form.prefs.help.external_font_hosts": "Space separated list of external font hosts to allow. For example: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Classificação das categorias", "form.prefs.label.cjk_reading_speed": "Velocidade de leitura para chinês, coreano e japonês (caracteres por minuto)", "form.prefs.label.custom_css": "CSS customizado", @@ -348,7 +352,6 @@ "form.prefs.label.mark_read_on_view": "Marcar automaticamente as entradas como lidas quando visualizadas", "form.prefs.label.mark_read_on_view_or_media_completion": "Mark entries as read when viewed. For audio/video, mark as read at 90%% completion", "form.prefs.label.media_playback_rate": "Velocidade de reprodução do áudio/vídeo", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Mostrar tempo estimado de leitura de artigos", "form.prefs.label.theme": "Tema", "form.prefs.label.timezone": "Fuso horário", diff --git a/internal/locale/translations/ro_RO.json b/internal/locale/translations/ro_RO.json index 40d1b7b4..e9ed17e9 100644 --- a/internal/locale/translations/ro_RO.json +++ b/internal/locale/translations/ro_RO.json @@ -235,6 +235,9 @@ "form.integration.instapaper_activate": "Salvează înregistrările pe Instapaper", "form.integration.instapaper_password": "Parolă Instapaper", "form.integration.instapaper_username": "Utilizator Instapaper", + "form.integration.karakeep_activate": "Salvare înregistrări în Karakeep", + "form.integration.karakeep_api_key": "Cheie API Karakeep", + "form.integration.karakeep_url": "Punct acces API Karakeep", "form.integration.linkace_activate": "Salvează intrările în LinkAce", "form.integration.linkace_api_key": "Cheie API LinkAce", "form.integration.linkace_check_disabled": "Dezactivează verificarea link-urilor", @@ -330,6 +333,7 @@ "form.prefs.fieldset.global_feed_settings": "Setări Globale pt. Flux", "form.prefs.fieldset.reader_settings": "Setări Citire", "form.prefs.help.external_font_hosts": "Lista fonturilor de pe gazdă separate de virgulă care poate fi utilizate. De exemplu: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Sortare categorii", "form.prefs.label.cjk_reading_speed": "Viteză de citire pentru Chineză, Coreană și Japoneză (caractere pe minut)", "form.prefs.label.custom_css": "CSS personalizat", @@ -350,7 +354,6 @@ "form.prefs.label.mark_read_on_view": "Marchează intrările ca citite la vizualizare", "form.prefs.label.mark_read_on_view_or_media_completion": "Marchează intrările ca citite la vizualizare. Pentru audio/video, marchează ca citit la redarea a 90%% de conținut", "form.prefs.label.media_playback_rate": "Viteza de rulare audio/video", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Afișare timp estimat de citire pentru înregistrări", "form.prefs.label.theme": "Temă", "form.prefs.label.timezone": "Fus orar", diff --git a/internal/locale/translations/ru_RU.json b/internal/locale/translations/ru_RU.json index f69fdeb8..5e89597e 100644 --- a/internal/locale/translations/ru_RU.json +++ b/internal/locale/translations/ru_RU.json @@ -235,6 +235,9 @@ "form.integration.instapaper_activate": "Сохранять статьи в Instapaper", "form.integration.instapaper_password": "Пароль Instapaper", "form.integration.instapaper_username": "Имя пользователя Instapaper", + "form.integration.karakeep_activate": "Сохранять статьи в Karakeep", + "form.integration.karakeep_api_key": "API-ключ Karakeep", + "form.integration.karakeep_url": "Конечная точка Karakeep API", "form.integration.linkace_activate": "Сохранять статьи в LinkAce", "form.integration.linkace_api_key": "API-ключ LinkAce", "form.integration.linkace_check_disabled": "Отключить проверку ссылок", @@ -330,6 +333,7 @@ "form.prefs.fieldset.global_feed_settings": "Глобальные настройки подписок", "form.prefs.fieldset.reader_settings": "Настройки чтения", "form.prefs.help.external_font_hosts": "Список разрешённых внешних хостов для шрифтов, разделенных пробелами. Например: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Сортировка категорий", "form.prefs.label.cjk_reading_speed": "Скорость чтения на китайском, корейском и японском языках (знаков в минуту)", "form.prefs.label.custom_css": "Пользовательский CSS", @@ -350,7 +354,6 @@ "form.prefs.label.mark_read_on_view": "Автоматически отмечать записи как прочитанные при просмотре", "form.prefs.label.mark_read_on_view_or_media_completion": "Отмечать статьи как прочитанные при просмотре. Для аудио/видео - при 90%% завершения воспроизведения", "form.prefs.label.media_playback_rate": "Скорость воспроизведения аудио/видео", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Показать примерное время чтения статей", "form.prefs.label.theme": "Тема", "form.prefs.label.timezone": "Часовой пояс", diff --git a/internal/locale/translations/tr_TR.json b/internal/locale/translations/tr_TR.json index b3250e71..809350db 100644 --- a/internal/locale/translations/tr_TR.json +++ b/internal/locale/translations/tr_TR.json @@ -233,6 +233,9 @@ "form.integration.instapaper_activate": "Makaleleri Instapaper'a kaydet", "form.integration.instapaper_password": "Instapaper Parolası", "form.integration.instapaper_username": "Instapaper Kullanıcı Adı", + "form.integration.karakeep_activate": "Makaleleri Karakeep'a kaydet", + "form.integration.karakeep_api_key": "Karakeep API anahtarı", + "form.integration.karakeep_url": "Karakeep API Uç Noktası", "form.integration.linkace_activate": "Makaleleri LinkAce'e kaydet", "form.integration.linkace_api_key": "LinkAce API anahtarı", "form.integration.linkace_check_disabled": "Link kontrolünü devre dışı bırak", @@ -328,6 +331,7 @@ "form.prefs.fieldset.global_feed_settings": "Genel Besleme Ayarları", "form.prefs.fieldset.reader_settings": "Okuyucu Ayarları", "form.prefs.help.external_font_hosts": "Space separated list of external font hosts to allow. For example: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Kategori sıralaması", "form.prefs.label.cjk_reading_speed": "Çince, Korece ve Japonca için okuma hızı (dakika başına karakter)", "form.prefs.label.custom_css": "Özel CSS", @@ -348,7 +352,6 @@ "form.prefs.label.mark_read_on_view": "Makaleler görüntülendiğinde otomatik olarak okundu olarak işaretle", "form.prefs.label.mark_read_on_view_or_media_completion": "Mark entries as read when viewed. For audio/video, mark as read at 90%% completion", "form.prefs.label.media_playback_rate": "Ses/video oynatma hızı", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Makaleler için tahmini okuma süresini göster", "form.prefs.label.theme": "Tema", "form.prefs.label.timezone": "Saat Dilimi", diff --git a/internal/locale/translations/uk_UA.json b/internal/locale/translations/uk_UA.json index b55fe438..4238963a 100644 --- a/internal/locale/translations/uk_UA.json +++ b/internal/locale/translations/uk_UA.json @@ -235,6 +235,9 @@ "form.integration.instapaper_activate": "Зберігати статті до Instapaper", "form.integration.instapaper_password": "Пароль Instapaper", "form.integration.instapaper_username": "Ім’я користувача Instapaper", + "form.integration.karakeep_activate": "Зберігати статті до Karakeep", + "form.integration.karakeep_api_key": "Ключ API Karakeep", + "form.integration.karakeep_url": "Karakeep API Endpoint", "form.integration.linkace_activate": "Save entries to LinkAce", "form.integration.linkace_api_key": "LinkAce API key", "form.integration.linkace_check_disabled": "Disable link check", @@ -330,6 +333,7 @@ "form.prefs.fieldset.global_feed_settings": "Global Feed Settings", "form.prefs.fieldset.reader_settings": "Reader Settings", "form.prefs.help.external_font_hosts": "Space separated list of external font hosts to allow. For example: \"fonts.gstatic.com fonts.googleapis.com\".", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "Сортування за категоріями", "form.prefs.label.cjk_reading_speed": "Швидкість читання для китайської, корейської та японської мови (символів на хвилину)", "form.prefs.label.custom_css": "Спеціальний CSS", @@ -350,7 +354,6 @@ "form.prefs.label.mark_read_on_view": "Автоматично позначати записи як прочитані під час перегляду", "form.prefs.label.mark_read_on_view_or_media_completion": "Mark entries as read when viewed. For audio/video, mark as read at 90%% completion", "form.prefs.label.media_playback_rate": "Швидкість відтворення аудіо/відео", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "Показувати приблизний час читання для записів", "form.prefs.label.theme": "Тема", "form.prefs.label.timezone": "Часовий пояс", diff --git a/internal/locale/translations/zh_CN.json b/internal/locale/translations/zh_CN.json index e1de9a1c..f5cce230 100644 --- a/internal/locale/translations/zh_CN.json +++ b/internal/locale/translations/zh_CN.json @@ -231,6 +231,9 @@ "form.integration.instapaper_activate": "保存文章到 Instapaper", "form.integration.instapaper_password": "Instapaper 密码", "form.integration.instapaper_username": "Instapaper 用户名", + "form.integration.karakeep_activate": "保存文章到 Karakeep", + "form.integration.karakeep_api_key": "Karakeep API 密钥", + "form.integration.karakeep_url": "Karakeep API 端点", "form.integration.linkace_activate": "保存文章到 LinkAce", "form.integration.linkace_api_key": "LinkAce API 密钥", "form.integration.linkace_check_disabled": "关闭链接检查", @@ -326,6 +329,7 @@ "form.prefs.fieldset.global_feed_settings": "全局订阅源设置", "form.prefs.fieldset.reader_settings": "阅读器设置", "form.prefs.help.external_font_hosts": "允许外部字体托管的空格分隔列表。例如:\"fonts.gstatic.com fonts.googleapis.com\"。", + "form.prefs.label.always_open_external_links": "打开外部链接阅读文章", "form.prefs.label.categories_sorting_order": "分类排序", "form.prefs.label.cjk_reading_speed": "中文、韩文和日文的阅读速度(每分钟字符数)", "form.prefs.label.custom_css": "自定义 CSS", @@ -346,7 +350,6 @@ "form.prefs.label.mark_read_on_view": "查看时自动将条目标记为已读", "form.prefs.label.mark_read_on_view_or_media_completion": "当浏览时标记条目为已读。对于音频/视频,当播放完成90%%时标记为已读", "form.prefs.label.media_playback_rate": "音频/视频的播放速度", - "form.prefs.label.always_open_external_links": "打开外部链接阅读文章", "form.prefs.label.show_reading_time": "显示文章的预计阅读时间", "form.prefs.label.theme": "主题", "form.prefs.label.timezone": "时区", diff --git a/internal/locale/translations/zh_TW.json b/internal/locale/translations/zh_TW.json index 5f7ea975..4c0f6d0c 100644 --- a/internal/locale/translations/zh_TW.json +++ b/internal/locale/translations/zh_TW.json @@ -231,6 +231,9 @@ "form.integration.instapaper_activate": "儲存文章到 Instapaper", "form.integration.instapaper_password": "Instapaper 密碼", "form.integration.instapaper_username": "Instapaper 使用者名稱", + "form.integration.karakeep_activate": "儲存文章到 Karakeep", + "form.integration.karakeep_api_key": "Karakeep API 金鑰", + "form.integration.karakeep_url": "Karakeep API 端點", "form.integration.linkace_activate": "儲存文章到 LinkAce", "form.integration.linkace_api_key": "LinkAce API 金鑰", "form.integration.linkace_check_disabled": "停用連結檢查", @@ -326,6 +329,7 @@ "form.prefs.fieldset.global_feed_settings": "全域 Feed 設定", "form.prefs.fieldset.reader_settings": "閱讀器設定", "form.prefs.help.external_font_hosts": "以空白分隔允許的外部字型來源。例如:「fonts.gstatic.com fonts.googleapis.com」。", + "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.categories_sorting_order": "分類排序", "form.prefs.label.cjk_reading_speed": "中文、韓文和日文的閱讀速度(每分鐘字元數)", "form.prefs.label.custom_css": "自訂 CSS", @@ -346,7 +350,6 @@ "form.prefs.label.mark_read_on_view": "檢視時自動將文章標記為已讀", "form.prefs.label.mark_read_on_view_or_media_completion": "檢視文章即標記為已讀;若是音訊/視訊則在 90% 播放完成時標記", "form.prefs.label.media_playback_rate": "音訊/視訊播放速度", - "form.prefs.label.always_open_external_links": "Read articles by opening external links", "form.prefs.label.show_reading_time": "顯示文章的預計閱讀時間", "form.prefs.label.theme": "主題", "form.prefs.label.timezone": "時區", diff --git a/internal/model/integration.go b/internal/model/integration.go index 5311b04e..113ad4e4 100644 --- a/internal/model/integration.go +++ b/internal/model/integration.go @@ -94,6 +94,9 @@ type Integration struct { OmnivoreEnabled bool OmnivoreAPIKey string OmnivoreURL string + KarakeepEnabled bool + KarakeepAPIKey string + KarakeepURL string RaindropEnabled bool RaindropToken string RaindropCollectionID string diff --git a/internal/storage/integration.go b/internal/storage/integration.go index 4ab85861..3d099c4e 100644 --- a/internal/storage/integration.go +++ b/internal/storage/integration.go @@ -220,7 +220,10 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) { pushover_token, pushover_device, pushover_prefix, - rssbridge_token + rssbridge_token, + karakeep_enabled, + karakeep_api_key, + karakeep_url FROM integrations WHERE @@ -340,6 +343,9 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) { &integration.PushoverDevice, &integration.PushoverPrefix, &integration.RSSBridgeToken, + &integration.KarakeepEnabled, + &integration.KarakeepAPIKey, + &integration.KarakeepURL, ) switch { case err == sql.ErrNoRows: @@ -467,9 +473,12 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error { pushover_token=$108, pushover_device=$109, pushover_prefix=$110, - rssbridge_token=$111 + rssbridge_token=$111, + karakeep_enabled=$112, + karakeep_api_key=$113, + karakeep_url=$114 WHERE - user_id=$112 + user_id=$115 ` _, err := s.db.Exec( query, @@ -584,6 +593,9 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error { integration.PushoverDevice, integration.PushoverPrefix, integration.RSSBridgeToken, + integration.KarakeepEnabled, + integration.KarakeepAPIKey, + integration.KarakeepURL, integration.UserID, ) @@ -622,6 +634,7 @@ func (s *Storage) HasSaveEntry(userID int64) (result bool) { shaarli_enabled='t' OR webhook_enabled='t' OR omnivore_enabled='t' OR + karakeep_enabled='t' OR raindrop_enabled='t' OR betula_enabled='t' OR cubox_enabled='t' OR diff --git a/internal/template/templates/views/integrations.html b/internal/template/templates/views/integrations.html index 86948f06..05688781 100644 --- a/internal/template/templates/views/integrations.html +++ b/internal/template/templates/views/integrations.html @@ -364,6 +364,25 @@ +
+ Karakeep +
+ + + + + + + + +
+ +
+
+
+
Pinboard
diff --git a/internal/ui/form/integration.go b/internal/ui/form/integration.go index 09c2a5f2..7f35fd99 100644 --- a/internal/ui/form/integration.go +++ b/internal/ui/form/integration.go @@ -97,6 +97,9 @@ type IntegrationForm struct { OmnivoreEnabled bool OmnivoreAPIKey string OmnivoreURL string + KarakeepEnabled bool + KarakeepAPIKey string + KarakeepURL string RaindropEnabled bool RaindropToken string RaindropCollectionID string @@ -209,6 +212,9 @@ func (i IntegrationForm) Merge(integration *model.Integration) { integration.OmnivoreEnabled = i.OmnivoreEnabled integration.OmnivoreAPIKey = i.OmnivoreAPIKey integration.OmnivoreURL = i.OmnivoreURL + integration.KarakeepEnabled = i.KarakeepEnabled + integration.KarakeepAPIKey = i.KarakeepAPIKey + integration.KarakeepURL = i.KarakeepURL integration.RaindropEnabled = i.RaindropEnabled integration.RaindropToken = i.RaindropToken integration.RaindropCollectionID = i.RaindropCollectionID @@ -324,6 +330,9 @@ func NewIntegrationForm(r *http.Request) *IntegrationForm { OmnivoreEnabled: r.FormValue("omnivore_enabled") == "1", OmnivoreAPIKey: r.FormValue("omnivore_api_key"), OmnivoreURL: r.FormValue("omnivore_url"), + KarakeepEnabled: r.FormValue("karakeep_enabled") == "1", + KarakeepAPIKey: r.FormValue("karakeep_api_key"), + KarakeepURL: r.FormValue("karakeep_url"), RaindropEnabled: r.FormValue("raindrop_enabled") == "1", RaindropToken: r.FormValue("raindrop_token"), RaindropCollectionID: r.FormValue("raindrop_collection_id"), diff --git a/internal/ui/integration_show.go b/internal/ui/integration_show.go index 57ef3400..95070c10 100644 --- a/internal/ui/integration_show.go +++ b/internal/ui/integration_show.go @@ -111,6 +111,9 @@ func (h *handler) showIntegrationPage(w http.ResponseWriter, r *http.Request) { OmnivoreEnabled: integration.OmnivoreEnabled, OmnivoreAPIKey: integration.OmnivoreAPIKey, OmnivoreURL: integration.OmnivoreURL, + KarakeepEnabled: integration.KarakeepEnabled, + KarakeepAPIKey: integration.KarakeepAPIKey, + KarakeepURL: integration.KarakeepURL, RaindropEnabled: integration.RaindropEnabled, RaindropToken: integration.RaindropToken, RaindropCollectionID: integration.RaindropCollectionID,