forked from akai/readest
feat: Readwise highlights sync (#3311)
This commit is contained in:
@@ -1085,5 +1085,24 @@
|
||||
"Next Image": "الصورة التالية",
|
||||
"Zoomed": "مكبّر",
|
||||
"Zoom level": "مستوى التكبير",
|
||||
"Table viewer": "عارض الجداول"
|
||||
"Table viewer": "عارض الجداول",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "تعذر الاتصال بـ Readwise. يرجى التحقق من اتصال الشبكة لديك.",
|
||||
"Invalid Readwise access token": "رمز وصول Readwise غير صالح",
|
||||
"Disconnected from Readwise": "تم قطع الاتصال بـ Readwise",
|
||||
"Never": "أبداً",
|
||||
"Readwise Settings": "إعدادات Readwise",
|
||||
"Connected to Readwise": "متصل بـ Readwise",
|
||||
"Last synced: {{time}}": "آخر مزامنة: {{time}}",
|
||||
"Sync Enabled": "تم تمكين المزامنة",
|
||||
"Disconnect": "قطع الاتصال",
|
||||
"Connect your Readwise account to sync highlights.": "قم بتوصيل حساب Readwise الخاص بك لمزامنة التمييزات.",
|
||||
"Get your access token at": "احصل على رمز الوصول الخاص بك من",
|
||||
"Access Token": "رمز الوصول",
|
||||
"Paste your Readwise access token": "الصق رمز وصول Readwise الخاص بك",
|
||||
"Config": "تكوين",
|
||||
"Readwise Sync": "مزامنة Readwise",
|
||||
"Push Highlights": "إرسال التمييزات",
|
||||
"Highlights synced to Readwise": "تمت مزامنة التمييزات مع Readwise",
|
||||
"Readwise sync failed: no internet connection": "فشلت مزامنة Readwise: لا يوجد اتصال بالإنترنت",
|
||||
"Readwise sync failed: {{error}}": "فشلت مزامنة Readwise: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1037,5 +1037,24 @@
|
||||
"Next Image": "পরবর্তী চিত্র",
|
||||
"Zoomed": "জুম করা হয়েছে",
|
||||
"Zoom level": "জুম স্তর",
|
||||
"Table viewer": "টেবিল প্রদর্শক"
|
||||
"Table viewer": "টেবিল প্রদর্শক",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Readwise এর সাথে সংযোগ করতে অক্ষম। আপনার নেটওয়ার্ক সংযোগটি পরীক্ষা করুন।",
|
||||
"Invalid Readwise access token": "অকার্যকর Readwise অ্যাক্সেস টোকেন",
|
||||
"Disconnected from Readwise": "Readwise থেকে সংযোগ বিচ্ছিন্ন হয়েছে",
|
||||
"Never": "কখনো না",
|
||||
"Readwise Settings": "Readwise সেটিংস",
|
||||
"Connected to Readwise": "Readwise এর সাথে সংযুক্ত",
|
||||
"Last synced: {{time}}": "শেষ সিঙ্ক করা হয়েছে: {{time}}",
|
||||
"Sync Enabled": "সিঙ্কিং সক্ষম",
|
||||
"Disconnect": "সংযোগ বিচ্ছিন্ন করুন",
|
||||
"Connect your Readwise account to sync highlights.": "হাইলাইটগুলি সিঙ্ক করার জন্য আপনার Readwise অ্যাকাউন্টটি সংযোগ করুন।",
|
||||
"Get your access token at": "আপনার অ্যাক্সেস টোকেনটি এখানে পাবেন",
|
||||
"Access Token": "অ্যাক্সেস টোকেন",
|
||||
"Paste your Readwise access token": "আপনার Readwise অ্যাক্সেস টোকেনটি পেস্ট করুন",
|
||||
"Config": "কনফিগ",
|
||||
"Readwise Sync": "Readwise সিঙ্ক",
|
||||
"Push Highlights": "হাইলাইট পাঠান",
|
||||
"Highlights synced to Readwise": "হাইলাইটগুলি Readwise এ সিঙ্ক করা হয়েছে",
|
||||
"Readwise sync failed: no internet connection": "Readwise সিঙ্ক ব্যর্থ হয়েছে: ইন্টারনেট সংযোগ নেই",
|
||||
"Readwise sync failed: {{error}}": "Readwise সিঙ্ক ব্যর্থ হয়েছে: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1025,5 +1025,24 @@
|
||||
"Next Image": "རྗེས་མའི་པར་རིས།",
|
||||
"Zoomed": "ཆེར་བསྐྱེད་ཟིན།",
|
||||
"Zoom level": "ཆེར་བསྐྱེད་རིམ་པ།",
|
||||
"Table viewer": "རེའུ་མིག་ལྟ་བྱེད།"
|
||||
"Table viewer": "རེའུ་མིག་ལྟ་བྱེད།",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Readwise ལ་མཐུད་ཐུབ་མ་སོང་། ཁྱེད་ཀྱི་དྲ་རྒྱའི་མཐུད་ལམ་ལ་བརྟག་དཔྱད་གནང་རོགས།",
|
||||
"Invalid Readwise access token": "Readwise འཛུལ་སྤྱོད་ལག་ཁྱེར་ནོར་འདུག",
|
||||
"Disconnected from Readwise": "Readwise ནས་མཐུད་ལམ་བཅད་ཟིན།",
|
||||
"Never": "ནམ་ཡང་མིན།",
|
||||
"Readwise Settings": "Readwise སྒྲིག་བཀོད།",
|
||||
"Connected to Readwise": "Readwise ལ་མཐུད་ཟིན།",
|
||||
"Last synced: {{time}}": "མཐའ་མའི་མཉམ་བྱུང་དུས་ཚོད། {{time}}",
|
||||
"Sync Enabled": "མཉམ་བྱུང་ནུས་པ་སྤར་ཟིན།",
|
||||
"Disconnect": "མཐུད་ལམ་གཅོད་པ།",
|
||||
"Connect your Readwise account to sync highlights.": "ཁྱེད་ཀྱི་ Readwise རྩིས་ཐོ་མཐུད་ནས་བཀོད་མཆན་མཉམ་བྱུང་གནང་རོགས།",
|
||||
"Get your access token at": "འཛུལ་སྤྱོད་ལག་ཁྱེར་འདི་ནས་ལེན་རོགས།",
|
||||
"Access Token": "འཛུལ་སྤྱོད་ལག་ཁྱེེར།",
|
||||
"Paste your Readwise access token": "Readwise འཛུལ་སྤྱོད་ལག་ཁྱེར་འདིར་སྦྱོར་རོགས།",
|
||||
"Config": "སྒྲིག་བཀོད།",
|
||||
"Readwise Sync": "Readwise མཉམ་བྱུང་།",
|
||||
"Push Highlights": "བཀོད་མཆན་སྐྱེལ་བ།",
|
||||
"Highlights synced to Readwise": "བཀོད་མཆན་ Readwise ལ་མཉམ་བྱུང་བྱས་ཟིན།",
|
||||
"Readwise sync failed: no internet connection": "Readwise མཉམ་བྱུང་མ་ཐུབ། དྲ་རྒྱའི་མཐུད་ལམ་མི་འདུག",
|
||||
"Readwise sync failed: {{error}}": "Readwise མཉམ་བྱུང་མ་ཐུབ། {{error}}"
|
||||
}
|
||||
|
||||
@@ -1037,5 +1037,24 @@
|
||||
"Next Image": "Nächstes Bild",
|
||||
"Zoomed": "Gezoomt",
|
||||
"Zoom level": "Zoomstufe",
|
||||
"Table viewer": "Tabellenbetrachter"
|
||||
"Table viewer": "Tabellenbetrachter",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Verbindung zu Readwise nicht möglich. Bitte überprüfen Sie Ihre Netzwerkverbindung.",
|
||||
"Invalid Readwise access token": "Ungültiges Readwise-Zugriffstoken",
|
||||
"Disconnected from Readwise": "Von Readwise getrennt",
|
||||
"Never": "Nie",
|
||||
"Readwise Settings": "Readwise-Einstellungen",
|
||||
"Connected to Readwise": "Mit Readwise verbunden",
|
||||
"Last synced: {{time}}": "Zuletzt synchronisiert: {{time}}",
|
||||
"Sync Enabled": "Synchronisierung aktiviert",
|
||||
"Disconnect": "Trennen",
|
||||
"Connect your Readwise account to sync highlights.": "Verbinden Sie Ihr Readwise-Konto, um Highlights zu synchronisieren.",
|
||||
"Get your access token at": "Holen Sie sich Ihr Zugriffstoken unter",
|
||||
"Access Token": "Zugriffstoken",
|
||||
"Paste your Readwise access token": "Fügen Sie Ihr Readwise-Zugriffstoken ein",
|
||||
"Config": "Konfiguration",
|
||||
"Readwise Sync": "Readwise-Synchronisierung",
|
||||
"Push Highlights": "Highlights übertragen",
|
||||
"Highlights synced to Readwise": "Highlights mit Readwise synchronisiert",
|
||||
"Readwise sync failed: no internet connection": "Readwise-Synchronisierung fehlgeschlagen: Keine Internetverbindung",
|
||||
"Readwise sync failed: {{error}}": "Readwise-Synchronisierung fehlgeschlagen: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1037,5 +1037,24 @@
|
||||
"Next Image": "Επόμενη εικόνα",
|
||||
"Zoomed": "Ζουμαρισμένο",
|
||||
"Zoom level": "Επίπεδο ζουμ",
|
||||
"Table viewer": "Πρόγραμμα προβολής πινάκων"
|
||||
"Table viewer": "Πρόγραμμα προβολής πινάκων",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Αδυναμία σύνδεσης στο Readwise. Ελέγξτε τη σύνδεση του δικτύου σας.",
|
||||
"Invalid Readwise access token": "Μη έγκυρο διακριτικό πρόσβασης Readwise",
|
||||
"Disconnected from Readwise": "Αποσυνδέθηκε από το Readwise",
|
||||
"Never": "Ποτέ",
|
||||
"Readwise Settings": "Ρυθμίσεις Readwise",
|
||||
"Connected to Readwise": "Συνδέθηκε στο Readwise",
|
||||
"Last synced: {{time}}": "Τελευταίος συγχρονισμός: {{time}}",
|
||||
"Sync Enabled": "Ο συγχρονισμός ενεργοποιήθηκε",
|
||||
"Disconnect": "Αποσύνδεση",
|
||||
"Connect your Readwise account to sync highlights.": "Συνδέστε τον λογαριασμό σας Readwise για να συγχρονίσετε τις επισημάνσεις.",
|
||||
"Get your access token at": "Αποκτήστε το διακριτικό πρόσβασής σας στο",
|
||||
"Access Token": "Διακριτικό πρόσβασης",
|
||||
"Paste your Readwise access token": "Επικολλήστε το διακριτικό πρόσβασης Readwise",
|
||||
"Config": "Ρύθμιση παραμέτρων",
|
||||
"Readwise Sync": "Συγχρονισμός Readwise",
|
||||
"Push Highlights": "Προώθηση επισημάνσεων",
|
||||
"Highlights synced to Readwise": "Οι επισημάνσεις συγχρονίστηκαν στο Readwise",
|
||||
"Readwise sync failed: no internet connection": "Ο συγχρονισμός Readwise απέτυχε: δεν υπάρχει σύνδεση στο διαδίκτυο",
|
||||
"Readwise sync failed: {{error}}": "Ο συγχρονισμός Readwise απέτυχε: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1049,5 +1049,24 @@
|
||||
"Next Image": "Imagen siguiente",
|
||||
"Zoomed": "Con zoom",
|
||||
"Zoom level": "Nivel de zoom",
|
||||
"Table viewer": "Visor de tablas"
|
||||
"Table viewer": "Visor de tablas",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "No se pudo conectar a Readwise. Por favor, comprueba tu conexión a la red.",
|
||||
"Invalid Readwise access token": "Token de acceso a Readwise no válido",
|
||||
"Disconnected from Readwise": "Desconectado de Readwise",
|
||||
"Never": "Nunca",
|
||||
"Readwise Settings": "Ajustes de Readwise",
|
||||
"Connected to Readwise": "Conectado a Readwise",
|
||||
"Last synced: {{time}}": "Última sincronización: {{time}}",
|
||||
"Sync Enabled": "Sincronización habilitada",
|
||||
"Disconnect": "Desconectar",
|
||||
"Connect your Readwise account to sync highlights.": "Conecta tu cuenta de Readwise para sincronizar los resaltados.",
|
||||
"Get your access token at": "Obtén tu token de acceso en",
|
||||
"Access Token": "Token de acceso",
|
||||
"Paste your Readwise access token": "Pega tu token de acceso de Readwise",
|
||||
"Config": "Configuración",
|
||||
"Readwise Sync": "Sincronización con Readwise",
|
||||
"Push Highlights": "Enviar resaltados",
|
||||
"Highlights synced to Readwise": "Resaltados sincronizados con Readwise",
|
||||
"Readwise sync failed: no internet connection": "Error en la sincronización con Readwise: sin conexión a internet",
|
||||
"Readwise sync failed: {{error}}": "Error en la sincronización con Readwise: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1037,5 +1037,24 @@
|
||||
"Next Image": "تصویر بعدی",
|
||||
"Zoomed": "بزرگنمایی شده",
|
||||
"Zoom level": "سطح بزرگنمایی",
|
||||
"Table viewer": "نمایشگر جدول"
|
||||
"Table viewer": "نمایشگر جدول",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "اتصال به Readwise امکانپذیر نیست. لطفاً اتصال شبکه خود را بررسی کنید.",
|
||||
"Invalid Readwise access token": "توکن دسترسی Readwise نامعتبر است",
|
||||
"Disconnected from Readwise": "اتصال از Readwise قطع شد",
|
||||
"Never": "هرگز",
|
||||
"Readwise Settings": "تنظیمات Readwise",
|
||||
"Connected to Readwise": "به Readwise متصل شد",
|
||||
"Last synced: {{time}}": "آخرین همگامسازی: {{time}}",
|
||||
"Sync Enabled": "همگامسازی فعال شد",
|
||||
"Disconnect": "قطع اتصال",
|
||||
"Connect your Readwise account to sync highlights.": "برای همگامسازی هایلایتها، حساب Readwise خود را متصل کنید.",
|
||||
"Get your access token at": "توکن دسترسی خود را از اینجا دریافت کنید:",
|
||||
"Access Token": "توکن دسترسی",
|
||||
"Paste your Readwise access token": "توکن دسترسی Readwise خود را جایگذاری کنید",
|
||||
"Config": "پیکربندی",
|
||||
"Readwise Sync": "همگامسازی Readwise",
|
||||
"Push Highlights": "ارسال هایلایتها",
|
||||
"Highlights synced to Readwise": "هایلایتها با Readwise همگامسازی شدند",
|
||||
"Readwise sync failed: no internet connection": "همگامسازی Readwise ناموفق بود: اتصال اینترنت برقرار نیست",
|
||||
"Readwise sync failed: {{error}}": "همگامسازی Readwise ناموفق بود: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1049,5 +1049,24 @@
|
||||
"Next Image": "Image suivante",
|
||||
"Zoomed": "Zoomé",
|
||||
"Zoom level": "Niveau de zoom",
|
||||
"Table viewer": "Visionneuse de tableaux"
|
||||
"Table viewer": "Visionneuse de tableaux",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Impossible de se connecter à Readwise. Veuillez vérifier votre connexion réseau.",
|
||||
"Invalid Readwise access token": "Jeton d'accès Readwise invalide",
|
||||
"Disconnected from Readwise": "Déconnecté de Readwise",
|
||||
"Never": "Jamais",
|
||||
"Readwise Settings": "Paramètres Readwise",
|
||||
"Connected to Readwise": "Connecté à Readwise",
|
||||
"Last synced: {{time}}": "Dernière synchronisation : {{time}}",
|
||||
"Sync Enabled": "Synchronisation activée",
|
||||
"Disconnect": "Déconnecter",
|
||||
"Connect your Readwise account to sync highlights.": "Connectez votre compte Readwise pour synchroniser les surlignages.",
|
||||
"Get your access token at": "Obtenez votre jeton d'accès sur",
|
||||
"Access Token": "Jeton d'accès",
|
||||
"Paste your Readwise access token": "Collez votre jeton d'accès Readwise",
|
||||
"Config": "Configuration",
|
||||
"Readwise Sync": "Synchronisation Readwise",
|
||||
"Push Highlights": "Pousser les surlignages",
|
||||
"Highlights synced to Readwise": "Surlignages synchronisés avec Readwise",
|
||||
"Readwise sync failed: no internet connection": "Échec de la synchronisation Readwise : pas de connexion internet",
|
||||
"Readwise sync failed: {{error}}": "Échec de la synchronisation Readwise : {{error}}"
|
||||
}
|
||||
|
||||
@@ -1049,5 +1049,24 @@
|
||||
"Next Image": "תמונה הבאה",
|
||||
"Zoomed": "בזום",
|
||||
"Zoom level": "רמת זום",
|
||||
"Table viewer": "מציג טבלאות"
|
||||
"Table viewer": "מציג טבלאות",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "לא ניתן להתחבר ל-Readwise. אנא בדוק את חיבור הרשת שלך.",
|
||||
"Invalid Readwise access token": "אסימون גישה של Readwise לא חוקי",
|
||||
"Disconnected from Readwise": "נותק מ-Readwise",
|
||||
"Never": "לעולם לא",
|
||||
"Readwise Settings": "הגדרות Readwise",
|
||||
"Connected to Readwise": "מחובר ל-Readwise",
|
||||
"Last synced: {{time}}": "סונכרן לאחרונה: {{time}}",
|
||||
"Sync Enabled": "סנכרון מופעל",
|
||||
"Disconnect": "נתק",
|
||||
"Connect your Readwise account to sync highlights.": "חבר את חשבון Readwise שלך כדי לסנכרן את ההדגשות.",
|
||||
"Get your access token at": "קבל את אסימון הגישה שלך ב-",
|
||||
"Access Token": "אסימון גישה",
|
||||
"Paste your Readwise access token": "הדבק את אסימון הגישה של Readwise שלך",
|
||||
"Config": "תצורה",
|
||||
"Readwise Sync": "סנכרון Readwise",
|
||||
"Push Highlights": "שלח הדגשות",
|
||||
"Highlights synced to Readwise": "ההדגשות סונכרנו ל-Readwise",
|
||||
"Readwise sync failed: no internet connection": "סנכרון Readwise נכשל: אין חיבור לאינטרנט",
|
||||
"Readwise sync failed: {{error}}": "סנכרון Readwise נכשל: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1037,5 +1037,24 @@
|
||||
"Next Image": "अगली छवि",
|
||||
"Zoomed": "ज़ूम किया गया",
|
||||
"Zoom level": "ज़ूम स्तर",
|
||||
"Table viewer": "तालिका दर्शक"
|
||||
"Table viewer": "तालिका दर्शक",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Readwise से कनेक्ट करने में असमर्थ। कृपया अपना नेटवर्क कनेक्शन जांचें।",
|
||||
"Invalid Readwise access token": "अमान्य Readwise एक्सेस टोकन",
|
||||
"Disconnected from Readwise": "Readwise से डिस्कनेक्ट हो गया",
|
||||
"Never": "कभी नहीं",
|
||||
"Readwise Settings": "Readwise सेटिंग्स",
|
||||
"Connected to Readwise": "Readwise से जुड़ा हुआ",
|
||||
"Last synced: {{time}}": "पिछला सिंक: {{time}}",
|
||||
"Sync Enabled": "सिंक सक्षम",
|
||||
"Disconnect": "डिस्कनेक्ट करें",
|
||||
"Connect your Readwise account to sync highlights.": "हाइलाइट्स सिंक करने के लिए अपना Readwise खाता कनेक्ट करें।",
|
||||
"Get your access token at": "अपना एक्सेस टोकन यहाँ प्राप्त करें",
|
||||
"Access Token": "एक्सेस टोकन",
|
||||
"Paste your Readwise access token": "अपना Readwise एक्सेस टोकन पेस्ट करें",
|
||||
"Config": "कॉन्फिग",
|
||||
"Readwise Sync": "Readwise सिंक",
|
||||
"Push Highlights": "हाइलाइट्स भेजें",
|
||||
"Highlights synced to Readwise": "हाइलाइट्स Readwise में सिंक हो गए",
|
||||
"Readwise sync failed: no internet connection": "Readwise सिंक विफल रहा: कोई इंटरनेट कनेक्शन नहीं",
|
||||
"Readwise sync failed: {{error}}": "Readwise सिंक विफल रहा: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1025,5 +1025,24 @@
|
||||
"Next Image": "Gambar Berikutnya",
|
||||
"Zoomed": "Diperbesar",
|
||||
"Zoom level": "Tingkat zoom",
|
||||
"Table viewer": "Penampil tabel"
|
||||
"Table viewer": "Penampil tabel",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Tidak dapat terhubung ke Readwise. Silakan periksa koneksi jaringan Anda.",
|
||||
"Invalid Readwise access token": "Token akses Readwise tidak valid",
|
||||
"Disconnected from Readwise": "Terputus dari Readwise",
|
||||
"Never": "Tidak pernah",
|
||||
"Readwise Settings": "Pengaturan Readwise",
|
||||
"Connected to Readwise": "Terhubung ke Readwise",
|
||||
"Last synced: {{time}}": "Terakhir disinkronkan: {{time}}",
|
||||
"Sync Enabled": "Sinkronisasi Diaktifkan",
|
||||
"Disconnect": "Putuskan sambungan",
|
||||
"Connect your Readwise account to sync highlights.": "Hubungkan akun Readwise Anda untuk menyinkronkan sorotan.",
|
||||
"Get your access token at": "Dapatkan token akses Anda di",
|
||||
"Access Token": "Token Akses",
|
||||
"Paste your Readwise access token": "Tempelkan token akses Readwise Anda",
|
||||
"Config": "Konfigurasi",
|
||||
"Readwise Sync": "Sinkronisasi Readwise",
|
||||
"Push Highlights": "Kirim Sorotan",
|
||||
"Highlights synced to Readwise": "Sorotan disinkronkan ke Readwise",
|
||||
"Readwise sync failed: no internet connection": "Sinkronisasi Readwise gagal: tidak ada koneksi internet",
|
||||
"Readwise sync failed: {{error}}": "Sinkronisasi Readwise gagal: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1049,5 +1049,24 @@
|
||||
"Next Image": "Immagine successiva",
|
||||
"Zoomed": "Zoomato",
|
||||
"Zoom level": "Livello di zoom",
|
||||
"Table viewer": "Visualizzatore tabelle"
|
||||
"Table viewer": "Visualizzatore tabelle",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Impossibile connettersi a Readwise. Controlla la tua connessione di rete.",
|
||||
"Invalid Readwise access token": "Token di accesso Readwise non valido",
|
||||
"Disconnected from Readwise": "Disconnesso da Readwise",
|
||||
"Never": "Mai",
|
||||
"Readwise Settings": "Impostazioni Readwise",
|
||||
"Connected to Readwise": "Connesso a Readwise",
|
||||
"Last synced: {{time}}": "Ultima sincronizzazione: {{time}}",
|
||||
"Sync Enabled": "Sincronizzazione abilitata",
|
||||
"Disconnect": "Disconnetti",
|
||||
"Connect your Readwise account to sync highlights.": "Connetti il tuo account Readwise per sincronizzare le evidenziazioni.",
|
||||
"Get your access token at": "Ottieni il tuo token di accesso su",
|
||||
"Access Token": "Token di accesso",
|
||||
"Paste your Readwise access token": "Incolla il tuo token di accesso Readwise",
|
||||
"Config": "Configurazione",
|
||||
"Readwise Sync": "Sincronizzazione Readwise",
|
||||
"Push Highlights": "Invia evidenziazioni",
|
||||
"Highlights synced to Readwise": "Evidenziazioni sincronizzate su Readwise",
|
||||
"Readwise sync failed: no internet connection": "Sincronizzazione Readwise fallita: nessuna connessione internet",
|
||||
"Readwise sync failed: {{error}}": "Sincronizzazione Readwise fallita: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1025,5 +1025,24 @@
|
||||
"Next Image": "次の画像",
|
||||
"Zoomed": "ズーム済み",
|
||||
"Zoom level": "ズームレベル",
|
||||
"Table viewer": "テーブルビューア"
|
||||
"Table viewer": "テーブルビューア",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Readwise に接続できません。ネットワーク接続を確認してください。",
|
||||
"Invalid Readwise access token": "無効な Readwise アクセストークン",
|
||||
"Disconnected from Readwise": "Readwise から切断されました",
|
||||
"Never": "一度もなし",
|
||||
"Readwise Settings": "Readwise 設定",
|
||||
"Connected to Readwise": "Readwise に接続済み",
|
||||
"Last synced: {{time}}": "最終同期:{{time}}",
|
||||
"Sync Enabled": "同期有効",
|
||||
"Disconnect": "切断",
|
||||
"Connect your Readwise account to sync highlights.": "ハイライトを同期するには Readwise アカウントを接続してください。",
|
||||
"Get your access token at": "アクセストークンの取得先:",
|
||||
"Access Token": "アクセストークン",
|
||||
"Paste your Readwise access token": "Readwise アクセストークンを貼り付けてください",
|
||||
"Config": "設定",
|
||||
"Readwise Sync": "Readwise 同期",
|
||||
"Push Highlights": "ハイライトをプッシュ",
|
||||
"Highlights synced to Readwise": "ハイライトが Readwise に同期されました",
|
||||
"Readwise sync failed: no internet connection": "Readwise 同期失敗:インターネット接続がありません",
|
||||
"Readwise sync failed: {{error}}": "Readwise 同期失敗:{{error}}"
|
||||
}
|
||||
|
||||
@@ -1025,5 +1025,24 @@
|
||||
"Next Image": "다음 이미지",
|
||||
"Zoomed": "확대됨",
|
||||
"Zoom level": "확대 수준",
|
||||
"Table viewer": "테이블 뷰어"
|
||||
"Table viewer": "테이블 뷰어",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Readwise에 연결할 수 없습니다. 네트워크 연결을 확인해 주세요.",
|
||||
"Invalid Readwise access token": "유효하지 않은 Readwise 액세스 토큰입니다",
|
||||
"Disconnected from Readwise": "Readwise와 연결이 끊어졌습니다",
|
||||
"Never": "안 함",
|
||||
"Readwise Settings": "Readwise 설정",
|
||||
"Connected to Readwise": "Readwise에 연결됨",
|
||||
"Last synced: {{time}}": "마지막 동기화: {{time}}",
|
||||
"Sync Enabled": "동기화 활성화됨",
|
||||
"Disconnect": "연결 해제",
|
||||
"Connect your Readwise account to sync highlights.": "하이라이트를 동기화하려면 Readwise 계정렬 연결하세요.",
|
||||
"Get your access token at": "액세스 토큰 받기:",
|
||||
"Access Token": "액세스 토큰",
|
||||
"Paste your Readwise access token": "Readwise 액세스 토큰을 붙여넣으세요",
|
||||
"Config": "구성",
|
||||
"Readwise Sync": "Readwise 동기화",
|
||||
"Push Highlights": "하이라이트 푸시",
|
||||
"Highlights synced to Readwise": "하이라이트가 Readwise에 동기화되었습니다",
|
||||
"Readwise sync failed: no internet connection": "Readwise 동기화 실패: 인터넷 연결 없음",
|
||||
"Readwise sync failed: {{error}}": "Readwise 동기화 실패: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1025,5 +1025,24 @@
|
||||
"Next Image": "Imej Seterusnya",
|
||||
"Zoomed": "Dizum",
|
||||
"Zoom level": "Tahap zum",
|
||||
"Table viewer": "Penyorot jadual"
|
||||
"Table viewer": "Penyorot jadual",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Tidak dapat menyambung ke Readwise. Sila periksa sambungan rangkaian anda.",
|
||||
"Invalid Readwise access token": "Token akses Readwise tidak sah",
|
||||
"Disconnected from Readwise": "Terputus sambungan daripada Readwise",
|
||||
"Never": "Tidak pernah",
|
||||
"Readwise Settings": "Tetapan Readwise",
|
||||
"Connected to Readwise": "Disambungkan ke Readwise",
|
||||
"Last synced: {{time}}": "Kali terakhir disinkronkan: {{time}}",
|
||||
"Sync Enabled": "Penyinkronan Didayakan",
|
||||
"Disconnect": "Putuskan sambungan",
|
||||
"Connect your Readwise account to sync highlights.": "Sambungkan akaun Readwise anda untuk menyinkronkan sorotan.",
|
||||
"Get your access token at": "Dapatkan token akses anda di",
|
||||
"Access Token": "Token Akses",
|
||||
"Paste your Readwise access token": "Tampal token akses Readwise anda",
|
||||
"Config": "Konfigurasi",
|
||||
"Readwise Sync": "Penyinkronan Readwise",
|
||||
"Push Highlights": "Hantar Sorotan",
|
||||
"Highlights synced to Readwise": "Sorotan disinkronkan ke Readwise",
|
||||
"Readwise sync failed: no internet connection": "Penyinkronan Readwise gagal: tiada sambungan internet",
|
||||
"Readwise sync failed: {{error}}": "Penyinkronan Readwise gagal: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1037,5 +1037,24 @@
|
||||
"Next Image": "Volgende afbeelding",
|
||||
"Zoomed": "Gezoomd",
|
||||
"Zoom level": "Zoomniveau",
|
||||
"Table viewer": "Tabelviewer"
|
||||
"Table viewer": "Tabelviewer",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Kan geen verbinding maken met Readwise. Controleer uw netwerkverbinding.",
|
||||
"Invalid Readwise access token": "Ongeldige Readwise-toegangstoken",
|
||||
"Disconnected from Readwise": "Verbinding met Readwise verbroken",
|
||||
"Never": "Nooit",
|
||||
"Readwise Settings": "Readwise-instellingen",
|
||||
"Connected to Readwise": "Verbonden met Readwise",
|
||||
"Last synced: {{time}}": "Laatst gesynchroniseerd: {{time}}",
|
||||
"Sync Enabled": "Synchronisatie ingeschakeld",
|
||||
"Disconnect": "Verbinding verbreken",
|
||||
"Connect your Readwise account to sync highlights.": "Verbind uw Readwise-account om markeringen te synchroniseren.",
|
||||
"Get your access token at": "Verkrijg uw toegangstoken op",
|
||||
"Access Token": "Toegangstoken",
|
||||
"Paste your Readwise access token": "Plak uw Readwise-toegangstoken",
|
||||
"Config": "Configuratie",
|
||||
"Readwise Sync": "Readwise-synchronisatie",
|
||||
"Push Highlights": "Markeringen verzenden",
|
||||
"Highlights synced to Readwise": "Markeringen gesynchroniseerd met Readwise",
|
||||
"Readwise sync failed: no internet connection": "Readwise-synchronisatie mislukt: geen internetverbinding",
|
||||
"Readwise sync failed: {{error}}": "Readwise-synchronisatie mislukt: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1061,5 +1061,24 @@
|
||||
"Next Image": "Następny obraz",
|
||||
"Zoomed": "Powiększone",
|
||||
"Zoom level": "Poziom powiększenia",
|
||||
"Table viewer": "Przeglądarka tabel"
|
||||
"Table viewer": "Przeglądarka tabel",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Nie można połączyć się z Readwise. Sprawdź połączenie sieciowe.",
|
||||
"Invalid Readwise access token": "Nieprawidłowy token dostępu Readwise",
|
||||
"Disconnected from Readwise": "Rozłączono z Readwise",
|
||||
"Never": "Nigdy",
|
||||
"Readwise Settings": "Ustawienia Readwise",
|
||||
"Connected to Readwise": "Połączono z Readwise",
|
||||
"Last synced: {{time}}": "Ostatnia synchronizacja: {{time}}",
|
||||
"Sync Enabled": "Synchronizacja włączona",
|
||||
"Disconnect": "Rozłącz",
|
||||
"Connect your Readwise account to sync highlights.": "Połącz swoje konto Readwise, aby synchronizować wyróżnienia.",
|
||||
"Get your access token at": "Pobierz token dostępu pod adresem",
|
||||
"Access Token": "Token dostępu",
|
||||
"Paste your Readwise access token": "Wklej swój token dostępu Readwise",
|
||||
"Config": "Konfiguracja",
|
||||
"Readwise Sync": "Synchronizacja Readwise",
|
||||
"Push Highlights": "Wyślij wyróżnienia",
|
||||
"Highlights synced to Readwise": "Wyróżnienia zsynchronizowane z Readwise",
|
||||
"Readwise sync failed: no internet connection": "Synchronizacja Readwise nie powiodła się: brak połączenia z Internetem",
|
||||
"Readwise sync failed: {{error}}": "Synchronizacja Readwise nie powiodła się: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1049,5 +1049,24 @@
|
||||
"Next Image": "Próxima imagem",
|
||||
"Zoomed": "Com zoom",
|
||||
"Zoom level": "Nível de zoom",
|
||||
"Table viewer": "Visualizador de tabelas"
|
||||
"Table viewer": "Visualizador de tabelas",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Não foi possível conectar ao Readwise. Por favor, verifique sua conexão de rede.",
|
||||
"Invalid Readwise access token": "Token de acesso do Readwise inválido",
|
||||
"Disconnected from Readwise": "Desconectado do Readwise",
|
||||
"Never": "Nunca",
|
||||
"Readwise Settings": "Configurações do Readwise",
|
||||
"Connected to Readwise": "Conectado ao Readwise",
|
||||
"Last synced: {{time}}": "Última sincronização: {{time}}",
|
||||
"Sync Enabled": "Sincronização ativada",
|
||||
"Disconnect": "Desconectar",
|
||||
"Connect your Readwise account to sync highlights.": "Conecte sua conta do Readwise para sincronizar os destaques.",
|
||||
"Get your access token at": "Obtenha seu token de acesso em",
|
||||
"Access Token": "Token de acesso",
|
||||
"Paste your Readwise access token": "Cole seu token de acesso do Readwise",
|
||||
"Config": "Configuração",
|
||||
"Readwise Sync": "Sincronização com o Readwise",
|
||||
"Push Highlights": "Enviar destaques",
|
||||
"Highlights synced to Readwise": "Destaques sincronizados com o Readwise",
|
||||
"Readwise sync failed: no internet connection": "Sincronização com o Readwise falhou: sem conexão com a internet",
|
||||
"Readwise sync failed: {{error}}": "Sincronização com o Readwise falhou: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1061,5 +1061,24 @@
|
||||
"Next Image": "Следующее изображение",
|
||||
"Zoomed": "Увеличено",
|
||||
"Zoom level": "Уровень масштаба",
|
||||
"Table viewer": "Просмотрщик таблиц"
|
||||
"Table viewer": "Просмотрщик таблиц",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Не удалось подключиться к Readwise. Пожалуйста, проверьте ваше сетевое соединение.",
|
||||
"Invalid Readwise access token": "Недействительный токен доступа Readwise",
|
||||
"Disconnected from Readwise": "Отключено от Readwise",
|
||||
"Never": "Никогда",
|
||||
"Readwise Settings": "Настройки Readwise",
|
||||
"Connected to Readwise": "Подключено к Readwise",
|
||||
"Last synced: {{time}}": "Последняя синхронизация: {{time}}",
|
||||
"Sync Enabled": "Синхронизация включена",
|
||||
"Disconnect": "Отключить",
|
||||
"Connect your Readwise account to sync highlights.": "Подключите ваш аккаунт Readwise для синхронизации выделений.",
|
||||
"Get your access token at": "Получите ваш токен доступа на",
|
||||
"Access Token": "Токен доступа",
|
||||
"Paste your Readwise access token": "Вставьте ваш токен доступа Readwise",
|
||||
"Config": "Конфигурация",
|
||||
"Readwise Sync": "Синхронизация Readwise",
|
||||
"Push Highlights": "Отправить выделения",
|
||||
"Highlights synced to Readwise": "Выделения синхронизированы с Readwise",
|
||||
"Readwise sync failed: no internet connection": "Синхронизация Readwise не удалась: нет интернет-соединения",
|
||||
"Readwise sync failed: {{error}}": "Синхронизация Readwise не удалась: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1037,5 +1037,24 @@
|
||||
"Next Image": "මීළඟ රූපය",
|
||||
"Zoomed": "විශාලනය කරන ලදී",
|
||||
"Zoom level": "විශාලන මට්ටම",
|
||||
"Table viewer": "වගු නරඹන්නා"
|
||||
"Table viewer": "වගු නරඹන්නා",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Readwise වෙත සම්බන්ධ වීමට නොහැක. කරුණාකර ඔබගේ ජාල සම්බන්ධතාවය පරීක්ෂා කරන්න.",
|
||||
"Invalid Readwise access token": "අවලංගු Readwise ප්රවේශ ටෝකනය",
|
||||
"Disconnected from Readwise": "Readwise වෙතින් විසන්ධි විය",
|
||||
"Never": "කවදාවත් නැහැ",
|
||||
"Readwise Settings": "Readwise සැකසුම්",
|
||||
"Connected to Readwise": "Readwise වෙත සම්බන්ධ විය",
|
||||
"Last synced: {{time}}": "අවසානයට සමමුහුර්ත කළේ: {{time}}",
|
||||
"Sync Enabled": "සමමුහුර්ත කිරීම සබල කර ඇත",
|
||||
"Disconnect": "විසන්ධි කරන්න",
|
||||
"Connect your Readwise account to sync highlights.": "විශේෂ අවස්ථා සමමුහුර්ත කිරීමට ඔබගේ Readwise ගිණුම සම්බන්ධ කරන්න.",
|
||||
"Get your access token at": "ඔබගේ ප්රවේශ ටෝකනය මෙතැනින් ලබා ගන්න",
|
||||
"Access Token": "ප්රවේශ ටෝකනය",
|
||||
"Paste your Readwise access token": "ඔබගේ Readwise ප්රවේශ ටෝකනය මෙහි අලවන්න",
|
||||
"Config": "වින්යාසය",
|
||||
"Readwise Sync": "Readwise සමමුහුර්තකරණය",
|
||||
"Push Highlights": "විශේෂ අවස්ථා යොමු කරන්න",
|
||||
"Highlights synced to Readwise": "විශේෂ අවස්ථා Readwise සමඟ සමමුහුර්ත විය",
|
||||
"Readwise sync failed: no internet connection": "Readwise සමමුහුර්තකරණය අසාර්ථක විය: අන්තර්ජාල සම්බන්ධතාවයක් නොමැත",
|
||||
"Readwise sync failed: {{error}}": "Readwise සමමුහුර්තකරණය අසාර්ථක විය: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1037,5 +1037,24 @@
|
||||
"Next Image": "Nästa bild",
|
||||
"Zoomed": "Zoomad",
|
||||
"Zoom level": "Zoomnivå",
|
||||
"Table viewer": "Tabellvisare"
|
||||
"Table viewer": "Tabellvisare",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Kunde inte ansluta till Readwise. Kontrollera din nätverksanslutning.",
|
||||
"Invalid Readwise access token": "Ogiltig Readwise-åtkomsttoken",
|
||||
"Disconnected from Readwise": "Frånkopplad från Readwise",
|
||||
"Never": "Aldrig",
|
||||
"Readwise Settings": "Readwise-inställningar",
|
||||
"Connected to Readwise": "Ansluten till Readwise",
|
||||
"Last synced: {{time}}": "Senast synkroniserad: {{time}}",
|
||||
"Sync Enabled": "Synkronisering aktiverad",
|
||||
"Disconnect": "Koppla från",
|
||||
"Connect your Readwise account to sync highlights.": "Anslut ditt Readwise-konto för att synkronisera markeringar.",
|
||||
"Get your access token at": "Hämta din åtkomsttoken på",
|
||||
"Access Token": "Åtkomsttoken",
|
||||
"Paste your Readwise access token": "Klistra in din Readwise-åtkomsttoken",
|
||||
"Config": "Konfiguration",
|
||||
"Readwise Sync": "Readwise-synkronisering",
|
||||
"Push Highlights": "Skicka markeringar",
|
||||
"Highlights synced to Readwise": "Markeringar synkroniserade till Readwise",
|
||||
"Readwise sync failed: no internet connection": "Readwise-synkronisering misslyckades: ingen internetanslutning",
|
||||
"Readwise sync failed: {{error}}": "Readwise-synkronisering misslyckades: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1037,5 +1037,24 @@
|
||||
"Next Image": "அடுத்த படம்",
|
||||
"Zoomed": "பெரிதாக்கப்பட்டது",
|
||||
"Zoom level": "பெரிதாக்கும் நிலை",
|
||||
"Table viewer": "அட்டவணை காட்சிப்பவர்"
|
||||
"Table viewer": "அட்டவணை காட்சிப்பவர்",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Readwise உடன் இணைக்க முடியவில்லை. உங்கள் நெட்வொர்க் இணைப்பைச் சரிபார்க்கவும்.",
|
||||
"Invalid Readwise access token": "தவறான Readwise அணுகல் டோக்கன்",
|
||||
"Disconnected from Readwise": "Readwise இலிருந்து துண்டிக்கப்பட்டது",
|
||||
"Never": "ஒருபோதும் இல்லை",
|
||||
"Readwise Settings": "Readwise அமைப்புகள்",
|
||||
"Connected to Readwise": "Readwise உடன் இணைக்கப்பட்டது",
|
||||
"Last synced: {{time}}": "கடைசியாக ஒத்திசைக்கப்பட்டது: {{time}}",
|
||||
"Sync Enabled": "ஒத்திசைவு இயக்கப்பட்டது",
|
||||
"Disconnect": "துண்டி",
|
||||
"Connect your Readwise account to sync highlights.": "சிறப்பம்சங்களை ஒத்திசைக்க உங்கள் Readwise கணக்கை இணைக்கவும்.",
|
||||
"Get your access token at": "உங்கள் அணுகல் டோக்கனை இங்கே பெறவும்",
|
||||
"Access Token": "அணுகல் டோக்கன்",
|
||||
"Paste your Readwise access token": "உங்கள் Readwise அணுகல் டோக்கனை ஒட்டவும்",
|
||||
"Config": "கட்டமைப்பு",
|
||||
"Readwise Sync": "Readwise ஒத்திசைவு",
|
||||
"Push Highlights": "சிறப்பம்சங்களை அனுப்பு",
|
||||
"Highlights synced to Readwise": "சிறப்பம்சங்கள் Readwise உடன் ஒத்திசைக்கப்பட்டன",
|
||||
"Readwise sync failed: no internet connection": "Readwise ஒத்திசைவு தோல்வியடைந்தது: இணைய இணைப்பு இல்லை",
|
||||
"Readwise sync failed: {{error}}": "Readwise ஒத்திசைவு தோல்வியடைந்தது: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1025,5 +1025,24 @@
|
||||
"Next Image": "รูปภาพถัดไป",
|
||||
"Zoomed": "ซูมแล้ว",
|
||||
"Zoom level": "ระดับการซูม",
|
||||
"Table viewer": "ตัวดูตาราง"
|
||||
"Table viewer": "ตัวดูตาราง",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "ไม่สามารถเชื่อมต่อกับ Readwise ได้ โปรดตรวจสอบการเชื่อมต่ออินเทอร์เน็ตของคุณ",
|
||||
"Invalid Readwise access token": "โทเคนการเข้าถึง Readwise ไม่ถูกต้อง",
|
||||
"Disconnected from Readwise": "ยกเลิกการเชื่อมต่อกับ Readwise แล้ว",
|
||||
"Never": "ไม่เคย",
|
||||
"Readwise Settings": "การตั้งค่า Readwise",
|
||||
"Connected to Readwise": "เชื่อมต่อกับ Readwise แล้ว",
|
||||
"Last synced: {{time}}": "ซิงค์ล่าสุดเมื่อ: {{time}}",
|
||||
"Sync Enabled": "เปิดใช้งานการซิงค์",
|
||||
"Disconnect": "ยกเลิกการเชื่อมต่อ",
|
||||
"Connect your Readwise account to sync highlights.": "เชื่อมต่อบัญชี Readwise ของคุณเพื่อซิงค์ไฮไลต์",
|
||||
"Get your access token at": "รับโทเคนการเข้าถึงของคุณได้ที่",
|
||||
"Access Token": "โทเคนการเข้าถึง",
|
||||
"Paste your Readwise access token": "วางโทเคนการเข้าถึง Readwise ของคุณ",
|
||||
"Config": "การกำหนดค่า",
|
||||
"Readwise Sync": "การซิงค์ Readwise",
|
||||
"Push Highlights": "พุชไฮไลต์",
|
||||
"Highlights synced to Readwise": "ซิงค์ไฮไลต์ไปยัง Readwise แล้ว",
|
||||
"Readwise sync failed: no internet connection": "การซิงค์ Readwise ล้มเหลว: ไม่มีการเชื่อมต่ออินเทอร์เน็ต",
|
||||
"Readwise sync failed: {{error}}": "การซิงค์ Readwise ล้มเหลว: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1037,5 +1037,24 @@
|
||||
"Next Image": "Sonraki Resim",
|
||||
"Zoomed": "Yakınlaştırıldı",
|
||||
"Zoom level": "Yakınlaştırma düzeyi",
|
||||
"Table viewer": "Tablo görüntüleyici"
|
||||
"Table viewer": "Tablo görüntüleyici",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Readwise'a bağlanılamadı. Lütfen ağ bağlantınızı kontrol edin.",
|
||||
"Invalid Readwise access token": "Geçersiz Readwise erişim kodu",
|
||||
"Disconnected from Readwise": "Readwise bağlantısı kesildi",
|
||||
"Never": "Asla",
|
||||
"Readwise Settings": "Readwise Ayarları",
|
||||
"Connected to Readwise": "Readwise'a Bağlandı",
|
||||
"Last synced: {{time}}": "Son senkronizasyon: {{time}}",
|
||||
"Sync Enabled": "Senkronizasyon Etkin",
|
||||
"Disconnect": "Bağlantıyı Kes",
|
||||
"Connect your Readwise account to sync highlights.": "Vurguları senkronize etmek için Readwise hesabınızı bağlayın.",
|
||||
"Get your access token at": "Erişim kodunuzu şuradan alın:",
|
||||
"Access Token": "Erişim Kodu",
|
||||
"Paste your Readwise access token": "Readwise erişim kodunuzu yapıştırın",
|
||||
"Config": "Yapılandırma",
|
||||
"Readwise Sync": "Readwise Senkronizasyonu",
|
||||
"Push Highlights": "Vurguları Gönder",
|
||||
"Highlights synced to Readwise": "Vurgular Readwise ile senkronize edildi",
|
||||
"Readwise sync failed: no internet connection": "Readwise senkronizasyonu başarısız: internet bağlantısı yok",
|
||||
"Readwise sync failed: {{error}}": "Readwise senkronizasyonu başarısız: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1061,5 +1061,24 @@
|
||||
"Next Image": "Наступне зображення",
|
||||
"Zoomed": "Збільшено",
|
||||
"Zoom level": "Рівень масштабу",
|
||||
"Table viewer": "Переглядач таблиць"
|
||||
"Table viewer": "Переглядач таблиць",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Не вдалося підключитися до Readwise. Будь ласка, перевірте мережеве з'єднання.",
|
||||
"Invalid Readwise access token": "Недійсний токен доступу Readwise",
|
||||
"Disconnected from Readwise": "Відключено від Readwise",
|
||||
"Never": "Ніколи",
|
||||
"Readwise Settings": "Налаштування Readwise",
|
||||
"Connected to Readwise": "Підключено до Readwise",
|
||||
"Last synced: {{time}}": "Остання синхронізація: {{time}}",
|
||||
"Sync Enabled": "Синхронізацію увімкнено",
|
||||
"Disconnect": "Відключити",
|
||||
"Connect your Readwise account to sync highlights.": "Підключіть свій обліковий запис Readwise, щоб синхронізувати виділення.",
|
||||
"Get your access token at": "Отримайте токен доступу за адресою",
|
||||
"Access Token": "Токен доступу",
|
||||
"Paste your Readwise access token": "Вставте ваш токен доступу Readwise",
|
||||
"Config": "Конфігурація",
|
||||
"Readwise Sync": "Синхронізація Readwise",
|
||||
"Push Highlights": "Надіслати виділення",
|
||||
"Highlights synced to Readwise": "Виділення синхронізовано з Readwise",
|
||||
"Readwise sync failed: no internet connection": "Синхронізація Readwise не вдалася: немає інтернет-з'єднання",
|
||||
"Readwise sync failed: {{error}}": "Синхронізація Readwise не вдалася: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1025,5 +1025,24 @@
|
||||
"Next Image": "Ảnh sau",
|
||||
"Zoomed": "Đã thu phóng",
|
||||
"Zoom level": "Mức thu phóng",
|
||||
"Table viewer": "Trình xem bảng"
|
||||
"Table viewer": "Trình xem bảng",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "Không thể kết nối với Readwise. Vui lòng kiểm tra kết nối mạng của bạn.",
|
||||
"Invalid Readwise access token": "Mã xác thực Readwise không hợp lệ",
|
||||
"Disconnected from Readwise": "Đã ngắt kết nối với Readwise",
|
||||
"Never": "Không bao giờ",
|
||||
"Readwise Settings": "Cài đặt Readwise",
|
||||
"Connected to Readwise": "Đã kết nối với Readwise",
|
||||
"Last synced: {{time}}": "Lần đồng bộ cuối: {{time}}",
|
||||
"Sync Enabled": "Đã bật đồng bộ",
|
||||
"Disconnect": "Ngắt kết nối",
|
||||
"Connect your Readwise account to sync highlights.": "Kết nối tài khoản Readwise của bạn để đồng bộ các phần đánh dấu.",
|
||||
"Get your access token at": "Lấy mã xác thực tại",
|
||||
"Access Token": "Mã xác thực",
|
||||
"Paste your Readwise access token": "Dán mã xác thực Readwise của bạn vào đây",
|
||||
"Config": "Cấu hình",
|
||||
"Readwise Sync": "Đồng bộ Readwise",
|
||||
"Push Highlights": "Đẩy các phần đánh dấu",
|
||||
"Highlights synced to Readwise": "Các phần đánh dấu đã được đồng bộ với Readwise",
|
||||
"Readwise sync failed: no internet connection": "Đồng bộ Readwise thất bại: không có kết nối internet",
|
||||
"Readwise sync failed: {{error}}": "Đồng bộ Readwise thất bại: {{error}}"
|
||||
}
|
||||
|
||||
@@ -1025,5 +1025,24 @@
|
||||
"Next Image": "下一张图片",
|
||||
"Zoomed": "已缩放",
|
||||
"Zoom level": "缩放级别",
|
||||
"Table viewer": "表格查看器"
|
||||
"Table viewer": "表格查看器",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "无法连接到 Readwise。请检查您的网络连接。",
|
||||
"Invalid Readwise access token": "无效的 Readwise 访问令牌",
|
||||
"Disconnected from Readwise": "已断开与 Readwise 的连接",
|
||||
"Never": "从不",
|
||||
"Readwise Settings": "Readwise 设置",
|
||||
"Connected to Readwise": "已连接到 Readwise",
|
||||
"Last synced: {{time}}": "上次同步时间:{{time}}",
|
||||
"Sync Enabled": "同步已启用",
|
||||
"Disconnect": "断开连接",
|
||||
"Connect your Readwise account to sync highlights.": "连接您的 Readwise 账户以同步高亮内容。",
|
||||
"Get your access token at": "获取您的访问令牌:",
|
||||
"Access Token": "访问令牌",
|
||||
"Paste your Readwise access token": "粘贴您的 Readwise 访问令牌",
|
||||
"Config": "配置",
|
||||
"Readwise Sync": "Readwise 同步",
|
||||
"Push Highlights": "推送高亮内容",
|
||||
"Highlights synced to Readwise": "高亮内容已同步到 Readwise",
|
||||
"Readwise sync failed: no internet connection": "Readwise 同步失败:无网络连接",
|
||||
"Readwise sync failed: {{error}}": "Readwise 同步失败:{{error}}"
|
||||
}
|
||||
|
||||
@@ -1025,5 +1025,24 @@
|
||||
"Next Image": "下一張圖片",
|
||||
"Zoomed": "已縮放",
|
||||
"Zoom level": "縮放級別",
|
||||
"Table viewer": "表格檢視器"
|
||||
"Table viewer": "表格檢視器",
|
||||
"Unable to connect to Readwise. Please check your network connection.": "無法連接到 Readwise。請檢查您的網路連線。",
|
||||
"Invalid Readwise access token": "無效的 Readwise 存取權杖",
|
||||
"Disconnected from Readwise": "已斷開與 Readwise 的連線",
|
||||
"Never": "從不",
|
||||
"Readwise Settings": "Readwise 設定",
|
||||
"Connected to Readwise": "已連接到 Readwise",
|
||||
"Last synced: {{time}}": "上次同步時間:{{time}}",
|
||||
"Sync Enabled": "同步已啟用",
|
||||
"Disconnect": "斷開連線",
|
||||
"Connect your Readwise account to sync highlights.": "連接您的 Readwise 帳戶以同步高亮內容。",
|
||||
"Get your access token at": "獲取您的存取權杖:",
|
||||
"Access Token": "存取權杖",
|
||||
"Paste your Readwise access token": "貼上您的 Readwise 存取權杖",
|
||||
"Config": "配置",
|
||||
"Readwise Sync": "Readwise 同步",
|
||||
"Push Highlights": "推送高亮內容",
|
||||
"Highlights synced to Readwise": "高亮內容已同步到 Readwise",
|
||||
"Readwise sync failed: no internet connection": "Readwise 同步失敗:無網路連線",
|
||||
"Readwise sync failed: {{error}}": "Readwise 同步失敗:{{error}}"
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ vi.mock('@/services/environment', async (importOriginal) => {
|
||||
|
||||
import { EnvProvider } from '@/context/EnvContext';
|
||||
import { AuthProvider } from '@/context/AuthContext';
|
||||
import { DEFAULT_SYSTEM_SETTINGS } from '@/services/constants';
|
||||
|
||||
function renderWithProviders(ui: React.ReactNode) {
|
||||
return render(
|
||||
@@ -81,12 +82,7 @@ describe('ProofreadRulesManager', () => {
|
||||
beforeEach(() => {
|
||||
// Reset stores
|
||||
(useSettingsStore.setState as unknown as (state: unknown) => void)({
|
||||
settings: {
|
||||
globalViewSettings: { proofreadRules: [] },
|
||||
kosync: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
settings: DEFAULT_SYSTEM_SETTINGS,
|
||||
});
|
||||
(useReaderStore.setState as unknown as (state: unknown) => void)({ viewStates: {} });
|
||||
useSidebarStore.setState({ sideBarBookKey: null });
|
||||
@@ -101,6 +97,7 @@ describe('ProofreadRulesManager', () => {
|
||||
// Arrange: populate stores
|
||||
(useSettingsStore.setState as unknown as (state: unknown) => void)({
|
||||
settings: {
|
||||
...DEFAULT_SYSTEM_SETTINGS,
|
||||
globalViewSettings: {
|
||||
proofreadRules: [
|
||||
{
|
||||
@@ -127,7 +124,6 @@ describe('ProofreadRulesManager', () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
kosync: { enabled: false },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -164,8 +160,8 @@ describe('ProofreadRulesManager', () => {
|
||||
// Arrange: populate stores with a selection rule persisted in book config
|
||||
(useSettingsStore.setState as unknown as (state: unknown) => void)({
|
||||
settings: {
|
||||
...DEFAULT_SYSTEM_SETTINGS,
|
||||
globalViewSettings: { proofreadRules: [] },
|
||||
kosync: { enabled: false },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -284,10 +280,10 @@ describe('ProofreadRulesManager', () => {
|
||||
|
||||
(useSettingsStore.setState as unknown as (state: unknown) => void)({
|
||||
settings: {
|
||||
...DEFAULT_SYSTEM_SETTINGS,
|
||||
globalViewSettings: {
|
||||
proofreadRules: [libraryRule],
|
||||
},
|
||||
kosync: { enabled: false },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -364,8 +360,8 @@ describe('ProofreadRulesManager', () => {
|
||||
|
||||
(useSettingsStore.setState as unknown as (state: unknown) => void)({
|
||||
settings: {
|
||||
...DEFAULT_SYSTEM_SETTINGS,
|
||||
globalViewSettings: { proofreadRules: [] },
|
||||
kosync: { enabled: false },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -418,8 +414,8 @@ describe('ProofreadRulesManager', () => {
|
||||
// Arrange stores
|
||||
(useSettingsStore.setState as unknown as (state: unknown) => void)({
|
||||
settings: {
|
||||
...DEFAULT_SYSTEM_SETTINGS,
|
||||
globalViewSettings: { proofreadRules: [] },
|
||||
kosync: { enabled: false },
|
||||
},
|
||||
});
|
||||
(useReaderStore.setState as unknown as (state: unknown) => void)({
|
||||
@@ -453,8 +449,8 @@ describe('ProofreadRulesManager', () => {
|
||||
it('shows empty state messages when no rules exist', async () => {
|
||||
(useSettingsStore.setState as unknown as (state: unknown) => void)({
|
||||
settings: {
|
||||
...DEFAULT_SYSTEM_SETTINGS,
|
||||
globalViewSettings: { proofreadRules: [] },
|
||||
kosync: { enabled: false },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -509,10 +505,10 @@ describe('ProofreadRulesManager', () => {
|
||||
|
||||
(useSettingsStore.setState as unknown as (state: unknown) => void)({
|
||||
settings: {
|
||||
...DEFAULT_SYSTEM_SETTINGS,
|
||||
globalViewSettings: {
|
||||
proofreadRules: [libraryRule],
|
||||
},
|
||||
kosync: { enabled: false },
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import { getSysFontsList, setSystemUIVisibility } from '@/utils/bridge';
|
||||
import { AboutWindow } from '@/components/AboutWindow';
|
||||
import { UpdaterWindow } from '@/components/UpdaterWindow';
|
||||
import { KOSyncSettingsWindow } from './KOSyncSettings';
|
||||
import { ReadwiseSettingsWindow } from './ReadwiseSettings';
|
||||
import { ProofreadRulesManager } from './ProofreadRules';
|
||||
import { Toast } from '@/components/Toast';
|
||||
import { getLocale } from '@/utils/misc';
|
||||
@@ -169,6 +170,7 @@ const Reader: React.FC<{ ids?: string }> = ({ ids }) => {
|
||||
<AboutWindow />
|
||||
<UpdaterWindow />
|
||||
<KOSyncSettingsWindow />
|
||||
<ReadwiseSettingsWindow />
|
||||
<ProofreadRulesManager />
|
||||
<Toast />
|
||||
</Suspense>
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { eventDispatcher } from '@/utils/event';
|
||||
import { ReadwiseClient } from '@/services/readwise';
|
||||
import Dialog from '@/components/Dialog';
|
||||
|
||||
export const setReadwiseSettingsWindowVisible = (visible: boolean) => {
|
||||
const dialog = document.getElementById('readwise_settings_window');
|
||||
if (dialog) {
|
||||
const event = new CustomEvent('setReadwiseSettingsVisibility', {
|
||||
detail: { visible },
|
||||
});
|
||||
dialog.dispatchEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
export const ReadwiseSettingsWindow: React.FC = () => {
|
||||
const _ = useTranslation();
|
||||
const { envConfig } = useEnv();
|
||||
const { settings, setSettings, saveSettings } = useSettingsStore();
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [accessToken, setAccessToken] = useState('');
|
||||
const [isConnecting, setIsConnecting] = useState(false);
|
||||
|
||||
const isConfigured = !!settings.readwise?.accessToken;
|
||||
|
||||
useEffect(() => {
|
||||
const handleCustomEvent = (event: CustomEvent) => {
|
||||
setIsOpen(event.detail.visible);
|
||||
if (event.detail.visible) {
|
||||
setAccessToken('');
|
||||
}
|
||||
};
|
||||
const el = document.getElementById('readwise_settings_window');
|
||||
el?.addEventListener('setReadwiseSettingsVisibility', handleCustomEvent as EventListener);
|
||||
return () => {
|
||||
el?.removeEventListener('setReadwiseSettingsVisibility', handleCustomEvent as EventListener);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleConnect = async () => {
|
||||
setIsConnecting(true);
|
||||
try {
|
||||
const client = new ReadwiseClient({ enabled: true, accessToken, lastSyncedAt: 0 });
|
||||
const { valid, isNetworkError } = await client.validateToken();
|
||||
if (valid) {
|
||||
const newSettings = {
|
||||
...settings,
|
||||
readwise: {
|
||||
enabled: true,
|
||||
accessToken,
|
||||
lastSyncedAt: settings.readwise?.lastSyncedAt ?? 0,
|
||||
},
|
||||
};
|
||||
setSettings(newSettings);
|
||||
await saveSettings(envConfig, newSettings);
|
||||
} else if (isNetworkError) {
|
||||
eventDispatcher.dispatch('toast', {
|
||||
message: _('Unable to connect to Readwise. Please check your network connection.'),
|
||||
type: 'error',
|
||||
});
|
||||
} else {
|
||||
eventDispatcher.dispatch('toast', {
|
||||
message: _('Invalid Readwise access token'),
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
setIsConnecting(false);
|
||||
setAccessToken('');
|
||||
}
|
||||
};
|
||||
|
||||
const handleDisconnect = async () => {
|
||||
const newSettings = {
|
||||
...settings,
|
||||
readwise: { enabled: false, accessToken: '', lastSyncedAt: 0 },
|
||||
};
|
||||
setSettings(newSettings);
|
||||
await saveSettings(envConfig, newSettings);
|
||||
eventDispatcher.dispatch('toast', { message: _('Disconnected from Readwise'), type: 'info' });
|
||||
};
|
||||
|
||||
const handleToggleEnabled = async () => {
|
||||
const newSettings = {
|
||||
...settings,
|
||||
readwise: { ...settings.readwise, enabled: !settings.readwise?.enabled },
|
||||
};
|
||||
setSettings(newSettings);
|
||||
await saveSettings(envConfig, newSettings);
|
||||
};
|
||||
|
||||
const lastSyncedAt = settings.readwise?.lastSyncedAt ?? 0;
|
||||
const lastSyncedLabel = lastSyncedAt ? new Date(lastSyncedAt).toLocaleString() : _('Never');
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
id='readwise_settings_window'
|
||||
isOpen={isOpen}
|
||||
onClose={() => setIsOpen(false)}
|
||||
title={_('Readwise Settings')}
|
||||
boxClassName='sm:!min-w-[520px] sm:h-auto'
|
||||
>
|
||||
{isOpen && (
|
||||
<div className='mb-4 mt-0 flex flex-col gap-4 p-2 sm:p-4'>
|
||||
{isConfigured ? (
|
||||
<>
|
||||
<div className='text-center'>
|
||||
<p className='text-base-content/80 text-sm'>{_('Connected to Readwise')}</p>
|
||||
<p className='text-base-content/60 mt-1 text-xs'>
|
||||
{_('Last synced: {{time}}', { time: lastSyncedLabel })}
|
||||
</p>
|
||||
</div>
|
||||
<div className='flex h-14 items-center justify-between'>
|
||||
<span className='text-base-content/80'>{_('Sync Enabled')}</span>
|
||||
<input
|
||||
type='checkbox'
|
||||
className='toggle'
|
||||
checked={settings.readwise?.enabled ?? false}
|
||||
onChange={handleToggleEnabled}
|
||||
/>
|
||||
</div>
|
||||
<button className='btn btn-outline btn-sm mt-2' onClick={handleDisconnect}>
|
||||
{_('Disconnect')}
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<p className='text-base-content/70 text-center text-sm'>
|
||||
{_('Connect your Readwise account to sync highlights.')}
|
||||
</p>
|
||||
<p className='text-base-content/60 text-center text-xs'>
|
||||
{_('Get your access token at')}{' '}
|
||||
<a
|
||||
href='https://readwise.io/access_token'
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
className='link link-primary'
|
||||
>
|
||||
readwise.io/access_token
|
||||
</a>
|
||||
</p>
|
||||
<div className='form-control w-full'>
|
||||
<label className='label py-1'>
|
||||
<span className='label-text font-medium'>{_('Access Token')}</span>
|
||||
</label>
|
||||
<input
|
||||
type='password'
|
||||
placeholder={_('Paste your Readwise access token')}
|
||||
className='input input-bordered h-12 w-full focus:outline-none focus:ring-0'
|
||||
spellCheck='false'
|
||||
value={accessToken}
|
||||
onChange={(e) => setAccessToken(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
className='btn btn-primary mt-2 h-12 min-h-12 w-full'
|
||||
onClick={handleConnect}
|
||||
disabled={isConnecting || !accessToken}
|
||||
>
|
||||
{isConnecting ? <span className='loading loading-spinner'></span> : _('Connect')}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -18,6 +18,7 @@ import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
import { useDeviceControlStore } from '@/store/deviceStore';
|
||||
import { useFoliateEvents } from '../../hooks/useFoliateEvents';
|
||||
import { useNotesSync } from '../../hooks/useNotesSync';
|
||||
import { useReadwiseSync } from '../../hooks/useReadwiseSync';
|
||||
import { useTextSelector } from '../../hooks/useTextSelector';
|
||||
import { Position, TextSelection } from '@/utils/sel';
|
||||
import { getPopupPosition, getPosition, getTextFromRange } from '@/utils/sel';
|
||||
@@ -51,6 +52,7 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
const { listenToNativeTouchEvents } = useDeviceControlStore();
|
||||
|
||||
useNotesSync(bookKey);
|
||||
useReadwiseSync(bookKey);
|
||||
|
||||
const osPlatform = getOSPlatform();
|
||||
const config = getConfig(bookKey)!;
|
||||
|
||||
@@ -19,6 +19,7 @@ import { DOWNLOAD_READEST_URL } from '@/services/constants';
|
||||
import { navigateToLogin } from '@/utils/nav';
|
||||
import { saveSysSettings } from '@/helpers/settings';
|
||||
import { setKOSyncSettingsWindowVisible } from '@/app/reader/components/KOSyncSettings';
|
||||
import { setReadwiseSettingsWindowVisible } from '@/app/reader/components/ReadwiseSettings';
|
||||
import { setProofreadRulesVisibility } from '@/app/reader/components/ProofreadRules';
|
||||
import { setAboutDialogVisible } from '@/components/AboutWindow';
|
||||
import useBooksManager from '../../hooks/useBooksManager';
|
||||
@@ -99,6 +100,14 @@ const BookMenu: React.FC<BookMenuProps> = ({ menuClassName, setIsDropdownOpen })
|
||||
eventDispatcher.dispatch('push-kosync', { bookKey: sideBarBookKey });
|
||||
setIsDropdownOpen?.(false);
|
||||
};
|
||||
const showReadwiseSettingsWindow = () => {
|
||||
setReadwiseSettingsWindowVisible(true);
|
||||
setIsDropdownOpen?.(false);
|
||||
};
|
||||
const handlePushReadwise = () => {
|
||||
eventDispatcher.dispatch('readwise-push-all', { bookKey: sideBarBookKey });
|
||||
setIsDropdownOpen?.(false);
|
||||
};
|
||||
const toggleDiscordPresence = () => {
|
||||
const discordRichPresenceEnabled = !settings.discordRichPresenceEnabled;
|
||||
saveSysSettings(envConfig, 'discordRichPresenceEnabled', discordRichPresenceEnabled);
|
||||
@@ -160,12 +169,26 @@ const BookMenu: React.FC<BookMenuProps> = ({ menuClassName, setIsDropdownOpen })
|
||||
<MenuItem label={_('Enter Parallel Read')} onClick={handleSetParallel} />
|
||||
))}
|
||||
<hr aria-hidden='true' className='border-base-200 my-1' />
|
||||
<MenuItem label={_('KOReader Sync')} onClick={showKoSyncSettingsWindow} />
|
||||
{settings.kosync.enabled && (
|
||||
<>
|
||||
<MenuItem label={_('Push Progress')} onClick={handlePushKOSync} />
|
||||
<MenuItem label={_('Pull Progress')} onClick={handlePullKOSync} />
|
||||
</>
|
||||
{settings.kosync.enabled ? (
|
||||
<MenuItem label={_('KOReader Sync')} detailsOpen={false} buttonClass='py-2'>
|
||||
<ul className='flex flex-col ps-1'>
|
||||
<MenuItem label={_('Config')} noIcon onClick={showKoSyncSettingsWindow} />
|
||||
<MenuItem label={_('Push Progress')} noIcon onClick={handlePushKOSync} />
|
||||
<MenuItem label={_('Pull Progress')} noIcon onClick={handlePullKOSync} />
|
||||
</ul>
|
||||
</MenuItem>
|
||||
) : (
|
||||
<MenuItem label={_('KOReader Sync')} onClick={showKoSyncSettingsWindow} />
|
||||
)}
|
||||
{settings.readwise.enabled ? (
|
||||
<MenuItem label={_('Readwise Sync')} detailsOpen={false} buttonClass='py-2'>
|
||||
<ul className='flex flex-col ps-1'>
|
||||
<MenuItem label={_('Config')} noIcon onClick={showReadwiseSettingsWindow} />
|
||||
<MenuItem label={_('Push Highlights')} noIcon onClick={handlePushReadwise} />
|
||||
</ul>
|
||||
</MenuItem>
|
||||
) : (
|
||||
<MenuItem label={_('Readwise Sync')} onClick={showReadwiseSettingsWindow} />
|
||||
)}
|
||||
{appService?.isDesktopApp && (
|
||||
<>
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useBookDataStore } from '@/store/bookDataStore';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { eventDispatcher } from '@/utils/event';
|
||||
import { debounce } from '@/utils/debounce';
|
||||
import { ReadwiseClient } from '@/services/readwise';
|
||||
|
||||
const READWISE_SYNC_DEBOUNCE_MS = 5000;
|
||||
|
||||
export const useReadwiseSync = (bookKey: string) => {
|
||||
const _ = useTranslation();
|
||||
const { envConfig } = useEnv();
|
||||
const { getConfig, getBookData } = useBookDataStore();
|
||||
|
||||
// Read settings from store at call time to avoid stale closures
|
||||
const updateLastSyncedAt = useCallback(
|
||||
async (timestamp: number) => {
|
||||
const { settings, setSettings, saveSettings } = useSettingsStore.getState();
|
||||
const newSettings = {
|
||||
...settings,
|
||||
readwise: { ...settings.readwise, lastSyncedAt: timestamp },
|
||||
};
|
||||
setSettings(newSettings);
|
||||
await saveSettings(envConfig, newSettings);
|
||||
},
|
||||
[envConfig],
|
||||
);
|
||||
|
||||
// useMemo (not useCallback) so the debounce timer isn't reset on every render
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const debouncedPush = useMemo(
|
||||
() =>
|
||||
debounce(async () => {
|
||||
const { settings } = useSettingsStore.getState();
|
||||
if (!settings.readwise?.enabled || !settings.readwise?.accessToken) return;
|
||||
const client = new ReadwiseClient(settings.readwise);
|
||||
const book = getBookData(bookKey)?.book;
|
||||
const config = getConfig(bookKey);
|
||||
if (!book || !config?.booknotes) return;
|
||||
|
||||
const lastSyncedAt = settings.readwise.lastSyncedAt ?? 0;
|
||||
const newNotes = config.booknotes.filter(
|
||||
(n) => n.updatedAt > lastSyncedAt || (n.deletedAt ?? 0) > lastSyncedAt,
|
||||
);
|
||||
if (newNotes.length === 0) return;
|
||||
|
||||
const result = await client.pushHighlights(newNotes, book);
|
||||
if (result.success) {
|
||||
await updateLastSyncedAt(Date.now());
|
||||
} else if (!result.isNetworkError) {
|
||||
console.error('Readwise sync failed:', result.message);
|
||||
}
|
||||
}, READWISE_SYNC_DEBOUNCE_MS),
|
||||
[bookKey, getBookData, getConfig, updateLastSyncedAt],
|
||||
);
|
||||
|
||||
// Manual "Push All": sends every annotation/excerpt regardless of sync timestamp
|
||||
const pushAllHighlights = useCallback(async () => {
|
||||
const { settings } = useSettingsStore.getState();
|
||||
if (!settings.readwise?.enabled || !settings.readwise?.accessToken) return;
|
||||
const client = new ReadwiseClient(settings.readwise);
|
||||
const book = getBookData(bookKey)?.book;
|
||||
const config = getConfig(bookKey);
|
||||
if (!book || !config?.booknotes) return;
|
||||
|
||||
const result = await client.pushHighlights(config.booknotes, book);
|
||||
if (result.success) {
|
||||
await updateLastSyncedAt(Date.now());
|
||||
eventDispatcher.dispatch('toast', {
|
||||
message: _('Highlights synced to Readwise'),
|
||||
type: 'success',
|
||||
});
|
||||
} else {
|
||||
const message = result.isNetworkError
|
||||
? _('Readwise sync failed: no internet connection')
|
||||
: _('Readwise sync failed: {{error}}', { error: result.message });
|
||||
eventDispatcher.dispatch('toast', { message, type: 'error' });
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [bookKey, getBookData, getConfig, updateLastSyncedAt]);
|
||||
|
||||
// Cancel any pending debounced sync on unmount to avoid background network requests
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
debouncedPush.cancel();
|
||||
};
|
||||
}, [debouncedPush]);
|
||||
|
||||
// Listen for manual push-all events dispatched from BookMenu / BooknoteView
|
||||
useEffect(() => {
|
||||
const handlePushAll = async (e: CustomEvent) => {
|
||||
if (e.detail.bookKey !== bookKey) return;
|
||||
await pushAllHighlights();
|
||||
};
|
||||
eventDispatcher.on('readwise-push-all', handlePushAll);
|
||||
return () => {
|
||||
eventDispatcher.off('readwise-push-all', handlePushAll);
|
||||
};
|
||||
}, [bookKey, pushAllHighlights]);
|
||||
|
||||
// Auto-sync whenever booknotes change; debouncedPush reads enabled state internally
|
||||
const config = getConfig(bookKey);
|
||||
useEffect(() => {
|
||||
debouncedPush();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [config?.booknotes]);
|
||||
|
||||
return { pushAllHighlights };
|
||||
};
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
LibraryGroupByType,
|
||||
LibrarySortByType,
|
||||
ReadSettings,
|
||||
ReadwiseSettings,
|
||||
SystemSettings,
|
||||
} from '@/types/settings';
|
||||
import { UserStorageQuota, UserDailyTranslationQuota } from '@/types/quota';
|
||||
@@ -64,6 +65,14 @@ export const DEFAULT_KOSYNC_SETTINGS = {
|
||||
enabled: false,
|
||||
} as KOSyncSettings;
|
||||
|
||||
export const READWISE_API_BASE_URL = 'https://readwise.io/api/v2';
|
||||
|
||||
export const DEFAULT_READWISE_SETTINGS = {
|
||||
enabled: false,
|
||||
accessToken: '',
|
||||
lastSyncedAt: 0,
|
||||
} as ReadwiseSettings;
|
||||
|
||||
export const DEFAULT_SYSTEM_SETTINGS: Partial<SystemSettings> = {
|
||||
keepLogin: false,
|
||||
autoUpload: true,
|
||||
@@ -93,6 +102,7 @@ export const DEFAULT_SYSTEM_SETTINGS: Partial<SystemSettings> = {
|
||||
metadataDescriptionCollapsed: false,
|
||||
|
||||
kosync: DEFAULT_KOSYNC_SETTINGS,
|
||||
readwise: DEFAULT_READWISE_SETTINGS,
|
||||
aiSettings: DEFAULT_AI_SETTINGS,
|
||||
|
||||
lastSyncedAtBooks: 0,
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import { Book, BookNote, HighlightColor } from '@/types/book';
|
||||
import { ReadwiseSettings } from '@/types/settings';
|
||||
import { READWISE_API_BASE_URL } from '@/services/constants';
|
||||
|
||||
const READEST_TO_READWISE_COLOR: Record<HighlightColor, string> = {
|
||||
red: 'pink',
|
||||
yellow: 'yellow',
|
||||
green: 'green',
|
||||
blue: 'blue',
|
||||
violet: 'purple',
|
||||
};
|
||||
|
||||
export class ReadwiseClient {
|
||||
private config: ReadwiseSettings;
|
||||
|
||||
constructor(config: ReadwiseSettings) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
private async request(
|
||||
endpoint: string,
|
||||
options: { method?: 'GET' | 'POST'; body?: string } = {},
|
||||
): Promise<Response> {
|
||||
const { method = 'GET', body } = options;
|
||||
return fetch(`${READWISE_API_BASE_URL}${endpoint}`, {
|
||||
method,
|
||||
headers: {
|
||||
Authorization: `Token ${this.config.accessToken}`,
|
||||
...(body ? { 'Content-Type': 'application/json' } : {}),
|
||||
},
|
||||
body,
|
||||
});
|
||||
}
|
||||
|
||||
async validateToken(): Promise<{ valid: boolean; isNetworkError?: boolean }> {
|
||||
try {
|
||||
const res = await this.request('/auth/');
|
||||
return { valid: res.status === 204 };
|
||||
} catch {
|
||||
return { valid: false, isNetworkError: true };
|
||||
}
|
||||
}
|
||||
|
||||
async pushHighlights(
|
||||
notes: BookNote[],
|
||||
book: Book,
|
||||
): Promise<{ success: boolean; message?: string; isNetworkError?: boolean }> {
|
||||
const syncable = notes.filter(
|
||||
(n) => (n.type === 'annotation' || n.type === 'excerpt') && !n.deletedAt && n.text,
|
||||
);
|
||||
if (syncable.length === 0) return { success: true };
|
||||
|
||||
const isPublicUrl = (url?: string | null) =>
|
||||
!!url && /^https?:\/\/(?!localhost|127\.|asset\.localhost)/.test(url);
|
||||
|
||||
const highlights = syncable.map((note) => ({
|
||||
text: note.text!,
|
||||
title: book.title,
|
||||
author: book.author,
|
||||
...(isPublicUrl(book.coverImageUrl) ? { image_url: book.coverImageUrl } : {}),
|
||||
source_type: 'readest',
|
||||
category: 'books',
|
||||
note: note.note || undefined,
|
||||
location: 0,
|
||||
location_type: 'none',
|
||||
highlighted_at: new Date(note.createdAt).toISOString(),
|
||||
highlight_url: `readest://annotation/${book.hash}/${note.id}`,
|
||||
color: note.color ? (READEST_TO_READWISE_COLOR[note.color] ?? 'yellow') : 'yellow',
|
||||
}));
|
||||
|
||||
try {
|
||||
const res = await this.request('/highlights/', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ highlights }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const errText = await res.text().catch(() => '');
|
||||
console.error('Readwise API error:', res.status, errText);
|
||||
let message = `HTTP ${res.status}`;
|
||||
try {
|
||||
const err = JSON.parse(errText);
|
||||
message = err.detail || err.message || JSON.stringify(err) || message;
|
||||
} catch {
|
||||
if (errText) message = errText;
|
||||
}
|
||||
return { success: false, message };
|
||||
}
|
||||
return { success: true };
|
||||
} catch (e) {
|
||||
return { success: false, message: (e as Error).message, isNetworkError: true };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { ReadwiseClient } from './ReadwiseClient';
|
||||
@@ -547,7 +547,8 @@ foliate-fxl {
|
||||
color: theme('colors.base-content') !important;
|
||||
}
|
||||
|
||||
[data-eink='true'] .btn-primary {
|
||||
[data-eink='true'] .btn-primary,
|
||||
[data-eink='true'] .btn-outline {
|
||||
background-color: theme('colors.base-content') !important;
|
||||
border: 1px solid theme('colors.base-content') !important;
|
||||
color: theme('colors.base-100') !important;
|
||||
|
||||
@@ -64,6 +64,12 @@ export interface KOSyncSettings {
|
||||
strategy: KOSyncStrategy;
|
||||
}
|
||||
|
||||
export interface ReadwiseSettings {
|
||||
enabled: boolean;
|
||||
accessToken: string;
|
||||
lastSyncedAt: number;
|
||||
}
|
||||
|
||||
export interface SystemSettings {
|
||||
version: number;
|
||||
localBooksDir: string;
|
||||
@@ -101,6 +107,7 @@ export interface SystemSettings {
|
||||
metadataDescriptionCollapsed: boolean;
|
||||
|
||||
kosync: KOSyncSettings;
|
||||
readwise: ReadwiseSettings;
|
||||
|
||||
lastSyncedAtBooks: number;
|
||||
lastSyncedAtConfigs: number;
|
||||
|
||||
Reference in New Issue
Block a user