fix(share): correct recipient import flow and assorted UI polish (#4043)
- ensureSharedBookLocal helper makes sure the local library has both the Book entry and the bytes on disk after /import succeeds; navigating into the reader before this lands on "Book not found" - ShareLanding navigates via navigateToReader (path form on web) so the reader actually renders instead of hitting the App Router stub and going blank - Loading + progress UI on the landing page while bytes stream in; Open-in-app disabled mid-import to avoid races - UserInfo header: vertically center avatar with name/email, tighter mobile gap, and a fillContainer prop on UserAvatar so a parent can size the box via classes without the inline style fighting back - Rename "Share current page" -> "Share reading progress" (and matching post-generation hint) and shrink the dialog from 480 to 460px - Drop the unused Reload Page menu item from SettingsMenu - Translate the two new i18n keys across 31 locales Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -306,7 +306,6 @@
|
||||
"No notes match your search": "لا توجد ملاحظات تطابق بحثك",
|
||||
"Search notes and excerpts...": "بحث في الملاحظات والمقتطفات...",
|
||||
"Sign in to Sync": "قم بتسجيل الدخول للمزامنة",
|
||||
"Synced at {{time}}": "تمت المزامنة في {{time}}",
|
||||
"Never synced": "لم تتم المزامنة بعد",
|
||||
"Show Remaining Time": "إظهار الوقت المتبقي",
|
||||
"{{time}} min left in chapter": "{{time}} دقيقة متبقية حتى نهاية الفصل",
|
||||
@@ -1275,7 +1274,6 @@
|
||||
"{{count}} failed_many": "{{count}} فشل",
|
||||
"{{count}} failed_other": "{{count}} فشل",
|
||||
"(none)": "(لا شيء)",
|
||||
"Metadata Hash": "تجزئة البيانات الوصفية",
|
||||
"Meta Hash": "تجزئة البيانات الوصفية",
|
||||
"Computed Hash": "التجزئة المحسوبة",
|
||||
"Identifiers": "المعرفات",
|
||||
@@ -1337,7 +1335,6 @@
|
||||
"Uploading book…": "جاري رفع الكتاب…",
|
||||
"Generating…": "جاري الإنشاء…",
|
||||
"Generate share link": "إنشاء رابط مشاركة",
|
||||
"Includes your current page": "يشمل صفحتك الحالية",
|
||||
"Share URL": "رابط المشاركة",
|
||||
"Copy link": "نسخ الرابط",
|
||||
"Copied": "تم النسخ",
|
||||
@@ -1385,7 +1382,6 @@
|
||||
"Added to your library": "تمت الإضافة إلى مكتبتك",
|
||||
"Could not import shared book": "تعذر استيراد الكتاب المشترك",
|
||||
"Manage Shared Links": "إدارة روابط المشاركة",
|
||||
"Share current page": "مشاركة الصفحة الحالية",
|
||||
"Expires in": "تنتهي خلال",
|
||||
"{{count}} days_zero": "لا توجد أيام",
|
||||
"{{count}} days_one": "يوم واحد",
|
||||
@@ -1406,5 +1402,12 @@
|
||||
"Expires in {{count}} hours_many": "تنتهي خلال {{count}} ساعة",
|
||||
"Expires in {{count}} hours_other": "تنتهي خلال {{count}} ساعة",
|
||||
"Open in app": "فتح في التطبيق",
|
||||
"Shared with you": "تمت مشاركته معك"
|
||||
"Shared with you": "تمت مشاركته معك",
|
||||
"Downloading… {{percent}}%": "جارٍ التنزيل… {{percent}}٪",
|
||||
"Import progress": "تقدم الاستيراد",
|
||||
"Share reading progress": "مشاركة تقدّم القراءة",
|
||||
"Includes your reading progress": "يتضمن تقدّم قراءتك",
|
||||
"Synced {{time}}": "تمت المزامنة {{time}}",
|
||||
"Sync Info": "معلومات المزامنة",
|
||||
"Last Synced": "آخر مزامنة"
|
||||
}
|
||||
|
||||
@@ -330,7 +330,6 @@
|
||||
"{{engine}}: {{count}} voices_one": "{{engine}}: ১টি কণ্ঠস্বর",
|
||||
"{{engine}}: {{count}} voices_other": "{{engine}}: {{count}}টি কণ্ঠস্বর",
|
||||
"Sign in to Sync": "সিঙ্কের জন্য সাইন ইন",
|
||||
"Synced at {{time}}": "{{time}} এ সিঙ্ক হয়েছে",
|
||||
"Never synced": "কখনো সিঙ্ক হয়নি",
|
||||
"Reading Progress Synced": "পড়ার অগ্রগতি সিঙ্ক হয়েছে",
|
||||
"Page {{page}} of {{total}} ({{percentage}}%)": "{{total}} এর {{page}} পৃষ্ঠা ({{percentage}}%)",
|
||||
@@ -1207,7 +1206,6 @@
|
||||
"{{count}} failed_one": "{{count}}টি ব্যর্থ",
|
||||
"{{count}} failed_other": "{{count}}টি ব্যর্থ",
|
||||
"(none)": "(কোনোটি না)",
|
||||
"Metadata Hash": "মেটাডেটা হ্যাশ",
|
||||
"Meta Hash": "মেটা হ্যাশ",
|
||||
"Computed Hash": "গণিত হ্যাশ",
|
||||
"Identifiers": "শনাক্তকারী",
|
||||
@@ -1265,7 +1263,6 @@
|
||||
"Uploading book…": "বই আপলোড হচ্ছে…",
|
||||
"Generating…": "তৈরি হচ্ছে…",
|
||||
"Generate share link": "শেয়ার লিঙ্ক তৈরি করুন",
|
||||
"Includes your current page": "আপনার বর্তমান পৃষ্ঠা সহ",
|
||||
"Share URL": "শেয়ার URL",
|
||||
"Copy link": "লিঙ্ক কপি করুন",
|
||||
"Copied": "কপি হয়েছে",
|
||||
@@ -1305,7 +1302,6 @@
|
||||
"Added to your library": "আপনার লাইব্রেরিতে যোগ করা হয়েছে",
|
||||
"Could not import shared book": "শেয়ার করা বই আমদানি করা যায়নি",
|
||||
"Manage Shared Links": "শেয়ার লিঙ্ক পরিচালনা করুন",
|
||||
"Share current page": "বর্তমান পৃষ্ঠা শেয়ার করুন",
|
||||
"Expires in": "মেয়াদ শেষ হবে",
|
||||
"{{count}} days_one": "১ দিন",
|
||||
"{{count}} days_other": "{{count}} দিন",
|
||||
@@ -1314,5 +1310,12 @@
|
||||
"Expires in {{count}} hours_one": "১ ঘণ্টায় মেয়াদ শেষ",
|
||||
"Expires in {{count}} hours_other": "{{count}} ঘণ্টায় মেয়াদ শেষ",
|
||||
"Open in app": "অ্যাপে খুলুন",
|
||||
"Shared with you": "আপনার সাথে শেয়ার করা"
|
||||
"Shared with you": "আপনার সাথে শেয়ার করা",
|
||||
"Downloading… {{percent}}%": "ডাউনলোড হচ্ছে… {{percent}}%",
|
||||
"Import progress": "আমদানি অগ্রগতি",
|
||||
"Share reading progress": "পড়ার অগ্রগতি শেয়ার করুন",
|
||||
"Includes your reading progress": "আপনার পড়ার অগ্রগতি অন্তর্ভুক্ত",
|
||||
"Synced {{time}}": "{{time}} সিঙ্ক হয়েছে",
|
||||
"Sync Info": "সিঙ্ক তথ্য",
|
||||
"Last Synced": "শেষ সিঙ্ক"
|
||||
}
|
||||
|
||||
@@ -296,7 +296,6 @@
|
||||
"No notes match your search": "མཐུན་པའི་ཟིན་བྲིས་མ་རྙེད།",
|
||||
"Search notes and excerpts...": "ཟིན་བྲིས་འཚོལ་བཤེར།...",
|
||||
"Sign in to Sync": "ནང་བསྐྱོད་བྱས་རྗེས་སྐད་མཉམ་བྱེད་པ།",
|
||||
"Synced at {{time}}": "སྐད་མཉམ་བྱས་པའི་དུས་ཚོད། {{time}}",
|
||||
"Never synced": "ནམ་ཡང་སྐད་མཉམ་བྱས་མ་མྱོང་།",
|
||||
"Show Remaining Time": "ལྷག་མའི་དུས་ཚོད་མངོན་པ།",
|
||||
"{{time}} min left in chapter": "ལེའུ་འདིར་ད་དུང་ {{time}} སྐར་མ་ལྷག་ཡོད།",
|
||||
@@ -1190,7 +1189,6 @@
|
||||
"Retry all": "ཡོད་ཚད་ཡང་སྐྱར།",
|
||||
"{{count}} failed_other": "{{count}} ཕམ་ཁ།",
|
||||
"(none)": "(མེད)",
|
||||
"Metadata Hash": "དཔྱད་གཞིའི་ཧེཤི",
|
||||
"Meta Hash": "དཔྱད་གཞིའི་ཧེཤི",
|
||||
"Computed Hash": "རྩིས་པའི་ཧེཤི",
|
||||
"Identifiers": "ངོས་འཛིན་བྱེད་མཁན",
|
||||
@@ -1247,7 +1245,6 @@
|
||||
"Uploading book…": "དཔེ་ཆ་ཡར་སྐྱེལ་བཞིན་པ…",
|
||||
"Generating…": "བཟོ་བཞིན་པ…",
|
||||
"Generate share link": "མཉམ་སྤྱོད་འབྲེལ་མཐུད་བཟོ།",
|
||||
"Includes your current page": "ཁྱེད་ཀྱི་ད་ལྟའི་ཤོག་ངོས་འདུས།",
|
||||
"Share URL": "མཉམ་སྤྱོད་གནས་སྡོད།",
|
||||
"Copy link": "འབྲེལ་མཐུད་པར་སློག",
|
||||
"Copied": "པར་སློག་གྲུབ།",
|
||||
@@ -1285,11 +1282,17 @@
|
||||
"Added to your library": "ཁྱེད་ཀྱི་དཔེ་མཛོད་ལ་སྣོན་ཟིན།",
|
||||
"Could not import shared book": "མཉམ་སྤྱོད་དཔེ་ཆ་འདྲེན་མ་ཐུབ།",
|
||||
"Manage Shared Links": "མཉམ་སྤྱོད་འབྲེལ་མཐུད་དོ་དམ།",
|
||||
"Share current page": "ད་ལྟའི་ཤོག་ངོས་མཉམ་སྤྱོད།",
|
||||
"Expires in": "དུས་ཟད།",
|
||||
"{{count}} days_other": "ཉིན་{{count}}",
|
||||
"Expires in {{count}} days_other": "ཉིན་{{count}}ནང་ཟད།",
|
||||
"Expires in {{count}} hours_other": "ཆུ་ཚོད་{{count}}ནང་ཟད།",
|
||||
"Open in app": "ཉེར་སྤྱོད་ནང་ཁ་ཕྱེ།",
|
||||
"Shared with you": "ཁྱེད་དང་མཉམ་སྤྱོད་བྱས།"
|
||||
"Shared with you": "ཁྱེད་དང་མཉམ་སྤྱོད་བྱས།",
|
||||
"Downloading… {{percent}}%": "ཕབ་ལེན་བྱེད་བཞིན་པ… {{percent}}%",
|
||||
"Import progress": "ནང་འདྲེན་གྱི་ཡར་ཐོན།",
|
||||
"Share reading progress": "ཀློག་འདོན་གྱི་ཡར་ཐོན་སྤེལ་མཁོ།",
|
||||
"Includes your reading progress": "ཁྱེད་ཀྱི་ཀློག་འདོན་གྱི་ཡར་ཐོན་འདུས།",
|
||||
"Synced {{time}}": "{{time}}མཉམ་སྒྲིག་བྱས་པ",
|
||||
"Sync Info": "མཉམ་སྒྲིག་གྱི་ཆ་འཕྲིན",
|
||||
"Last Synced": "མཐའ་མའི་མཉམ་སྒྲིག"
|
||||
}
|
||||
|
||||
@@ -298,7 +298,6 @@
|
||||
"No notes match your search": "Noch keine Notizen gefunden",
|
||||
"Search notes and excerpts...": "Notizen und Auszüge suchen...",
|
||||
"Sign in to Sync": "Anmelden zum Synchronisieren",
|
||||
"Synced at {{time}}": "Synchronisiert um {{time}}",
|
||||
"Never synced": "Nie synchronisiert",
|
||||
"Show Remaining Time": "Verbleibende Zeit anzeigen",
|
||||
"{{time}} min left in chapter": "{{time}} min verbleibend im Kapitel",
|
||||
@@ -1207,7 +1206,6 @@
|
||||
"{{count}} failed_one": "{{count}} fehlgeschlagen",
|
||||
"{{count}} failed_other": "{{count}} fehlgeschlagen",
|
||||
"(none)": "(keine)",
|
||||
"Metadata Hash": "Metadaten-Hash",
|
||||
"Meta Hash": "Meta-Hash",
|
||||
"Computed Hash": "Berechneter Hash",
|
||||
"Identifiers": "Bezeichner",
|
||||
@@ -1265,7 +1263,6 @@
|
||||
"Uploading book…": "Buch wird hochgeladen…",
|
||||
"Generating…": "Wird erstellt…",
|
||||
"Generate share link": "Freigabelink erstellen",
|
||||
"Includes your current page": "Enthält Ihre aktuelle Seite",
|
||||
"Share URL": "Freigabelink",
|
||||
"Copy link": "Link kopieren",
|
||||
"Copied": "Kopiert",
|
||||
@@ -1305,7 +1302,6 @@
|
||||
"Added to your library": "Zu deiner Bibliothek hinzugefügt",
|
||||
"Could not import shared book": "Geteiltes Buch konnte nicht importiert werden",
|
||||
"Manage Shared Links": "Freigabelinks verwalten",
|
||||
"Share current page": "Aktuelle Seite teilen",
|
||||
"Expires in": "Läuft ab in",
|
||||
"{{count}} days_one": "1 Tag",
|
||||
"{{count}} days_other": "{{count}} Tage",
|
||||
@@ -1314,5 +1310,12 @@
|
||||
"Expires in {{count}} hours_one": "Läuft in 1 Stunde ab",
|
||||
"Expires in {{count}} hours_other": "Läuft in {{count}} Stunden ab",
|
||||
"Open in app": "In der App öffnen",
|
||||
"Shared with you": "Mit dir geteilt"
|
||||
"Shared with you": "Mit dir geteilt",
|
||||
"Downloading… {{percent}}%": "Wird heruntergeladen… {{percent}}%",
|
||||
"Import progress": "Importfortschritt",
|
||||
"Share reading progress": "Lesefortschritt teilen",
|
||||
"Includes your reading progress": "Enthält deinen Lesefortschritt",
|
||||
"Synced {{time}}": "Synchronisiert {{time}}",
|
||||
"Sync Info": "Synchronisierungs-Info",
|
||||
"Last Synced": "Zuletzt synchronisiert"
|
||||
}
|
||||
|
||||
@@ -299,7 +299,6 @@
|
||||
"No notes match your search": "Καμία σημείωση δεν βρέθηκε",
|
||||
"Search notes and excerpts...": "Αναζήτηση σημειώσεων...",
|
||||
"Sign in to Sync": "Σύνδεση για συγχρονισμό",
|
||||
"Synced at {{time}}": "Συγχρονίστηκε στις {{time}}",
|
||||
"Never synced": "Ποτέ δεν συγχρονίστηκε",
|
||||
"Show Remaining Time": "Εμφάνιση υπολειπόμενου χρόνου",
|
||||
"{{time}} min left in chapter": "{{time}} λεπτά απομένουν στο κεφάλαιο",
|
||||
@@ -1207,7 +1206,6 @@
|
||||
"{{count}} failed_one": "{{count}} απέτυχε",
|
||||
"{{count}} failed_other": "{{count}} απέτυχαν",
|
||||
"(none)": "(κανένα)",
|
||||
"Metadata Hash": "Hash Μεταδεδομένων",
|
||||
"Meta Hash": "Meta Hash",
|
||||
"Computed Hash": "Υπολογισμένο Hash",
|
||||
"Identifiers": "Αναγνωριστικά",
|
||||
@@ -1265,7 +1263,6 @@
|
||||
"Uploading book…": "Μεταφόρτωση βιβλίου…",
|
||||
"Generating…": "Δημιουργία…",
|
||||
"Generate share link": "Δημιουργία συνδέσμου κοινής χρήσης",
|
||||
"Includes your current page": "Περιλαμβάνει την τρέχουσα σελίδα σας",
|
||||
"Share URL": "URL κοινής χρήσης",
|
||||
"Copy link": "Αντιγραφή συνδέσμου",
|
||||
"Copied": "Αντιγράφηκε",
|
||||
@@ -1305,7 +1302,6 @@
|
||||
"Added to your library": "Προστέθηκε στη βιβλιοθήκη σας",
|
||||
"Could not import shared book": "Δεν ήταν δυνατή η εισαγωγή του κοινόχρηστου βιβλίου",
|
||||
"Manage Shared Links": "Διαχείριση συνδέσμων κοινής χρήσης",
|
||||
"Share current page": "Κοινή χρήση τρέχουσας σελίδας",
|
||||
"Expires in": "Λήγει σε",
|
||||
"{{count}} days_one": "1 ημέρα",
|
||||
"{{count}} days_other": "{{count}} ημέρες",
|
||||
@@ -1314,5 +1310,12 @@
|
||||
"Expires in {{count}} hours_one": "Λήγει σε 1 ώρα",
|
||||
"Expires in {{count}} hours_other": "Λήγει σε {{count}} ώρες",
|
||||
"Open in app": "Άνοιγμα στην εφαρμογή",
|
||||
"Shared with you": "Κοινοποιήθηκε σε εσάς"
|
||||
"Shared with you": "Κοινοποιήθηκε σε εσάς",
|
||||
"Downloading… {{percent}}%": "Λήψη… {{percent}}%",
|
||||
"Import progress": "Πρόοδος εισαγωγής",
|
||||
"Share reading progress": "Κοινή χρήση προόδου ανάγνωσης",
|
||||
"Includes your reading progress": "Περιλαμβάνει την πρόοδο ανάγνωσής σας",
|
||||
"Synced {{time}}": "Συγχρονίστηκε {{time}}",
|
||||
"Sync Info": "Πληροφορίες συγχρονισμού",
|
||||
"Last Synced": "Τελευταίος συγχρονισμός"
|
||||
}
|
||||
|
||||
@@ -328,7 +328,6 @@
|
||||
"No notes match your search": "No se encontraron notas",
|
||||
"Search notes and excerpts...": "Buscar notas...",
|
||||
"Sign in to Sync": "Inicia sesión para sincronizar",
|
||||
"Synced at {{time}}": "Sincronizado a las {{time}}",
|
||||
"Never synced": "Nunca sincronizado",
|
||||
"Show Remaining Time": "Mostrar tiempo restante",
|
||||
"{{time}} min left in chapter": "{{time}} min restantes en el capítulo",
|
||||
@@ -1224,7 +1223,6 @@
|
||||
"{{count}} failed_many": "{{count}} fallidas",
|
||||
"{{count}} failed_other": "{{count}} fallidas",
|
||||
"(none)": "(ninguno)",
|
||||
"Metadata Hash": "Hash de Metadatos",
|
||||
"Meta Hash": "Meta Hash",
|
||||
"Computed Hash": "Hash Calculado",
|
||||
"Identifiers": "Identificadores",
|
||||
@@ -1283,7 +1281,6 @@
|
||||
"Uploading book…": "Subiendo libro…",
|
||||
"Generating…": "Generando…",
|
||||
"Generate share link": "Generar enlace de compartir",
|
||||
"Includes your current page": "Incluye tu página actual",
|
||||
"Share URL": "URL de compartir",
|
||||
"Copy link": "Copiar enlace",
|
||||
"Copied": "Copiado",
|
||||
@@ -1325,7 +1322,6 @@
|
||||
"Added to your library": "Añadido a tu biblioteca",
|
||||
"Could not import shared book": "No se pudo importar el libro compartido",
|
||||
"Manage Shared Links": "Gestionar enlaces compartidos",
|
||||
"Share current page": "Compartir página actual",
|
||||
"Expires in": "Caduca en",
|
||||
"{{count}} days_one": "1 día",
|
||||
"{{count}} days_many": "{{count}} días",
|
||||
@@ -1337,5 +1333,12 @@
|
||||
"Expires in {{count}} hours_many": "Caduca en {{count}} horas",
|
||||
"Expires in {{count}} hours_other": "Caduca en {{count}} horas",
|
||||
"Open in app": "Abrir en la app",
|
||||
"Shared with you": "Compartido contigo"
|
||||
"Shared with you": "Compartido contigo",
|
||||
"Downloading… {{percent}}%": "Descargando… {{percent}}%",
|
||||
"Import progress": "Progreso de la importación",
|
||||
"Share reading progress": "Compartir el progreso de lectura",
|
||||
"Includes your reading progress": "Incluye tu progreso de lectura",
|
||||
"Synced {{time}}": "Sincronizado {{time}}",
|
||||
"Sync Info": "Información de sincronización",
|
||||
"Last Synced": "Última sincronización"
|
||||
}
|
||||
|
||||
@@ -298,7 +298,6 @@
|
||||
"No notes match your search": "هیچ یادداشتی با جستجوی شما مطابقت ندارد",
|
||||
"Search notes and excerpts...": "جستجوی یادداشتها و گزیدهها...",
|
||||
"Sign in to Sync": "برای همگامسازی وارد شوید",
|
||||
"Synced at {{time}}": "همگامسازی شده در {{time}}",
|
||||
"Never synced": "هرگز همگامسازی نشده",
|
||||
"Show Remaining Time": "نمایش زمان باقیمانده",
|
||||
"{{time}} min left in chapter": "{{time}} دقیقه تا انتهای فصل",
|
||||
@@ -1207,7 +1206,6 @@
|
||||
"{{count}} failed_one": "{{count}} ناموفق",
|
||||
"{{count}} failed_other": "{{count}} ناموفق",
|
||||
"(none)": "(هیچکدام)",
|
||||
"Metadata Hash": "هش متادیتا",
|
||||
"Meta Hash": "متا هش",
|
||||
"Computed Hash": "هش محاسبهشده",
|
||||
"Identifiers": "شناسهها",
|
||||
@@ -1265,7 +1263,6 @@
|
||||
"Uploading book…": "در حال آپلود کتاب…",
|
||||
"Generating…": "در حال ایجاد…",
|
||||
"Generate share link": "ایجاد لینک اشتراکگذاری",
|
||||
"Includes your current page": "شامل صفحه فعلی شما",
|
||||
"Share URL": "آدرس اشتراکگذاری",
|
||||
"Copy link": "کپی لینک",
|
||||
"Copied": "کپی شد",
|
||||
@@ -1305,7 +1302,6 @@
|
||||
"Added to your library": "به کتابخانه شما افزوده شد",
|
||||
"Could not import shared book": "وارد کردن کتاب اشتراکگذاری شده امکانپذیر نبود",
|
||||
"Manage Shared Links": "مدیریت لینکهای اشتراکگذاری",
|
||||
"Share current page": "اشتراک صفحه فعلی",
|
||||
"Expires in": "منقضی میشود در",
|
||||
"{{count}} days_one": "۱ روز",
|
||||
"{{count}} days_other": "{{count}} روز",
|
||||
@@ -1314,5 +1310,12 @@
|
||||
"Expires in {{count}} hours_one": "در ۱ ساعت منقضی میشود",
|
||||
"Expires in {{count}} hours_other": "در {{count}} ساعت منقضی میشود",
|
||||
"Open in app": "باز کردن در برنامه",
|
||||
"Shared with you": "با شما به اشتراک گذاشته شده"
|
||||
"Shared with you": "با شما به اشتراک گذاشته شده",
|
||||
"Downloading… {{percent}}%": "در حال دانلود… {{percent}}٪",
|
||||
"Import progress": "پیشرفت وارد کردن",
|
||||
"Share reading progress": "اشتراکگذاری پیشرفت مطالعه",
|
||||
"Includes your reading progress": "شامل پیشرفت مطالعهٔ شماست",
|
||||
"Synced {{time}}": "{{time}} همگامسازی شد",
|
||||
"Sync Info": "اطلاعات همگامسازی",
|
||||
"Last Synced": "آخرین همگامسازی"
|
||||
}
|
||||
|
||||
@@ -300,7 +300,6 @@
|
||||
"No notes match your search": "Aucune note trouvée",
|
||||
"Search notes and excerpts...": "Rechercher des notes...",
|
||||
"Sign in to Sync": "Connectez-vous pour synchroniser",
|
||||
"Synced at {{time}}": "Synchronisé à {{time}}",
|
||||
"Never synced": "Jamais synchronisé",
|
||||
"Show Remaining Time": "Afficher le temps restant",
|
||||
"{{time}} min left in chapter": "{{time}} min restant dans le chapitre",
|
||||
@@ -1224,7 +1223,6 @@
|
||||
"{{count}} failed_many": "{{count}} échecs",
|
||||
"{{count}} failed_other": "{{count}} échecs",
|
||||
"(none)": "(aucun)",
|
||||
"Metadata Hash": "Hachage des métadonnées",
|
||||
"Meta Hash": "Hachage Meta",
|
||||
"Computed Hash": "Hachage calculé",
|
||||
"Identifiers": "Identifiants",
|
||||
@@ -1283,7 +1281,6 @@
|
||||
"Uploading book…": "Téléchargement du livre…",
|
||||
"Generating…": "Génération…",
|
||||
"Generate share link": "Créer un lien de partage",
|
||||
"Includes your current page": "Inclut votre page actuelle",
|
||||
"Share URL": "URL de partage",
|
||||
"Copy link": "Copier le lien",
|
||||
"Copied": "Copié",
|
||||
@@ -1325,7 +1322,6 @@
|
||||
"Added to your library": "Ajouté à votre bibliothèque",
|
||||
"Could not import shared book": "Impossible d'importer le livre partagé",
|
||||
"Manage Shared Links": "Gérer les liens de partage",
|
||||
"Share current page": "Partager la page actuelle",
|
||||
"Expires in": "Expire dans",
|
||||
"{{count}} days_one": "1 jour",
|
||||
"{{count}} days_many": "{{count}} jours",
|
||||
@@ -1337,5 +1333,12 @@
|
||||
"Expires in {{count}} hours_many": "Expire dans {{count}} heures",
|
||||
"Expires in {{count}} hours_other": "Expire dans {{count}} heures",
|
||||
"Open in app": "Ouvrir dans l'app",
|
||||
"Shared with you": "Partagé avec vous"
|
||||
"Shared with you": "Partagé avec vous",
|
||||
"Downloading… {{percent}}%": "Téléchargement… {{percent}} %",
|
||||
"Import progress": "Progression de l’importation",
|
||||
"Share reading progress": "Partager la progression de lecture",
|
||||
"Includes your reading progress": "Inclut votre progression de lecture",
|
||||
"Synced {{time}}": "Synchronisé {{time}}",
|
||||
"Sync Info": "Infos de synchronisation",
|
||||
"Last Synced": "Dernière synchronisation"
|
||||
}
|
||||
|
||||
@@ -130,7 +130,6 @@
|
||||
"Cloud File Transfers": "העברות קבצים בענן",
|
||||
"{{activeCount}} active, {{pendingCount}} pending": "{{activeCount}} פעילים, {{pendingCount}} בהמתנה",
|
||||
"{{failedCount}} failed": "{{failedCount}} נכשלו",
|
||||
"Synced at {{time}}": "סונכרן ב-{{time}}",
|
||||
"Never synced": "מעולם לא סונכרן",
|
||||
"Account": "חשבון",
|
||||
"Sign In": "התחבר",
|
||||
@@ -1224,7 +1223,6 @@
|
||||
"{{count}} failed_two": "{{count}} נכשלו",
|
||||
"{{count}} failed_other": "{{count}} נכשלו",
|
||||
"(none)": "(אין)",
|
||||
"Metadata Hash": "גיבוב מטא-נתונים",
|
||||
"Meta Hash": "גיבוב מטא",
|
||||
"Computed Hash": "גיבוב מחושב",
|
||||
"Identifiers": "מזהים",
|
||||
@@ -1283,7 +1281,6 @@
|
||||
"Uploading book…": "מעלה ספר…",
|
||||
"Generating…": "יוצר…",
|
||||
"Generate share link": "צור קישור שיתוף",
|
||||
"Includes your current page": "כולל את העמוד הנוכחי שלך",
|
||||
"Share URL": "כתובת שיתוף",
|
||||
"Copy link": "העתק קישור",
|
||||
"Copied": "הועתק",
|
||||
@@ -1325,7 +1322,6 @@
|
||||
"Added to your library": "נוסף לספרייה שלך",
|
||||
"Could not import shared book": "לא ניתן היה לייבא את הספר המשותף",
|
||||
"Manage Shared Links": "ניהול קישורי שיתוף",
|
||||
"Share current page": "שתף את העמוד הנוכחי",
|
||||
"Expires in": "יפוג בעוד",
|
||||
"{{count}} days_one": "יום אחד",
|
||||
"{{count}} days_two": "יומיים",
|
||||
@@ -1337,5 +1333,12 @@
|
||||
"Expires in {{count}} hours_two": "יפוג בעוד שעתיים",
|
||||
"Expires in {{count}} hours_other": "יפוג בעוד {{count}} שעות",
|
||||
"Open in app": "פתח באפליקציה",
|
||||
"Shared with you": "שותף איתך"
|
||||
"Shared with you": "שותף איתך",
|
||||
"Downloading… {{percent}}%": "מוריד… {{percent}}%",
|
||||
"Import progress": "התקדמות הייבוא",
|
||||
"Share reading progress": "שיתוף התקדמות הקריאה",
|
||||
"Includes your reading progress": "כולל את התקדמות הקריאה שלך",
|
||||
"Synced {{time}}": "סונכרן {{time}}",
|
||||
"Sync Info": "פרטי סנכרון",
|
||||
"Last Synced": "סונכרן לאחרונה"
|
||||
}
|
||||
|
||||
@@ -299,7 +299,6 @@
|
||||
"No notes match your search": "कोई नोट्स नहीं मिले",
|
||||
"Search notes and excerpts...": "नोट्स खोजें...",
|
||||
"Sign in to Sync": "सिंक करने के लिए साइन इन करें",
|
||||
"Synced at {{time}}": "{{time}} पर सिंक किया गया",
|
||||
"Never synced": "कभी सिंक नहीं किया गया",
|
||||
"Show Remaining Time": "शेष समय दिखाएं",
|
||||
"{{time}} min left in chapter": "{{time}} मिनट शेष अध्याय में",
|
||||
@@ -1207,7 +1206,6 @@
|
||||
"{{count}} failed_one": "{{count}} असफल",
|
||||
"{{count}} failed_other": "{{count}} असफल",
|
||||
"(none)": "(कोई नहीं)",
|
||||
"Metadata Hash": "मेटाडेटा हैश",
|
||||
"Meta Hash": "मेटा हैश",
|
||||
"Computed Hash": "परिकलित हैश",
|
||||
"Identifiers": "पहचानकर्ता",
|
||||
@@ -1265,7 +1263,6 @@
|
||||
"Uploading book…": "पुस्तक अपलोड हो रही है…",
|
||||
"Generating…": "बना रहा है…",
|
||||
"Generate share link": "साझा लिंक बनाएँ",
|
||||
"Includes your current page": "आपका वर्तमान पृष्ठ शामिल है",
|
||||
"Share URL": "साझा URL",
|
||||
"Copy link": "लिंक कॉपी करें",
|
||||
"Copied": "कॉपी किया गया",
|
||||
@@ -1305,7 +1302,6 @@
|
||||
"Added to your library": "आपकी लाइब्रेरी में जोड़ा गया",
|
||||
"Could not import shared book": "साझा पुस्तक आयात नहीं की जा सकी",
|
||||
"Manage Shared Links": "साझा लिंक प्रबंधित करें",
|
||||
"Share current page": "वर्तमान पृष्ठ साझा करें",
|
||||
"Expires in": "समाप्त होगा",
|
||||
"{{count}} days_one": "1 दिन",
|
||||
"{{count}} days_other": "{{count}} दिन",
|
||||
@@ -1314,5 +1310,12 @@
|
||||
"Expires in {{count}} hours_one": "1 घंटे में समाप्त",
|
||||
"Expires in {{count}} hours_other": "{{count}} घंटों में समाप्त",
|
||||
"Open in app": "ऐप में खोलें",
|
||||
"Shared with you": "आपके साथ साझा किया गया"
|
||||
"Shared with you": "आपके साथ साझा किया गया",
|
||||
"Downloading… {{percent}}%": "डाउनलोड हो रहा है… {{percent}}%",
|
||||
"Import progress": "आयात प्रगति",
|
||||
"Share reading progress": "पढ़ने की प्रगति साझा करें",
|
||||
"Includes your reading progress": "आपकी पढ़ने की प्रगति शामिल है",
|
||||
"Synced {{time}}": "{{time}} सिंक हुआ",
|
||||
"Sync Info": "सिंक जानकारी",
|
||||
"Last Synced": "अंतिम सिंक"
|
||||
}
|
||||
|
||||
@@ -146,7 +146,6 @@
|
||||
"Cloud File Transfers": "Felhő fájlátvitelek",
|
||||
"{{activeCount}} active, {{pendingCount}} pending": "{{activeCount}} aktív, {{pendingCount}} függőben",
|
||||
"{{failedCount}} failed": "{{failedCount}} sikertelen",
|
||||
"Synced at {{time}}": "Szinkronizálva: {{time}}",
|
||||
"Never synced": "Még nem szinkronizált",
|
||||
"Account": "Fiók",
|
||||
"Sign In": "Bejelentkezés",
|
||||
@@ -1207,7 +1206,6 @@
|
||||
"{{count}} failed_one": "{{count}} sikertelen",
|
||||
"{{count}} failed_other": "{{count}} sikertelen",
|
||||
"(none)": "(nincs)",
|
||||
"Metadata Hash": "Metaadat-hash",
|
||||
"Meta Hash": "Meta-hash",
|
||||
"Computed Hash": "Számított hash",
|
||||
"Identifiers": "Azonosítók",
|
||||
@@ -1265,7 +1263,6 @@
|
||||
"Uploading book…": "Könyv feltöltése…",
|
||||
"Generating…": "Létrehozás…",
|
||||
"Generate share link": "Megosztási link létrehozása",
|
||||
"Includes your current page": "Tartalmazza az aktuális oldalt",
|
||||
"Share URL": "Megosztási URL",
|
||||
"Copy link": "Link másolása",
|
||||
"Copied": "Másolva",
|
||||
@@ -1305,7 +1302,6 @@
|
||||
"Added to your library": "Hozzáadva a könyvtáradhoz",
|
||||
"Could not import shared book": "A megosztott könyv importálása nem sikerült",
|
||||
"Manage Shared Links": "Megosztási linkek kezelése",
|
||||
"Share current page": "Aktuális oldal megosztása",
|
||||
"Expires in": "Lejár",
|
||||
"{{count}} days_one": "1 nap",
|
||||
"{{count}} days_other": "{{count}} nap",
|
||||
@@ -1314,5 +1310,12 @@
|
||||
"Expires in {{count}} hours_one": "Lejár 1 óra múlva",
|
||||
"Expires in {{count}} hours_other": "Lejár {{count}} óra múlva",
|
||||
"Open in app": "Megnyitás az alkalmazásban",
|
||||
"Shared with you": "Megosztva veled"
|
||||
"Shared with you": "Megosztva veled",
|
||||
"Downloading… {{percent}}%": "Letöltés… {{percent}}%",
|
||||
"Import progress": "Importálás folyamata",
|
||||
"Share reading progress": "Olvasási folyamat megosztása",
|
||||
"Includes your reading progress": "Tartalmazza az olvasási folyamatot",
|
||||
"Synced {{time}}": "Szinkronizálva {{time}}",
|
||||
"Sync Info": "Szinkronizálási információk",
|
||||
"Last Synced": "Utolsó szinkronizálás"
|
||||
}
|
||||
|
||||
@@ -297,7 +297,6 @@
|
||||
"No notes match your search": "Tidak ada catatan ditemukan",
|
||||
"Search notes and excerpts...": "Cari catatan...",
|
||||
"Sign in to Sync": "Masuk untuk Sinkronisasi",
|
||||
"Synced at {{time}}": "Disinkronkan pada {{time}}",
|
||||
"Never synced": "Belum pernah disinkronkan",
|
||||
"Show Remaining Time": "Perlihatkan Waktu Tersisa",
|
||||
"{{time}} min left in chapter": "{{time}} menit tersisa di bab",
|
||||
@@ -1190,7 +1189,6 @@
|
||||
"Retry all": "Coba lagi semua",
|
||||
"{{count}} failed_other": "{{count}} gagal",
|
||||
"(none)": "(tidak ada)",
|
||||
"Metadata Hash": "Hash Metadata",
|
||||
"Meta Hash": "Meta Hash",
|
||||
"Computed Hash": "Hash Terhitung",
|
||||
"Identifiers": "Pengenal",
|
||||
@@ -1247,7 +1245,6 @@
|
||||
"Uploading book…": "Mengunggah buku…",
|
||||
"Generating…": "Membuat…",
|
||||
"Generate share link": "Buat tautan berbagi",
|
||||
"Includes your current page": "Termasuk halaman Anda saat ini",
|
||||
"Share URL": "URL Berbagi",
|
||||
"Copy link": "Salin tautan",
|
||||
"Copied": "Disalin",
|
||||
@@ -1285,11 +1282,17 @@
|
||||
"Added to your library": "Ditambahkan ke pustaka Anda",
|
||||
"Could not import shared book": "Tidak dapat mengimpor buku yang dibagikan",
|
||||
"Manage Shared Links": "Kelola tautan berbagi",
|
||||
"Share current page": "Bagikan halaman saat ini",
|
||||
"Expires in": "Kedaluwarsa dalam",
|
||||
"{{count}} days_other": "{{count}} hari",
|
||||
"Expires in {{count}} days_other": "Kedaluwarsa dalam {{count}} hari",
|
||||
"Expires in {{count}} hours_other": "Kedaluwarsa dalam {{count}} jam",
|
||||
"Open in app": "Buka di aplikasi",
|
||||
"Shared with you": "Dibagikan dengan Anda"
|
||||
"Shared with you": "Dibagikan dengan Anda",
|
||||
"Downloading… {{percent}}%": "Mengunduh… {{percent}}%",
|
||||
"Import progress": "Kemajuan impor",
|
||||
"Share reading progress": "Bagikan progres baca",
|
||||
"Includes your reading progress": "Termasuk progres baca Anda",
|
||||
"Synced {{time}}": "Disinkronkan {{time}}",
|
||||
"Sync Info": "Info sinkronisasi",
|
||||
"Last Synced": "Sinkronisasi terakhir"
|
||||
}
|
||||
|
||||
@@ -301,7 +301,6 @@
|
||||
"No notes match your search": "Nessuna nota trovata",
|
||||
"Search notes and excerpts...": "Cerca nelle note...",
|
||||
"Sign in to Sync": "Accedi per sincronizzare",
|
||||
"Synced at {{time}}": "Sincronizzato alle {{time}}",
|
||||
"Never synced": "Mai sincronizzato",
|
||||
"Show Remaining Time": "Mostra tempo rimanente",
|
||||
"{{time}} min left in chapter": "{{time}} min rimasti nel capitolo",
|
||||
@@ -1224,7 +1223,6 @@
|
||||
"{{count}} failed_many": "{{count}} non riusciti",
|
||||
"{{count}} failed_other": "{{count}} non riusciti",
|
||||
"(none)": "(nessuno)",
|
||||
"Metadata Hash": "Hash Metadati",
|
||||
"Meta Hash": "Meta Hash",
|
||||
"Computed Hash": "Hash Calcolato",
|
||||
"Identifiers": "Identificatori",
|
||||
@@ -1283,7 +1281,6 @@
|
||||
"Uploading book…": "Caricamento libro…",
|
||||
"Generating…": "Generazione…",
|
||||
"Generate share link": "Genera link di condivisione",
|
||||
"Includes your current page": "Include la tua pagina attuale",
|
||||
"Share URL": "URL di condivisione",
|
||||
"Copy link": "Copia link",
|
||||
"Copied": "Copiato",
|
||||
@@ -1325,7 +1322,6 @@
|
||||
"Added to your library": "Aggiunto alla tua libreria",
|
||||
"Could not import shared book": "Impossibile importare il libro condiviso",
|
||||
"Manage Shared Links": "Gestisci link di condivisione",
|
||||
"Share current page": "Condividi pagina attuale",
|
||||
"Expires in": "Scade tra",
|
||||
"{{count}} days_one": "1 giorno",
|
||||
"{{count}} days_many": "{{count}} giorni",
|
||||
@@ -1337,5 +1333,12 @@
|
||||
"Expires in {{count}} hours_many": "Scade tra {{count}} ore",
|
||||
"Expires in {{count}} hours_other": "Scade tra {{count}} ore",
|
||||
"Open in app": "Apri nell'app",
|
||||
"Shared with you": "Condiviso con te"
|
||||
"Shared with you": "Condiviso con te",
|
||||
"Downloading… {{percent}}%": "Download in corso… {{percent}}%",
|
||||
"Import progress": "Avanzamento dell'importazione",
|
||||
"Share reading progress": "Condividi i progressi di lettura",
|
||||
"Includes your reading progress": "Include i tuoi progressi di lettura",
|
||||
"Synced {{time}}": "Sincronizzato {{time}}",
|
||||
"Sync Info": "Info di sincronizzazione",
|
||||
"Last Synced": "Ultima sincronizzazione"
|
||||
}
|
||||
|
||||
@@ -297,7 +297,6 @@
|
||||
"No notes match your search": "ノートが見つかりません",
|
||||
"Search notes and excerpts...": "ノートを検索...",
|
||||
"Sign in to Sync": "同期するにはサインイン",
|
||||
"Synced at {{time}}": "{{time}} に同期済み",
|
||||
"Never synced": "まだ同期されていません",
|
||||
"Show Remaining Time": "残り時間を表示",
|
||||
"{{time}} min left in chapter": "{{time}}分残り",
|
||||
@@ -1190,7 +1189,6 @@
|
||||
"Retry all": "すべて再試行",
|
||||
"{{count}} failed_other": "{{count}}件失敗",
|
||||
"(none)": "(なし)",
|
||||
"Metadata Hash": "メタデータハッシュ",
|
||||
"Meta Hash": "メタハッシュ",
|
||||
"Computed Hash": "計算されたハッシュ",
|
||||
"Identifiers": "識別子",
|
||||
@@ -1247,7 +1245,6 @@
|
||||
"Uploading book…": "本をアップロード中…",
|
||||
"Generating…": "生成中…",
|
||||
"Generate share link": "共有リンクを作成",
|
||||
"Includes your current page": "現在のページを含む",
|
||||
"Share URL": "共有URL",
|
||||
"Copy link": "リンクをコピー",
|
||||
"Copied": "コピーしました",
|
||||
@@ -1285,11 +1282,17 @@
|
||||
"Added to your library": "ライブラリに追加しました",
|
||||
"Could not import shared book": "共有された本を取り込めませんでした",
|
||||
"Manage Shared Links": "共有リンクを管理",
|
||||
"Share current page": "現在のページを共有",
|
||||
"Expires in": "有効期限",
|
||||
"{{count}} days_other": "{{count}}日",
|
||||
"Expires in {{count}} days_other": "{{count}}日で期限切れ",
|
||||
"Expires in {{count}} hours_other": "{{count}}時間で期限切れ",
|
||||
"Open in app": "アプリで開く",
|
||||
"Shared with you": "あなたへの共有"
|
||||
"Shared with you": "あなたへの共有",
|
||||
"Downloading… {{percent}}%": "ダウンロード中… {{percent}}%",
|
||||
"Import progress": "インポートの進行状況",
|
||||
"Share reading progress": "読書の進捗を共有",
|
||||
"Includes your reading progress": "読書の進捗を含みます",
|
||||
"Synced {{time}}": "{{time}}に同期",
|
||||
"Sync Info": "同期情報",
|
||||
"Last Synced": "最終同期"
|
||||
}
|
||||
|
||||
@@ -297,7 +297,6 @@
|
||||
"No notes match your search": "일치하는 노트가 없습니다",
|
||||
"Search notes and excerpts...": "노트 검색...",
|
||||
"Sign in to Sync": "동기화를 위해 로그인하세요",
|
||||
"Synced at {{time}}": "{{time}}에 동기화됨",
|
||||
"Never synced": "동기화된 적 없음",
|
||||
"Show Remaining Time": "남은 시간 표시",
|
||||
"{{time}} min left in chapter": "{{time}}분 남음",
|
||||
@@ -1190,7 +1189,6 @@
|
||||
"Retry all": "모두 재시도",
|
||||
"{{count}} failed_other": "{{count}}개 실패",
|
||||
"(none)": "(없음)",
|
||||
"Metadata Hash": "메타데이터 해시",
|
||||
"Meta Hash": "메타 해시",
|
||||
"Computed Hash": "계산된 해시",
|
||||
"Identifiers": "식별자",
|
||||
@@ -1247,7 +1245,6 @@
|
||||
"Uploading book…": "책 업로드 중…",
|
||||
"Generating…": "생성 중…",
|
||||
"Generate share link": "공유 링크 만들기",
|
||||
"Includes your current page": "현재 페이지 포함",
|
||||
"Share URL": "공유 URL",
|
||||
"Copy link": "링크 복사",
|
||||
"Copied": "복사됨",
|
||||
@@ -1285,11 +1282,17 @@
|
||||
"Added to your library": "라이브러리에 추가되었습니다",
|
||||
"Could not import shared book": "공유된 책을 가져올 수 없습니다",
|
||||
"Manage Shared Links": "공유 링크 관리",
|
||||
"Share current page": "현재 페이지 공유",
|
||||
"Expires in": "만료",
|
||||
"{{count}} days_other": "{{count}}일",
|
||||
"Expires in {{count}} days_other": "{{count}}일 후 만료",
|
||||
"Expires in {{count}} hours_other": "{{count}}시간 후 만료",
|
||||
"Open in app": "앱에서 열기",
|
||||
"Shared with you": "회원님과 공유됨"
|
||||
"Shared with you": "회원님과 공유됨",
|
||||
"Downloading… {{percent}}%": "다운로드 중… {{percent}}%",
|
||||
"Import progress": "가져오기 진행률",
|
||||
"Share reading progress": "읽기 진행률 공유",
|
||||
"Includes your reading progress": "읽기 진행률 포함됨",
|
||||
"Synced {{time}}": "{{time}} 동기화됨",
|
||||
"Sync Info": "동기화 정보",
|
||||
"Last Synced": "마지막 동기화"
|
||||
}
|
||||
|
||||
@@ -315,7 +315,6 @@
|
||||
"Separate Cover Page": "Halaman Kulit Berasingan",
|
||||
"Scrolled Mode": "Mod Tatal",
|
||||
"Sign in to Sync": "Log masuk untuk Segerak",
|
||||
"Synced at {{time}}": "Disegerak pada {{time}}",
|
||||
"Never synced": "Tidak pernah disegerak",
|
||||
"Invert Image In Dark Mode": "Songsangkan Imej Dalam Mod Gelap",
|
||||
"Failed to auto-save book cover for lock screen: {{error}}": "Gagal auto-simpan kulit buku untuk skrin kunci: {{error}}",
|
||||
@@ -1190,7 +1189,6 @@
|
||||
"Retry all": "Cuba lagi semua",
|
||||
"{{count}} failed_other": "{{count}} gagal",
|
||||
"(none)": "(tiada)",
|
||||
"Metadata Hash": "Cincang Metadata",
|
||||
"Meta Hash": "Cincang Meta",
|
||||
"Computed Hash": "Cincang Dikira",
|
||||
"Identifiers": "Pengenal",
|
||||
@@ -1247,7 +1245,6 @@
|
||||
"Uploading book…": "Memuat naik buku…",
|
||||
"Generating…": "Menjana…",
|
||||
"Generate share link": "Jana pautan kongsi",
|
||||
"Includes your current page": "Termasuk halaman semasa anda",
|
||||
"Share URL": "URL Kongsi",
|
||||
"Copy link": "Salin pautan",
|
||||
"Copied": "Disalin",
|
||||
@@ -1285,11 +1282,17 @@
|
||||
"Added to your library": "Ditambah ke pustaka anda",
|
||||
"Could not import shared book": "Tidak dapat mengimport buku yang dikongsi",
|
||||
"Manage Shared Links": "Urus pautan kongsi",
|
||||
"Share current page": "Kongsi halaman semasa",
|
||||
"Expires in": "Tamat dalam",
|
||||
"{{count}} days_other": "{{count}} hari",
|
||||
"Expires in {{count}} days_other": "Tamat dalam {{count}} hari",
|
||||
"Expires in {{count}} hours_other": "Tamat dalam {{count}} jam",
|
||||
"Open in app": "Buka dalam app",
|
||||
"Shared with you": "Dikongsi dengan anda"
|
||||
"Shared with you": "Dikongsi dengan anda",
|
||||
"Downloading… {{percent}}%": "Memuat turun… {{percent}}%",
|
||||
"Import progress": "Kemajuan import",
|
||||
"Share reading progress": "Kongsi kemajuan bacaan",
|
||||
"Includes your reading progress": "Termasuk kemajuan bacaan anda",
|
||||
"Synced {{time}}": "Disegerakkan {{time}}",
|
||||
"Sync Info": "Maklumat penyegerakan",
|
||||
"Last Synced": "Penyegerakan terakhir"
|
||||
}
|
||||
|
||||
@@ -299,7 +299,6 @@
|
||||
"No notes match your search": "Geen notities gevonden",
|
||||
"Search notes and excerpts...": "Zoek notities...",
|
||||
"Sign in to Sync": "Meld je aan om te synchroniseren",
|
||||
"Synced at {{time}}": "Gesynchroniseerd om {{time}}",
|
||||
"Never synced": "Nooit gesynchroniseerd",
|
||||
"Show Remaining Time": "Toon resterende tijd",
|
||||
"{{time}} min left in chapter": "Nog {{time}} min in hoofdstuk",
|
||||
@@ -1207,7 +1206,6 @@
|
||||
"{{count}} failed_one": "{{count}} mislukt",
|
||||
"{{count}} failed_other": "{{count}} mislukt",
|
||||
"(none)": "(geen)",
|
||||
"Metadata Hash": "Metadata-hash",
|
||||
"Meta Hash": "Meta-hash",
|
||||
"Computed Hash": "Berekende hash",
|
||||
"Identifiers": "Identificatoren",
|
||||
@@ -1265,7 +1263,6 @@
|
||||
"Uploading book…": "Boek uploaden…",
|
||||
"Generating…": "Genereren…",
|
||||
"Generate share link": "Deellink maken",
|
||||
"Includes your current page": "Bevat uw huidige pagina",
|
||||
"Share URL": "Deel-URL",
|
||||
"Copy link": "Koppeling kopiëren",
|
||||
"Copied": "Gekopieerd",
|
||||
@@ -1305,7 +1302,6 @@
|
||||
"Added to your library": "Toegevoegd aan uw bibliotheek",
|
||||
"Could not import shared book": "Kan gedeeld boek niet importeren",
|
||||
"Manage Shared Links": "Deelkoppelingen beheren",
|
||||
"Share current page": "Huidige pagina delen",
|
||||
"Expires in": "Verloopt over",
|
||||
"{{count}} days_one": "1 dag",
|
||||
"{{count}} days_other": "{{count}} dagen",
|
||||
@@ -1314,5 +1310,12 @@
|
||||
"Expires in {{count}} hours_one": "Verloopt over 1 uur",
|
||||
"Expires in {{count}} hours_other": "Verloopt over {{count}} uur",
|
||||
"Open in app": "Openen in app",
|
||||
"Shared with you": "Met u gedeeld"
|
||||
"Shared with you": "Met u gedeeld",
|
||||
"Downloading… {{percent}}%": "Downloaden… {{percent}}%",
|
||||
"Import progress": "Voortgang import",
|
||||
"Share reading progress": "Leesvoortgang delen",
|
||||
"Includes your reading progress": "Inclusief je leesvoortgang",
|
||||
"Synced {{time}}": "Gesynchroniseerd {{time}}",
|
||||
"Sync Info": "Synchronisatie-info",
|
||||
"Last Synced": "Laatst gesynchroniseerd"
|
||||
}
|
||||
|
||||
@@ -303,7 +303,6 @@
|
||||
"No notes match your search": "Nie znaleziono notatek",
|
||||
"Search notes and excerpts...": "Szukaj notatek...",
|
||||
"Sign in to Sync": "Zaloguj się",
|
||||
"Synced at {{time}}": "Sync: {{time}}",
|
||||
"Never synced": "Brak synchronizacji",
|
||||
"Show Remaining Time": "Pokazuj pozostały czas",
|
||||
"{{time}} min left in chapter": "{{time}} min pozostało do końca rozdziału",
|
||||
@@ -1241,7 +1240,6 @@
|
||||
"{{count}} failed_many": "{{count}} nieudanych",
|
||||
"{{count}} failed_other": "{{count}} nieudanych",
|
||||
"(none)": "(brak)",
|
||||
"Metadata Hash": "Skrót metadanych",
|
||||
"Meta Hash": "Meta-skrót",
|
||||
"Computed Hash": "Obliczony skrót",
|
||||
"Identifiers": "Identyfikatory",
|
||||
@@ -1301,7 +1299,6 @@
|
||||
"Uploading book…": "Przesyłanie książki…",
|
||||
"Generating…": "Generowanie…",
|
||||
"Generate share link": "Utwórz link udostępniania",
|
||||
"Includes your current page": "Zawiera Twoją bieżącą stronę",
|
||||
"Share URL": "Adres udostępniania",
|
||||
"Copy link": "Kopiuj link",
|
||||
"Copied": "Skopiowano",
|
||||
@@ -1345,7 +1342,6 @@
|
||||
"Added to your library": "Dodano do biblioteki",
|
||||
"Could not import shared book": "Nie można zaimportować udostępnionej książki",
|
||||
"Manage Shared Links": "Zarządzaj linkami udostępniania",
|
||||
"Share current page": "Udostępnij bieżącą stronę",
|
||||
"Expires in": "Wygasa za",
|
||||
"{{count}} days_one": "1 dzień",
|
||||
"{{count}} days_few": "{{count}} dni",
|
||||
@@ -1360,5 +1356,12 @@
|
||||
"Expires in {{count}} hours_many": "Wygasa za {{count}} godz.",
|
||||
"Expires in {{count}} hours_other": "Wygasa za {{count}} godz.",
|
||||
"Open in app": "Otwórz w aplikacji",
|
||||
"Shared with you": "Udostępnione Tobie"
|
||||
"Shared with you": "Udostępnione Tobie",
|
||||
"Downloading… {{percent}}%": "Pobieranie… {{percent}}%",
|
||||
"Import progress": "Postęp importu",
|
||||
"Share reading progress": "Udostępnij postęp czytania",
|
||||
"Includes your reading progress": "Zawiera Twój postęp czytania",
|
||||
"Synced {{time}}": "Zsynchronizowano {{time}}",
|
||||
"Sync Info": "Informacje o synchronizacji",
|
||||
"Last Synced": "Ostatnia synchronizacja"
|
||||
}
|
||||
|
||||
@@ -301,7 +301,6 @@
|
||||
"No notes match your search": "Nenhuma nota encontrada",
|
||||
"Search notes and excerpts...": "Buscar notas...",
|
||||
"Sign in to Sync": "Entrar",
|
||||
"Synced at {{time}}": "Sincronizado às {{time}}",
|
||||
"Never synced": "Nunca sincronizado",
|
||||
"Show Remaining Time": "Mostrar Tempo Restante",
|
||||
"{{time}} min left in chapter": "{{time}} min restantes no capítulo",
|
||||
@@ -1224,7 +1223,6 @@
|
||||
"{{count}} failed_many": "{{count}} falhadas",
|
||||
"{{count}} failed_other": "{{count}} falhadas",
|
||||
"(none)": "(nenhum)",
|
||||
"Metadata Hash": "Hash de Metadados",
|
||||
"Meta Hash": "Meta Hash",
|
||||
"Computed Hash": "Hash Calculado",
|
||||
"Identifiers": "Identificadores",
|
||||
@@ -1283,7 +1281,6 @@
|
||||
"Uploading book…": "Enviando livro…",
|
||||
"Generating…": "Gerando…",
|
||||
"Generate share link": "Gerar link de compartilhamento",
|
||||
"Includes your current page": "Inclui sua página atual",
|
||||
"Share URL": "URL de compartilhamento",
|
||||
"Copy link": "Copiar link",
|
||||
"Copied": "Copiado",
|
||||
@@ -1325,7 +1322,6 @@
|
||||
"Added to your library": "Adicionado à sua biblioteca",
|
||||
"Could not import shared book": "Não foi possível importar o livro compartilhado",
|
||||
"Manage Shared Links": "Gerenciar links de compartilhamento",
|
||||
"Share current page": "Compartilhar página atual",
|
||||
"Expires in": "Expira em",
|
||||
"{{count}} days_one": "1 dia",
|
||||
"{{count}} days_many": "{{count}} dias",
|
||||
@@ -1337,5 +1333,12 @@
|
||||
"Expires in {{count}} hours_many": "Expira em {{count}} horas",
|
||||
"Expires in {{count}} hours_other": "Expira em {{count}} horas",
|
||||
"Open in app": "Abrir no app",
|
||||
"Shared with you": "Compartilhado com você"
|
||||
"Shared with you": "Compartilhado com você",
|
||||
"Downloading… {{percent}}%": "Baixando… {{percent}}%",
|
||||
"Import progress": "Progresso da importação",
|
||||
"Share reading progress": "Compartilhar progresso de leitura",
|
||||
"Includes your reading progress": "Inclui seu progresso de leitura",
|
||||
"Synced {{time}}": "Sincronizado {{time}}",
|
||||
"Sync Info": "Informações de sincronização",
|
||||
"Last Synced": "Última sincronização"
|
||||
}
|
||||
|
||||
@@ -150,7 +150,6 @@
|
||||
"Cloud File Transfers": "Transferuri de fișiere în cloud",
|
||||
"{{activeCount}} active, {{pendingCount}} pending": "{{activeCount}} activ, {{pendingCount}} în așteptare",
|
||||
"{{failedCount}} failed": "{{failedCount}} a eșuat",
|
||||
"Synced at {{time}}": "Sincronizat la {{time}}",
|
||||
"Never synced": "Nu s-a sincronizat niciodată",
|
||||
"Account": "Cont",
|
||||
"Sign In": "Conectare",
|
||||
@@ -1224,7 +1223,6 @@
|
||||
"{{count}} failed_few": "{{count}} eșuate",
|
||||
"{{count}} failed_other": "{{count}} eșuate",
|
||||
"(none)": "(niciunul)",
|
||||
"Metadata Hash": "Hash metadate",
|
||||
"Meta Hash": "Meta hash",
|
||||
"Computed Hash": "Hash calculat",
|
||||
"Identifiers": "Identificatori",
|
||||
@@ -1283,7 +1281,6 @@
|
||||
"Uploading book…": "Se încarcă cartea…",
|
||||
"Generating…": "Se generează…",
|
||||
"Generate share link": "Generează link de partajare",
|
||||
"Includes your current page": "Include pagina ta curentă",
|
||||
"Share URL": "URL de partajare",
|
||||
"Copy link": "Copiază linkul",
|
||||
"Copied": "Copiat",
|
||||
@@ -1325,7 +1322,6 @@
|
||||
"Added to your library": "Adăugat în biblioteca ta",
|
||||
"Could not import shared book": "Nu s-a putut importa cartea partajată",
|
||||
"Manage Shared Links": "Gestionează linkurile de partajare",
|
||||
"Share current page": "Partajează pagina curentă",
|
||||
"Expires in": "Expiră în",
|
||||
"{{count}} days_one": "1 zi",
|
||||
"{{count}} days_few": "{{count}} zile",
|
||||
@@ -1337,5 +1333,12 @@
|
||||
"Expires in {{count}} hours_few": "Expiră în {{count}} ore",
|
||||
"Expires in {{count}} hours_other": "Expiră în {{count}} de ore",
|
||||
"Open in app": "Deschide în aplicație",
|
||||
"Shared with you": "Partajat cu tine"
|
||||
"Shared with you": "Partajat cu tine",
|
||||
"Downloading… {{percent}}%": "Se descarcă… {{percent}}%",
|
||||
"Import progress": "Progresul importului",
|
||||
"Share reading progress": "Partajează progresul lecturii",
|
||||
"Includes your reading progress": "Include progresul tău de lectură",
|
||||
"Synced {{time}}": "Sincronizat {{time}}",
|
||||
"Sync Info": "Informații sincronizare",
|
||||
"Last Synced": "Ultima sincronizare"
|
||||
}
|
||||
|
||||
@@ -303,7 +303,6 @@
|
||||
"No notes match your search": "Записи не найдены",
|
||||
"Search notes and excerpts...": "Искать записи...",
|
||||
"Sign in to Sync": "Войти",
|
||||
"Synced at {{time}}": "Синхр. в {{time}}",
|
||||
"Never synced": "Не синхр.",
|
||||
"Show Remaining Time": "Показать оставшееся время",
|
||||
"{{time}} min left in chapter": "{{time}} мин осталось в главе",
|
||||
@@ -1241,7 +1240,6 @@
|
||||
"{{count}} failed_many": "{{count}} ошибок",
|
||||
"{{count}} failed_other": "{{count}} ошибок",
|
||||
"(none)": "(нет)",
|
||||
"Metadata Hash": "Хеш метаданных",
|
||||
"Meta Hash": "Мета-хеш",
|
||||
"Computed Hash": "Вычисленный хеш",
|
||||
"Identifiers": "Идентификаторы",
|
||||
@@ -1301,7 +1299,6 @@
|
||||
"Uploading book…": "Загрузка книги…",
|
||||
"Generating…": "Создание…",
|
||||
"Generate share link": "Создать ссылку",
|
||||
"Includes your current page": "Включает вашу текущую страницу",
|
||||
"Share URL": "URL для общего доступа",
|
||||
"Copy link": "Копировать ссылку",
|
||||
"Copied": "Скопировано",
|
||||
@@ -1345,7 +1342,6 @@
|
||||
"Added to your library": "Добавлено в вашу библиотеку",
|
||||
"Could not import shared book": "Не удалось импортировать книгу",
|
||||
"Manage Shared Links": "Управление ссылками",
|
||||
"Share current page": "Поделиться текущей страницей",
|
||||
"Expires in": "Истекает через",
|
||||
"{{count}} days_one": "{{count}} день",
|
||||
"{{count}} days_few": "{{count}} дня",
|
||||
@@ -1360,5 +1356,12 @@
|
||||
"Expires in {{count}} hours_many": "Истекает через {{count}} часов",
|
||||
"Expires in {{count}} hours_other": "Истекает через {{count}} часов",
|
||||
"Open in app": "Открыть в приложении",
|
||||
"Shared with you": "Поделились с вами"
|
||||
"Shared with you": "Поделились с вами",
|
||||
"Downloading… {{percent}}%": "Загрузка… {{percent}}%",
|
||||
"Import progress": "Ход импорта",
|
||||
"Share reading progress": "Поделиться прогрессом чтения",
|
||||
"Includes your reading progress": "Включает ваш прогресс чтения",
|
||||
"Synced {{time}}": "Синхронизировано {{time}}",
|
||||
"Sync Info": "Информация о синхронизации",
|
||||
"Last Synced": "Последняя синхронизация"
|
||||
}
|
||||
|
||||
@@ -330,7 +330,6 @@
|
||||
"{{engine}}: {{count}} voices_one": "{{engine}}: හඬ 1",
|
||||
"{{engine}}: {{count}} voices_other": "{{engine}}: හඬ {{count}}",
|
||||
"Sign in to Sync": "සමමුහුර්ත කිරීම සඳහා ඇතුල් වන්න",
|
||||
"Synced at {{time}}": "{{time}} වේලාවේ සමමුහුර්ත විය",
|
||||
"Never synced": "කිසි විටෙක සමමුහුර්ත නොවිණි",
|
||||
"Reading Progress Synced": "කියවීමේ ප්රගතිය සමමුහුර්ත විය",
|
||||
"Page {{page}} of {{total}} ({{percentage}}%)": "{{total}} න් {{page}} පිටුව ({{percentage}}%)",
|
||||
@@ -1207,7 +1206,6 @@
|
||||
"{{count}} failed_one": "{{count}} අසාර්ථකයි",
|
||||
"{{count}} failed_other": "{{count}} අසාර්ථකයි",
|
||||
"(none)": "(කිසිවක් නැත)",
|
||||
"Metadata Hash": "පාරදත්ත හෑෂ්",
|
||||
"Meta Hash": "මෙටා හෑෂ්",
|
||||
"Computed Hash": "ගණනය කළ හෑෂ්",
|
||||
"Identifiers": "හඳුනාගැනීම්",
|
||||
@@ -1265,7 +1263,6 @@
|
||||
"Uploading book…": "පොත උඩුගත කරමින්…",
|
||||
"Generating…": "සාදමින්…",
|
||||
"Generate share link": "බෙදාගැනීමේ සබැඳිය සාදන්න",
|
||||
"Includes your current page": "ඔබගේ වර්තමාන පිටුව ඇතුළත්",
|
||||
"Share URL": "බෙදාගැනීමේ URL",
|
||||
"Copy link": "සබැඳිය පිටපත් කරන්න",
|
||||
"Copied": "පිටපත් කළා",
|
||||
@@ -1305,7 +1302,6 @@
|
||||
"Added to your library": "ඔබගේ පුස්තකාලයට එක් කළා",
|
||||
"Could not import shared book": "බෙදාගත් පොත ආයාත කළ නොහැක",
|
||||
"Manage Shared Links": "බෙදාගැනීමේ සබැඳි කළමනාකරණය",
|
||||
"Share current page": "වර්තමාන පිටුව බෙදාගන්න",
|
||||
"Expires in": "කල් ඉකුත් වේ",
|
||||
"{{count}} days_one": "දින 1",
|
||||
"{{count}} days_other": "දින {{count}}",
|
||||
@@ -1314,5 +1310,12 @@
|
||||
"Expires in {{count}} hours_one": "පැය 1කින් කල් ඉකුත් වේ",
|
||||
"Expires in {{count}} hours_other": "පැය {{count}}කින් කල් ඉකුත් වේ",
|
||||
"Open in app": "යෙදුමෙන් විවෘත කරන්න",
|
||||
"Shared with you": "ඔබ සමඟ බෙදාගත්"
|
||||
"Shared with you": "ඔබ සමඟ බෙදාගත්",
|
||||
"Downloading… {{percent}}%": "බාගත කරමින්… {{percent}}%",
|
||||
"Import progress": "ආයාත ප්රගතිය",
|
||||
"Share reading progress": "කියවීමේ ප්රගතිය බෙදාගන්න",
|
||||
"Includes your reading progress": "ඔබේ කියවීමේ ප්රගතිය ඇතුළත්",
|
||||
"Synced {{time}}": "{{time}} සමමුහුර්ත කළේ",
|
||||
"Sync Info": "සමමුහුර්ත තොරතුරු",
|
||||
"Last Synced": "අවසන් සමමුහුර්තය"
|
||||
}
|
||||
|
||||
@@ -133,7 +133,6 @@
|
||||
"Cloud File Transfers": "Prenosi datotek v oblaku",
|
||||
"{{activeCount}} active, {{pendingCount}} pending": "{{activeCount}} aktivnih, {{pendingCount}} na čakanju",
|
||||
"{{failedCount}} failed": "{{failedCount}} spodletelih",
|
||||
"Synced at {{time}}": "Sinhronizirano ob {{time}}",
|
||||
"Never synced": "Nikoli sinhronizirano",
|
||||
"Account": "Račun",
|
||||
"Sign In": "Prijava",
|
||||
@@ -1241,7 +1240,6 @@
|
||||
"{{count}} failed_few": "{{count}} niso uspele",
|
||||
"{{count}} failed_other": "{{count}} jih ni uspelo",
|
||||
"(none)": "(brez)",
|
||||
"Metadata Hash": "Hash metapodatkov",
|
||||
"Meta Hash": "Meta hash",
|
||||
"Computed Hash": "Izračunani hash",
|
||||
"Identifiers": "Identifikatorji",
|
||||
@@ -1301,7 +1299,6 @@
|
||||
"Uploading book…": "Prenašanje knjige…",
|
||||
"Generating…": "Ustvarjanje…",
|
||||
"Generate share link": "Ustvari povezavo za deljenje",
|
||||
"Includes your current page": "Vključuje vašo trenutno stran",
|
||||
"Share URL": "URL za deljenje",
|
||||
"Copy link": "Kopiraj povezavo",
|
||||
"Copied": "Kopirano",
|
||||
@@ -1345,7 +1342,6 @@
|
||||
"Added to your library": "Dodano v vašo knjižnico",
|
||||
"Could not import shared book": "Deljene knjige ni bilo mogoče uvoziti",
|
||||
"Manage Shared Links": "Upravljanje povezav za deljenje",
|
||||
"Share current page": "Deli trenutno stran",
|
||||
"Expires in": "Poteče čez",
|
||||
"{{count}} days_one": "{{count}} dan",
|
||||
"{{count}} days_two": "{{count}} dneva",
|
||||
@@ -1360,5 +1356,12 @@
|
||||
"Expires in {{count}} hours_few": "Poteče čez {{count}} ure",
|
||||
"Expires in {{count}} hours_other": "Poteče čez {{count}} ur",
|
||||
"Open in app": "Odpri v aplikaciji",
|
||||
"Shared with you": "Deljeno z vami"
|
||||
"Shared with you": "Deljeno z vami",
|
||||
"Downloading… {{percent}}%": "Prenašanje… {{percent}} %",
|
||||
"Import progress": "Napredek uvoza",
|
||||
"Share reading progress": "Deli napredek branja",
|
||||
"Includes your reading progress": "Vključuje vaš napredek branja",
|
||||
"Synced {{time}}": "Sinhronizirano {{time}}",
|
||||
"Sync Info": "Informacije o sinhronizaciji",
|
||||
"Last Synced": "Zadnja sinhronizacija"
|
||||
}
|
||||
|
||||
@@ -301,7 +301,6 @@
|
||||
"Separate Cover Page": "Separat omslagssida",
|
||||
"Scrolled Mode": "Rullningsläge",
|
||||
"Sign in to Sync": "Logga in för synk",
|
||||
"Synced at {{time}}": "Synkad {{time}}",
|
||||
"Never synced": "Aldrig synkad",
|
||||
"Invert Image In Dark Mode": "Invertera bild i mörkt läge",
|
||||
"Reading Progress Synced": "Läsframsteg synkat",
|
||||
@@ -1207,7 +1206,6 @@
|
||||
"{{count}} failed_one": "{{count}} misslyckades",
|
||||
"{{count}} failed_other": "{{count}} misslyckades",
|
||||
"(none)": "(ingen)",
|
||||
"Metadata Hash": "Metadata-hash",
|
||||
"Meta Hash": "Meta-hash",
|
||||
"Computed Hash": "Beräknat hash",
|
||||
"Identifiers": "Identifierare",
|
||||
@@ -1265,7 +1263,6 @@
|
||||
"Uploading book…": "Laddar upp bok…",
|
||||
"Generating…": "Genererar…",
|
||||
"Generate share link": "Skapa delningslänk",
|
||||
"Includes your current page": "Inkluderar din nuvarande sida",
|
||||
"Share URL": "Delnings-URL",
|
||||
"Copy link": "Kopiera länk",
|
||||
"Copied": "Kopierad",
|
||||
@@ -1305,7 +1302,6 @@
|
||||
"Added to your library": "Tillagd i ditt bibliotek",
|
||||
"Could not import shared book": "Det gick inte att importera den delade boken",
|
||||
"Manage Shared Links": "Hantera delningslänkar",
|
||||
"Share current page": "Dela nuvarande sida",
|
||||
"Expires in": "Upphör om",
|
||||
"{{count}} days_one": "1 dag",
|
||||
"{{count}} days_other": "{{count}} dagar",
|
||||
@@ -1314,5 +1310,12 @@
|
||||
"Expires in {{count}} hours_one": "Upphör om 1 timme",
|
||||
"Expires in {{count}} hours_other": "Upphör om {{count}} timmar",
|
||||
"Open in app": "Öppna i appen",
|
||||
"Shared with you": "Delat med dig"
|
||||
"Shared with you": "Delat med dig",
|
||||
"Downloading… {{percent}}%": "Laddar ner… {{percent}} %",
|
||||
"Import progress": "Importförlopp",
|
||||
"Share reading progress": "Dela läsförloppet",
|
||||
"Includes your reading progress": "Inkluderar ditt läsförlopp",
|
||||
"Synced {{time}}": "Synkroniserades {{time}}",
|
||||
"Sync Info": "Synkroniseringsinformation",
|
||||
"Last Synced": "Senast synkroniserad"
|
||||
}
|
||||
|
||||
@@ -330,7 +330,6 @@
|
||||
"{{engine}}: {{count}} voices_one": "{{engine}}: 1 குரல்",
|
||||
"{{engine}}: {{count}} voices_other": "{{engine}}: {{count}} குரல்கள்",
|
||||
"Sign in to Sync": "ஒத்திசைக்க உள்நுழையவும்",
|
||||
"Synced at {{time}}": "{{time}} இல் ஒத்திசைக்கப்பட்டது",
|
||||
"Never synced": "ஒத்திசைக்கப்படவில்லை",
|
||||
"Reading Progress Synced": "வாசிப்பு முன்னேற்றம் ஒத்திசைக்கப்பட்டது",
|
||||
"Page {{page}} of {{total}} ({{percentage}}%)": "{{total}} இல் {{page}} பக்கம் ({{percentage}}%)",
|
||||
@@ -1207,7 +1206,6 @@
|
||||
"{{count}} failed_one": "{{count}} தோல்வி",
|
||||
"{{count}} failed_other": "{{count}} தோல்விகள்",
|
||||
"(none)": "(இல்லை)",
|
||||
"Metadata Hash": "மெட்டாடேட்டா ஹாஷ்",
|
||||
"Meta Hash": "மெட்டா ஹாஷ்",
|
||||
"Computed Hash": "கணக்கிடப்பட்ட ஹாஷ்",
|
||||
"Identifiers": "அடையாளங்காட்டிகள்",
|
||||
@@ -1265,7 +1263,6 @@
|
||||
"Uploading book…": "புத்தகத்தை பதிவேற்றுகிறது…",
|
||||
"Generating…": "உருவாக்குகிறது…",
|
||||
"Generate share link": "பகிர்வு இணைப்பை உருவாக்கு",
|
||||
"Includes your current page": "உங்கள் தற்போதைய பக்கத்தை உள்ளடக்கியது",
|
||||
"Share URL": "பகிர்வு URL",
|
||||
"Copy link": "இணைப்பை நகலெடு",
|
||||
"Copied": "நகலெடுக்கப்பட்டது",
|
||||
@@ -1305,7 +1302,6 @@
|
||||
"Added to your library": "உங்கள் நூலகத்தில் சேர்க்கப்பட்டது",
|
||||
"Could not import shared book": "பகிரப்பட்ட புத்தகத்தை இறக்குமதி செய்ய முடியவில்லை",
|
||||
"Manage Shared Links": "பகிர்வு இணைப்புகளை நிர்வகி",
|
||||
"Share current page": "தற்போதைய பக்கத்தைப் பகிர்",
|
||||
"Expires in": "காலாவதியாகும்",
|
||||
"{{count}} days_one": "1 நாள்",
|
||||
"{{count}} days_other": "{{count}} நாட்கள்",
|
||||
@@ -1314,5 +1310,12 @@
|
||||
"Expires in {{count}} hours_one": "1 மணிநேரத்தில் காலாவதியாகும்",
|
||||
"Expires in {{count}} hours_other": "{{count}} மணிநேரத்தில் காலாவதியாகும்",
|
||||
"Open in app": "பயன்பாட்டில் திற",
|
||||
"Shared with you": "உங்களுடன் பகிரப்பட்டது"
|
||||
"Shared with you": "உங்களுடன் பகிரப்பட்டது",
|
||||
"Downloading… {{percent}}%": "பதிவிறக்கம்… {{percent}}%",
|
||||
"Import progress": "இறக்குமதி முன்னேற்றம்",
|
||||
"Share reading progress": "வாசிப்பு முன்னேற்றத்தைப் பகிரவும்",
|
||||
"Includes your reading progress": "உங்கள் வாசிப்பு முன்னேற்றத்தை உள்ளடக்கியது",
|
||||
"Synced {{time}}": "{{time}} ஒத்திசைக்கப்பட்டது",
|
||||
"Sync Info": "ஒத்திசைவு தகவல்",
|
||||
"Last Synced": "கடைசி ஒத்திசைவு"
|
||||
}
|
||||
|
||||
@@ -277,7 +277,6 @@
|
||||
"Fast": "เร็ว",
|
||||
"{{engine}}: {{count}} voices_other": "{{engine}}: {{count}} เสียง",
|
||||
"Sign in to Sync": "เข้าสู่ระบบเพื่อซิงค์",
|
||||
"Synced at {{time}}": "ซิงค์เมื่อ {{time}}",
|
||||
"Never synced": "ไม่เคยซิงค์",
|
||||
"Reading Progress Synced": "ซิงค์ความคืบหน้าแล้ว",
|
||||
"Delete Your Account?": "ลบบัญชีของคุณ?",
|
||||
@@ -1190,7 +1189,6 @@
|
||||
"Retry all": "ลองอีกครั้งทั้งหมด",
|
||||
"{{count}} failed_other": "{{count}} ล้มเหลว",
|
||||
"(none)": "(ไม่มี)",
|
||||
"Metadata Hash": "แฮชเมตาดาต้า",
|
||||
"Meta Hash": "แฮชเมตา",
|
||||
"Computed Hash": "แฮชที่คำนวณ",
|
||||
"Identifiers": "ตัวระบุ",
|
||||
@@ -1247,7 +1245,6 @@
|
||||
"Uploading book…": "กำลังอัปโหลดหนังสือ…",
|
||||
"Generating…": "กำลังสร้าง…",
|
||||
"Generate share link": "สร้างลิงก์แชร์",
|
||||
"Includes your current page": "รวมหน้าปัจจุบันของคุณ",
|
||||
"Share URL": "URL แชร์",
|
||||
"Copy link": "คัดลอกลิงก์",
|
||||
"Copied": "คัดลอกแล้ว",
|
||||
@@ -1285,11 +1282,17 @@
|
||||
"Added to your library": "เพิ่มลงในคลังของคุณแล้ว",
|
||||
"Could not import shared book": "ไม่สามารถนำเข้าหนังสือที่แชร์ได้",
|
||||
"Manage Shared Links": "จัดการลิงก์แชร์",
|
||||
"Share current page": "แชร์หน้าปัจจุบัน",
|
||||
"Expires in": "หมดอายุใน",
|
||||
"{{count}} days_other": "{{count}} วัน",
|
||||
"Expires in {{count}} days_other": "หมดอายุใน {{count}} วัน",
|
||||
"Expires in {{count}} hours_other": "หมดอายุใน {{count}} ชั่วโมง",
|
||||
"Open in app": "เปิดในแอป",
|
||||
"Shared with you": "แชร์กับคุณ"
|
||||
"Shared with you": "แชร์กับคุณ",
|
||||
"Downloading… {{percent}}%": "กำลังดาวน์โหลด… {{percent}}%",
|
||||
"Import progress": "ความคืบหน้าการนำเข้า",
|
||||
"Share reading progress": "แชร์ความคืบหน้าการอ่าน",
|
||||
"Includes your reading progress": "รวมถึงความคืบหน้าการอ่านของคุณ",
|
||||
"Synced {{time}}": "ซิงค์เมื่อ {{time}}",
|
||||
"Sync Info": "ข้อมูลการซิงค์",
|
||||
"Last Synced": "ซิงค์ล่าสุด"
|
||||
}
|
||||
|
||||
@@ -299,7 +299,6 @@
|
||||
"No notes match your search": "Eşleşen not bulunamadı",
|
||||
"Search notes and excerpts...": "Notlarda ara...",
|
||||
"Sign in to Sync": "Giriş yap",
|
||||
"Synced at {{time}}": "{{time}}'de eşzlendi",
|
||||
"Never synced": "Hiç eşzlenmedi",
|
||||
"Show Remaining Time": "Kalan Süreyi Göster",
|
||||
"{{time}} min left in chapter": "{{time}} dakika bölümde kaldı",
|
||||
@@ -1207,7 +1206,6 @@
|
||||
"{{count}} failed_one": "{{count}} başarısız",
|
||||
"{{count}} failed_other": "{{count}} başarısız",
|
||||
"(none)": "(yok)",
|
||||
"Metadata Hash": "Üst Veri Hash'i",
|
||||
"Meta Hash": "Meta Hash",
|
||||
"Computed Hash": "Hesaplanan Hash",
|
||||
"Identifiers": "Tanımlayıcılar",
|
||||
@@ -1265,7 +1263,6 @@
|
||||
"Uploading book…": "Kitap yükleniyor…",
|
||||
"Generating…": "Oluşturuluyor…",
|
||||
"Generate share link": "Paylaşım bağlantısı oluştur",
|
||||
"Includes your current page": "Mevcut sayfanızı içerir",
|
||||
"Share URL": "Paylaşım URL’si",
|
||||
"Copy link": "Bağlantıyı kopyala",
|
||||
"Copied": "Kopyalandı",
|
||||
@@ -1305,7 +1302,6 @@
|
||||
"Added to your library": "Kütüphanenize eklendi",
|
||||
"Could not import shared book": "Paylaşılan kitap içe aktarılamadı",
|
||||
"Manage Shared Links": "Paylaşım bağlantılarını yönet",
|
||||
"Share current page": "Mevcut sayfayı paylaş",
|
||||
"Expires in": "Sona erer",
|
||||
"{{count}} days_one": "1 gün",
|
||||
"{{count}} days_other": "{{count}} gün",
|
||||
@@ -1314,5 +1310,12 @@
|
||||
"Expires in {{count}} hours_one": "1 saat içinde sona erer",
|
||||
"Expires in {{count}} hours_other": "{{count}} saat içinde sona erer",
|
||||
"Open in app": "Uygulamada aç",
|
||||
"Shared with you": "Sizinle paylaşıldı"
|
||||
"Shared with you": "Sizinle paylaşıldı",
|
||||
"Downloading… {{percent}}%": "İndiriliyor… %{{percent}}",
|
||||
"Import progress": "İçe aktarma ilerlemesi",
|
||||
"Share reading progress": "Okuma ilerlemesini paylaş",
|
||||
"Includes your reading progress": "Okuma ilerlemenizi içerir",
|
||||
"Synced {{time}}": "{{time}} senkronize edildi",
|
||||
"Sync Info": "Senkronizasyon bilgisi",
|
||||
"Last Synced": "Son senkronizasyon"
|
||||
}
|
||||
|
||||
@@ -303,7 +303,6 @@
|
||||
"No notes match your search": "Нотаток не знайдено",
|
||||
"Search notes and excerpts...": "Шукати нотатки...",
|
||||
"Sign in to Sync": "Увійти",
|
||||
"Synced at {{time}}": "Синхр. о {{time}}",
|
||||
"Never synced": "Ніколи не синхр.",
|
||||
"Show Remaining Time": "Показати залишок часу",
|
||||
"{{time}} min left in chapter": "{{time}} хв до кінця розділу",
|
||||
@@ -1241,7 +1240,6 @@
|
||||
"{{count}} failed_many": "{{count}} помилок",
|
||||
"{{count}} failed_other": "{{count}} помилок",
|
||||
"(none)": "(немає)",
|
||||
"Metadata Hash": "Хеш метаданих",
|
||||
"Meta Hash": "Мета-хеш",
|
||||
"Computed Hash": "Обчислений хеш",
|
||||
"Identifiers": "Ідентифікатори",
|
||||
@@ -1301,7 +1299,6 @@
|
||||
"Uploading book…": "Завантаження книги…",
|
||||
"Generating…": "Створення…",
|
||||
"Generate share link": "Створити посилання",
|
||||
"Includes your current page": "Включає вашу поточну сторінку",
|
||||
"Share URL": "URL для поширення",
|
||||
"Copy link": "Копіювати посилання",
|
||||
"Copied": "Скопійовано",
|
||||
@@ -1345,7 +1342,6 @@
|
||||
"Added to your library": "Додано до вашої бібліотеки",
|
||||
"Could not import shared book": "Не вдалося імпортувати поширену книгу",
|
||||
"Manage Shared Links": "Керування посиланнями",
|
||||
"Share current page": "Поділитися поточною сторінкою",
|
||||
"Expires in": "Закінчується через",
|
||||
"{{count}} days_one": "{{count}} день",
|
||||
"{{count}} days_few": "{{count}} дні",
|
||||
@@ -1360,5 +1356,12 @@
|
||||
"Expires in {{count}} hours_many": "Дійсне ще {{count}} годин",
|
||||
"Expires in {{count}} hours_other": "Дійсне ще {{count}} годин",
|
||||
"Open in app": "Відкрити в застосунку",
|
||||
"Shared with you": "Поділилися з вами"
|
||||
"Shared with you": "Поділилися з вами",
|
||||
"Downloading… {{percent}}%": "Завантаження… {{percent}}%",
|
||||
"Import progress": "Хід імпорту",
|
||||
"Share reading progress": "Поділитися прогресом читання",
|
||||
"Includes your reading progress": "Містить ваш прогрес читання",
|
||||
"Synced {{time}}": "Синхронізовано {{time}}",
|
||||
"Sync Info": "Інформація про синхронізацію",
|
||||
"Last Synced": "Остання синхронізація"
|
||||
}
|
||||
|
||||
@@ -297,7 +297,6 @@
|
||||
"No notes match your search": "Không tìm thấy ghi chú nào",
|
||||
"Search notes and excerpts...": "Tìm ghi chú...",
|
||||
"Sign in to Sync": "Đăng nhập",
|
||||
"Synced at {{time}}": "Đã đồng bộ lúc {{time}}",
|
||||
"Never synced": "Chưa từng đồng bộ",
|
||||
"Show Remaining Time": "Hiển thị thời gian còn lại",
|
||||
"{{time}} min left in chapter": "{{time}} phút còn lại trong chương",
|
||||
@@ -1190,7 +1189,6 @@
|
||||
"Retry all": "Thử lại tất cả",
|
||||
"{{count}} failed_other": "{{count}} thất bại",
|
||||
"(none)": "(không có)",
|
||||
"Metadata Hash": "Hash Siêu Dữ Liệu",
|
||||
"Meta Hash": "Meta Hash",
|
||||
"Computed Hash": "Hash Đã Tính",
|
||||
"Identifiers": "Định Danh",
|
||||
@@ -1247,7 +1245,6 @@
|
||||
"Uploading book…": "Đang tải lên sách…",
|
||||
"Generating…": "Đang tạo…",
|
||||
"Generate share link": "Tạo liên kết chia sẻ",
|
||||
"Includes your current page": "Bao gồm trang hiện tại của bạn",
|
||||
"Share URL": "URL chia sẻ",
|
||||
"Copy link": "Sao chép liên kết",
|
||||
"Copied": "Đã sao chép",
|
||||
@@ -1285,11 +1282,17 @@
|
||||
"Added to your library": "Đã thêm vào thư viện của bạn",
|
||||
"Could not import shared book": "Không thể nhập sách được chia sẻ",
|
||||
"Manage Shared Links": "Quản lý liên kết chia sẻ",
|
||||
"Share current page": "Chia sẻ trang hiện tại",
|
||||
"Expires in": "Hết hạn sau",
|
||||
"{{count}} days_other": "{{count}} ngày",
|
||||
"Expires in {{count}} days_other": "Hết hạn sau {{count}} ngày",
|
||||
"Expires in {{count}} hours_other": "Hết hạn sau {{count}} giờ",
|
||||
"Open in app": "Mở trong ứng dụng",
|
||||
"Shared with you": "Được chia sẻ với bạn"
|
||||
"Shared with you": "Được chia sẻ với bạn",
|
||||
"Downloading… {{percent}}%": "Đang tải xuống… {{percent}}%",
|
||||
"Import progress": "Tiến độ nhập",
|
||||
"Share reading progress": "Chia sẻ tiến độ đọc",
|
||||
"Includes your reading progress": "Bao gồm tiến độ đọc của bạn",
|
||||
"Synced {{time}}": "Đã đồng bộ {{time}}",
|
||||
"Sync Info": "Thông tin đồng bộ",
|
||||
"Last Synced": "Đồng bộ lần cuối"
|
||||
}
|
||||
|
||||
@@ -298,7 +298,6 @@
|
||||
"No notes match your search": "未找到匹配的笔记",
|
||||
"Search notes and excerpts...": "搜索笔记...",
|
||||
"Sign in to Sync": "登录后同步",
|
||||
"Synced at {{time}}": "同步于:{{time}}",
|
||||
"Never synced": "从未同步",
|
||||
"Show Remaining Time": "显示剩余时间",
|
||||
"{{time}} min left in chapter": "本章剩余 {{time}} 分钟",
|
||||
@@ -1190,7 +1189,6 @@
|
||||
"Retry all": "全部重试",
|
||||
"{{count}} failed_other": "{{count}} 个失败",
|
||||
"(none)": "(无)",
|
||||
"Metadata Hash": "元数据哈希",
|
||||
"Meta Hash": "元哈希",
|
||||
"Computed Hash": "计算的哈希",
|
||||
"Identifiers": "标识符",
|
||||
@@ -1247,7 +1245,6 @@
|
||||
"Uploading book…": "正在上传书籍…",
|
||||
"Generating…": "正在生成…",
|
||||
"Generate share link": "生成分享链接",
|
||||
"Includes your current page": "包含你当前的页面",
|
||||
"Share URL": "分享 URL",
|
||||
"Copy link": "复制链接",
|
||||
"Copied": "已复制",
|
||||
@@ -1285,11 +1282,17 @@
|
||||
"Added to your library": "已加入你的书库",
|
||||
"Could not import shared book": "无法导入共享书籍",
|
||||
"Manage Shared Links": "管理分享链接",
|
||||
"Share current page": "分享当前页",
|
||||
"Expires in": "有效期",
|
||||
"{{count}} days_other": "{{count}} 天",
|
||||
"Expires in {{count}} days_other": "{{count}} 天后到期",
|
||||
"Expires in {{count}} hours_other": "{{count}} 小时后到期",
|
||||
"Open in app": "在应用中打开",
|
||||
"Shared with you": "与你分享"
|
||||
"Shared with you": "与你分享",
|
||||
"Downloading… {{percent}}%": "下载中… {{percent}}%",
|
||||
"Import progress": "导入进度",
|
||||
"Share reading progress": "分享阅读进度",
|
||||
"Includes your reading progress": "包含你的阅读进度",
|
||||
"Synced {{time}}": "{{time}}已同步",
|
||||
"Sync Info": "同步信息",
|
||||
"Last Synced": "上一次同步"
|
||||
}
|
||||
|
||||
@@ -297,7 +297,6 @@
|
||||
"No notes match your search": "找不到符合的筆記",
|
||||
"Search notes and excerpts...": "搜尋筆記...",
|
||||
"Sign in to Sync": "登入以同步",
|
||||
"Synced at {{time}}": "同步於:{{time}}",
|
||||
"Never synced": "從未同步",
|
||||
"Show Remaining Time": "顯示剩餘時間",
|
||||
"{{time}} min left in chapter": "本章剩餘 {{time}} 分鐘",
|
||||
@@ -1190,7 +1189,6 @@
|
||||
"Retry all": "全部重試",
|
||||
"{{count}} failed_other": "{{count}} 個失敗",
|
||||
"(none)": "(無)",
|
||||
"Metadata Hash": "中繼資料雜湊",
|
||||
"Meta Hash": "中繼雜湊",
|
||||
"Computed Hash": "計算所得雜湊",
|
||||
"Identifiers": "識別碼",
|
||||
@@ -1247,7 +1245,6 @@
|
||||
"Uploading book…": "正在上傳書籍…",
|
||||
"Generating…": "正在產生…",
|
||||
"Generate share link": "產生分享連結",
|
||||
"Includes your current page": "包含您目前的頁面",
|
||||
"Share URL": "分享 URL",
|
||||
"Copy link": "複製連結",
|
||||
"Copied": "已複製",
|
||||
@@ -1285,11 +1282,17 @@
|
||||
"Added to your library": "已加入您的書庫",
|
||||
"Could not import shared book": "無法匯入分享書籍",
|
||||
"Manage Shared Links": "管理分享連結",
|
||||
"Share current page": "分享目前頁面",
|
||||
"Expires in": "有效期",
|
||||
"{{count}} days_other": "{{count}} 天",
|
||||
"Expires in {{count}} days_other": "{{count}} 天後到期",
|
||||
"Expires in {{count}} hours_other": "{{count}} 小時後到期",
|
||||
"Open in app": "在應用中開啟",
|
||||
"Shared with you": "與您分享"
|
||||
"Shared with you": "與您分享",
|
||||
"Downloading… {{percent}}%": "下載中… {{percent}}%",
|
||||
"Import progress": "匯入進度",
|
||||
"Share reading progress": "分享閱讀進度",
|
||||
"Includes your reading progress": "包含你的閱讀進度",
|
||||
"Synced {{time}}": "{{time}}已同步",
|
||||
"Sync Info": "同步資訊",
|
||||
"Last Synced": "上一次同步"
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import { setMigrateDataDirDialogVisible } from '@/app/library/components/Migrate
|
||||
import { requestStoragePermission } from '@/utils/permission';
|
||||
import { saveSysSettings } from '@/helpers/settings';
|
||||
import { selectDirectory } from '@/utils/bridge';
|
||||
import { formatLocaleDateTime } from '@/utils/book';
|
||||
import dayjs from 'dayjs';
|
||||
import UserAvatar from '@/components/UserAvatar';
|
||||
import MenuItem from '@/components/MenuItem';
|
||||
import Quota from '@/components/Quota';
|
||||
@@ -101,11 +101,6 @@ const SettingsMenu: React.FC<SettingsMenuProps> = ({ onPullLibrary, setIsDropdow
|
||||
setThemeMode(nextMode);
|
||||
};
|
||||
|
||||
const handleReloadPage = () => {
|
||||
window.location.reload();
|
||||
setIsDropdownOpen?.(false);
|
||||
};
|
||||
|
||||
const handleFullScreen = () => {
|
||||
tauriHandleToggleFullScreen();
|
||||
setIsDropdownOpen?.(false);
|
||||
@@ -319,8 +314,8 @@ const SettingsMenu: React.FC<SettingsMenuProps> = ({ onPullLibrary, setIsDropdow
|
||||
<MenuItem
|
||||
label={
|
||||
settings.lastSyncedAtBooks
|
||||
? _('Synced at {{time}}', {
|
||||
time: formatLocaleDateTime(settings.lastSyncedAtBooks),
|
||||
? _('Synced {{time}}', {
|
||||
time: dayjs(settings.lastSyncedAtBooks).fromNow(),
|
||||
})
|
||||
: _('Never synced')
|
||||
}
|
||||
@@ -398,7 +393,6 @@ const SettingsMenu: React.FC<SettingsMenuProps> = ({ onPullLibrary, setIsDropdow
|
||||
onClick={toggleAlwaysInForeground}
|
||||
/>
|
||||
)}
|
||||
<MenuItem label={_('Reload Page')} onClick={handleReloadPage} />
|
||||
<MenuItem
|
||||
label={themeModeLabel}
|
||||
Icon={themeMode === 'dark' ? PiMoon : themeMode === 'light' ? PiSun : TbSunMoon}
|
||||
|
||||
@@ -222,7 +222,7 @@ const ShareBookDialog: React.FC<ShareBookDialogProps> = ({ isOpen, book, cfi, on
|
||||
isOpen={isOpen}
|
||||
title={_('Share Book')}
|
||||
onClose={onClose}
|
||||
boxClassName='sm:min-w-[480px] sm:max-w-[480px] sm:h-auto sm:max-h-[90%]'
|
||||
boxClassName='sm:min-w-[460px] sm:max-w-[460px] sm:h-auto sm:max-h-[90%]'
|
||||
contentClassName='!px-6 !py-4'
|
||||
>
|
||||
<div className='flex flex-col gap-5 pt-2'>
|
||||
@@ -278,7 +278,7 @@ const ShareBookDialog: React.FC<ShareBookDialogProps> = ({ isOpen, book, cfi, on
|
||||
{cfi && (
|
||||
<label className='flex min-h-12 cursor-pointer select-none items-center justify-between gap-3 px-4 py-2'>
|
||||
<span className='text-base-content text-sm font-medium'>
|
||||
{_('Share current page')}
|
||||
{_('Share reading progress')}
|
||||
</span>
|
||||
<input
|
||||
type='checkbox'
|
||||
@@ -325,7 +325,7 @@ const ShareBookDialog: React.FC<ShareBookDialogProps> = ({ isOpen, book, cfi, on
|
||||
{created.hasCfi && (
|
||||
<div className='text-primary inline-flex items-center gap-1.5 self-start text-xs font-medium'>
|
||||
<IoCheckmarkCircle className='h-4 w-4' aria-hidden='true' />
|
||||
{_('Includes your current page')}
|
||||
{_('Includes your reading progress')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import NotebookToggler from './NotebookToggler';
|
||||
import SettingsToggler from './SettingsToggler';
|
||||
import TranslationToggler from './TranslationToggler';
|
||||
import ViewMenu from './ViewMenu';
|
||||
import MetaHashInfoDialog from './MetaHashInfoDialog';
|
||||
import SyncInfoDialog from './SyncInfoDialog';
|
||||
|
||||
interface HeaderBarProps {
|
||||
bookKey: string;
|
||||
@@ -64,9 +64,12 @@ const HeaderBar: React.FC<HeaderBarProps> = ({
|
||||
const { isDarkMode, systemUIVisible, statusBarHeight } = useThemeStore();
|
||||
const { isSideBarVisible, getIsSideBarVisible } = useSidebarStore();
|
||||
const { getView, getViewSettings, setHoveredBookKey } = useReaderStore();
|
||||
const { getBookData } = useBookDataStore();
|
||||
const { getBookData, getConfig } = useBookDataStore();
|
||||
const viewSettings = getViewSettings(bookKey);
|
||||
const bookData = getBookData(bookKey);
|
||||
const bookConfig = getConfig(bookKey);
|
||||
const lastSyncedAt =
|
||||
Math.max(bookConfig?.lastSyncedAtConfig || 0, bookConfig?.lastSyncedAtNotes || 0) || undefined;
|
||||
|
||||
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
||||
const [isMetaHashDialogOpen, setIsMetaHashDialogOpen] = useState(false);
|
||||
@@ -295,10 +298,11 @@ const HeaderBar: React.FC<HeaderBarProps> = ({
|
||||
</Dropdown>
|
||||
{isMetaHashDialogOpen && (
|
||||
<ModalPortal showOverlay={false}>
|
||||
<MetaHashInfoDialog
|
||||
<SyncInfoDialog
|
||||
isOpen={isMetaHashDialogOpen}
|
||||
metadata={bookData?.bookDoc?.metadata ?? bookData?.book?.metadata}
|
||||
storedMetaHash={bookData?.book?.metaHash}
|
||||
lastSyncedAt={lastSyncedAt}
|
||||
onClose={() => setIsMetaHashDialogOpen(false)}
|
||||
/>
|
||||
</ModalPortal>
|
||||
|
||||
+13
-7
@@ -2,28 +2,31 @@ import React from 'react';
|
||||
import Dialog from '@/components/Dialog';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { BookMetadata } from '@/libs/document';
|
||||
import { getMetadataHashInfo } from '@/utils/book';
|
||||
import { formatLocaleDateTime, getMetadataHashInfo } from '@/utils/book';
|
||||
|
||||
interface MetaHashInfoDialogProps {
|
||||
interface SyncInfoDialogProps {
|
||||
isOpen: boolean;
|
||||
metadata: BookMetadata | null | undefined;
|
||||
storedMetaHash?: string;
|
||||
/** Most recent sync timestamp across pull + push of config and notes. */
|
||||
lastSyncedAt?: number;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const Row: React.FC<{ label: string; value: React.ReactNode }> = ({ label, value }) => (
|
||||
<div className='flex flex-col gap-1'>
|
||||
<span className='text-base-content/60 text-xs uppercase tracking-wide'>{label}</span>
|
||||
<div className='bg-base-200 text-base-content/90 break-all rounded-md p-2 font-mono text-xs'>
|
||||
<span className='text-base-content/60 text-sm uppercase tracking-wide sm:text-xs'>{label}</span>
|
||||
<div className='bg-base-200 text-base-content/90 break-all rounded-md p-2 font-mono text-sm sm:text-xs'>
|
||||
{value}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const MetaHashInfoDialog: React.FC<MetaHashInfoDialogProps> = ({
|
||||
const SyncInfoDialog: React.FC<SyncInfoDialogProps> = ({
|
||||
isOpen,
|
||||
metadata,
|
||||
storedMetaHash,
|
||||
lastSyncedAt,
|
||||
onClose,
|
||||
}) => {
|
||||
const _ = useTranslation();
|
||||
@@ -31,12 +34,14 @@ const MetaHashInfoDialog: React.FC<MetaHashInfoDialogProps> = ({
|
||||
const displayHash = storedMetaHash || info?.metaHash || '';
|
||||
const hashesMatch = !info || !storedMetaHash || storedMetaHash === info.metaHash;
|
||||
const placeholder = _('(none)');
|
||||
const lastSyncedLabel = lastSyncedAt ? formatLocaleDateTime(lastSyncedAt) : _('Never synced');
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
title={_('Metadata Hash')}
|
||||
snapHeight={0.7}
|
||||
title={_('Sync Info')}
|
||||
boxClassName='sm:!min-w-[520px] sm:h-auto'
|
||||
>
|
||||
{isOpen && (
|
||||
@@ -52,10 +57,11 @@ const MetaHashInfoDialog: React.FC<MetaHashInfoDialogProps> = ({
|
||||
label={_('Identifiers')}
|
||||
value={info && info.identifiers.length > 0 ? info.identifiers.join(', ') : placeholder}
|
||||
/>
|
||||
<Row label={_('Last Synced')} value={lastSyncedLabel} />
|
||||
</div>
|
||||
)}
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default MetaHashInfoDialog;
|
||||
export default SyncInfoDialog;
|
||||
@@ -23,7 +23,7 @@ import { getStyles } from '@/utils/style';
|
||||
import { navigateToLogin } from '@/utils/nav';
|
||||
import { eventDispatcher } from '@/utils/event';
|
||||
import { getMaxInlineSize } from '@/utils/config';
|
||||
import { formatLocaleDateTime } from '@/utils/book';
|
||||
import dayjs from 'dayjs';
|
||||
import { saveViewSettings } from '@/helpers/settings';
|
||||
import { tauriHandleToggleFullScreen } from '@/utils/window';
|
||||
import MenuItem from '@/components/MenuItem';
|
||||
@@ -327,8 +327,8 @@ const ViewMenu: React.FC<ViewMenuProps> = ({
|
||||
!user
|
||||
? _('Sign in to Sync')
|
||||
: lastSyncTime
|
||||
? _('Synced at {{time}}', {
|
||||
time: formatLocaleDateTime(lastSyncTime),
|
||||
? _('Synced {{time}}', {
|
||||
time: dayjs(lastSyncTime).fromNow(),
|
||||
})
|
||||
: _('Never synced')
|
||||
}
|
||||
@@ -337,8 +337,8 @@ const ViewMenu: React.FC<ViewMenuProps> = ({
|
||||
onClick={handleSync}
|
||||
siblings={
|
||||
<button
|
||||
aria-label={_('Metadata Hash')}
|
||||
title={_('Metadata Hash')}
|
||||
aria-label={_('Sync Info')}
|
||||
title={_('Sync Info')}
|
||||
className='hover:bg-base-300 text-base-content/70 mx-1 rounded-md px-2'
|
||||
onClick={() => {
|
||||
setIsDropdownOpen?.(false);
|
||||
|
||||
@@ -12,11 +12,14 @@ import {
|
||||
import { DOWNLOAD_READEST_URL } from '@/services/constants';
|
||||
import { useTranslation, type TranslationFunc } from '@/hooks/useTranslation';
|
||||
import { useAuth } from '@/context/AuthContext';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { BrandHeader } from '@/components/landing/BrandHeader';
|
||||
import { Card } from '@/components/landing/Card';
|
||||
import { PageFooter } from '@/components/landing/PageFooter';
|
||||
import { getShare, importShare, type ShareMetadata } from '@/libs/share';
|
||||
import { ensureSharedBookLocal } from '@/libs/shareImport';
|
||||
import { formatBytes } from '@/utils/book';
|
||||
import { navigateToReader } from '@/utils/nav';
|
||||
|
||||
const formatExpiry = (iso: string, _: TranslationFunc): string => {
|
||||
const ms = new Date(iso).getTime() - Date.now();
|
||||
@@ -33,6 +36,7 @@ const ShareLanding = () => {
|
||||
const searchParams = useSearchParams();
|
||||
const pathname = usePathname();
|
||||
const { user } = useAuth();
|
||||
const { appService } = useEnv();
|
||||
|
||||
// Resolve the token from either the rewritten query (?token=) or the pretty
|
||||
// path (/s/{token}). The next.config.mjs rewrite handles the web build; the
|
||||
@@ -50,6 +54,7 @@ const ShareLanding = () => {
|
||||
const [meta, setMeta] = useState<ShareMetadata | null>(null);
|
||||
const [loadError, setLoadError] = useState<{ status: number; message: string } | null>(null);
|
||||
const [importing, setImporting] = useState(false);
|
||||
const [importProgress, setImportProgress] = useState<number | null>(null);
|
||||
const [importError, setImportError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -80,19 +85,32 @@ const ShareLanding = () => {
|
||||
const appHref = `readest://share/${encodeURIComponent(token)}`;
|
||||
|
||||
const handleAddToLibrary = async () => {
|
||||
if (!token || importing) return;
|
||||
if (!token || importing || !appService) return;
|
||||
setImporting(true);
|
||||
setImportProgress(null);
|
||||
setImportError(null);
|
||||
try {
|
||||
const result = await importShare(token);
|
||||
// The reader resolves `ids` via getBookByHash, so pass the book hash —
|
||||
// not the `files.id` UUID. Same identifier used by /reader/:hash links.
|
||||
const params = new URLSearchParams();
|
||||
params.set('ids', result.bookHash);
|
||||
if (result.cfi) params.set('cfi', result.cfi);
|
||||
router.push(`/reader?${params.toString()}`);
|
||||
// /import only mutates server state (R2 byte-copy + files row). The
|
||||
// local library is unchanged, so the reader's getBookByHash would miss.
|
||||
// Pull bytes + create the local Book entry before navigating; meta is
|
||||
// already in state from the initial getShare call so no extra round-trip.
|
||||
await ensureSharedBookLocal({
|
||||
token,
|
||||
importResult: result,
|
||||
appService,
|
||||
meta: meta ?? undefined,
|
||||
onProgress: setImportProgress,
|
||||
});
|
||||
// navigateToReader routes web to /reader/{hash} (Pages Router page that
|
||||
// actually renders) and Tauri to /reader?ids={hash}. Building the URL
|
||||
// by hand here lands on the App Router /reader page instead, which is
|
||||
// a stub for this flow and renders blank.
|
||||
const queryParams = result.cfi ? `cfi=${encodeURIComponent(result.cfi)}` : undefined;
|
||||
navigateToReader(router, [result.bookHash], queryParams);
|
||||
} catch (err) {
|
||||
setImporting(false);
|
||||
setImportProgress(null);
|
||||
const message = err instanceof Error ? err.message : _('Could not add to your library');
|
||||
setImportError(message);
|
||||
}
|
||||
@@ -227,14 +245,42 @@ const ShareLanding = () => {
|
||||
type='button'
|
||||
onClick={handleAddToLibrary}
|
||||
disabled={importing}
|
||||
aria-busy={importing}
|
||||
className='btn btn-primary btn-block flex-nowrap gap-2 whitespace-nowrap rounded-xl'
|
||||
>
|
||||
<IoLibraryOutline className='h-5 w-5' aria-hidden='true' />
|
||||
{importing ? _('Adding…') : _('Add to my library')}
|
||||
{importing ? (
|
||||
<span className='loading loading-spinner loading-sm' aria-hidden='true' />
|
||||
) : (
|
||||
<IoLibraryOutline className='h-5 w-5' aria-hidden='true' />
|
||||
)}
|
||||
{importing
|
||||
? importProgress !== null
|
||||
? _('Downloading… {{percent}}%', { percent: importProgress })
|
||||
: _('Adding…')
|
||||
: _('Add to my library')}
|
||||
</button>
|
||||
{/* Live progress bar while bytes are streaming in. Stays at
|
||||
the indeterminate striped state until we get the first
|
||||
progress event from the byte transfer. */}
|
||||
{importing && (
|
||||
<progress
|
||||
className='progress progress-primary w-full'
|
||||
value={importProgress ?? undefined}
|
||||
max={100}
|
||||
aria-label={_('Import progress')}
|
||||
/>
|
||||
)}
|
||||
<a
|
||||
href={appHref}
|
||||
className='btn btn-ghost btn-block flex-nowrap gap-2 whitespace-nowrap rounded-xl'
|
||||
aria-disabled={importing}
|
||||
onClick={(e) => {
|
||||
if (importing) e.preventDefault();
|
||||
}}
|
||||
className={
|
||||
importing
|
||||
? 'btn btn-ghost btn-block btn-disabled flex-nowrap gap-2 whitespace-nowrap rounded-xl'
|
||||
: 'btn btn-ghost btn-block flex-nowrap gap-2 whitespace-nowrap rounded-xl'
|
||||
}
|
||||
>
|
||||
<IoOpenOutline className='h-5 w-5' aria-hidden='true' />
|
||||
{_('Open in app')}
|
||||
|
||||
@@ -13,18 +13,23 @@ interface UserInfoProps {
|
||||
const UserInfo: React.FC<UserInfoProps> = ({ avatarUrl, userFullName, userEmail, planDetails }) => {
|
||||
const _ = useTranslation();
|
||||
return (
|
||||
<div className='flex flex-col items-center gap-x-6 gap-y-4 md:flex-row md:items-start'>
|
||||
<div className='flex-shrink-0'>
|
||||
<div className='flex flex-col items-center gap-x-6 gap-y-2 md:flex-row md:items-center'>
|
||||
{/* Lock the avatar box to a square via classes so it can't go oval
|
||||
across breakpoints. fillContainer drops UserAvatar's inline
|
||||
width/height so the child stretches to this wrapper instead of
|
||||
fighting it. */}
|
||||
<div className='aspect-square h-16 w-16 flex-shrink-0 md:h-24 md:w-24'>
|
||||
{avatarUrl ? (
|
||||
<UserAvatar
|
||||
url={avatarUrl}
|
||||
size={window.innerWidth < 640 ? 64 : 128}
|
||||
size={128}
|
||||
DefaultIcon={PiUserCircle}
|
||||
className='h-16 w-16 md:h-24 md:w-24'
|
||||
className='h-full w-full'
|
||||
borderClassName='border-base-100 border-4'
|
||||
fillContainer
|
||||
/>
|
||||
) : (
|
||||
<PiUserCircle className='h-16 w-16 md:h-24 md:w-24' />
|
||||
<PiUserCircle className='h-full w-full' />
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -9,6 +9,15 @@ interface UserAvatarProps {
|
||||
DefaultIcon: IconType;
|
||||
className?: string;
|
||||
borderClassName?: string;
|
||||
/**
|
||||
* When true, the root box stretches via h-full/w-full instead of getting
|
||||
* the explicit `size` pinned via inline style. Use this when a parent
|
||||
* constrains the avatar with its own (responsive) classes — otherwise the
|
||||
* inline style overrides the parent box and the avatar can overflow on
|
||||
* smaller breakpoints. `size` is still used as the intrinsic dimension
|
||||
* for next/image and the fallback icon.
|
||||
*/
|
||||
fillContainer?: boolean;
|
||||
}
|
||||
|
||||
const getStorageKey = (url: string) => {
|
||||
@@ -21,6 +30,7 @@ const UserAvatar: React.FC<UserAvatarProps> = ({
|
||||
className,
|
||||
borderClassName,
|
||||
DefaultIcon,
|
||||
fillContainer,
|
||||
}) => {
|
||||
const [cachedImageUrl, setCachedImageUrl] = useState<string | null>(() => {
|
||||
if (!url) return null;
|
||||
@@ -64,7 +74,7 @@ const UserAvatar: React.FC<UserAvatarProps> = ({
|
||||
return (
|
||||
<div
|
||||
className='relative flex h-full w-full items-center justify-center rounded-full'
|
||||
style={{ width: size, height: size }}
|
||||
style={fillContainer ? undefined : { width: size, height: size }}
|
||||
>
|
||||
{url ? (
|
||||
<div>
|
||||
|
||||
@@ -8,6 +8,7 @@ import { eventDispatcher } from '@/utils/event';
|
||||
import { useAuth } from '@/context/AuthContext';
|
||||
import { navigateToReader } from '@/utils/nav';
|
||||
import { ShareApiError, confirmDownload, importShare } from '@/libs/share';
|
||||
import { ensureSharedBookLocal } from '@/libs/shareImport';
|
||||
import { parseShareDeepLink, type ShareDeepLink } from '@/utils/share';
|
||||
import { useTranslation } from './useTranslation';
|
||||
|
||||
@@ -57,13 +58,18 @@ export function useOpenShareLink() {
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!appService) return;
|
||||
try {
|
||||
const result = await importShare(token);
|
||||
// The /import endpoint only creates rows + R2 bytes server-side; the
|
||||
// local library is unchanged. Make sure the local library has both the
|
||||
// Book entry and the bytes on disk before navigating, otherwise
|
||||
// `getBookByHash` returns undefined and the reader throws "Book not
|
||||
// found". See src/libs/shareImport.ts for the three branches.
|
||||
await ensureSharedBookLocal({ token, importResult: result, appService });
|
||||
// Best-effort analytics ping; doesn't affect UX.
|
||||
confirmDownload(token);
|
||||
|
||||
// The reader resolves IDs via getBookByHash, so navigate with the
|
||||
// book hash (not the `files.id` UUID).
|
||||
const queryParams = result.cfi ? `cfi=${encodeURIComponent(result.cfi)}` : undefined;
|
||||
navigateToReader(router, [result.bookHash], queryParams);
|
||||
|
||||
@@ -86,7 +92,7 @@ export function useOpenShareLink() {
|
||||
});
|
||||
}
|
||||
},
|
||||
[_, router, user],
|
||||
[_, router, user, appService],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
import type { Book } from '@/types/book';
|
||||
import type { AppService } from '@/types/system';
|
||||
import { useLibraryStore } from '@/store/libraryStore';
|
||||
import { getAPIBaseUrl } from '@/services/environment';
|
||||
import { ShareApiError, getShare, type ImportShareResponse, type ShareMetadata } from './share';
|
||||
|
||||
interface EnsureSharedBookLocalArgs {
|
||||
token: string;
|
||||
importResult: ImportShareResponse;
|
||||
appService: AppService;
|
||||
/** Optional cached share metadata to avoid an extra GET on the new-import branch. */
|
||||
meta?: ShareMetadata;
|
||||
/** Progress callback for byte transfers (0-100). */
|
||||
onProgress?: (percent: number) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* After `importShare(token)` succeeds (server-side R2 byte-copy done), make
|
||||
* sure the local library has BOTH the Book entry AND the bytes on local fs,
|
||||
* so opening the reader at the shared book works without a "Book not found"
|
||||
* error.
|
||||
*
|
||||
* Three branches:
|
||||
* - Book is in library and bytes are present on fs → no-op, return book.
|
||||
* - Book is in library but bytes are missing locally (e.g. previously deleted
|
||||
* or imported from another device) → `appService.downloadBook` pulls from
|
||||
* the recipient's R2 namespace, which the import endpoint just populated.
|
||||
* - Book is NOT in the local library → fetch bytes via the public share
|
||||
* download endpoint, then run `appService.importBook` so a proper local
|
||||
* Book entry is created (metadata, cover extraction, dir layout). Mark
|
||||
* `uploadedAt` + `coverDownloadedAt` so transferManager doesn't re-upload
|
||||
* bytes the server already has, and so the cover-pull doesn't redo what
|
||||
* `importBook` just extracted from the book file.
|
||||
*/
|
||||
export const ensureSharedBookLocal = async ({
|
||||
token,
|
||||
importResult,
|
||||
appService,
|
||||
meta,
|
||||
onProgress,
|
||||
}: EnsureSharedBookLocalArgs): Promise<Book> => {
|
||||
const storeState = useLibraryStore.getState();
|
||||
const { setLibrary } = storeState;
|
||||
// When the share landing runs this helper, `libraryLoaded` is false because
|
||||
// /s/[token] doesn't mount useLibrary(). We load fresh from disk and only
|
||||
// push the result back into the store if the store had already been hydrated
|
||||
// by useLibrary somewhere else (e.g. /library, /reader, /opds). Otherwise we
|
||||
// *must not* set libraryLoaded ourselves: useLibrary's init block loads BOTH
|
||||
// the library AND `settings.globalReadSettings` in one go, and skips the
|
||||
// whole block when libraryLoaded is already true. Setting it prematurely
|
||||
// here leaves settings unloaded, and the Reader gate at Reader.tsx:167
|
||||
// (`libraryLoaded && settings.globalReadSettings`) renders the empty
|
||||
// fallback — exactly the blank-page symptom.
|
||||
const wasLibraryLoaded = storeState.libraryLoaded;
|
||||
const library = wasLibraryLoaded ? storeState.library : await appService.loadLibraryBooks();
|
||||
const findByHash = (hash: string): Book | undefined =>
|
||||
wasLibraryLoaded ? storeState.getBookByHash(hash) : library.find((b) => b.hash === hash);
|
||||
const existing = findByHash(importResult.bookHash);
|
||||
|
||||
const persistLibrary = async () => {
|
||||
await appService.saveLibraryBooks(library);
|
||||
if (wasLibraryLoaded) setLibrary(library);
|
||||
};
|
||||
|
||||
const reportProgress = onProgress
|
||||
? (prog: { progress: number; total: number }) => {
|
||||
if (prog.total > 0) onProgress(Math.floor((prog.progress / prog.total) * 100));
|
||||
}
|
||||
: undefined;
|
||||
|
||||
if (existing) {
|
||||
const bytesPresent = !!existing.downloadedAt && (await appService.isBookAvailable(existing));
|
||||
if (bytesPresent) return existing;
|
||||
|
||||
// Pull from recipient's namespace — the import endpoint already byte-copied
|
||||
// both the book and the cover there. downloadBook handles missing-cover
|
||||
// gracefully (covers may not exist) and sets downloadedAt internally.
|
||||
await appService.downloadBook(existing, false, false, reportProgress);
|
||||
// cloudService.downloadBook is silent on failure: if the cloud path
|
||||
// mismatches the local Book's filename (e.g. share-import wrote bytes at
|
||||
// the sharer's title, recipient's local Book has a different title) the
|
||||
// function resolves without touching downloadedAt and the bytes are still
|
||||
// absent. Verify before claiming success — otherwise the recipient
|
||||
// navigates into the reader and hits "Book file not found".
|
||||
if (!(await appService.isBookAvailable(existing))) {
|
||||
throw new Error('Could not download shared book');
|
||||
}
|
||||
if (!existing.downloadedAt) existing.downloadedAt = Date.now();
|
||||
existing.updatedAt = Date.now();
|
||||
await persistLibrary();
|
||||
return existing;
|
||||
}
|
||||
|
||||
// Book is not in the local library yet. Fetch the bytes via the public share
|
||||
// download endpoint (302 → presigned URL; fetch follows redirects), then
|
||||
// hand them to importBook which knows how to create the proper local Book.
|
||||
const shareMeta = meta ?? (await getShare(token));
|
||||
const downloadUrl = `${getAPIBaseUrl()}/share/${encodeURIComponent(token)}/download`;
|
||||
const response = await fetch(downloadUrl);
|
||||
if (!response.ok) {
|
||||
throw new ShareApiError(
|
||||
response.status,
|
||||
undefined,
|
||||
response.statusText || 'Could not download shared book',
|
||||
);
|
||||
}
|
||||
const blob = await response.blob();
|
||||
const filename = `${shareMeta.title}.${shareMeta.format.toLowerCase()}`;
|
||||
const file = new File([blob], filename, { type: blob.type || 'application/octet-stream' });
|
||||
|
||||
const imported = await appService.importBook(file, library);
|
||||
if (!imported) {
|
||||
throw new Error('Could not import shared book');
|
||||
}
|
||||
|
||||
// The server already holds the book + cover bytes (R2 byte-copy in the
|
||||
// import endpoint), so we tag uploadedAt/coverDownloadedAt to skip work
|
||||
// transferManager and the cloud cover-pull would otherwise repeat.
|
||||
const now = Date.now();
|
||||
imported.uploadedAt = now;
|
||||
if (!imported.downloadedAt) imported.downloadedAt = now;
|
||||
imported.coverDownloadedAt = now;
|
||||
|
||||
await persistLibrary();
|
||||
return imported;
|
||||
};
|
||||
Reference in New Issue
Block a user