diff --git a/apps/readest-app/package.json b/apps/readest-app/package.json index 962e62e3..c4a3542d 100644 --- a/apps/readest-app/package.json +++ b/apps/readest-app/package.json @@ -125,6 +125,7 @@ "marked": "^15.0.12", "nanoid": "^5.1.6", "next": "16.0.10", + "nunjucks": "^3.2.4", "overlayscrollbars": "^2.11.4", "overlayscrollbars-react": "^0.5.6", "posthog-js": "^1.246.0", @@ -158,6 +159,7 @@ "@types/cssbeautify": "^0.3.5", "@types/lunr": "^2.3.7", "@types/node": "^22.15.31", + "@types/nunjucks": "^3.2.6", "@types/react": "^19.0.0", "@types/react-color": "^3.0.13", "@types/react-dom": "^19.0.0", diff --git a/apps/readest-app/public/locales/ar/translation.json b/apps/readest-app/public/locales/ar/translation.json index 41c27f50..d3dd1424 100644 --- a/apps/readest-app/public/locales/ar/translation.json +++ b/apps/readest-app/public/locales/ar/translation.json @@ -914,7 +914,6 @@ "Array of annotations": "مصفوفة التعليقات", "Highlighted text": "النص المميز", "Annotation note": "ملاحظة التعليق", - "Update time": "وقت التحديث", "Date Format Tokens:": "رموز تنسيق التاريخ:", "Year (4 digits)": "السنة (4 أرقام)", "Month (01-12)": "الشهر (01-12)", @@ -932,5 +931,50 @@ "Show on Discord": "عرض على Discord", "Instant {{action}}": "{{action}} فوري", "Instant {{action}} Disabled": "تم تعطيل {{action}} فوري", - "Annotation": "التعليق" + "Annotation": "التعليق", + "Reset Template": "إعادة تعيين القالب", + "Annotation style": "نمط التعليق", + "Annotation color": "لون التعليق", + "Annotation time": "وقت التعليق", + "AI": "الذكاء الاصطناعي", + "Are you sure you want to re-index this book?": "هل أنت متأكد من إعادة فهرسة هذا الكتاب؟", + "Enable AI in Settings": "تفعيل الذكاء الاصطناعي في الإعدادات", + "Index This Book": "فهرسة هذا الكتاب", + "Enable AI search and chat for this book": "تفعيل البحث والدردشة بالذكاء الاصطناعي لهذا الكتاب", + "Start Indexing": "بدء الفهرسة", + "Indexing book...": "جاري فهرسة الكتاب...", + "Preparing...": "جاري التحضير...", + "Delete this conversation?": "حذف هذه المحادثة؟", + "No conversations yet": "لا توجد محادثات بعد", + "Start a new chat to ask questions about this book": "ابدأ محادثة جديدة لطرح أسئلة حول هذا الكتاب", + "Rename": "إعادة التسمية", + "New Chat": "محادثة جديدة", + "Chat": "محادثة", + "Please enter a model ID": "الرجاء إدخال معرف النموذج", + "Model not available or invalid": "النموذج غير متاح أو غير صالح", + "Failed to validate model": "فشل التحقق من النموذج", + "Couldn't connect to Ollama. Is it running?": "تعذر الاتصال بـ Ollama. هل يعمل؟", + "Invalid API key or connection failed": "مفتاح API غير صالح أو فشل الاتصال", + "Connection failed": "فشل الاتصال", + "AI Assistant": "مساعد الذكاء الاصطناعي", + "Enable AI Assistant": "تفعيل مساعد الذكاء الاصطناعي", + "Provider": "المزود", + "Ollama (Local)": "Ollama (محلي)", + "AI Gateway (Cloud)": "بوابة الذكاء الاصطناعي (سحابي)", + "Ollama Configuration": "إعدادات Ollama", + "Refresh Models": "تحديث النماذج", + "AI Model": "نموذج الذكاء الاصطناعي", + "No models detected": "لم يتم اكتشاف نماذج", + "AI Gateway Configuration": "إعدادات بوابة الذكاء الاصطناعي", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "اختر من مجموعة من نماذج الذكاء الاصطناعي عالية الجودة والاقتصادية. يمكنك أيضًا استخدام نموذجك الخاص بتحديد \"نموذج مخصص\" أدناه.", + "API Key": "مفتاح API", + "Get Key": "احصل على المفتاح", + "Model": "النموذج", + "Custom Model...": "نموذج مخصص...", + "Custom Model ID": "معرف النموذج المخصص", + "Validate": "تحقق", + "Model available": "النموذج متاح", + "Connection": "الاتصال", + "Test Connection": "اختبار الاتصال", + "Connected": "متصل" } diff --git a/apps/readest-app/public/locales/bn/translation.json b/apps/readest-app/public/locales/bn/translation.json index 9c28afa2..27779c59 100644 --- a/apps/readest-app/public/locales/bn/translation.json +++ b/apps/readest-app/public/locales/bn/translation.json @@ -874,7 +874,6 @@ "Array of annotations": "টীকাগুলির তালিকা", "Highlighted text": "হাইলাইট করা পাঠ্য", "Annotation note": "টীকা নোট", - "Update time": "আপডেট সময়", "Date Format Tokens:": "তারিখ বিন্যাস টোকেন:", "Year (4 digits)": "বছর (4 সংখ্যা)", "Month (01-12)": "মাস (01-12)", @@ -892,5 +891,50 @@ "Show on Discord": "Discord-এ দেখান", "Instant {{action}}": "তাৎক্ষণিক {{action}}", "Instant {{action}} Disabled": "তাৎক্ষণিক {{action}} নিষ্ক্রিয়", - "Annotation": "টীকা" + "Annotation": "টীকা", + "Reset Template": "টেমপ্লেট রিসেট করুন", + "Annotation style": "টীকা শৈলী", + "Annotation color": "টীকা রঙ", + "Annotation time": "টীকা সময়", + "AI": "কৃত্রিম বুদ্ধিমত্তা (AI)", + "Are you sure you want to re-index this book?": "আপনি কি নিশ্চিত যে আপনি এই বইটি পুনরায় ইনডেক্স করতে চান?", + "Enable AI in Settings": "সেটিংস থেকে AI সক্রিয় করুন", + "Index This Book": "এই বইটি ইনডেক্স করুন", + "Enable AI search and chat for this book": "এই বইটির জন্য AI অনুসন্ধান এবং চ্যাট সক্রিয় করুন", + "Start Indexing": "ইনডেক্সিং শুরু করুন", + "Indexing book...": "বই ইনডেক্স করা হচ্ছে...", + "Preparing...": "প্রস্তুত করা হচ্ছে...", + "Delete this conversation?": "এই কথোপকথনটি মুছবেন?", + "No conversations yet": "এখনও কোনও কথোপকথন নেই", + "Start a new chat to ask questions about this book": "এই বইটি সম্পর্কে প্রশ্ন জিজ্ঞাসা করতে একটি নতুন চ্যাট শুরু করুন", + "Rename": "নাম পরিবর্তন", + "New Chat": "নতুন চ্যাট", + "Chat": "চ্যাট", + "Please enter a model ID": "দয়া করে একটি মডেল আইডি লিখুন", + "Model not available or invalid": "মডেল উপলব্ধ নয় বা অবৈধ", + "Failed to validate model": "মডেল যাচাই করতে ব্যর্থ হয়েছে", + "Couldn't connect to Ollama. Is it running?": "Ollama এর সাথে সংযোগ করা যায়নি। এটি কি চলছে?", + "Invalid API key or connection failed": "অবৈধ API কী বা সংযোগ ব্যর্থ হয়েছে", + "Connection failed": "সংযোগ ব্যর্থ হয়েছে", + "AI Assistant": "AI সহকারী", + "Enable AI Assistant": "AI সহকারী সক্রিয় করুন", + "Provider": "প্রদানকারী", + "Ollama (Local)": "Ollama (স্থানীয়)", + "AI Gateway (Cloud)": "AI গেটওয়ে (ক্লাউড)", + "Ollama Configuration": "Ollama কনফিগারেশন", + "Refresh Models": "মডেল রিফ্রেশ করুন", + "AI Model": "AI মডেল", + "No models detected": "কোনও মডেল শনাক্ত করা যায়নি", + "AI Gateway Configuration": "AI গেটওয়ে কনফিগারেশন", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "উচ্চ-মানের, সাশ্রয়ী AI মডেলগুলি থেকে নির্বাচন করুন। আপনি নিচে \"কাস্টম মডেল\" নির্বাচন করে আপনার নিজস্ব মডেলও আনতে পারেন।", + "API Key": "API কী", + "Get Key": "কী পান", + "Model": "মডেল", + "Custom Model...": "কাস্টম মডেল...", + "Custom Model ID": "কাস্টম মডেল আইডি", + "Validate": "যাচাই করুন", + "Model available": "মডেল উপলব্ধ", + "Connection": "সংযোগ", + "Test Connection": "সংযোগ পরীক্ষা করুন", + "Connected": "সংযুক্ত" } diff --git a/apps/readest-app/public/locales/bo/translation.json b/apps/readest-app/public/locales/bo/translation.json index ca93df37..d25f25cd 100644 --- a/apps/readest-app/public/locales/bo/translation.json +++ b/apps/readest-app/public/locales/bo/translation.json @@ -864,7 +864,6 @@ "Array of annotations": "གསལ་བཤད་ལེབ་ངོས།", "Highlighted text": "གཙོ་གནད་ཡིག་རྐྱང་།", "Annotation note": "གསལ་བཤད་ཟིན་བྲིས།", - "Update time": "གསར་བཅོས་དུས་ཚོད།", "Date Format Tokens:": "ཚེས་གྲངས་རྣམ་གཞག་རྟགས།:", "Year (4 digits)": "ལོ། (གྲངས་ཐང་4)", "Month (01-12)": "ཟླ། (01-12)", @@ -882,5 +881,50 @@ "Show on Discord": "Discord ཐོག་སྟོན།", "Instant {{action}}": "འཕྲལ་མར་{{action}}", "Instant {{action}} Disabled": "འཕྲལ་མར་{{action}}་ལྕོགས་མིན་བཟོས།", - "Annotation": "མཆན་འགྲེལ།" + "Annotation": "མཆན་འགྲེལ།", + "Reset Template": "དཔེ་གཞི་བསྐྱར་སྒྲིག", + "Annotation style": "མཆན་འགྲེལ་གྱི་བཟོ་ལྟ།", + "Annotation color": "མཆན་འགྲེལ་གྱི་ཚོན་མདོག", + "Annotation time": "མཆན་འགྲེལ་གྱི་དུས་ཚོད།", + "AI": "རིག་ནུས་མིས་བཟོས། (AI)", + "Are you sure you want to re-index this book?": "ཁྱེད་ཀྱིས་དཔེ་དེབ་འདི་བསྐྱར་དུ་དཀར་ཆག་བཟོ་རྒྱུ་གཏན་འཁེལ་ཡིན་ནམ།", + "Enable AI in Settings": "སྒྲིག་བཀོད་ནང་ AI སྤྱོད་པར་བྱོས།", + "Index This Book": "དཔེ་དེབ་འདི་དཀར་ཆག་བཟོ་བ།", + "Enable AI search and chat for this book": "དཔེ་དེབ་འདིར་ AI འཚོལ་བཤེར་དང་ཁ་བརྡ་སྤྱོད་པར་བྱོས།", + "Start Indexing": "དཀར་ཆག་བཟོ་འགོ་བཙུགས་པ།", + "Indexing book...": "དཔེ་དེབ་དཀར་ཆག་བཟོ་བཞིན་པ།...", + "Preparing...": "གྲ་སྒྲིག་བྱེད་བཞིན་པ།...", + "Delete this conversation?": "ཁ་བརྡ་འདི་བསུབ་དགོས་སམ།", + "No conversations yet": "ད་ལྟའི་བར་ཁ་བརྡ་མེད།", + "Start a new chat to ask questions about this book": "དཔེ་དེབ་འདིའི་སྐོར་ལ་དྲི་བ་དྲི་བར་ཁ་བརྡ་གསར་པ་ཞིག་འགོ་བཙུགས་པ།", + "Rename": "མིང་བརྗེ་བ།", + "New Chat": "ཁ་བརྡ་གསར་པ།", + "Chat": "ཁ་བརྡ།", + "Please enter a model ID": "དཔེ་གཞིའི་ཨང་རྟགས་ནང་འཇུག་བྱོས།", + "Model not available or invalid": "དཔེ་གཞི་མེད་པ་འམ་ནུས་མེད།", + "Failed to validate model": "དཔེ་གཞི་བདེན་སྦྱོར་བྱེད་ཐུབ་མེད།", + "Couldn't connect to Ollama. Is it running?": "Ollama ལ་འབྲེལ་མཐུད་བྱེད་ཐུབ་མེད། དེ་འཁོར་བཞིན་ཡོད་དམ།", + "Invalid API key or connection failed": "API ལྡེ་མིག་ནུས་མེད་དམ་འབྲེལ་མཐུད་ཕམ་པ།", + "Connection failed": "འབྲེལ་མཐུད་ཕམ་པ།", + "AI Assistant": "AI རོགས་པ།", + "Enable AI Assistant": "AI རོགས་པ་སྤྱོད་པར་བྱོས།", + "Provider": "མཁོ་འདོན་པ།", + "Ollama (Local)": "Ollama (ས་གནས།)", + "AI Gateway (Cloud)": "AI འཛུལ་སྒོ། (སྤྲིན་གནས།)", + "Ollama Configuration": "Ollama སྒྲིག་བཀོད།", + "Refresh Models": "དཔེ་གཞི་བསྐྱར་བརྗེ།", + "AI Model": "AI དཔེ་གཞི།", + "No models detected": "དཔེ་གཞི་མ་རྙེད།", + "AI Gateway Configuration": "AI འཛུལ་སྒོའི་སྒྲིག་བཀོད།", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "སྤུས་ལེགས་དང་ཁེ་ཕན་ཆེ་བའི་ AI དཔེ་གཞི་འདེམས་དགོས། ཁྱེད་ཀྱིས་འོག་གི་ \"རང་བཟོའི་དཔེ་གཞི།\" བདམས་ནས་རང་གི་དཔེ་གཞི་བེད་སྤྱོད་ཀྱང་ཆོག", + "API Key": "API ལྡེ་མིག་", + "Get Key": "ལྡེ་མིག་ལེན་པ།", + "Model": "དཔེ་གཞི།", + "Custom Model...": "རང་བཟོའི་དཔེ་གཞི།...", + "Custom Model ID": "རང་བཟོའི་དཔེ་གཞིའི་ཨང་རྟགས།", + "Validate": "བདེན་སྦྱོར།", + "Model available": "དཔེ་གཞི་ཡོད།", + "Connection": "འབྲེལ་མཐུད།", + "Test Connection": "འབྲེལ་མཐུད་ཚོད་ལྟ།", + "Connected": "འབྲེལ་མཐུད་ཟིན།" } diff --git a/apps/readest-app/public/locales/de/translation.json b/apps/readest-app/public/locales/de/translation.json index 777f2323..6f387eda 100644 --- a/apps/readest-app/public/locales/de/translation.json +++ b/apps/readest-app/public/locales/de/translation.json @@ -874,7 +874,6 @@ "Array of annotations": "Array von Anmerkungen", "Highlighted text": "Markierter Text", "Annotation note": "Anmerkungsnotiz", - "Update time": "Aktualisierungszeit", "Date Format Tokens:": "Datumsformat-Token:", "Year (4 digits)": "Jahr (4 Ziffern)", "Month (01-12)": "Monat (01-12)", @@ -892,5 +891,50 @@ "Show on Discord": "Auf Discord zeigen", "Instant {{action}}": "Sofort {{action}}", "Instant {{action}} Disabled": "Sofort {{action}} deaktiviert", - "Annotation": "Anmerkung" + "Annotation": "Anmerkung", + "Reset Template": "Vorlage zurücksetzen", + "Annotation style": "Anmerkungsstil", + "Annotation color": "Anmerkungsfarbe", + "Annotation time": "Anmerkungszeit", + "AI": "KI", + "Are you sure you want to re-index this book?": "Möchten Sie dieses Buch wirklich neu indizieren?", + "Enable AI in Settings": "KI in den Einstellungen aktivieren", + "Index This Book": "Dieses Buch indizieren", + "Enable AI search and chat for this book": "KI-Suche und Chat für dieses Buch aktivieren", + "Start Indexing": "Indizierung starten", + "Indexing book...": "Buch wird indiziert...", + "Preparing...": "Vorbereitung...", + "Delete this conversation?": "Diese Unterhaltung löschen?", + "No conversations yet": "Noch keine Unterhaltungen", + "Start a new chat to ask questions about this book": "Starten Sie einen neuen Chat, um Fragen zu diesem Buch zu stellen", + "Rename": "Umbenennen", + "New Chat": "Neuer Chat", + "Chat": "Chat", + "Please enter a model ID": "Bitte geben Sie eine Modell-ID ein", + "Model not available or invalid": "Modell nicht verfügbar oder ungültig", + "Failed to validate model": "Modellvalidierung fehlgeschlagen", + "Couldn't connect to Ollama. Is it running?": "Verbindung zu Ollama fehlgeschlagen. Läuft es?", + "Invalid API key or connection failed": "Ungültiger API-Schlüssel oder Verbindung fehlgeschlagen", + "Connection failed": "Verbindung fehlgeschlagen", + "AI Assistant": "KI-Assistent", + "Enable AI Assistant": "KI-Assistent aktivieren", + "Provider": "Anbieter", + "Ollama (Local)": "Ollama (Lokal)", + "AI Gateway (Cloud)": "KI-Gateway (Cloud)", + "Ollama Configuration": "Ollama-Konfiguration", + "Refresh Models": "Modelle aktualisieren", + "AI Model": "KI-Modell", + "No models detected": "Keine Modelle erkannt", + "AI Gateway Configuration": "KI-Gateway-Konfiguration", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Wählen Sie aus einer Auswahl hochwertiger, wirtschaftlicher KI-Modelle. Sie können auch Ihr eigenes Modell verwenden, indem Sie unten \"Benutzerdefiniertes Modell\" auswählen.", + "API Key": "API-Schlüssel", + "Get Key": "Schlüssel erhalten", + "Model": "Modell", + "Custom Model...": "Benutzerdefiniertes Modell...", + "Custom Model ID": "Benutzerdefinierte Modell-ID", + "Validate": "Validieren", + "Model available": "Modell verfügbar", + "Connection": "Verbindung", + "Test Connection": "Verbindung testen", + "Connected": "Verbunden" } diff --git a/apps/readest-app/public/locales/el/translation.json b/apps/readest-app/public/locales/el/translation.json index f36e9349..c2192633 100644 --- a/apps/readest-app/public/locales/el/translation.json +++ b/apps/readest-app/public/locales/el/translation.json @@ -874,7 +874,6 @@ "Array of annotations": "Πίνακας σχολιασμών", "Highlighted text": "Επισημασμένο κείμενο", "Annotation note": "Σημείωση σχολιασμού", - "Update time": "Ώρα ενημέρωσης", "Date Format Tokens:": "Σύμβολα μορφοποίησης ημερομηνίας:", "Year (4 digits)": "Έτος (4 ψηφία)", "Month (01-12)": "Μήνας (01-12)", @@ -892,5 +891,50 @@ "Show on Discord": "Εμφάνιση στο Discord", "Instant {{action}}": "Άμεση {{action}}", "Instant {{action}} Disabled": "Άμεση {{action}} απενεργοποιημένη", - "Annotation": "Σημείωση" + "Annotation": "Σημείωση", + "Reset Template": "Επαναφορά προτύπου", + "Annotation style": "Στυλ σχολίου", + "Annotation color": "Χρώμα σχολίου", + "Annotation time": "Ώρα σχολίου", + "AI": "AI", + "Are you sure you want to re-index this book?": "Είστε σίγουροι ότι θέλετε να επαναδημιουργήσετε το ευρετήριο αυτού του βιβλίου;", + "Enable AI in Settings": "Ενεργοποίηση AI στις ρυθμίσεις", + "Index This Book": "Δημιουργία ευρετηρίου για αυτό το βιβλίο", + "Enable AI search and chat for this book": "Ενεργοποίηση αναζήτησης AI και συνομιλίας για αυτό το βιβλίο", + "Start Indexing": "Έναρξη δημιουργίας ευρετηρίου", + "Indexing book...": "Δημιουργία ευρετηρίου βιβλίου...", + "Preparing...": "Προετοιμασία...", + "Delete this conversation?": "Διαγραφή αυτής της συνομιλίας;", + "No conversations yet": "Δεν υπάρχουν συνομιλίες ακόμα", + "Start a new chat to ask questions about this book": "Ξεκινήστε μια νέα συνομιλία για να κάνετε ερωτήσεις σχετικά με αυτό το βιβλίο", + "Rename": "Μετονομασία", + "New Chat": "Νέα συνομιλία", + "Chat": "Συνομιλία", + "Please enter a model ID": "Εισάγετε ένα αναγνωριστικό μοντέλου", + "Model not available or invalid": "Το μοντέλο δεν είναι διαθέσιμο ή δεν είναι έγκυρο", + "Failed to validate model": "Αποτυχία επικύρωσης μοντέλου", + "Couldn't connect to Ollama. Is it running?": "Δεν ήταν δυνατή η σύνδεση με το Ollama. Εκτελείται;", + "Invalid API key or connection failed": "Μη έγκυρο κλειδί API ή αποτυχία σύνδεσης", + "Connection failed": "Αποτυχία σύνδεσης", + "AI Assistant": "Βοηθός AI", + "Enable AI Assistant": "Ενεργοποίηση βοηθού AI", + "Provider": "Πάροχος", + "Ollama (Local)": "Ollama (Τοπικό)", + "AI Gateway (Cloud)": "Πύλη AI (Cloud)", + "Ollama Configuration": "Διαμόρφωση Ollama", + "Refresh Models": "Ανανέωση μοντέλων", + "AI Model": "Μοντέλο AI", + "No models detected": "Δεν εντοπίστηκαν μοντέλα", + "AI Gateway Configuration": "Διαμόρφωση πύλης AI", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Επιλέξτε από μια συλλογή υψηλής ποιότητας, οικονομικών μοντέλων AI. Μπορείτε επίσης να χρησιμοποιήσετε το δικό σας μοντέλο επιλέγοντας \"Προσαρμοσμένο μοντέλο\" παρακάτω.", + "API Key": "Κλειδί API", + "Get Key": "Λήψη κλειδιού", + "Model": "Μοντέλο", + "Custom Model...": "Προσαρμοσμένο μοντέλο...", + "Custom Model ID": "Αναγνωριστικό προσαρμοσμένου μοντέλου", + "Validate": "Επικύρωση", + "Model available": "Το μοντέλο είναι διαθέσιμο", + "Connection": "Σύνδεση", + "Test Connection": "Δοκιμή σύνδεσης", + "Connected": "Συνδεδεμένο" } diff --git a/apps/readest-app/public/locales/es/translation.json b/apps/readest-app/public/locales/es/translation.json index 8ad1edf7..5a7fe03b 100644 --- a/apps/readest-app/public/locales/es/translation.json +++ b/apps/readest-app/public/locales/es/translation.json @@ -884,7 +884,6 @@ "Array of annotations": "Lista de anotaciones", "Highlighted text": "Texto resaltado", "Annotation note": "Nota de anotación", - "Update time": "Hora de actualización", "Date Format Tokens:": "Tokens de formato de fecha:", "Year (4 digits)": "Año (4 dígitos)", "Month (01-12)": "Mes (01-12)", @@ -902,5 +901,50 @@ "Show on Discord": "Mostrar en Discord", "Instant {{action}}": "{{action}} instantáneo", "Instant {{action}} Disabled": "{{action}} instantáneo desactivado", - "Annotation": "Anotación" + "Annotation": "Anotación", + "Reset Template": "Restablecer plantilla", + "Annotation style": "Estilo de anotación", + "Annotation color": "Color de anotación", + "Annotation time": "Hora de anotación", + "AI": "IA", + "Are you sure you want to re-index this book?": "¿Está seguro de que desea reindexar este libro?", + "Enable AI in Settings": "Habilitar IA en Configuración", + "Index This Book": "Indexar este libro", + "Enable AI search and chat for this book": "Habilitar búsqueda y chat con IA para este libro", + "Start Indexing": "Iniciar indexación", + "Indexing book...": "Indexando libro...", + "Preparing...": "Preparando...", + "Delete this conversation?": "¿Eliminar esta conversación?", + "No conversations yet": "Aún no hay conversaciones", + "Start a new chat to ask questions about this book": "Inicie un nuevo chat para hacer preguntas sobre este libro", + "Rename": "Renombrar", + "New Chat": "Nuevo chat", + "Chat": "Chat", + "Please enter a model ID": "Por favor, ingrese un ID de modelo", + "Model not available or invalid": "Modelo no disponible o inválido", + "Failed to validate model": "Error al validar el modelo", + "Couldn't connect to Ollama. Is it running?": "No se pudo conectar a Ollama. ¿Está ejecutándose?", + "Invalid API key or connection failed": "Clave API inválida o conexión fallida", + "Connection failed": "Conexión fallida", + "AI Assistant": "Asistente de IA", + "Enable AI Assistant": "Habilitar asistente de IA", + "Provider": "Proveedor", + "Ollama (Local)": "Ollama (Local)", + "AI Gateway (Cloud)": "Pasarela de IA (Nube)", + "Ollama Configuration": "Configuración de Ollama", + "Refresh Models": "Actualizar modelos", + "AI Model": "Modelo de IA", + "No models detected": "No se detectaron modelos", + "AI Gateway Configuration": "Configuración de pasarela de IA", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Elija entre una selección de modelos de IA de alta calidad y económicos. También puede usar su propio modelo seleccionando \"Modelo personalizado\" a continuación.", + "API Key": "Clave API", + "Get Key": "Obtener clave", + "Model": "Modelo", + "Custom Model...": "Modelo personalizado...", + "Custom Model ID": "ID de modelo personalizado", + "Validate": "Validar", + "Model available": "Modelo disponible", + "Connection": "Conexión", + "Test Connection": "Probar conexión", + "Connected": "Conectado" } diff --git a/apps/readest-app/public/locales/fa/translation.json b/apps/readest-app/public/locales/fa/translation.json index bac6c9df..dd1ea20e 100644 --- a/apps/readest-app/public/locales/fa/translation.json +++ b/apps/readest-app/public/locales/fa/translation.json @@ -874,7 +874,6 @@ "Array of annotations": "آرایه یادداشت‌ها", "Highlighted text": "متن برجسته‌شده", "Annotation note": "یادداشت حاشیه", - "Update time": "زمان به‌روزرسانی", "Date Format Tokens:": "نشانه‌های قالب تاریخ:", "Year (4 digits)": "سال (۴ رقم)", "Month (01-12)": "ماه (۰۱-۱۲)", @@ -892,5 +891,50 @@ "Show on Discord": "نمایش در Discord", "Instant {{action}}": "{{action}} فوری", "Instant {{action}} Disabled": "{{action}} فوری غیرفعال شد", - "Annotation": "یادداشت" + "Annotation": "یادداشت", + "Reset Template": "بازنشانی قالب", + "Annotation style": "سبک یادداشت", + "Annotation color": "رنگ یادداشت", + "Annotation time": "زمان یادداشت", + "AI": "هوش مصنوعی", + "Are you sure you want to re-index this book?": "آیا مطمئن هستید که می‌خواهید این کتاب را دوباره فهرست کنید؟", + "Enable AI in Settings": "فعال کردن هوش مصنوعی در تنظیمات", + "Index This Book": "فهرست کردن این کتاب", + "Enable AI search and chat for this book": "فعال کردن جستجو و گفتگوی هوش مصنوعی برای این کتاب", + "Start Indexing": "شروع فهرست‌بندی", + "Indexing book...": "در حال فهرست‌بندی کتاب...", + "Preparing...": "در حال آماده‌سازی...", + "Delete this conversation?": "این مکالمه حذف شود؟", + "No conversations yet": "هنوز مکالمه‌ای وجود ندارد", + "Start a new chat to ask questions about this book": "یک گفتگوی جدید برای پرسیدن سؤال درباره این کتاب شروع کنید", + "Rename": "تغییر نام", + "New Chat": "گفتگوی جدید", + "Chat": "گفتگو", + "Please enter a model ID": "لطفاً شناسه مدل را وارد کنید", + "Model not available or invalid": "مدل در دسترس نیست یا نامعتبر است", + "Failed to validate model": "اعتبارسنجی مدل ناموفق بود", + "Couldn't connect to Ollama. Is it running?": "اتصال به Ollama ممکن نشد. آیا در حال اجرا است؟", + "Invalid API key or connection failed": "کلید API نامعتبر است یا اتصال ناموفق بود", + "Connection failed": "اتصال ناموفق بود", + "AI Assistant": "دستیار هوش مصنوعی", + "Enable AI Assistant": "فعال کردن دستیار هوش مصنوعی", + "Provider": "ارائه‌دهنده", + "Ollama (Local)": "Ollama (محلی)", + "AI Gateway (Cloud)": "دروازه هوش مصنوعی (ابری)", + "Ollama Configuration": "پیکربندی Ollama", + "Refresh Models": "بازخوانی مدل‌ها", + "AI Model": "مدل هوش مصنوعی", + "No models detected": "هیچ مدلی شناسایی نشد", + "AI Gateway Configuration": "پیکربندی دروازه هوش مصنوعی", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "از میان مجموعه‌ای از مدل‌های هوش مصنوعی با کیفیت و اقتصادی انتخاب کنید. همچنین می‌توانید با انتخاب \"مدل سفارشی\" در زیر، مدل خود را استفاده کنید.", + "API Key": "کلید API", + "Get Key": "دریافت کلید", + "Model": "مدل", + "Custom Model...": "مدل سفارشی...", + "Custom Model ID": "شناسه مدل سفارشی", + "Validate": "اعتبارسنجی", + "Model available": "مدل در دسترس است", + "Connection": "اتصال", + "Test Connection": "تست اتصال", + "Connected": "متصل" } diff --git a/apps/readest-app/public/locales/fr/translation.json b/apps/readest-app/public/locales/fr/translation.json index 0356f154..e7fe30cb 100644 --- a/apps/readest-app/public/locales/fr/translation.json +++ b/apps/readest-app/public/locales/fr/translation.json @@ -884,7 +884,6 @@ "Array of annotations": "Liste d'annotations", "Highlighted text": "Texte surligné", "Annotation note": "Note d'annotation", - "Update time": "Heure de mise à jour", "Date Format Tokens:": "Jetons de format de date :", "Year (4 digits)": "Année (4 chiffres)", "Month (01-12)": "Mois (01-12)", @@ -902,5 +901,50 @@ "Show on Discord": "Afficher sur Discord", "Instant {{action}}": "{{action}} instantané", "Instant {{action}} Disabled": "{{action}} instantané désactivé", - "Annotation": "Annotation" + "Annotation": "Annotation", + "Reset Template": "Réinitialiser le modèle", + "Annotation style": "Style d'annotation", + "Annotation color": "Couleur d'annotation", + "Annotation time": "Heure d'annotation", + "AI": "IA", + "Are you sure you want to re-index this book?": "Voulez-vous vraiment réindexer ce livre ?", + "Enable AI in Settings": "Activer l'IA dans les paramètres", + "Index This Book": "Indexer ce livre", + "Enable AI search and chat for this book": "Activer la recherche IA et le chat pour ce livre", + "Start Indexing": "Démarrer l'indexation", + "Indexing book...": "Indexation du livre...", + "Preparing...": "Préparation...", + "Delete this conversation?": "Supprimer cette conversation ?", + "No conversations yet": "Pas encore de conversations", + "Start a new chat to ask questions about this book": "Démarrez une nouvelle conversation pour poser des questions sur ce livre", + "Rename": "Renommer", + "New Chat": "Nouvelle conversation", + "Chat": "Chat", + "Please enter a model ID": "Veuillez entrer un ID de modèle", + "Model not available or invalid": "Modèle non disponible ou invalide", + "Failed to validate model": "Échec de la validation du modèle", + "Couldn't connect to Ollama. Is it running?": "Impossible de se connecter à Ollama. Est-il en cours d'exécution ?", + "Invalid API key or connection failed": "Clé API invalide ou échec de connexion", + "Connection failed": "Échec de connexion", + "AI Assistant": "Assistant IA", + "Enable AI Assistant": "Activer l'assistant IA", + "Provider": "Fournisseur", + "Ollama (Local)": "Ollama (Local)", + "AI Gateway (Cloud)": "Passerelle IA (Cloud)", + "Ollama Configuration": "Configuration Ollama", + "Refresh Models": "Actualiser les modèles", + "AI Model": "Modèle IA", + "No models detected": "Aucun modèle détecté", + "AI Gateway Configuration": "Configuration de la passerelle IA", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Choisissez parmi une sélection de modèles IA de haute qualité et économiques. Vous pouvez également utiliser votre propre modèle en sélectionnant \"Modèle personnalisé\" ci-dessous.", + "API Key": "Clé API", + "Get Key": "Obtenir la clé", + "Model": "Modèle", + "Custom Model...": "Modèle personnalisé...", + "Custom Model ID": "ID du modèle personnalisé", + "Validate": "Valider", + "Model available": "Modèle disponible", + "Connection": "Connexion", + "Test Connection": "Tester la connexion", + "Connected": "Connecté" } diff --git a/apps/readest-app/public/locales/hi/translation.json b/apps/readest-app/public/locales/hi/translation.json index dc5618be..469ee802 100644 --- a/apps/readest-app/public/locales/hi/translation.json +++ b/apps/readest-app/public/locales/hi/translation.json @@ -874,7 +874,6 @@ "Array of annotations": "एनोटेशन की सूची", "Highlighted text": "हाइलाइट किया गया पाठ", "Annotation note": "एनोटेशन नोट", - "Update time": "अपडेट समय", "Date Format Tokens:": "तिथि प्रारूप टोकन:", "Year (4 digits)": "वर्ष (4 अंक)", "Month (01-12)": "माह (01-12)", @@ -892,5 +891,50 @@ "Show on Discord": "Discord पर दिखाएं", "Instant {{action}}": "तत्काल {{action}}", "Instant {{action}} Disabled": "तत्काल {{action}} अक्षम", - "Annotation": "टिप्पणी" + "Annotation": "टिप्पणी", + "Reset Template": "टेम्पलेट रीसेट करें", + "Annotation style": "एनोटेशन शैली", + "Annotation color": "एनोटेशन रंग", + "Annotation time": "एनोटेशन समय", + "AI": "AI", + "Are you sure you want to re-index this book?": "क्या आप वाकई इस पुस्तक को फिर से इंडेक्स करना चाहते हैं?", + "Enable AI in Settings": "सेटिंग्स में AI सक्षम करें", + "Index This Book": "इस पुस्तक को इंडेक्स करें", + "Enable AI search and chat for this book": "इस पुस्तक के लिए AI खोज और चैट सक्षम करें", + "Start Indexing": "इंडेक्सिंग शुरू करें", + "Indexing book...": "पुस्तक इंडेक्स हो रही है...", + "Preparing...": "तैयारी हो रही है...", + "Delete this conversation?": "इस वार्तालाप को हटाएं?", + "No conversations yet": "अभी तक कोई वार्तालाप नहीं", + "Start a new chat to ask questions about this book": "इस पुस्तक के बारे में प्रश्न पूछने के लिए नई चैट शुरू करें", + "Rename": "नाम बदलें", + "New Chat": "नई चैट", + "Chat": "चैट", + "Please enter a model ID": "कृपया मॉडल ID दर्ज करें", + "Model not available or invalid": "मॉडल उपलब्ध नहीं या अमान्य है", + "Failed to validate model": "मॉडल सत्यापित करने में विफल", + "Couldn't connect to Ollama. Is it running?": "Ollama से कनेक्ट नहीं हो सका। क्या यह चल रहा है?", + "Invalid API key or connection failed": "अमान्य API कुंजी या कनेक्शन विफल", + "Connection failed": "कनेक्शन विफल", + "AI Assistant": "AI सहायक", + "Enable AI Assistant": "AI सहायक सक्षम करें", + "Provider": "प्रदाता", + "Ollama (Local)": "Ollama (स्थानीय)", + "AI Gateway (Cloud)": "AI गेटवे (क्लाउड)", + "Ollama Configuration": "Ollama कॉन्फ़िगरेशन", + "Refresh Models": "मॉडल रीफ्रेश करें", + "AI Model": "AI मॉडल", + "No models detected": "कोई मॉडल नहीं मिला", + "AI Gateway Configuration": "AI गेटवे कॉन्फ़िगरेशन", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "उच्च-गुणवत्ता, किफायती AI मॉडल के चयन में से चुनें। आप नीचे \"कस्टम मॉडल\" का चयन करके अपना मॉडल भी उपयोग कर सकते हैं।", + "API Key": "API कुंजी", + "Get Key": "कुंजी प्राप्त करें", + "Model": "मॉडल", + "Custom Model...": "कस्टम मॉडल...", + "Custom Model ID": "कस्टम मॉडल ID", + "Validate": "सत्यापित करें", + "Model available": "मॉडल उपलब्ध", + "Connection": "कनेक्शन", + "Test Connection": "कनेक्शन परीक्षण", + "Connected": "कनेक्टेड" } diff --git a/apps/readest-app/public/locales/id/translation.json b/apps/readest-app/public/locales/id/translation.json index a8d02224..bbec74ca 100644 --- a/apps/readest-app/public/locales/id/translation.json +++ b/apps/readest-app/public/locales/id/translation.json @@ -864,7 +864,6 @@ "Array of annotations": "Daftar anotasi", "Highlighted text": "Teks yang disorot", "Annotation note": "Catatan anotasi", - "Update time": "Waktu pembaruan", "Date Format Tokens:": "Token Format Tanggal:", "Year (4 digits)": "Tahun (4 digit)", "Month (01-12)": "Bulan (01-12)", @@ -882,5 +881,50 @@ "Show on Discord": "Tampilkan di Discord", "Instant {{action}}": "{{action}} Instan", "Instant {{action}} Disabled": "{{action}} Instan Dinonaktifkan", - "Annotation": "Anotasi" + "Annotation": "Anotasi", + "Reset Template": "Atur Ulang Template", + "Annotation style": "Gaya anotasi", + "Annotation color": "Warna anotasi", + "Annotation time": "Waktu anotasi", + "AI": "AI", + "Are you sure you want to re-index this book?": "Apakah Anda yakin ingin mengindeks ulang buku ini?", + "Enable AI in Settings": "Aktifkan AI di Pengaturan", + "Index This Book": "Indeks Buku Ini", + "Enable AI search and chat for this book": "Aktifkan pencarian AI dan obrolan untuk buku ini", + "Start Indexing": "Mulai Mengindeks", + "Indexing book...": "Mengindeks buku...", + "Preparing...": "Mempersiapkan...", + "Delete this conversation?": "Hapus percakapan ini?", + "No conversations yet": "Belum ada percakapan", + "Start a new chat to ask questions about this book": "Mulai obrolan baru untuk mengajukan pertanyaan tentang buku ini", + "Rename": "Ubah nama", + "New Chat": "Obrolan Baru", + "Chat": "Obrolan", + "Please enter a model ID": "Silakan masukkan ID model", + "Model not available or invalid": "Model tidak tersedia atau tidak valid", + "Failed to validate model": "Gagal memvalidasi model", + "Couldn't connect to Ollama. Is it running?": "Tidak dapat terhubung ke Ollama. Apakah sedang berjalan?", + "Invalid API key or connection failed": "Kunci API tidak valid atau koneksi gagal", + "Connection failed": "Koneksi gagal", + "AI Assistant": "Asisten AI", + "Enable AI Assistant": "Aktifkan Asisten AI", + "Provider": "Penyedia", + "Ollama (Local)": "Ollama (Lokal)", + "AI Gateway (Cloud)": "Gateway AI (Cloud)", + "Ollama Configuration": "Konfigurasi Ollama", + "Refresh Models": "Segarkan Model", + "AI Model": "Model AI", + "No models detected": "Tidak ada model terdeteksi", + "AI Gateway Configuration": "Konfigurasi Gateway AI", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Pilih dari pilihan model AI berkualitas tinggi dan ekonomis. Anda juga dapat menggunakan model Anda sendiri dengan memilih \"Model Kustom\" di bawah.", + "API Key": "Kunci API", + "Get Key": "Dapatkan Kunci", + "Model": "Model", + "Custom Model...": "Model Kustom...", + "Custom Model ID": "ID Model Kustom", + "Validate": "Validasi", + "Model available": "Model tersedia", + "Connection": "Koneksi", + "Test Connection": "Uji Koneksi", + "Connected": "Terhubung" } diff --git a/apps/readest-app/public/locales/it/translation.json b/apps/readest-app/public/locales/it/translation.json index 6522bb33..9667680e 100644 --- a/apps/readest-app/public/locales/it/translation.json +++ b/apps/readest-app/public/locales/it/translation.json @@ -884,7 +884,6 @@ "Array of annotations": "Elenco annotazioni", "Highlighted text": "Testo evidenziato", "Annotation note": "Nota annotazione", - "Update time": "Ora aggiornamento", "Date Format Tokens:": "Token formato data:", "Year (4 digits)": "Anno (4 cifre)", "Month (01-12)": "Mese (01-12)", @@ -902,5 +901,50 @@ "Show on Discord": "Mostra su Discord", "Instant {{action}}": "{{action}} istantaneo", "Instant {{action}} Disabled": "{{action}} istantaneo disattivato", - "Annotation": "Annotazione" + "Annotation": "Annotazione", + "Reset Template": "Reimposta modello", + "Annotation style": "Stile annotazione", + "Annotation color": "Colore annotazione", + "Annotation time": "Ora annotazione", + "AI": "IA", + "Are you sure you want to re-index this book?": "Sei sicuro di voler reindicizzare questo libro?", + "Enable AI in Settings": "Abilita IA nelle impostazioni", + "Index This Book": "Indicizza questo libro", + "Enable AI search and chat for this book": "Abilita ricerca IA e chat per questo libro", + "Start Indexing": "Avvia indicizzazione", + "Indexing book...": "Indicizzazione libro...", + "Preparing...": "Preparazione...", + "Delete this conversation?": "Eliminare questa conversazione?", + "No conversations yet": "Ancora nessuna conversazione", + "Start a new chat to ask questions about this book": "Avvia una nuova chat per fare domande su questo libro", + "Rename": "Rinomina", + "New Chat": "Nuova chat", + "Chat": "Chat", + "Please enter a model ID": "Inserisci un ID modello", + "Model not available or invalid": "Modello non disponibile o non valido", + "Failed to validate model": "Validazione modello fallita", + "Couldn't connect to Ollama. Is it running?": "Impossibile connettersi a Ollama. È in esecuzione?", + "Invalid API key or connection failed": "Chiave API non valida o connessione fallita", + "Connection failed": "Connessione fallita", + "AI Assistant": "Assistente IA", + "Enable AI Assistant": "Abilita assistente IA", + "Provider": "Fornitore", + "Ollama (Local)": "Ollama (Locale)", + "AI Gateway (Cloud)": "Gateway IA (Cloud)", + "Ollama Configuration": "Configurazione Ollama", + "Refresh Models": "Aggiorna modelli", + "AI Model": "Modello IA", + "No models detected": "Nessun modello rilevato", + "AI Gateway Configuration": "Configurazione gateway IA", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Scegli tra una selezione di modelli IA di alta qualità ed economici. Puoi anche usare il tuo modello selezionando \"Modello personalizzato\" qui sotto.", + "API Key": "Chiave API", + "Get Key": "Ottieni chiave", + "Model": "Modello", + "Custom Model...": "Modello personalizzato...", + "Custom Model ID": "ID modello personalizzato", + "Validate": "Convalida", + "Model available": "Modello disponibile", + "Connection": "Connessione", + "Test Connection": "Testa connessione", + "Connected": "Connesso" } diff --git a/apps/readest-app/public/locales/ja/translation.json b/apps/readest-app/public/locales/ja/translation.json index 33899d91..1f48549c 100644 --- a/apps/readest-app/public/locales/ja/translation.json +++ b/apps/readest-app/public/locales/ja/translation.json @@ -864,7 +864,6 @@ "Array of annotations": "注釈の配列", "Highlighted text": "ハイライトテキスト", "Annotation note": "注釈ノート", - "Update time": "更新時刻", "Date Format Tokens:": "日付形式トークン:", "Year (4 digits)": "年(4桁)", "Month (01-12)": "月(01-12)", @@ -882,5 +881,50 @@ "Show on Discord": "Discordに表示", "Instant {{action}}": "インスタント{{action}}", "Instant {{action}} Disabled": "インスタント{{action}}を無効化", - "Annotation": "注釈" + "Annotation": "注釈", + "Reset Template": "テンプレートをリセット", + "Annotation style": "注釈スタイル", + "Annotation color": "注釈の色", + "Annotation time": "注釈時間", + "AI": "AI", + "Are you sure you want to re-index this book?": "この本を再インデックスしてもよろしいですか?", + "Enable AI in Settings": "設定でAIを有効にする", + "Index This Book": "この本をインデックス", + "Enable AI search and chat for this book": "この本のAI検索とチャットを有効にする", + "Start Indexing": "インデックス開始", + "Indexing book...": "本をインデックス中...", + "Preparing...": "準備中...", + "Delete this conversation?": "この会話を削除しますか?", + "No conversations yet": "まだ会話がありません", + "Start a new chat to ask questions about this book": "この本について質問するには新しいチャットを開始してください", + "Rename": "名前を変更", + "New Chat": "新しいチャット", + "Chat": "チャット", + "Please enter a model ID": "モデルIDを入力してください", + "Model not available or invalid": "モデルが利用できないか無効です", + "Failed to validate model": "モデルの検証に失敗しました", + "Couldn't connect to Ollama. Is it running?": "Ollamaに接続できませんでした。実行中ですか?", + "Invalid API key or connection failed": "APIキーが無効か接続に失敗しました", + "Connection failed": "接続に失敗しました", + "AI Assistant": "AIアシスタント", + "Enable AI Assistant": "AIアシスタントを有効にする", + "Provider": "プロバイダー", + "Ollama (Local)": "Ollama(ローカル)", + "AI Gateway (Cloud)": "AIゲートウェイ(クラウド)", + "Ollama Configuration": "Ollama設定", + "Refresh Models": "モデルを更新", + "AI Model": "AIモデル", + "No models detected": "モデルが検出されませんでした", + "AI Gateway Configuration": "AIゲートウェイ設定", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "高品質で経済的なAIモデルからお選びください。下の「カスタムモデル」を選択して独自のモデルを使用することもできます。", + "API Key": "APIキー", + "Get Key": "キーを取得", + "Model": "モデル", + "Custom Model...": "カスタムモデル...", + "Custom Model ID": "カスタムモデルID", + "Validate": "検証", + "Model available": "モデルが利用可能", + "Connection": "接続", + "Test Connection": "接続をテスト", + "Connected": "接続済み" } diff --git a/apps/readest-app/public/locales/ko/translation.json b/apps/readest-app/public/locales/ko/translation.json index cd51c8fc..c7e0167a 100644 --- a/apps/readest-app/public/locales/ko/translation.json +++ b/apps/readest-app/public/locales/ko/translation.json @@ -864,7 +864,6 @@ "Array of annotations": "주석 배열", "Highlighted text": "하이라이트된 텍스트", "Annotation note": "주석 노트", - "Update time": "업데이트 시간", "Date Format Tokens:": "날짜 형식 토큰:", "Year (4 digits)": "연도 (4자리)", "Month (01-12)": "월 (01-12)", @@ -882,5 +881,50 @@ "Show on Discord": "Discord에 표시", "Instant {{action}}": "즉시 {{action}}", "Instant {{action}} Disabled": "즉시 {{action}} 비활성화", - "Annotation": "주석" + "Annotation": "주석", + "Reset Template": "템플릿 초기화", + "Annotation style": "주석 스타일", + "Annotation color": "주석 색상", + "Annotation time": "주석 시간", + "AI": "AI", + "Are you sure you want to re-index this book?": "이 책을 다시 인덱싱하시겠습니까?", + "Enable AI in Settings": "설정에서 AI 활성화", + "Index This Book": "이 책 인덱싱", + "Enable AI search and chat for this book": "이 책에 대한 AI 검색 및 채팅 활성화", + "Start Indexing": "인덱싱 시작", + "Indexing book...": "책 인덱싱 중...", + "Preparing...": "준비 중...", + "Delete this conversation?": "이 대화를 삭제하시겠습니까?", + "No conversations yet": "아직 대화가 없습니다", + "Start a new chat to ask questions about this book": "이 책에 대해 질문하려면 새 채팅을 시작하세요", + "Rename": "이름 변경", + "New Chat": "새 채팅", + "Chat": "채팅", + "Please enter a model ID": "모델 ID를 입력하세요", + "Model not available or invalid": "모델을 사용할 수 없거나 유효하지 않습니다", + "Failed to validate model": "모델 검증 실패", + "Couldn't connect to Ollama. Is it running?": "Ollama에 연결할 수 없습니다. 실행 중인가요?", + "Invalid API key or connection failed": "API 키가 유효하지 않거나 연결 실패", + "Connection failed": "연결 실패", + "AI Assistant": "AI 어시스턴트", + "Enable AI Assistant": "AI 어시스턴트 활성화", + "Provider": "제공자", + "Ollama (Local)": "Ollama (로컬)", + "AI Gateway (Cloud)": "AI 게이트웨이 (클라우드)", + "Ollama Configuration": "Ollama 설정", + "Refresh Models": "모델 새로고침", + "AI Model": "AI 모델", + "No models detected": "모델이 감지되지 않았습니다", + "AI Gateway Configuration": "AI 게이트웨이 설정", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "고품질의 경제적인 AI 모델 중에서 선택하세요. 아래의 \"사용자 정의 모델\"을 선택하여 자신의 모델을 사용할 수도 있습니다.", + "API Key": "API 키", + "Get Key": "키 받기", + "Model": "모델", + "Custom Model...": "사용자 정의 모델...", + "Custom Model ID": "사용자 정의 모델 ID", + "Validate": "검증", + "Model available": "모델 사용 가능", + "Connection": "연결", + "Test Connection": "연결 테스트", + "Connected": "연결됨" } diff --git a/apps/readest-app/public/locales/ms/translation.json b/apps/readest-app/public/locales/ms/translation.json index 7cce045d..2b78360d 100644 --- a/apps/readest-app/public/locales/ms/translation.json +++ b/apps/readest-app/public/locales/ms/translation.json @@ -864,7 +864,6 @@ "Array of annotations": "Senarai anotasi", "Highlighted text": "Teks yang diserlahkan", "Annotation note": "Nota anotasi", - "Update time": "Masa kemas kini", "Date Format Tokens:": "Token Format Tarikh:", "Year (4 digits)": "Tahun (4 digit)", "Month (01-12)": "Bulan (01-12)", @@ -882,5 +881,50 @@ "Show on Discord": "Papar di Discord", "Instant {{action}}": "{{action}} Segera", "Instant {{action}} Disabled": "{{action}} Segera Dilumpuhkan", - "Annotation": "Anotasi" + "Annotation": "Anotasi", + "Reset Template": "Tetapkan Semula Templat", + "Annotation style": "Gaya anotasi", + "Annotation color": "Warna anotasi", + "Annotation time": "Masa anotasi", + "AI": "AI", + "Are you sure you want to re-index this book?": "Adakah anda pasti mahu mengindeks semula buku ini?", + "Enable AI in Settings": "Aktifkan AI dalam Tetapan", + "Index This Book": "Indeks Buku Ini", + "Enable AI search and chat for this book": "Aktifkan carian AI dan sembang untuk buku ini", + "Start Indexing": "Mula Mengindeks", + "Indexing book...": "Mengindeks buku...", + "Preparing...": "Menyediakan...", + "Delete this conversation?": "Padam perbualan ini?", + "No conversations yet": "Tiada perbualan lagi", + "Start a new chat to ask questions about this book": "Mulakan sembang baharu untuk bertanya tentang buku ini", + "Rename": "Namakan Semula", + "New Chat": "Sembang Baharu", + "Chat": "Sembang", + "Please enter a model ID": "Sila masukkan ID model", + "Model not available or invalid": "Model tidak tersedia atau tidak sah", + "Failed to validate model": "Gagal mengesahkan model", + "Couldn't connect to Ollama. Is it running?": "Tidak dapat menyambung ke Ollama. Adakah ia sedang berjalan?", + "Invalid API key or connection failed": "Kunci API tidak sah atau sambungan gagal", + "Connection failed": "Sambungan gagal", + "AI Assistant": "Pembantu AI", + "Enable AI Assistant": "Aktifkan Pembantu AI", + "Provider": "Pembekal", + "Ollama (Local)": "Ollama (Tempatan)", + "AI Gateway (Cloud)": "Gateway AI (Awan)", + "Ollama Configuration": "Konfigurasi Ollama", + "Refresh Models": "Muat Semula Model", + "AI Model": "Model AI", + "No models detected": "Tiada model dikesan", + "AI Gateway Configuration": "Konfigurasi Gateway AI", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Pilih dari pelbagai model AI berkualiti tinggi dan ekonomi. Anda juga boleh menggunakan model anda sendiri dengan memilih \"Model Tersuai\" di bawah.", + "API Key": "Kunci API", + "Get Key": "Dapatkan Kunci", + "Model": "Model", + "Custom Model...": "Model Tersuai...", + "Custom Model ID": "ID Model Tersuai", + "Validate": "Sahkan", + "Model available": "Model tersedia", + "Connection": "Sambungan", + "Test Connection": "Uji Sambungan", + "Connected": "Disambung" } diff --git a/apps/readest-app/public/locales/nl/translation.json b/apps/readest-app/public/locales/nl/translation.json index e1bb3388..e31d81df 100644 --- a/apps/readest-app/public/locales/nl/translation.json +++ b/apps/readest-app/public/locales/nl/translation.json @@ -874,7 +874,6 @@ "Array of annotations": "Reeks annotaties", "Highlighted text": "Gemarkeerde tekst", "Annotation note": "Annotatienotitie", - "Update time": "Updatetijd", "Date Format Tokens:": "Datumformaattokens:", "Year (4 digits)": "Jaar (4 cijfers)", "Month (01-12)": "Maand (01-12)", @@ -892,5 +891,50 @@ "Show on Discord": "Toon op Discord", "Instant {{action}}": "Directe {{action}}", "Instant {{action}} Disabled": "Directe {{action}} uitgeschakeld", - "Annotation": "Annotatie" + "Annotation": "Annotatie", + "Reset Template": "Sjabloon resetten", + "Annotation style": "Annotatiestijl", + "Annotation color": "Annotatiekleur", + "Annotation time": "Annotatietijd", + "AI": "AI", + "Are you sure you want to re-index this book?": "Weet u zeker dat u dit boek opnieuw wilt indexeren?", + "Enable AI in Settings": "AI inschakelen in Instellingen", + "Index This Book": "Dit boek indexeren", + "Enable AI search and chat for this book": "AI-zoeken en chat voor dit boek inschakelen", + "Start Indexing": "Indexeren starten", + "Indexing book...": "Boek wordt geïndexeerd...", + "Preparing...": "Voorbereiden...", + "Delete this conversation?": "Dit gesprek verwijderen?", + "No conversations yet": "Nog geen gesprekken", + "Start a new chat to ask questions about this book": "Start een nieuwe chat om vragen te stellen over dit boek", + "Rename": "Hernoemen", + "New Chat": "Nieuwe chat", + "Chat": "Chat", + "Please enter a model ID": "Voer een model-ID in", + "Model not available or invalid": "Model niet beschikbaar of ongeldig", + "Failed to validate model": "Model valideren mislukt", + "Couldn't connect to Ollama. Is it running?": "Kon geen verbinding maken met Ollama. Is het actief?", + "Invalid API key or connection failed": "Ongeldige API-sleutel of verbinding mislukt", + "Connection failed": "Verbinding mislukt", + "AI Assistant": "AI-assistent", + "Enable AI Assistant": "AI-assistent inschakelen", + "Provider": "Provider", + "Ollama (Local)": "Ollama (Lokaal)", + "AI Gateway (Cloud)": "AI-gateway (Cloud)", + "Ollama Configuration": "Ollama-configuratie", + "Refresh Models": "Modellen vernieuwen", + "AI Model": "AI-model", + "No models detected": "Geen modellen gedetecteerd", + "AI Gateway Configuration": "AI-gateway configuratie", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Kies uit een selectie van hoogwaardige, voordelige AI-modellen. U kunt ook uw eigen model gebruiken door hieronder \"Aangepast model\" te selecteren.", + "API Key": "API-sleutel", + "Get Key": "Sleutel ophalen", + "Model": "Model", + "Custom Model...": "Aangepast model...", + "Custom Model ID": "Aangepast model-ID", + "Validate": "Valideren", + "Model available": "Model beschikbaar", + "Connection": "Verbinding", + "Test Connection": "Verbinding testen", + "Connected": "Verbonden" } diff --git a/apps/readest-app/public/locales/pl/translation.json b/apps/readest-app/public/locales/pl/translation.json index 909da2d7..c5c83174 100644 --- a/apps/readest-app/public/locales/pl/translation.json +++ b/apps/readest-app/public/locales/pl/translation.json @@ -894,7 +894,6 @@ "Array of annotations": "Tablica adnotacji", "Highlighted text": "Zaznaczony tekst", "Annotation note": "Notatka adnotacji", - "Update time": "Czas aktualizacji", "Date Format Tokens:": "Tokeny formatu daty:", "Year (4 digits)": "Rok (4 cyfry)", "Month (01-12)": "Miesiąc (01-12)", @@ -912,5 +911,50 @@ "Show on Discord": "Pokaż na Discord", "Instant {{action}}": "Natychmiastowe {{action}}", "Instant {{action}} Disabled": "Natychmiastowe {{action}} wyłączone", - "Annotation": "Adnotacja" + "Annotation": "Adnotacja", + "Reset Template": "Resetuj szablon", + "Annotation style": "Styl adnotacji", + "Annotation color": "Kolor adnotacji", + "Annotation time": "Czas adnotacji", + "AI": "AI", + "Are you sure you want to re-index this book?": "Czy na pewno chcesz ponownie zaindeksować tę książkę?", + "Enable AI in Settings": "Włącz AI w ustawieniach", + "Index This Book": "Zaindeksuj tę książkę", + "Enable AI search and chat for this book": "Włącz wyszukiwanie AI i czat dla tej książki", + "Start Indexing": "Rozpocznij indeksowanie", + "Indexing book...": "Indeksowanie książki...", + "Preparing...": "Przygotowywanie...", + "Delete this conversation?": "Usunąć tę rozmowę?", + "No conversations yet": "Brak rozmów", + "Start a new chat to ask questions about this book": "Rozpocznij nowy czat, aby zadać pytania o tę książkę", + "Rename": "Zmień nazwę", + "New Chat": "Nowy czat", + "Chat": "Czat", + "Please enter a model ID": "Wprowadź ID modelu", + "Model not available or invalid": "Model niedostępny lub nieprawidłowy", + "Failed to validate model": "Nie udało się zwalidować modelu", + "Couldn't connect to Ollama. Is it running?": "Nie można połączyć się z Ollama. Czy jest uruchomiona?", + "Invalid API key or connection failed": "Nieprawidłowy klucz API lub błąd połączenia", + "Connection failed": "Połączenie nieudane", + "AI Assistant": "Asystent AI", + "Enable AI Assistant": "Włącz asystenta AI", + "Provider": "Dostawca", + "Ollama (Local)": "Ollama (Lokalny)", + "AI Gateway (Cloud)": "Brama AI (Chmura)", + "Ollama Configuration": "Konfiguracja Ollama", + "Refresh Models": "Odśwież modele", + "AI Model": "Model AI", + "No models detected": "Nie wykryto modeli", + "AI Gateway Configuration": "Konfiguracja bramy AI", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Wybierz spośród wysokiej jakości, ekonomicznych modeli AI. Możesz również użyć własnego modelu, wybierając \"Model niestandardowy\" poniżej.", + "API Key": "Klucz API", + "Get Key": "Pobierz klucz", + "Model": "Model", + "Custom Model...": "Model niestandardowy...", + "Custom Model ID": "ID modelu niestandardowego", + "Validate": "Waliduj", + "Model available": "Model dostępny", + "Connection": "Połączenie", + "Test Connection": "Testuj połączenie", + "Connected": "Połączono" } diff --git a/apps/readest-app/public/locales/pt/translation.json b/apps/readest-app/public/locales/pt/translation.json index 0c769bff..8988f70b 100644 --- a/apps/readest-app/public/locales/pt/translation.json +++ b/apps/readest-app/public/locales/pt/translation.json @@ -884,7 +884,6 @@ "Array of annotations": "Lista de anotações", "Highlighted text": "Texto destacado", "Annotation note": "Nota de anotação", - "Update time": "Hora de atualização", "Date Format Tokens:": "Tokens de formato de data:", "Year (4 digits)": "Ano (4 dígitos)", "Month (01-12)": "Mês (01-12)", @@ -902,5 +901,50 @@ "Show on Discord": "Mostrar no Discord", "Instant {{action}}": "{{action}} instantâneo", "Instant {{action}} Disabled": "{{action}} instantâneo desativado", - "Annotation": "Anotação" + "Annotation": "Anotação", + "Reset Template": "Redefinir modelo", + "Annotation style": "Estilo de anotação", + "Annotation color": "Cor da anotação", + "Annotation time": "Hora da anotação", + "AI": "IA", + "Are you sure you want to re-index this book?": "Tem certeza de que deseja reindexar este livro?", + "Enable AI in Settings": "Ativar IA nas configurações", + "Index This Book": "Indexar este livro", + "Enable AI search and chat for this book": "Ativar pesquisa e chat com IA para este livro", + "Start Indexing": "Iniciar indexação", + "Indexing book...": "Indexando livro...", + "Preparing...": "Preparando...", + "Delete this conversation?": "Excluir esta conversa?", + "No conversations yet": "Ainda não há conversas", + "Start a new chat to ask questions about this book": "Inicie um novo chat para fazer perguntas sobre este livro", + "Rename": "Renomear", + "New Chat": "Novo chat", + "Chat": "Chat", + "Please enter a model ID": "Por favor, insira um ID de modelo", + "Model not available or invalid": "Modelo não disponível ou inválido", + "Failed to validate model": "Falha ao validar modelo", + "Couldn't connect to Ollama. Is it running?": "Não foi possível conectar ao Ollama. Está em execução?", + "Invalid API key or connection failed": "Chave API inválida ou falha na conexão", + "Connection failed": "Falha na conexão", + "AI Assistant": "Assistente de IA", + "Enable AI Assistant": "Ativar assistente de IA", + "Provider": "Provedor", + "Ollama (Local)": "Ollama (Local)", + "AI Gateway (Cloud)": "Gateway de IA (Nuvem)", + "Ollama Configuration": "Configuração do Ollama", + "Refresh Models": "Atualizar modelos", + "AI Model": "Modelo de IA", + "No models detected": "Nenhum modelo detectado", + "AI Gateway Configuration": "Configuração do gateway de IA", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Escolha entre uma seleção de modelos de IA de alta qualidade e econômicos. Você também pode usar seu próprio modelo selecionando \"Modelo personalizado\" abaixo.", + "API Key": "Chave API", + "Get Key": "Obter chave", + "Model": "Modelo", + "Custom Model...": "Modelo personalizado...", + "Custom Model ID": "ID do modelo personalizado", + "Validate": "Validar", + "Model available": "Modelo disponível", + "Connection": "Conexão", + "Test Connection": "Testar conexão", + "Connected": "Conectado" } diff --git a/apps/readest-app/public/locales/ru/translation.json b/apps/readest-app/public/locales/ru/translation.json index bc30b01d..7d980df1 100644 --- a/apps/readest-app/public/locales/ru/translation.json +++ b/apps/readest-app/public/locales/ru/translation.json @@ -894,7 +894,6 @@ "Array of annotations": "Массив примечаний", "Highlighted text": "Выделенный текст", "Annotation note": "Примечание аннотации", - "Update time": "Время обновления", "Date Format Tokens:": "Токены формата даты:", "Year (4 digits)": "Год (4 цифры)", "Month (01-12)": "Месяц (01-12)", @@ -912,5 +911,50 @@ "Show on Discord": "Показать в Discord", "Instant {{action}}": "Мгновенное {{action}}", "Instant {{action}} Disabled": "Мгновенное {{action}} отключено", - "Annotation": "Аннотация" + "Annotation": "Аннотация", + "Reset Template": "Сбросить шаблон", + "Annotation style": "Стиль аннотации", + "Annotation color": "Цвет аннотации", + "Annotation time": "Время аннотации", + "AI": "ИИ", + "Are you sure you want to re-index this book?": "Вы уверены, что хотите переиндексировать эту книгу?", + "Enable AI in Settings": "Включить ИИ в настройках", + "Index This Book": "Индексировать эту книгу", + "Enable AI search and chat for this book": "Включить ИИ-поиск и чат для этой книги", + "Start Indexing": "Начать индексацию", + "Indexing book...": "Индексация книги...", + "Preparing...": "Подготовка...", + "Delete this conversation?": "Удалить этот разговор?", + "No conversations yet": "Пока нет разговоров", + "Start a new chat to ask questions about this book": "Начните новый чат, чтобы задать вопросы об этой книге", + "Rename": "Переименовать", + "New Chat": "Новый чат", + "Chat": "Чат", + "Please enter a model ID": "Пожалуйста, введите ID модели", + "Model not available or invalid": "Модель недоступна или недействительна", + "Failed to validate model": "Не удалось проверить модель", + "Couldn't connect to Ollama. Is it running?": "Не удалось подключиться к Ollama. Он запущен?", + "Invalid API key or connection failed": "Недействительный API-ключ или ошибка подключения", + "Connection failed": "Ошибка подключения", + "AI Assistant": "ИИ-ассистент", + "Enable AI Assistant": "Включить ИИ-ассистента", + "Provider": "Провайдер", + "Ollama (Local)": "Ollama (Локальный)", + "AI Gateway (Cloud)": "ИИ-шлюз (Облако)", + "Ollama Configuration": "Настройка Ollama", + "Refresh Models": "Обновить модели", + "AI Model": "ИИ-модель", + "No models detected": "Модели не обнаружены", + "AI Gateway Configuration": "Настройка ИИ-шлюза", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Выберите из высококачественных, экономичных ИИ-моделей. Вы также можете использовать свою модель, выбрав \"Пользовательская модель\" ниже.", + "API Key": "API-ключ", + "Get Key": "Получить ключ", + "Model": "Модель", + "Custom Model...": "Пользовательская модель...", + "Custom Model ID": "ID пользовательской модели", + "Validate": "Проверить", + "Model available": "Модель доступна", + "Connection": "Соединение", + "Test Connection": "Проверить соединение", + "Connected": "Подключено" } diff --git a/apps/readest-app/public/locales/si/translation.json b/apps/readest-app/public/locales/si/translation.json index da813d41..309a7f79 100644 --- a/apps/readest-app/public/locales/si/translation.json +++ b/apps/readest-app/public/locales/si/translation.json @@ -874,7 +874,6 @@ "Array of annotations": "අනුසටහන් අරය", "Highlighted text": "ඉස්මතු කළ පෙළ", "Annotation note": "අනුසටහන් සටහන", - "Update time": "යාවත්කාලීන කාලය", "Date Format Tokens:": "දිනය ආකෘති ටෝකන:", "Year (4 digits)": "වසර (අංක 4)", "Month (01-12)": "මාසය (01-12)", @@ -892,5 +891,50 @@ "Show on Discord": "Discord හි පෙන්වන්න", "Instant {{action}}": "ක්ෂණික {{action}}", "Instant {{action}} Disabled": "ක්ෂණික {{action}} අබල කර ඇත", - "Annotation": "විවරණය" + "Annotation": "විවරණය", + "Reset Template": "සැකිල්ල නැවත සකස් කරන්න", + "Annotation style": "විවරණ විලාසය", + "Annotation color": "විවරණ වර්ණය", + "Annotation time": "විවරණ වේලාව", + "AI": "කෘතිම බුද්ධිය (AI)", + "Are you sure you want to re-index this book?": "ඔබට මෙම පොත නැවත දර්ශකය කිරීමට අවශ්‍ය බව සහතිකද?", + "Enable AI in Settings": "සැකසුම් තුළ AI සක්‍රීය කරන්න", + "Index This Book": "මෙම පොත දර්ශකය කරන්න", + "Enable AI search and chat for this book": "මෙම පොත සඳහා AI සෙවීම සහ කතාබස් සක්‍රීය කරන්න", + "Start Indexing": "දර්ශකය කිරීම ආරම්භ කරන්න", + "Indexing book...": "පොත දර්ශකය කරමින්...", + "Preparing...": "සූදානම් වෙමින්...", + "Delete this conversation?": "මෙම සංවාදය මකා දමන්නද?", + "No conversations yet": "තවම සංවාද නැත", + "Start a new chat to ask questions about this book": "මෙම පොත ගැන ප්‍රශ්න ඇසීමට නව කතාබහක් ආරම්භ කරන්න", + "Rename": "නම වෙනස් කරන්න", + "New Chat": "නව කතාබහ", + "Chat": "කතාබහ", + "Please enter a model ID": "කරුණාකර මාදිලි හැඳුනුම්පතක් ඇතුළත් කරන්න", + "Model not available or invalid": "මාදිලිය ලබා ගත නොහැක හෝ අවලංගුයි", + "Failed to validate model": "මාදිලිය තහවුරු කිරීමට අසමත් විය", + "Couldn't connect to Ollama. Is it running?": "Ollama වෙත සම්බන්ධ වීමට නොහැකි විය. එය ක්‍රියාත්මක වේද?", + "Invalid API key or connection failed": "අවලංගු API යතුරක් හෝ සම්බන්ධතාවය අසාර්ථක විය", + "Connection failed": "සම්බන්ධතාවය අසාර්ථක විය", + "AI Assistant": "AI සහායකයා", + "Enable AI Assistant": "AI සහායකයා සක්‍රීය කරන්න", + "Provider": "සපයන්නා", + "Ollama (Local)": "Ollama (දේශීය)", + "AI Gateway (Cloud)": "AI Gateway (Cloud)", + "Ollama Configuration": "Ollama වින්‍යාසය", + "Refresh Models": "මාදිලි යාවත්කාලීන කරන්න", + "AI Model": "AI මාදිලිය", + "No models detected": "කිසිදු මාදිලියක් හඳුනාගෙන නැත", + "AI Gateway Configuration": "AI Gateway වින්‍යාසය", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "උසස් තත්ත්වයේ, ලාභදායී AI මාදිලි එකතුවකින් තෝරන්න. පහතින් \"අභිරුචි මාදිලිය\" තේරීමෙන් ඔබට ඔබේම මාදිලියක් ද ගෙන ඒමට හැකිය.", + "API Key": "API යතුර", + "Get Key": "යතුර ලබා ගන්න", + "Model": "මාදිලිය", + "Custom Model...": "අභිරුචි මාදිලිය...", + "Custom Model ID": "අභිරුචි මාදිලි හැඳුනුම්පත", + "Validate": "තහවුරු කරන්න", + "Model available": "මාදිලිය ලබා ගත හැකිය", + "Connection": "සම්බන්ධතාවය", + "Test Connection": "සම්බන්ධතාවය පරීක්ෂා කරන්න", + "Connected": "සම්බන්ධ විය" } diff --git a/apps/readest-app/public/locales/sv/translation.json b/apps/readest-app/public/locales/sv/translation.json index e8f3708c..71ff75a5 100644 --- a/apps/readest-app/public/locales/sv/translation.json +++ b/apps/readest-app/public/locales/sv/translation.json @@ -874,7 +874,6 @@ "Array of annotations": "Lista med anteckningar", "Highlighted text": "Markerad text", "Annotation note": "Anteckningsnotering", - "Update time": "Uppdateringstid", "Date Format Tokens:": "Datumformattecken:", "Year (4 digits)": "År (4 siffror)", "Month (01-12)": "Månad (01-12)", @@ -892,5 +891,50 @@ "Show on Discord": "Visa på Discord", "Instant {{action}}": "Omedelbar {{action}}", "Instant {{action}} Disabled": "Omedelbar {{action}} inaktiverad", - "Annotation": "Anteckning" + "Annotation": "Anteckning", + "Reset Template": "Återställ mall", + "Annotation style": "Anteckningsstil", + "Annotation color": "Anteckningsfärg", + "Annotation time": "Anteckningstid", + "AI": "AI", + "Are you sure you want to re-index this book?": "Är du säker på att du vill indexera om denna bok?", + "Enable AI in Settings": "Aktivera AI i inställningar", + "Index This Book": "Indexera denna bok", + "Enable AI search and chat for this book": "Aktivera AI-sökning och chatt för denna bok", + "Start Indexing": "Starta indexering", + "Indexing book...": "Indexerar bok...", + "Preparing...": "Förbereder...", + "Delete this conversation?": "Ta bort denna konversation?", + "No conversations yet": "Inga konversationer ännu", + "Start a new chat to ask questions about this book": "Starta en ny chatt för att ställa frågor om denna bok", + "Rename": "Byt namn", + "New Chat": "Ny chatt", + "Chat": "Chatt", + "Please enter a model ID": "Ange ett modell-ID", + "Model not available or invalid": "Modell ej tillgänglig eller ogiltig", + "Failed to validate model": "Misslyckades att validera modell", + "Couldn't connect to Ollama. Is it running?": "Kunde inte ansluta till Ollama. Körs den?", + "Invalid API key or connection failed": "Ogiltig API-nyckel eller anslutningen misslyckades", + "Connection failed": "Anslutningen misslyckades", + "AI Assistant": "AI-assistent", + "Enable AI Assistant": "Aktivera AI-assistent", + "Provider": "Leverantör", + "Ollama (Local)": "Ollama (Lokal)", + "AI Gateway (Cloud)": "AI-gateway (Moln)", + "Ollama Configuration": "Ollama-konfiguration", + "Refresh Models": "Uppdatera modeller", + "AI Model": "AI-modell", + "No models detected": "Inga modeller hittades", + "AI Gateway Configuration": "AI-gateway-konfiguration", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Välj bland ett urval av högkvalitativa, ekonomiska AI-modeller. Du kan också använda din egen modell genom att välja \"Anpassad modell\" nedan.", + "API Key": "API-nyckel", + "Get Key": "Hämta nyckel", + "Model": "Modell", + "Custom Model...": "Anpassad modell...", + "Custom Model ID": "Anpassat modell-ID", + "Validate": "Validera", + "Model available": "Modell tillgänglig", + "Connection": "Anslutning", + "Test Connection": "Testa anslutning", + "Connected": "Ansluten" } diff --git a/apps/readest-app/public/locales/ta/translation.json b/apps/readest-app/public/locales/ta/translation.json index b7e1ed44..36ab05af 100644 --- a/apps/readest-app/public/locales/ta/translation.json +++ b/apps/readest-app/public/locales/ta/translation.json @@ -874,7 +874,6 @@ "Array of annotations": "குறிப்புகளின் பட்டியல்", "Highlighted text": "முன்னிலைப்படுத்தப்பட்ட உரை", "Annotation note": "குறிப்பு குறிப்பு", - "Update time": "புதுப்பிப்பு நேரம்", "Date Format Tokens:": "தேதி வடிவமைப்பு டோக்கன்கள்:", "Year (4 digits)": "ஆண்டு (4 இலக்கங்கள்)", "Month (01-12)": "மாதம் (01-12)", @@ -892,5 +891,50 @@ "Show on Discord": "Discord இல் காட்டு", "Instant {{action}}": "உடனடி {{action}}", "Instant {{action}} Disabled": "உடனடி {{action}} முடக்கப்பட்டது", - "Annotation": "குறிப்பு" + "Annotation": "குறிப்பு", + "Reset Template": "வார்ப்புருவை மீட்டமைக்கவும்", + "Annotation style": "சிறுகுறிப்பு பாணி", + "Annotation color": "சிறுகுறிப்பு நிறம்", + "Annotation time": "சிறுகுறிப்பு நேரம்", + "AI": "செயற்கை நுண்ணறிவு (AI)", + "Are you sure you want to re-index this book?": "இந்த புத்தகத்தை மீண்டும் அட்டவணைப்படுத்த உறுதியாக இருக்கிறீர்களா?", + "Enable AI in Settings": "அமைப்புகளில் AI ஐ இயக்கவும்", + "Index This Book": "இந்த புத்தகத்தை அட்டவணைப்படுத்தவும்", + "Enable AI search and chat for this book": "இந்த புத்தகத்திற்கு AI தேடல் மற்றும் அரட்டையை இயக்கவும்", + "Start Indexing": "அட்டவணைப்படுத்தலைத் தொடங்கவும்", + "Indexing book...": "புத்தகம் அட்டவணைப்படுத்தப்படுகிறது...", + "Preparing...": "தயாராகிறது...", + "Delete this conversation?": "இந்த உரையாடலை நீக்கவா?", + "No conversations yet": "இதுவரை உரையாடல்கள் எதுவும் இல்லை", + "Start a new chat to ask questions about this book": "இந்த புத்தகத்தைப் பற்றி கேள்விகள் கேட்க புதிய அரட்டையைத் தொடங்கவும்", + "Rename": "மறுபெயரிடு", + "New Chat": "புதிய அரட்டை", + "Chat": "அரட்டை", + "Please enter a model ID": "மாதிரி ஐடியை உள்ளிடவும்", + "Model not available or invalid": "மாதிரி கிடைக்கவில்லை அல்லது தவறானது", + "Failed to validate model": "மாதிரியைச் சரிபார்க்கத் தவறிவிட்டது", + "Couldn't connect to Ollama. Is it running?": "Ollama வுடன் இணைக்க முடியவில்லை. அது இயங்குகிறதா?", + "Invalid API key or connection failed": "தவறான ஏபிஐ (API) விசை அல்லது இணைப்பு தோல்வியடைந்தது", + "Connection failed": "இணைப்பு தோல்வியடைந்தது", + "AI Assistant": "AI உதவியாளர்", + "Enable AI Assistant": "AI உதவியாளரை இயக்கவும்", + "Provider": "வழங்குநர்", + "Ollama (Local)": "Ollama (உள்ளூர்)", + "AI Gateway (Cloud)": "AI கேட்வே (கிளவுட்)", + "Ollama Configuration": "Ollama உள்ளமைவு", + "Refresh Models": "மாதிரிகளைப் புதுப்பிக்கவும்", + "AI Model": "AI மாதிரி", + "No models detected": "மாதிரிகள் எதுவும் கண்டறியப்படவில்லை", + "AI Gateway Configuration": "AI கேட்வே உள்ளமைவு", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "உயர்தர, சிக்கனமான AI மாதிரிகளிலிருந்து தேர்ந்தெடுக்கவும். கீழே உள்ள \"தனிப்பயன் மாதிரி\" என்பதைத் தேர்ந்தெடுப்பதன் மூலம் உங்கள் சொந்த மாதிரியையும் கொண்டு வரலாம்.", + "API Key": "API விசை", + "Get Key": "விசையைப் பெறவும்", + "Model": "மாதிரி", + "Custom Model...": "தனிப்பயன் மாதிரி...", + "Custom Model ID": "தனிப்பயன் மாதிரி ஐடி", + "Validate": "சரிபார்க்கவும்", + "Model available": "மாதிரி கிடைக்கிறது", + "Connection": "இணைப்பு", + "Test Connection": "இணைப்பைச் சோதிக்கவும்", + "Connected": "இணைக்கப்பட்டது" } diff --git a/apps/readest-app/public/locales/th/translation.json b/apps/readest-app/public/locales/th/translation.json index 30540c0d..e9bde3f0 100644 --- a/apps/readest-app/public/locales/th/translation.json +++ b/apps/readest-app/public/locales/th/translation.json @@ -864,7 +864,6 @@ "Array of annotations": "อาร์เรย์ของคำอธิบาย", "Highlighted text": "ข้อความที่ไฮไลต์", "Annotation note": "หมายเหตุคำอธิบาย", - "Update time": "เวลาอัปเดต", "Date Format Tokens:": "โทเค็นรูปแบบวันที่:", "Year (4 digits)": "ปี (4 หลัก)", "Month (01-12)": "เดือน (01-12)", @@ -882,5 +881,50 @@ "Show on Discord": "แสดงบน Discord", "Instant {{action}}": "{{action}}ทันที", "Instant {{action}} Disabled": "{{action}}ทันทีถูกปิดใช้งาน", - "Annotation": "คำอธิบาย" + "Annotation": "คำอธิบาย", + "Reset Template": "รีเซ็ตเทมเพลต", + "Annotation style": "สไตล์คำอธิบาย", + "Annotation color": "สีคำอธิบาย", + "Annotation time": "เวลาคำอธิบาย", + "AI": "AI", + "Are you sure you want to re-index this book?": "คุณแน่ใจหรือไม่ว่าต้องการสร้างดัชนีหนังสือเล่มนี้ใหม่?", + "Enable AI in Settings": "เปิดใช้งาน AI ในการตั้งค่า", + "Index This Book": "สร้างดัชนีหนังสือเล่มนี้", + "Enable AI search and chat for this book": "เปิดใช้งานการค้นหา AI และแชทสำหรับหนังสือเล่มนี้", + "Start Indexing": "เริ่มสร้างดัชนี", + "Indexing book...": "กำลังสร้างดัชนีหนังสือ...", + "Preparing...": "กำลังเตรียม...", + "Delete this conversation?": "ลบการสนทนานี้?", + "No conversations yet": "ยังไม่มีการสนทนา", + "Start a new chat to ask questions about this book": "เริ่มแชทใหม่เพื่อถามคำถามเกี่ยวกับหนังสือเล่มนี้", + "Rename": "เปลี่ยนชื่อ", + "New Chat": "แชทใหม่", + "Chat": "แชท", + "Please enter a model ID": "กรุณาป้อน ID โมเดล", + "Model not available or invalid": "โมเดลไม่พร้อมใช้งานหรือไม่ถูกต้อง", + "Failed to validate model": "ไม่สามารถตรวจสอบโมเดลได้", + "Couldn't connect to Ollama. Is it running?": "ไม่สามารถเชื่อมต่อกับ Ollama ได้ กำลังทำงานอยู่หรือไม่?", + "Invalid API key or connection failed": "คีย์ API ไม่ถูกต้องหรือการเชื่อมต่อล้มเหลว", + "Connection failed": "การเชื่อมต่อล้มเหลว", + "AI Assistant": "ผู้ช่วย AI", + "Enable AI Assistant": "เปิดใช้งานผู้ช่วย AI", + "Provider": "ผู้ให้บริการ", + "Ollama (Local)": "Ollama (ในเครื่อง)", + "AI Gateway (Cloud)": "เกตเวย์ AI (คลาวด์)", + "Ollama Configuration": "การกำหนดค่า Ollama", + "Refresh Models": "รีเฟรชโมเดล", + "AI Model": "โมเดล AI", + "No models detected": "ไม่พบโมเดล", + "AI Gateway Configuration": "การกำหนดค่าเกตเวย์ AI", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "เลือกจากโมเดล AI คุณภาพสูงและประหยัด คุณยังสามารถใช้โมเดลของคุณเองโดยเลือก \"โมเดลกำหนดเอง\" ด้านล่าง", + "API Key": "คีย์ API", + "Get Key": "รับคีย์", + "Model": "โมเดล", + "Custom Model...": "โมเดลกำหนดเอง...", + "Custom Model ID": "ID โมเดลกำหนดเอง", + "Validate": "ตรวจสอบ", + "Model available": "โมเดลพร้อมใช้งาน", + "Connection": "การเชื่อมต่อ", + "Test Connection": "ทดสอบการเชื่อมต่อ", + "Connected": "เชื่อมต่อแล้ว" } diff --git a/apps/readest-app/public/locales/tr/translation.json b/apps/readest-app/public/locales/tr/translation.json index c3f8b98c..19158a38 100644 --- a/apps/readest-app/public/locales/tr/translation.json +++ b/apps/readest-app/public/locales/tr/translation.json @@ -874,7 +874,6 @@ "Array of annotations": "Notlar dizisi", "Highlighted text": "Vurgulanan metin", "Annotation note": "Not açıklaması", - "Update time": "Güncelleme zamanı", "Date Format Tokens:": "Tarih Biçimi Belirteçleri:", "Year (4 digits)": "Yıl (4 basamak)", "Month (01-12)": "Ay (01-12)", @@ -892,5 +891,50 @@ "Show on Discord": "Discord'da göster", "Instant {{action}}": "Anında {{action}}", "Instant {{action}} Disabled": "Anında {{action}} Devre Dışı", - "Annotation": "Açıklama" + "Annotation": "Açıklama", + "Reset Template": "Şablonu Sıfırla", + "Annotation style": "Açıklama stili", + "Annotation color": "Açıklama rengi", + "Annotation time": "Açıklama zamanı", + "AI": "YZ", + "Are you sure you want to re-index this book?": "Bu kitabı yeniden dizinlemek istediğinizden emin misiniz?", + "Enable AI in Settings": "Ayarlarda YZ'yi Etkinleştir", + "Index This Book": "Bu Kitabı Dizinle", + "Enable AI search and chat for this book": "Bu kitap için YZ arama ve sohbeti etkinleştir", + "Start Indexing": "Dizinlemeyi Başlat", + "Indexing book...": "Kitap dizinleniyor...", + "Preparing...": "Hazırlanıyor...", + "Delete this conversation?": "Bu konuşmayı sil?", + "No conversations yet": "Henüz konuşma yok", + "Start a new chat to ask questions about this book": "Bu kitap hakkında soru sormak için yeni bir sohbet başlatın", + "Rename": "Yeniden Adlandır", + "New Chat": "Yeni Sohbet", + "Chat": "Sohbet", + "Please enter a model ID": "Lütfen bir model kimliği girin", + "Model not available or invalid": "Model kullanılamıyor veya geçersiz", + "Failed to validate model": "Model doğrulanamadı", + "Couldn't connect to Ollama. Is it running?": "Ollama'ya bağlanılamadı. Çalışıyor mu?", + "Invalid API key or connection failed": "Geçersiz API anahtarı veya bağlantı başarısız", + "Connection failed": "Bağlantı başarısız", + "AI Assistant": "YZ Asistanı", + "Enable AI Assistant": "YZ Asistanını Etkinleştir", + "Provider": "Sağlayıcı", + "Ollama (Local)": "Ollama (Yerel)", + "AI Gateway (Cloud)": "YZ Geçidi (Bulut)", + "Ollama Configuration": "Ollama Yapılandırması", + "Refresh Models": "Modelleri Yenile", + "AI Model": "YZ Modeli", + "No models detected": "Model algılanmadı", + "AI Gateway Configuration": "YZ Geçidi Yapılandırması", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Yüksek kaliteli, ekonomik YZ modelleri arasından seçim yapın. Aşağıdaki \"Özel Model\"i seçerek kendi modelinizi de kullanabilirsiniz.", + "API Key": "API Anahtarı", + "Get Key": "Anahtar Al", + "Model": "Model", + "Custom Model...": "Özel Model...", + "Custom Model ID": "Özel Model Kimliği", + "Validate": "Doğrula", + "Model available": "Model mevcut", + "Connection": "Bağlantı", + "Test Connection": "Bağlantıyı Test Et", + "Connected": "Bağlandı" } diff --git a/apps/readest-app/public/locales/uk/translation.json b/apps/readest-app/public/locales/uk/translation.json index 879d53fa..871ac072 100644 --- a/apps/readest-app/public/locales/uk/translation.json +++ b/apps/readest-app/public/locales/uk/translation.json @@ -894,7 +894,6 @@ "Array of annotations": "Масив приміток", "Highlighted text": "Виділений текст", "Annotation note": "Примітка анотації", - "Update time": "Час оновлення", "Date Format Tokens:": "Токени формату дати:", "Year (4 digits)": "Рік (4 цифри)", "Month (01-12)": "Місяць (01-12)", @@ -912,5 +911,50 @@ "Show on Discord": "Показати в Discord", "Instant {{action}}": "Миттєва {{action}}", "Instant {{action}} Disabled": "Миттєву {{action}} вимкнено", - "Annotation": "Анотація" + "Annotation": "Анотація", + "Reset Template": "Скинути шаблон", + "Annotation style": "Стиль анотації", + "Annotation color": "Колір анотації", + "Annotation time": "Час анотації", + "AI": "ШІ", + "Are you sure you want to re-index this book?": "Ви впевнені, що хочете переіндексувати цю книгу?", + "Enable AI in Settings": "Увімкнути ШІ в налаштуваннях", + "Index This Book": "Індексувати цю книгу", + "Enable AI search and chat for this book": "Увімкнути ШІ-пошук та чат для цієї книги", + "Start Indexing": "Почати індексацію", + "Indexing book...": "Індексація книги...", + "Preparing...": "Підготовка...", + "Delete this conversation?": "Видалити цю розмову?", + "No conversations yet": "Поки немає розмов", + "Start a new chat to ask questions about this book": "Почніть новий чат, щоб задати питання про цю книгу", + "Rename": "Перейменувати", + "New Chat": "Новий чат", + "Chat": "Чат", + "Please enter a model ID": "Будь ласка, введіть ID моделі", + "Model not available or invalid": "Модель недоступна або недійсна", + "Failed to validate model": "Не вдалося перевірити модель", + "Couldn't connect to Ollama. Is it running?": "Не вдалося підключитися до Ollama. Чи вона запущена?", + "Invalid API key or connection failed": "Недійсний API-ключ або помилка підключення", + "Connection failed": "Помилка підключення", + "AI Assistant": "ШІ-асистент", + "Enable AI Assistant": "Увімкнути ШІ-асистента", + "Provider": "Провайдер", + "Ollama (Local)": "Ollama (Локальний)", + "AI Gateway (Cloud)": "ШІ-шлюз (Хмара)", + "Ollama Configuration": "Налаштування Ollama", + "Refresh Models": "Оновити моделі", + "AI Model": "ШІ-модель", + "No models detected": "Моделі не знайдено", + "AI Gateway Configuration": "Налаштування ШІ-шлюзу", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Оберіть з високоякісних, економічних ШІ-моделей. Ви також можете використати власну модель, обравши \"Користувацька модель\" нижче.", + "API Key": "API-ключ", + "Get Key": "Отримати ключ", + "Model": "Модель", + "Custom Model...": "Користувацька модель...", + "Custom Model ID": "ID користувацької моделі", + "Validate": "Перевірити", + "Model available": "Модель доступна", + "Connection": "З'єднання", + "Test Connection": "Перевірити з'єднання", + "Connected": "Підключено" } diff --git a/apps/readest-app/public/locales/vi/translation.json b/apps/readest-app/public/locales/vi/translation.json index 71d4db62..8937ed69 100644 --- a/apps/readest-app/public/locales/vi/translation.json +++ b/apps/readest-app/public/locales/vi/translation.json @@ -864,7 +864,6 @@ "Array of annotations": "Danh sách chú thích", "Highlighted text": "Văn bản được đánh dấu", "Annotation note": "Ghi chú chú thích", - "Update time": "Thời gian cập nhật", "Date Format Tokens:": "Token định dạng ngày:", "Year (4 digits)": "Năm (4 chữ số)", "Month (01-12)": "Tháng (01-12)", @@ -882,5 +881,50 @@ "Show on Discord": "Hiện trên Discord", "Instant {{action}}": "{{action}} tức thì", "Instant {{action}} Disabled": "{{action}} tức thì đã tắt", - "Annotation": "Chú thích" + "Annotation": "Chú thích", + "Reset Template": "Đặt lại mẫu", + "Annotation style": "Kiểu chú thích", + "Annotation color": "Màu chú thích", + "Annotation time": "Thời gian chú thích", + "AI": "AI", + "Are you sure you want to re-index this book?": "Bạn có chắc muốn lập chỉ mục lại cuốn sách này?", + "Enable AI in Settings": "Bật AI trong Cài đặt", + "Index This Book": "Lập chỉ mục sách này", + "Enable AI search and chat for this book": "Bật tìm kiếm AI và trò chuyện cho cuốn sách này", + "Start Indexing": "Bắt đầu lập chỉ mục", + "Indexing book...": "Đang lập chỉ mục sách...", + "Preparing...": "Đang chuẩn bị...", + "Delete this conversation?": "Xóa cuộc trò chuyện này?", + "No conversations yet": "Chưa có cuộc trò chuyện nào", + "Start a new chat to ask questions about this book": "Bắt đầu cuộc trò chuyện mới để hỏi về cuốn sách này", + "Rename": "Đổi tên", + "New Chat": "Cuộc trò chuyện mới", + "Chat": "Trò chuyện", + "Please enter a model ID": "Vui lòng nhập ID mô hình", + "Model not available or invalid": "Mô hình không khả dụng hoặc không hợp lệ", + "Failed to validate model": "Xác thực mô hình thất bại", + "Couldn't connect to Ollama. Is it running?": "Không thể kết nối với Ollama. Nó có đang chạy không?", + "Invalid API key or connection failed": "Khóa API không hợp lệ hoặc kết nối thất bại", + "Connection failed": "Kết nối thất bại", + "AI Assistant": "Trợ lý AI", + "Enable AI Assistant": "Bật trợ lý AI", + "Provider": "Nhà cung cấp", + "Ollama (Local)": "Ollama (Cục bộ)", + "AI Gateway (Cloud)": "Cổng AI (Đám mây)", + "Ollama Configuration": "Cấu hình Ollama", + "Refresh Models": "Làm mới mô hình", + "AI Model": "Mô hình AI", + "No models detected": "Không phát hiện mô hình nào", + "AI Gateway Configuration": "Cấu hình cổng AI", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "Chọn từ các mô hình AI chất lượng cao, tiết kiệm. Bạn cũng có thể sử dụng mô hình riêng bằng cách chọn \"Mô hình tùy chỉnh\" bên dưới.", + "API Key": "Khóa API", + "Get Key": "Lấy khóa", + "Model": "Mô hình", + "Custom Model...": "Mô hình tùy chỉnh...", + "Custom Model ID": "ID mô hình tùy chỉnh", + "Validate": "Xác thực", + "Model available": "Mô hình khả dụng", + "Connection": "Kết nối", + "Test Connection": "Kiểm tra kết nối", + "Connected": "Đã kết nối" } diff --git a/apps/readest-app/public/locales/zh-CN/translation.json b/apps/readest-app/public/locales/zh-CN/translation.json index 52a5d656..0f1bc088 100644 --- a/apps/readest-app/public/locales/zh-CN/translation.json +++ b/apps/readest-app/public/locales/zh-CN/translation.json @@ -864,7 +864,6 @@ "Array of annotations": "标注数组", "Highlighted text": "高亮文本", "Annotation note": "标注笔记", - "Update time": "更新时间", "Date Format Tokens:": "日期格式标记:", "Year (4 digits)": "年(4位)", "Month (01-12)": "月(01-12)", @@ -882,5 +881,50 @@ "Show on Discord": "在Discord显示", "Instant {{action}}": "即时{{action}}", "Instant {{action}} Disabled": "即时{{action}}已禁用", - "Annotation": "标注" + "Annotation": "标注", + "Reset Template": "重置模板", + "Annotation style": "标注样式", + "Annotation color": "标注颜色", + "Annotation time": "标注时间", + "AI": "AI", + "Are you sure you want to re-index this book?": "确定要重新索引这本书吗?", + "Enable AI in Settings": "在设置中启用 AI", + "Index This Book": "索引这本书", + "Enable AI search and chat for this book": "为这本书启用 AI 搜索和聊天", + "Start Indexing": "开始索引", + "Indexing book...": "正在索引书籍...", + "Preparing...": "准备中...", + "Delete this conversation?": "删除此对话?", + "No conversations yet": "暂无对话", + "Start a new chat to ask questions about this book": "开始新对话来询问关于这本书的问题", + "Rename": "重命名", + "New Chat": "新对话", + "Chat": "聊天", + "Please enter a model ID": "请输入模型 ID", + "Model not available or invalid": "模型不可用或无效", + "Failed to validate model": "模型验证失败", + "Couldn't connect to Ollama. Is it running?": "无法连接到 Ollama。它是否正在运行?", + "Invalid API key or connection failed": "API 密钥无效或连接失败", + "Connection failed": "连接失败", + "AI Assistant": "AI 助手", + "Enable AI Assistant": "启用 AI 助手", + "Provider": "提供商", + "Ollama (Local)": "Ollama(本地)", + "AI Gateway (Cloud)": "AI 网关(云端)", + "Ollama Configuration": "Ollama 配置", + "Refresh Models": "刷新模型", + "AI Model": "AI 模型", + "No models detected": "未检测到模型", + "AI Gateway Configuration": "AI 网关配置", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "从一系列高质量、经济实惠的 AI 模型中选择。您也可以通过下方的\"自定义模型\"使用自己的模型。", + "API Key": "API 密钥", + "Get Key": "获取密钥", + "Model": "模型", + "Custom Model...": "自定义模型...", + "Custom Model ID": "自定义模型 ID", + "Validate": "验证", + "Model available": "模型可用", + "Connection": "连接", + "Test Connection": "测试连接", + "Connected": "已连接" } diff --git a/apps/readest-app/public/locales/zh-TW/translation.json b/apps/readest-app/public/locales/zh-TW/translation.json index 3525c96d..74342cee 100644 --- a/apps/readest-app/public/locales/zh-TW/translation.json +++ b/apps/readest-app/public/locales/zh-TW/translation.json @@ -864,7 +864,6 @@ "Array of annotations": "標註陣列", "Highlighted text": "標記文字", "Annotation note": "標註筆記", - "Update time": "更新時間", "Date Format Tokens:": "日期格式標記:", "Year (4 digits)": "年(4位)", "Month (01-12)": "月(01-12)", @@ -882,5 +881,50 @@ "Show on Discord": "在Discord顯示", "Instant {{action}}": "即時{{action}}", "Instant {{action}} Disabled": "即時{{action}}已停用", - "Annotation": "註解" + "Annotation": "註解", + "Reset Template": "重置範本", + "Annotation style": "標註樣式", + "Annotation color": "標註顏色", + "Annotation time": "標註時間", + "AI": "AI", + "Are you sure you want to re-index this book?": "確定要重新索引這本書嗎?", + "Enable AI in Settings": "在設定中啟用 AI", + "Index This Book": "索引這本書", + "Enable AI search and chat for this book": "為這本書啟用 AI 搜尋和聊天", + "Start Indexing": "開始索引", + "Indexing book...": "正在索引書籍...", + "Preparing...": "準備中...", + "Delete this conversation?": "刪除此對話?", + "No conversations yet": "尚無對話", + "Start a new chat to ask questions about this book": "開始新對話來詢問關於這本書的問題", + "Rename": "重新命名", + "New Chat": "新對話", + "Chat": "聊天", + "Please enter a model ID": "請輸入模型 ID", + "Model not available or invalid": "模型不可用或無效", + "Failed to validate model": "模型驗證失敗", + "Couldn't connect to Ollama. Is it running?": "無法連線到 Ollama。它是否正在執行?", + "Invalid API key or connection failed": "API 金鑰無效或連線失敗", + "Connection failed": "連線失敗", + "AI Assistant": "AI 助手", + "Enable AI Assistant": "啟用 AI 助手", + "Provider": "提供者", + "Ollama (Local)": "Ollama(本機)", + "AI Gateway (Cloud)": "AI 閘道(雲端)", + "Ollama Configuration": "Ollama 設定", + "Refresh Models": "重新整理模型", + "AI Model": "AI 模型", + "No models detected": "未偵測到模型", + "AI Gateway Configuration": "AI 閘道設定", + "Choose from a selection of high-quality, economical AI models. You can also bring your own model by selecting \"Custom Model\" below.": "從一系列高品質、經濟實惠的 AI 模型中選擇。您也可以透過下方的「自訂模型」使用自己的模型。", + "API Key": "API 金鑰", + "Get Key": "取得金鑰", + "Model": "模型", + "Custom Model...": "自訂模型...", + "Custom Model ID": "自訂模型 ID", + "Validate": "驗證", + "Model available": "模型可用", + "Connection": "連線", + "Test Connection": "測試連線", + "Connected": "已連線" } diff --git a/apps/readest-app/src/__tests__/utils/note.test.ts b/apps/readest-app/src/__tests__/utils/note.test.ts new file mode 100644 index 00000000..28a319db --- /dev/null +++ b/apps/readest-app/src/__tests__/utils/note.test.ts @@ -0,0 +1,572 @@ +import { describe, it, expect } from 'vitest'; +import { renderNoteTemplate, validateNoteTemplate, NoteTemplateData } from '../../utils/note'; + +describe('renderNoteTemplate', () => { + const sampleData: NoteTemplateData = { + title: 'The Great Gatsby', + author: 'F. Scott Fitzgerald', + exportDate: '2024-01-15', + chapters: [ + { + title: 'Chapter 1', + annotations: [ + { + text: 'In my younger and more vulnerable years', + note: 'Opening line', + style: 'highlight', + color: 'yellow', + timestamp: 1705312800000, // 2024-01-15 10:00:00 UTC + }, + { + text: 'So we beat on, boats against the current', + note: '', + style: 'underline', + color: 'blue', + timestamp: 1705316400000, // 2024-01-15 11:00:00 UTC + }, + ], + }, + { + title: 'Chapter 2', + annotations: [ + { + text: 'The eyes of Doctor T. J. Eckleburg', + note: 'Symbolism', + style: 'highlight', + color: 'green', + timestamp: 1705320000000, // 2024-01-15 12:00:00 UTC + }, + ], + }, + ], + }; + + describe('Variable substitution', () => { + it('should substitute simple variables', () => { + const template = 'Book: {{ title }} by {{ author }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('Book: The Great Gatsby by F. Scott Fitzgerald'); + }); + + it('should handle undefined variables gracefully', () => { + const template = '{{ nonexistent }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe(''); + }); + + it('should handle nested property access', () => { + const template = '{{ chapters[0].title }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('Chapter 1'); + }); + + it('should handle deeply nested property access', () => { + const template = '{{ chapters[0].annotations[0].text }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('In my younger and more vulnerable years'); + }); + }); + + describe('For loops', () => { + it('should iterate over arrays', () => { + const template = '{% for chapter in chapters %}{{ chapter.title }}\n{% endfor %}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toContain('Chapter 1'); + expect(result).toContain('Chapter 2'); + }); + + it('should handle nested for loops', () => { + const template = `{% for chapter in chapters %} +## {{ chapter.title }} +{% for annotation in chapter.annotations %} +- {{ annotation.text }} +{% endfor %} +{% endfor %}`; + const result = renderNoteTemplate(template, sampleData); + expect(result).toContain('## Chapter 1'); + expect(result).toContain('- In my younger and more vulnerable years'); + expect(result).toContain('## Chapter 2'); + expect(result).toContain('- The eyes of Doctor T. J. Eckleburg'); + }); + + it('should handle empty arrays', () => { + const emptyData: NoteTemplateData = { + title: 'Empty Book', + author: 'Nobody', + exportDate: '2024-01-15', + chapters: [], + }; + const template = '{% for chapter in chapters %}{{ chapter.title }}{% endfor %}'; + const result = renderNoteTemplate(template, emptyData); + expect(result).toBe(''); + }); + + it('should provide loop variables (loop.index, loop.first, loop.last)', () => { + const template = `{% for chapter in chapters %}{{ loop.index }}: {{ chapter.title }}{% if not loop.last %}, {% endif %}{% endfor %}`; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('1: Chapter 1, 2: Chapter 2'); + }); + + it('should provide loop.index0 (0-based index)', () => { + const template = `{% for chapter in chapters %}{{ loop.index0 }}: {{ chapter.title }}\n{% endfor %}`; + const result = renderNoteTemplate(template, sampleData); + expect(result).toContain('0: Chapter 1'); + expect(result).toContain('1: Chapter 2'); + }); + }); + + describe('Conditionals', () => { + it('should handle if statements', () => { + const template = '{% if author %}Author: {{ author }}{% endif %}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('Author: F. Scott Fitzgerald'); + }); + + it('should handle if-else statements', () => { + const template = '{% if nonexistent %}Has value{% else %}No value{% endif %}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('No value'); + }); + + it('should handle if-elif-else statements', () => { + const template = + '{% if chapters.length > 5 %}Many{% elif chapters.length > 1 %}Some{% else %}Few{% endif %}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('Some'); + }); + + it('should handle if statements with annotation note', () => { + const template = `{% for chapter in chapters %}{% for annotation in chapter.annotations %}{% if annotation.note %}Note: {{ annotation.note }} +{% endif %}{% endfor %}{% endfor %}`; + const result = renderNoteTemplate(template, sampleData); + expect(result).toContain('Note: Opening line'); + expect(result).toContain('Note: Symbolism'); + expect(result.match(/Note:/g)?.length).toBe(2); + }); + }); + + describe('Date filter', () => { + it('should format timestamp with default locale format', () => { + const template = '{{ chapters[0].annotations[0].timestamp | date }}'; + const result = renderNoteTemplate(template, sampleData); + // Result will be locale-dependent, just check it's not empty + expect(result).not.toBe(''); + expect(result.length).toBeGreaterThan(0); + }); + + it('should format timestamp with custom format %Y-%m-%d', () => { + const template = "{{ chapters[0].annotations[0].timestamp | date('%Y-%m-%d') }}"; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('2024-01-15'); + }); + + it('should format timestamp with time format %H:%M:%S', () => { + const template = "{{ chapters[0].annotations[0].timestamp | date('%H:%M:%S') }}"; + const result = renderNoteTemplate(template, sampleData); + // This depends on timezone, so just check the format + expect(result).toMatch(/^\d{2}:\d{2}:\d{2}$/); + }); + + it('should format timestamp with full datetime', () => { + const template = "{{ chapters[0].annotations[0].timestamp | date('%Y-%m-%d %H:%M') }}"; + const result = renderNoteTemplate(template, sampleData); + expect(result).toMatch(/^2024-01-15 \d{2}:\d{2}$/); + }); + + it('should handle 12-hour format with %I and %p', () => { + const template = "{{ chapters[0].annotations[0].timestamp | date('%I:%M %p') }}"; + const result = renderNoteTemplate(template, sampleData); + expect(result).toMatch(/^\d{2}:\d{2} (AM|PM)$/); + }); + + it('should handle undefined timestamp', () => { + const dataWithoutTimestamp: NoteTemplateData = { + ...sampleData, + chapters: [ + { + title: 'Chapter', + annotations: [{ text: 'Text' }], + }, + ], + }; + const template = "{{ chapters[0].annotations[0].timestamp | date('%Y-%m-%d') }}"; + const result = renderNoteTemplate(template, dataWithoutTimestamp); + expect(result).toBe(''); + }); + + it('should handle string date input', () => { + const template = "{{ exportDate | date('%Y-%m-%d') }}"; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('2024-01-15'); + }); + + it('should handle escaped percent signs', () => { + const template = + "{{ chapters[0].annotations[0].timestamp | date('100%% complete on %Y-%m-%d') }}"; + const result = renderNoteTemplate(template, sampleData); + expect(result).toContain('100% complete on 2024-01-15'); + }); + }); + + describe('Default filter', () => { + it('should return value when present', () => { + const template = "{{ title | default('Unknown') }}"; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('The Great Gatsby'); + }); + + it('should return default when value is undefined', () => { + const template = "{{ nonexistent | default('Unknown') }}"; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('Unknown'); + }); + + it('should return default when value is empty string', () => { + const template = "{{ chapters[0].annotations[1].note | default('No note') }}"; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('No note'); + }); + }); + + describe('String filters', () => { + it('should convert to uppercase with upper filter', () => { + const template = '{{ title | upper }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('THE GREAT GATSBY'); + }); + + it('should convert to lowercase with lower filter', () => { + const template = '{{ title | lower }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('the great gatsby'); + }); + + it('should capitalize with capitalize filter', () => { + const template = '{{ "hello world" | capitalize }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('Hello world'); + }); + + it('should title case with title filter', () => { + const template = '{{ "hello world" | title }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('Hello World'); + }); + + it('should trim whitespace with trim filter', () => { + const template = '{{ " spaced " | trim }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('spaced'); + }); + + it('should replace substrings with replace filter', () => { + const template = "{{ title | replace('Great', 'Amazing') }}"; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('The Amazing Gatsby'); + }); + }); + + describe('Truncate filter', () => { + it('should truncate long strings', () => { + const template = '{{ chapters[0].annotations[0].text | truncate(20) }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result.length).toBeLessThanOrEqual(23); // 20 + '...' + expect(result).toContain('...'); + }); + + it('should not truncate short strings', () => { + const template = '{{ title | truncate(50) }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('The Great Gatsby'); + }); + + it('should truncate at word boundaries by default', () => { + const template = '{{ chapters[0].annotations[0].text | truncate(25) }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).not.toMatch(/\s\.\.\.$/); // Should not end with space before ... + }); + }); + + describe('Length filter', () => { + it('should return string length', () => { + const template = '{{ title | length }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('16'); + }); + + it('should return array length', () => { + const template = '{{ chapters | length }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('2'); + }); + }); + + describe('First and last filters', () => { + it('should get first element of array', () => { + const template = '{% set first_chapter = chapters | first %}{{ first_chapter.title }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('Chapter 1'); + }); + + it('should get last element of array', () => { + const template = '{% set last_chapter = chapters | last %}{{ last_chapter.title }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('Chapter 2'); + }); + }); + + describe('Join filter', () => { + it('should join array elements', () => { + // Using a loop with conditional comma separator + const template = + '{% for chapter in chapters %}{{ chapter.title }}{% if not loop.last %}, {% endif %}{% endfor %}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('Chapter 1, Chapter 2'); + }); + }); + + describe('Newline to BR filter', () => { + it('should convert newlines to br tags', () => { + const dataWithNewlines: NoteTemplateData = { + ...sampleData, + chapters: [ + { + title: 'Chapter 1', + annotations: [ + { + text: 'Line 1\nLine 2\nLine 3', + note: 'Multiple lines', + }, + ], + }, + ], + }; + const template = '{{ chapters[0].annotations[0].text | nl2br }}'; + const result = renderNoteTemplate(template, dataWithNewlines); + expect(result).toBe('Line 1
\nLine 2
\nLine 3'); + }); + }); + + describe('Chained filters', () => { + it('should support chaining multiple filters', () => { + const template = '{{ title | upper | truncate(10) }}'; + const result = renderNoteTemplate(template, sampleData); + // truncate(10) with word boundaries results in "THE GREAT..." (breaks at word boundary) + expect(result).toBe('THE GREAT...'); + }); + + it('should support chaining with killwords option', () => { + const template = '{{ title | upper | truncate(5, true) }}'; + const result = renderNoteTemplate(template, sampleData); + // truncate(5, true) with killwords results in "THE G..." + expect(result).toBe('THE G...'); + }); + + it('should chain date and string filters', () => { + const template = '{{ exportDate | upper }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('2024-01-15'); + }); + }); + + describe('Complete template rendering', () => { + it('should render a complete export template', () => { + const template = `## {{ title }} +**Author**: {{ author }} + +**Exported**: {{ exportDate }} + +--- + +### Highlights & Annotations + +{% for chapter in chapters %} +#### {{ chapter.title }} +{% for annotation in chapter.annotations %} +> {{ annotation.text }} +{% if annotation.note %} +**Note:** {{ annotation.note }} +{% endif %} +*Time: {{ annotation.timestamp | date('%Y-%m-%d %H:%M') }}* +{% endfor %} + +--- +{% endfor %}`; + const result = renderNoteTemplate(template, sampleData); + + expect(result).toContain('## The Great Gatsby'); + expect(result).toContain('**Author**: F. Scott Fitzgerald'); + expect(result).toContain('#### Chapter 1'); + expect(result).toContain('> In my younger and more vulnerable years'); + expect(result).toContain('**Note:** Opening line'); + expect(result).toContain('#### Chapter 2'); + expect(result).toContain('> The eyes of Doctor T. J. Eckleburg'); + }); + + it('should handle template with no chapters', () => { + const emptyData: NoteTemplateData = { + title: 'Empty Book', + author: 'Unknown', + exportDate: '2024-01-15', + chapters: [], + }; + const template = `## {{ title }} +{% for chapter in chapters %} +{{ chapter.title }} +{% endfor %}`; + const result = renderNoteTemplate(template, emptyData); + expect(result).toContain('## Empty Book'); + expect(result).not.toContain('Chapter'); + }); + }); + + describe('Error handling', () => { + it('should handle invalid template syntax gracefully', () => { + const template = '{{ unclosed'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toContain('[Template Error:'); + }); + + it('should handle invalid filter', () => { + // Nunjucks throws on unknown filters + const template = '{{ title | nonexistentfilter }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toContain('[Template Error:'); + }); + }); + + describe('Special characters and escaping', () => { + it('should not auto-escape HTML characters', () => { + const dataWithHtml: NoteTemplateData = { + ...sampleData, + title: 'Bold Title', + }; + const template = '{{ title }}'; + const result = renderNoteTemplate(template, dataWithHtml); + expect(result).toBe('Bold Title'); + }); + + it('should handle markdown special characters', () => { + const dataWithMarkdown: NoteTemplateData = { + ...sampleData, + chapters: [ + { + title: '# Heading with **bold** and _italic_', + annotations: [{ text: '> Quoted text' }], + }, + ], + }; + const template = '{{ chapters[0].title }}\n{{ chapters[0].annotations[0].text }}'; + const result = renderNoteTemplate(template, dataWithMarkdown); + expect(result).toContain('# Heading with **bold** and _italic_'); + expect(result).toContain('> Quoted text'); + }); + + it('should handle unicode characters', () => { + const dataWithUnicode: NoteTemplateData = { + ...sampleData, + title: '红楼梦', + author: '曹雪芹', + chapters: [ + { + title: '第一回', + annotations: [{ text: '满纸荒唐言,一把辛酸泪。' }], + }, + ], + }; + const template = '{{ title }} - {{ author }}: {{ chapters[0].annotations[0].text }}'; + const result = renderNoteTemplate(template, dataWithUnicode); + expect(result).toBe('红楼梦 - 曹雪芹: 满纸荒唐言,一把辛酸泪。'); + }); + + it('should handle emoji', () => { + const dataWithEmoji: NoteTemplateData = { + ...sampleData, + title: '📚 My Book', + chapters: [ + { + title: 'Chapter 😀', + annotations: [{ text: 'Text with emoji 🎉' }], + }, + ], + }; + const template = '{{ title }} - {{ chapters[0].annotations[0].text }}'; + const result = renderNoteTemplate(template, dataWithEmoji); + expect(result).toBe('📚 My Book - Text with emoji 🎉'); + }); + }); + + describe('Whitespace handling', () => { + it('should trim blocks correctly', () => { + const template = `Start +{% if true %} +Content +{% endif %} +End`; + const result = renderNoteTemplate(template, sampleData); + // With trimBlocks and lstripBlocks enabled, whitespace should be managed + expect(result).toContain('Start'); + expect(result).toContain('Content'); + expect(result).toContain('End'); + }); + + it('should preserve intentional whitespace in content', () => { + const template = '{{ title }} {{ author }}'; + const result = renderNoteTemplate(template, sampleData); + expect(result).toBe('The Great Gatsby F. Scott Fitzgerald'); + }); + }); +}); + +describe('validateNoteTemplate', () => { + it('should return valid for correct template', () => { + const template = '{{ title }} by {{ author }}'; + const result = validateNoteTemplate(template); + expect(result.isValid).toBe(true); + expect(result.error).toBeUndefined(); + }); + + it('should return valid for complex template', () => { + const template = `{% for chapter in chapters %} +{{ chapter.title }} +{% for annotation in chapter.annotations %} +{{ annotation.text }} +{% endfor %} +{% endfor %}`; + const result = validateNoteTemplate(template); + expect(result.isValid).toBe(true); + }); + + it('should return invalid for unclosed variable', () => { + const template = '{{ unclosed'; + const result = validateNoteTemplate(template); + expect(result.isValid).toBe(false); + expect(result.error).toBeDefined(); + }); + + it('should return invalid for unclosed block', () => { + const template = '{% if true %}content'; + const result = validateNoteTemplate(template); + expect(result.isValid).toBe(false); + expect(result.error).toBeDefined(); + }); + + it('should return invalid for unclosed for loop', () => { + const template = '{% for item in items %}content'; + const result = validateNoteTemplate(template); + expect(result.isValid).toBe(false); + expect(result.error).toBeDefined(); + }); + + it('should return valid for empty template', () => { + const template = ''; + const result = validateNoteTemplate(template); + expect(result.isValid).toBe(true); + }); + + it('should return valid for plain text without template syntax', () => { + const template = 'Just plain text without any template syntax'; + const result = validateNoteTemplate(template); + expect(result.isValid).toBe(true); + }); +}); diff --git a/apps/readest-app/src/app/reader/components/annotator/ExportMarkdownDialog.tsx b/apps/readest-app/src/app/reader/components/annotator/ExportMarkdownDialog.tsx index fbfd0208..f8bc81e4 100644 --- a/apps/readest-app/src/app/reader/components/annotator/ExportMarkdownDialog.tsx +++ b/apps/readest-app/src/app/reader/components/annotator/ExportMarkdownDialog.tsx @@ -1,13 +1,14 @@ import clsx from 'clsx'; import React, { useState, useMemo, useEffect } from 'react'; import { marked } from 'marked'; -import { BookNote, BooknoteGroup, NoteExportConfig } from '@/types/book'; +import { useEnv } from '@/context/EnvContext'; import { useTranslation } from '@/hooks/useTranslation'; -import Dialog from '@/components/Dialog'; import { useReaderStore } from '@/store/readerStore'; +import { BookNote, BooknoteGroup, NoteExportConfig } from '@/types/book'; import { DEFAULT_NOTE_EXPORT_CONFIG } from '@/services/constants'; import { saveViewSettings } from '@/helpers/settings'; -import { useEnv } from '@/context/EnvContext'; +import { renderNoteTemplate } from '@/utils/note'; +import Dialog from '@/components/Dialog'; interface ExportMarkdownDialogProps { bookKey: string; @@ -20,135 +21,6 @@ interface ExportMarkdownDialogProps { onExport: (markdown: string) => void; } -type TemplateData = { - title: string; - author: string; - exportDate: string; - chapters: { - title: string; - annotations: { - text: string; - note?: string; - timestamp?: number; - }[]; - }[]; -}; - -type TemplateVariable = { [key: string]: number | string | TemplateVariable | TemplateVariable[] }; - -const renderTemplate = (template: string, data: TemplateData): string => { - const applyFilter = ( - value: TemplateVariable, - filter: string, - filterArg?: string, - ): TemplateVariable | string => { - if (filter === 'date') { - if (typeof value === 'number') { - const date = new Date(value); - if (filterArg) { - const format = filterArg; - return format - .replace('%Y', date.getFullYear().toString()) - .replace('%m', String(date.getMonth() + 1).padStart(2, '0')) - .replace('%d', String(date.getDate()).padStart(2, '0')) - .replace('%H', String(date.getHours()).padStart(2, '0')) - .replace('%M', String(date.getMinutes()).padStart(2, '0')) - .replace('%S', String(date.getSeconds()).padStart(2, '0')); - } - return date.toLocaleString(); - } - return value; - } - return value; - }; - - const getValue = (path: string, context: TemplateData) => { - const keys = path.trim().split('.'); - let value = context as TemplateVariable; - for (const key of keys) { - value = value?.[key] as TemplateVariable; - } - return value; - }; - - let result = template; - - // Process {% for %} loops - find first occurrence and recurse - const forMatch = result.match(/\{%\s*for\s+(\w+)\s+in\s+(\w+(?:\.\w+)*)\s*%\}/); - if (forMatch) { - const itemName = forMatch[1]!; - const collectionPath = forMatch[2]!; - - // Find matching {% endfor %} by counting nesting - let depth = 0; - let endPos = -1; - const startPos = forMatch.index! + forMatch[0].length; - - for (let i = startPos; i < result.length; i++) { - const remaining = result.slice(i); - if (remaining.startsWith('{% for ')) { - depth++; - i += 6; // skip past "{% for" - } else if (remaining.startsWith('{% endfor %}')) { - if (depth === 0) { - endPos = i; - break; - } - depth--; - i += 11; // skip past "{% endfor %}" - } - } - - if (endPos !== -1) { - const beforeLoop = result.slice(0, forMatch.index); - const loopContent = result.slice(startPos, endPos); - const afterLoop = result.slice(endPos + 13); // 13 = length of "{% endfor %}" - - const collection = getValue(collectionPath, data); - - if (Array.isArray(collection)) { - const renderedItems = collection - .map((item) => { - const loopData = { ...data, [itemName]: item }; - return renderTemplate(loopContent, loopData); - }) - .join(''); - - result = beforeLoop + renderedItems + afterLoop; - return renderTemplate(result, data); - } else { - // Collection not found or not an array, remove the loop - result = beforeLoop + afterLoop; - return renderTemplate(result, data); - } - } - } - - // Process {% if condition %}...{% endif %} - result = result.replace( - /\{%\s*if\s+([^%]+?)\s*%\}([\s\S]*?)\{%\s*endif\s*%\}/g, - (_match, condition, content) => { - const value = getValue(condition, data); - return value ? renderTemplate(content, data) : ''; - }, - ); - - // Replace {{ variable }}, {{ variable | filter }}, and {{ variable | filter('arg') }} - result = result.replace( - /\{\{\s*([^}|]+?)(?:\s*\|\s*(\w+)(?:\s*\((['"]?)([^)'"]*)\3\))?)?\s*\}\}/g, - (_match, path, filter, _quote, filterArg) => { - const value = getValue(path, data); - if (value === undefined || value === null) return ''; - if (filter) { - return applyFilter(value, filter, filterArg) as string; - } - return String(value); - }, - ); - - return result; -}; - const ExportMarkdownDialog: React.FC = ({ bookKey, isOpen, @@ -167,7 +39,7 @@ const ExportMarkdownDialog: React.FC = ({ const defaultTemplate = `## {{ title }} **${_('Author')}**: {{ author }} -**${_('Exported from Readest')}**: {{ exportDate }} +**${_('Exported from Readest')}**: {{ exportDate | date('%Y-%m-%d') }} --- @@ -176,7 +48,19 @@ const ExportMarkdownDialog: React.FC = ({ {% for chapter in chapters %} #### {{ chapter.title }} {% for annotation in chapter.annotations %} -> {{ annotation.text }} +{% if annotation.color == 'yellow' %} +- {{ annotation.text }} +{% elif annotation.color == 'red' %} +- ❗ {{ annotation.text }} +{% elif annotation.color == 'green' %} +- ✅ {{ annotation.text }} +{% elif annotation.color == 'blue' %} +- 💡 {{ annotation.text }} +{% elif annotation.color == 'violet' %} +- ✨ {{ annotation.text }} +{% else %} +- {{ annotation.text }} +{% endif %} {% if annotation.note %} **${_('Note:')}** {{ annotation.note }} {% endif %} @@ -219,7 +103,7 @@ const ExportMarkdownDialog: React.FC = ({ const templateData = { title: bookTitle, author: bookAuthor, - exportDate: new Date().toISOString().slice(0, 10), + exportDate: new Date().getTime(), chapters: sortedGroups.map((group) => ({ title: group.label || _('Untitled'), annotations: group.booknotes.map((note) => ({ @@ -232,7 +116,7 @@ const ExportMarkdownDialog: React.FC = ({ })), }; - return renderTemplate(exportConfig.customTemplate, templateData); + return renderNoteTemplate(exportConfig.customTemplate, templateData); } // Default formatting (non-template mode) @@ -456,7 +340,17 @@ const ExportMarkdownDialog: React.FC = ({ {exportConfig.useCustomTemplate && ( <>
- +
+ + +