From 24b68ac0461ad9bdf19ae9e5f3a03d8fdb619191 Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Wed, 26 Feb 2025 00:16:42 +0100 Subject: [PATCH] feat: add user profile page and option to delete account in the cloud (#452) --- apps/readest-app/.env.local.example | 2 + .../public/locales/ar/translation.json | 38 ++- .../public/locales/de/translation.json | 36 ++- .../public/locales/el/translation.json | 36 ++- .../public/locales/es/translation.json | 36 ++- .../public/locales/fr/translation.json | 36 ++- .../public/locales/hi/translation.json | 36 ++- .../public/locales/id/translation.json | 36 ++- .../public/locales/it/translation.json | 36 ++- .../public/locales/ja/translation.json | 36 ++- .../public/locales/ko/translation.json | 36 ++- .../public/locales/pl/translation.json | 36 ++- .../public/locales/pt/translation.json | 36 ++- .../public/locales/ru/translation.json | 36 ++- .../public/locales/tr/translation.json | 36 ++- .../public/locales/uk/translation.json | 36 ++- .../public/locales/vi/translation.json | 36 ++- .../public/locales/zh-CN/translation.json | 36 ++- .../public/locales/zh-TW/translation.json | 36 ++- apps/readest-app/src/app/auth/page.tsx | 24 +- .../app/library/components/SettingsMenu.tsx | 15 +- apps/readest-app/src/app/user/page.tsx | 289 ++++++++++++++++++ apps/readest-app/src/components/Quota.tsx | 49 ++- apps/readest-app/src/libs/storage.ts | 24 +- apps/readest-app/src/libs/user.ts | 21 ++ .../src/pages/api/deepl/translate.ts | 2 +- apps/readest-app/src/pages/api/user/delete.ts | 30 ++ apps/readest-app/src/utils/access.ts | 2 +- apps/readest-app/src/utils/fetch.ts | 22 ++ apps/readest-app/src/utils/nav.ts | 4 + apps/readest-app/src/utils/supabase.ts | 11 + 31 files changed, 1067 insertions(+), 78 deletions(-) create mode 100644 apps/readest-app/src/app/user/page.tsx create mode 100644 apps/readest-app/src/libs/user.ts create mode 100644 apps/readest-app/src/pages/api/user/delete.ts create mode 100644 apps/readest-app/src/utils/fetch.ts diff --git a/apps/readest-app/.env.local.example b/apps/readest-app/.env.local.example index 9f4102f2..ff251c2f 100644 --- a/apps/readest-app/.env.local.example +++ b/apps/readest-app/.env.local.example @@ -4,6 +4,8 @@ NEXT_PUBLIC_POSTHOG_HOST=YOUR_POSTHOG_HOST NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY +SUPABASE_ADMIN_KEY=YOUR_SUPABASE_ADMIN_KEY + DEEPL_PRO_API_KEYS=YOUR_DEEPL_PRO_API_KEYS DEEPL_FREE_API_KEYS=YOUR_DEEPL_FREE_API_KEYS diff --git a/apps/readest-app/public/locales/ar/translation.json b/apps/readest-app/public/locales/ar/translation.json index f8f6d74d..782f4388 100644 --- a/apps/readest-app/public/locales/ar/translation.json +++ b/apps/readest-app/public/locales/ar/translation.json @@ -198,5 +198,41 @@ "Verify token": "التحقق من الرمز", "Sign in with Google": "تسجيل الدخول عبر Google", "Sign in with Apple": "تسجيل الدخول عبر Apple", - "Sign in with GitHub": "تسجيل الدخول عبر GitHub" + "Sign in with GitHub": "تسجيل الدخول عبر GitHub", + "Account": "الحساب", + "Cloud Storage": "التخزين السحابي", + "Failed to delete user. Please try again later.": "فشل حذف المستخدم. يرجى المحاولة مرة أخرى لاحقًا.", + "Unlimited Offline/Online Reading": "قراءة غير محدودة بدون اتصال/متصلة بالإنترنت", + "Unlimited Cloud Sync Devices": "أجهزة مزامنة سحابية غير محدودة", + "Essential Text-to-Speech Voices": "أصوات أساسية لتحويل النص إلى كلام", + "DeepL Free Access": "وصول مجاني إلى DeepL", + "Community Support": "دعم المجتمع", + "500 MB Cloud Sync Space": "مساحة مزامنة سحابية 500 ميجابايت", + "Includes All Free Tier Benefits": "يتضمن جميع مزايا الفئة المجانية", + "AI Summaries": "ملخصات الذكاء الاصطناعي", + "AI Translations": "ترجمات الذكاء الاصطناعي", + "Priority Support": "دعم ذو أولوية", + "DeepL Pro Access": "وصول إلى DeepL Pro", + "Expanded Text-to-Speech Voices": "أصوات موسعة لتحويل النص إلى كلام", + "2000 MB Cloud Sync Space": "مساحة مزامنة سحابية 2000 ميجابايت", + "Includes All Plus Tier Benefits": "يتضمن جميع مزايا فئة Plus", + "Unlimited AI Summaries": "ملخصات ذكاء اصطناعي غير محدودة", + "Unlimited AI Translations": "ترجمات ذكاء اصطناعي غير محدودة", + "Unlimited DeepL Pro Access": "وصول غير محدود إلى DeepL Pro", + "Advanced AI Tools": "أدوات ذكاء اصطناعي متقدمة", + "Early Feature Access": "وصول مبكر للميزات", + "10 GB Cloud Sync Space": "مساحة مزامنة سحابية 10 جيجابايت", + "Unlimited Offline Reading": "قراءة غير محدودة بدون اتصال", + "Unlimited Customization": "تخصيص غير محدود", + "Loading profile...": "جارٍ تحميل الملف الشخصي...", + "Plan": "الخطة", + "Plan Details": "تفاصيل الخطة", + "Features": "الميزات", + "Delete Account": "حذف الحساب", + "Delete Your Account?": "حذف حسابك؟", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "لا يمكن التراجع عن هذا الإجراء. سيتم حذف جميع بياناتك في السحابة بشكل دائم.", + "Delete Permanently": "حذف نهائي", + "Free Tier": "الفئة المجانية", + "Plus Tier": "فئة Plus", + "Pro Tier": "فئة Pro" } diff --git a/apps/readest-app/public/locales/de/translation.json b/apps/readest-app/public/locales/de/translation.json index 69c17b5f..d2f708cb 100644 --- a/apps/readest-app/public/locales/de/translation.json +++ b/apps/readest-app/public/locales/de/translation.json @@ -198,5 +198,39 @@ "Verify token": "Token überprüfen", "Sign in with Google": "Mit Google anmelden", "Sign in with Apple": "Mit Apple anmelden", - "Sign in with GitHub": "Mit GitHub anmelden" + "Sign in with GitHub": "Mit GitHub anmelden", + "Account": "Konto", + "Cloud Storage": "Cloud-Speicher", + "Failed to delete user. Please try again later.": "Benutzer konnte nicht gelöscht werden. Bitte versuchen Sie es später erneut.", + "Unlimited Offline/Online Reading": "Unbegrenztes Offline/Online Lesen", + "Unlimited Cloud Sync Devices": "Unbegrenzte Cloud-Synchronisierungsgeräte", + "Essential Text-to-Speech Voices": "Grundlegende Text-zu-Sprache-Stimmen", + "DeepL Free Access": "Kostenloser DeepL-Zugang", + "Community Support": "Community-Support", + "500 MB Cloud Sync Space": "500 MB Cloud-Synchronisierungsspeicher", + "Includes All Free Tier Benefits": "Beinhaltet alle Vorteile der kostenlosen Stufe", + "AI Summaries": "KI-Zusammenfassungen", + "AI Translations": "KI-Übersetzungen", + "Priority Support": "Bevorzugter Support", + "DeepL Pro Access": "DeepL Pro-Zugang", + "Expanded Text-to-Speech Voices": "Erweiterte Text-zu-Sprache-Stimmen", + "2000 MB Cloud Sync Space": "2000 MB Cloud-Synchronisierungsspeicher", + "Includes All Plus Tier Benefits": "Beinhaltet alle Vorteile der Plus-Stufe", + "Unlimited AI Summaries": "Unbegrenzte KI-Zusammenfassungen", + "Unlimited AI Translations": "Unbegrenzte KI-Übersetzungen", + "Unlimited DeepL Pro Access": "Unbegrenzter DeepL Pro-Zugang", + "Advanced AI Tools": "Fortgeschrittene KI-Tools", + "Early Feature Access": "Früher Zugang zu neuen Funktionen", + "10 GB Cloud Sync Space": "10 GB Cloud-Synchronisierungsspeicher", + "Loading profile...": "Profil wird geladen...", + "Plan": "Tarif", + "Plan Details": "Tarifdetails", + "Features": "Funktionen", + "Delete Account": "Konto löschen", + "Delete Your Account?": "Ihr Konto löschen?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "Diese Aktion kann nicht rückgängig gemacht werden. Alle Ihre Daten in der Cloud werden dauerhaft gelöscht.", + "Delete Permanently": "Dauerhaft löschen", + "Free Tier": "Kostenlose Stufe", + "Plus Tier": "Plus-Stufe", + "Pro Tier": "Pro-Stufe" } diff --git a/apps/readest-app/public/locales/el/translation.json b/apps/readest-app/public/locales/el/translation.json index 51b4225d..80066ea9 100644 --- a/apps/readest-app/public/locales/el/translation.json +++ b/apps/readest-app/public/locales/el/translation.json @@ -198,5 +198,39 @@ "Verify token": "Επαλήθευση κωδικού", "Sign in with Google": "Σύνδεση με Google", "Sign in with Apple": "Σύνδεση με Apple", - "Sign in with GitHub": "Σύνδεση με GitHub" + "Sign in with GitHub": "Σύνδεση με GitHub", + "Account": "Λογαριασμός", + "Cloud Storage": "Αποθηκευτικός χώρος Cloud", + "Failed to delete user. Please try again later.": "Αποτυχία διαγραφής χρήστη. Παρακαλώ δοκιμάστε ξανά αργότερα.", + "Unlimited Offline/Online Reading": "Απεριόριστη ανάγνωση εκτός/εντός σύνδεσης", + "Unlimited Cloud Sync Devices": "Απεριόριστες συσκευές συγχρονισμού Cloud", + "Essential Text-to-Speech Voices": "Βασικές φωνές μετατροπής κειμένου σε ομιλία", + "DeepL Free Access": "Δωρεάν πρόσβαση DeepL", + "Community Support": "Υποστήριξη κοινότητας", + "500 MB Cloud Sync Space": "500 MB χώρος συγχρονισμού Cloud", + "Includes All Free Tier Benefits": "Περιλαμβάνει όλα τα οφέλη της δωρεάν βαθμίδας", + "AI Summaries": "Περιλήψεις AI", + "AI Translations": "Μεταφράσεις AI", + "Priority Support": "Υποστήριξη προτεραιότητας", + "DeepL Pro Access": "Πρόσβαση DeepL Pro", + "Expanded Text-to-Speech Voices": "Διευρυμένες φωνές μετατροπής κειμένου σε ομιλία", + "2000 MB Cloud Sync Space": "2000 MB χώρος συγχρονισμού Cloud", + "Includes All Plus Tier Benefits": "Περιλαμβάνει όλα τα οφέλη της βαθμίδας Plus", + "Unlimited AI Summaries": "Απεριόριστες περιλήψεις AI", + "Unlimited AI Translations": "Απεριόριστες μεταφράσεις AI", + "Unlimited DeepL Pro Access": "Απεριόριστη πρόσβαση DeepL Pro", + "Advanced AI Tools": "Προηγμένα εργαλεία AI", + "Early Feature Access": "Πρώιμη πρόσβαση σε λειτουργίες", + "10 GB Cloud Sync Space": "10 GB χώρος συγχρονισμού Cloud", + "Loading profile...": "Φόρτωση προφίλ...", + "Plan": "Πρόγραμμα", + "Plan Details": "Λεπτομέρειες προγράμματος", + "Features": "Χαρακτηριστικά", + "Delete Account": "Διαγραφή λογαριασμού", + "Delete Your Account?": "Διαγραφή του λογαριασμού σας;", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "Αυτή η ενέργεια δεν μπορεί να αναιρεθεί. Όλα τα δεδομένα σας στο cloud θα διαγραφούν μόνιμα.", + "Delete Permanently": "Μόνιμη διαγραφή", + "Free Tier": "Δωρεάν βαθμίδα", + "Plus Tier": "Βαθμίδα Plus", + "Pro Tier": "Βαθμίδα Pro" } diff --git a/apps/readest-app/public/locales/es/translation.json b/apps/readest-app/public/locales/es/translation.json index a7e3818f..ffe1d67e 100644 --- a/apps/readest-app/public/locales/es/translation.json +++ b/apps/readest-app/public/locales/es/translation.json @@ -198,5 +198,39 @@ "Verify token": "Verificar código", "Sign in with Google": "Iniciar sesión con Google", "Sign in with Apple": "Iniciar sesión con Apple", - "Sign in with GitHub": "Iniciar sesión con GitHub" + "Sign in with GitHub": "Iniciar sesión con GitHub", + "Account": "Cuenta", + "Cloud Storage": "Almacenamiento en la nube", + "Failed to delete user. Please try again later.": "Error al eliminar usuario. Por favor, inténtelo de nuevo más tarde.", + "Unlimited Offline/Online Reading": "Lectura sin límites en línea/sin conexión", + "Unlimited Cloud Sync Devices": "Sincronización ilimitada de dispositivos en la nube", + "Essential Text-to-Speech Voices": "Voces esenciales de texto a voz", + "DeepL Free Access": "Acceso gratuito a DeepL", + "Community Support": "Soporte comunitario", + "500 MB Cloud Sync Space": "500 MB de espacio de sincronización en la nube", + "Includes All Free Tier Benefits": "Incluye todos los beneficios del nivel gratuito", + "AI Summaries": "Resúmenes con IA", + "AI Translations": "Traducciones con IA", + "Priority Support": "Soporte prioritario", + "DeepL Pro Access": "Acceso a DeepL Pro", + "Expanded Text-to-Speech Voices": "Voces ampliadas de texto a voz", + "2000 MB Cloud Sync Space": "2000 MB de espacio de sincronización en la nube", + "Includes All Plus Tier Benefits": "Incluye todos los beneficios del nivel Plus", + "Unlimited AI Summaries": "Resúmenes ilimitados con IA", + "Unlimited AI Translations": "Traducciones ilimitadas con IA", + "Unlimited DeepL Pro Access": "Acceso ilimitado a DeepL Pro", + "Advanced AI Tools": "Herramientas avanzadas de IA", + "Early Feature Access": "Acceso anticipado a funciones", + "10 GB Cloud Sync Space": "10 GB de espacio de sincronización en la nube", + "Loading profile...": "Cargando perfil...", + "Plan": "Plan", + "Plan Details": "Detalles del plan", + "Features": "Características", + "Delete Account": "Eliminar cuenta", + "Delete Your Account?": "¿Eliminar tu cuenta?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "Esta acción no se puede deshacer. Todos tus datos en la nube se eliminarán permanentemente.", + "Delete Permanently": "Eliminar permanentemente", + "Free Tier": "Nivel gratuito", + "Plus Tier": "Nivel Plus", + "Pro Tier": "Nivel Pro" } diff --git a/apps/readest-app/public/locales/fr/translation.json b/apps/readest-app/public/locales/fr/translation.json index 0f9ca2be..d59b54bc 100644 --- a/apps/readest-app/public/locales/fr/translation.json +++ b/apps/readest-app/public/locales/fr/translation.json @@ -198,5 +198,39 @@ "Verify token": "Vérifier le code", "Sign in with Google": "Se connecter avec Google", "Sign in with Apple": "Se connecter avec Apple", - "Sign in with GitHub": "Se connecter avec GitHub" + "Sign in with GitHub": "Se connecter avec GitHub", + "Account": "Compte", + "Cloud Storage": "Stockage cloud", + "Failed to delete user. Please try again later.": "Échec de la suppression de l'utilisateur. Veuillez réessayer plus tard.", + "Unlimited Offline/Online Reading": "Lecture illimitée hors ligne/en ligne", + "Unlimited Cloud Sync Devices": "Synchronisation cloud sur appareils illimitée", + "Essential Text-to-Speech Voices": "Voix de synthèse vocale essentielles", + "DeepL Free Access": "Accès gratuit à DeepL", + "Community Support": "Support communautaire", + "500 MB Cloud Sync Space": "500 Mo d'espace de synchronisation cloud", + "Includes All Free Tier Benefits": "Inclut tous les avantages du niveau gratuit", + "AI Summaries": "Résumés par IA", + "AI Translations": "Traductions par IA", + "Priority Support": "Support prioritaire", + "DeepL Pro Access": "Accès à DeepL Pro", + "Expanded Text-to-Speech Voices": "Voix de synthèse vocale étendues", + "2000 MB Cloud Sync Space": "2000 Mo d'espace de synchronisation cloud", + "Includes All Plus Tier Benefits": "Inclut tous les avantages du niveau Plus", + "Unlimited AI Summaries": "Résumés par IA illimités", + "Unlimited AI Translations": "Traductions par IA illimitées", + "Unlimited DeepL Pro Access": "Accès illimité à DeepL Pro", + "Advanced AI Tools": "Outils IA avancés", + "Early Feature Access": "Accès anticipé aux fonctionnalités", + "10 GB Cloud Sync Space": "10 Go d'espace de synchronisation cloud", + "Loading profile...": "Chargement du profil...", + "Plan": "Forfait", + "Plan Details": "Détails du forfait", + "Features": "Fonctionnalités", + "Delete Account": "Supprimer le compte", + "Delete Your Account?": "Supprimer votre compte ?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "Cette action est irréversible. Toutes vos données dans le cloud seront définitivement supprimées.", + "Delete Permanently": "Supprimer définitivement", + "Free Tier": "Niveau gratuit", + "Plus Tier": "Niveau Plus", + "Pro Tier": "Niveau Pro" } diff --git a/apps/readest-app/public/locales/hi/translation.json b/apps/readest-app/public/locales/hi/translation.json index 52d06da1..4cf5795b 100644 --- a/apps/readest-app/public/locales/hi/translation.json +++ b/apps/readest-app/public/locales/hi/translation.json @@ -198,5 +198,39 @@ "Verify token": "टोकन सत्यापित करें", "Sign in with Google": "Google के साथ साइन इन करें", "Sign in with Apple": "Apple के साथ साइन इन करें", - "Sign in with GitHub": "GitHub के साथ साइन इन करें" + "Sign in with GitHub": "GitHub के साथ साइन इन करें", + "Account": "खाता", + "Cloud Storage": "क्लाउड स्टोरेज", + "Failed to delete user. Please try again later.": "उपयोगकर्ता को हटाने में विफल। कृपया बाद में पुनः प्रयास करें।", + "Unlimited Offline/Online Reading": "असीमित ऑफलाइन/ऑनलाइन पढ़ना", + "Unlimited Cloud Sync Devices": "असीमित क्लाउड सिंक उपकरण", + "Essential Text-to-Speech Voices": "आवश्यक टेक्स्ट-टू-स्पीच आवाज़ें", + "DeepL Free Access": "DeepL मुफ्त पहुंच", + "Community Support": "सामुदायिक सहायता", + "500 MB Cloud Sync Space": "500 MB क्लाउड सिंक स्पेस", + "Includes All Free Tier Benefits": "सभी फ्री टियर लाभ शामिल हैं", + "AI Summaries": "AI सारांश", + "AI Translations": "AI अनुवाद", + "Priority Support": "प्राथमिकता सहायता", + "DeepL Pro Access": "DeepL प्रो पहुंच", + "Expanded Text-to-Speech Voices": "विस्तारित टेक्स्ट-टू-स्पीच आवाज़ें", + "2000 MB Cloud Sync Space": "2000 MB क्लाउड सिंक स्पेस", + "Includes All Plus Tier Benefits": "सभी प्लस टियर लाभ शामिल हैं", + "Unlimited AI Summaries": "असीमित AI सारांश", + "Unlimited AI Translations": "असीमित AI अनुवाद", + "Unlimited DeepL Pro Access": "असीमित DeepL प्रो पहुंच", + "Advanced AI Tools": "उन्नत AI टूल्स", + "Early Feature Access": "प्रारंभिक फीचर पहुंच", + "10 GB Cloud Sync Space": "10 GB क्लाउड सिंक स्पेस", + "Loading profile...": "प्रोफ़ाइल लोड हो रहा है...", + "Plan": "योजना", + "Plan Details": "योजना विवरण", + "Features": "विशेषताएं", + "Delete Account": "खाता हटाएं", + "Delete Your Account?": "अपना खाता हटाएं?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "यह क्रिया पूर्ववत नहीं की जा सकती। क्लाउड में आपका सभी डेटा स्थायी रूप से हटा दिया जाएगा।", + "Delete Permanently": "स्थायी रूप से हटाएं", + "Free Tier": "फ्री टियर", + "Plus Tier": "प्लस टियर", + "Pro Tier": "प्रो टियर" } diff --git a/apps/readest-app/public/locales/id/translation.json b/apps/readest-app/public/locales/id/translation.json index 9b1e7168..3f26486d 100644 --- a/apps/readest-app/public/locales/id/translation.json +++ b/apps/readest-app/public/locales/id/translation.json @@ -198,5 +198,39 @@ "Verify token": "Verifikasi token", "Sign in with Google": "Masuk dengan Google", "Sign in with Apple": "Masuk dengan Apple", - "Sign in with GitHub": "Masuk dengan GitHub" + "Sign in with GitHub": "Masuk dengan GitHub", + "Account": "Akun", + "Cloud Storage": "Penyimpanan Cloud", + "Failed to delete user. Please try again later.": "Gagal menghapus pengguna. Silakan coba lagi nanti.", + "Unlimited Offline/Online Reading": "Membaca Offline/Online Tanpa Batas", + "Unlimited Cloud Sync Devices": "Perangkat Sinkronisasi Cloud Tanpa Batas", + "Essential Text-to-Speech Voices": "Suara Text-to-Speech Esensial", + "DeepL Free Access": "Akses DeepL Gratis", + "Community Support": "Dukungan Komunitas", + "500 MB Cloud Sync Space": "Ruang Sinkronisasi Cloud 500 MB", + "Includes All Free Tier Benefits": "Termasuk Semua Manfaat Tingkat Gratis", + "AI Summaries": "Ringkasan AI", + "AI Translations": "Terjemahan AI", + "Priority Support": "Dukungan Prioritas", + "DeepL Pro Access": "Akses DeepL Pro", + "Expanded Text-to-Speech Voices": "Suara Text-to-Speech yang Diperluas", + "2000 MB Cloud Sync Space": "Ruang Sinkronisasi Cloud 2000 MB", + "Includes All Plus Tier Benefits": "Termasuk Semua Manfaat Tingkat Plus", + "Unlimited AI Summaries": "Ringkasan AI Tanpa Batas", + "Unlimited AI Translations": "Terjemahan AI Tanpa Batas", + "Unlimited DeepL Pro Access": "Akses DeepL Pro Tanpa Batas", + "Advanced AI Tools": "Alat AI Lanjutan", + "Early Feature Access": "Akses Fitur Awal", + "10 GB Cloud Sync Space": "Ruang Sinkronisasi Cloud 10 GB", + "Loading profile...": "Memuat profil...", + "Plan": "Paket", + "Plan Details": "Detail Paket", + "Features": "Fitur", + "Delete Account": "Hapus Akun", + "Delete Your Account?": "Hapus Akun Anda?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "Tindakan ini tidak dapat dibatalkan. Semua data Anda di cloud akan dihapus secara permanen.", + "Delete Permanently": "Hapus Secara Permanen", + "Free Tier": "Tingkat Gratis", + "Plus Tier": "Tingkat Plus", + "Pro Tier": "Tingkat Pro" } diff --git a/apps/readest-app/public/locales/it/translation.json b/apps/readest-app/public/locales/it/translation.json index 3b78cd2b..95607928 100644 --- a/apps/readest-app/public/locales/it/translation.json +++ b/apps/readest-app/public/locales/it/translation.json @@ -198,5 +198,39 @@ "Verify token": "Verifica token", "Sign in with Google": "Accedi con Google", "Sign in with Apple": "Accedi con Apple", - "Sign in with GitHub": "Accedi con GitHub" + "Sign in with GitHub": "Accedi con GitHub", + "Account": "Account", + "Cloud Storage": "Archiviazione Cloud", + "Failed to delete user. Please try again later.": "Impossibile eliminare l'utente. Riprova più tardi.", + "Unlimited Offline/Online Reading": "Lettura offline/online illimitata", + "Unlimited Cloud Sync Devices": "Sincronizzazione cloud su dispositivi illimitati", + "Essential Text-to-Speech Voices": "Voci essenziali di sintesi vocale", + "DeepL Free Access": "Accesso gratuito a DeepL", + "Community Support": "Supporto della community", + "500 MB Cloud Sync Space": "500 MB di spazio di sincronizzazione cloud", + "Includes All Free Tier Benefits": "Include tutti i vantaggi del piano gratuito", + "AI Summaries": "Riassunti AI", + "AI Translations": "Traduzioni AI", + "Priority Support": "Supporto prioritario", + "DeepL Pro Access": "Accesso a DeepL Pro", + "Expanded Text-to-Speech Voices": "Voci di sintesi vocale ampliate", + "2000 MB Cloud Sync Space": "2000 MB di spazio di sincronizzazione cloud", + "Includes All Plus Tier Benefits": "Include tutti i vantaggi del piano Plus", + "Unlimited AI Summaries": "Riassunti AI illimitati", + "Unlimited AI Translations": "Traduzioni AI illimitate", + "Unlimited DeepL Pro Access": "Accesso illimitato a DeepL Pro", + "Advanced AI Tools": "Strumenti AI avanzati", + "Early Feature Access": "Accesso anticipato alle funzionalità", + "10 GB Cloud Sync Space": "10 GB di spazio di sincronizzazione cloud", + "Loading profile...": "Caricamento profilo...", + "Plan": "Piano", + "Plan Details": "Dettagli del piano", + "Features": "Funzionalità", + "Delete Account": "Elimina account", + "Delete Your Account?": "Eliminare il tuo account?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "Questa azione non può essere annullata. Tutti i tuoi dati nel cloud verranno eliminati definitivamente.", + "Delete Permanently": "Elimina definitivamente", + "Free Tier": "Piano gratuito", + "Plus Tier": "Piano Plus", + "Pro Tier": "Piano Pro" } diff --git a/apps/readest-app/public/locales/ja/translation.json b/apps/readest-app/public/locales/ja/translation.json index 2c8e9a95..1888b4fc 100644 --- a/apps/readest-app/public/locales/ja/translation.json +++ b/apps/readest-app/public/locales/ja/translation.json @@ -198,5 +198,39 @@ "Verify token": "トークンを確認", "Sign in with Google": "Googleでサインイン", "Sign in with Apple": "Appleでサインイン", - "Sign in with GitHub": "GitHubでサインイン" + "Sign in with GitHub": "GitHubでサインイン", + "Account": "アカウント", + "Cloud Storage": "クラウドストレージ", + "Failed to delete user. Please try again later.": "ユーザーの削除に失敗しました。後ほど再試行してください。", + "Unlimited Offline/Online Reading": "無制限のオフライン/オンライン読書", + "Unlimited Cloud Sync Devices": "無制限のクラウド同期デバイス", + "Essential Text-to-Speech Voices": "基本的な音声合成ボイス", + "DeepL Free Access": "DeepL無料アクセス", + "Community Support": "コミュニティサポート", + "500 MB Cloud Sync Space": "500 MBのクラウド同期スペース", + "Includes All Free Tier Benefits": "無料プランの全特典を含む", + "AI Summaries": "AI要約", + "AI Translations": "AI翻訳", + "Priority Support": "優先サポート", + "DeepL Pro Access": "DeepL Proアクセス", + "Expanded Text-to-Speech Voices": "拡張された音声合成ボイス", + "2000 MB Cloud Sync Space": "2000 MBのクラウド同期スペース", + "Includes All Plus Tier Benefits": "Plusプランの全特典を含む", + "Unlimited AI Summaries": "無制限のAI要約", + "Unlimited AI Translations": "無制限のAI翻訳", + "Unlimited DeepL Pro Access": "無制限のDeepL Proアクセス", + "Advanced AI Tools": "高度なAIツール", + "Early Feature Access": "新機能への早期アクセス", + "10 GB Cloud Sync Space": "10 GBのクラウド同期スペース", + "Loading profile...": "プロフィール読み込み中...", + "Plan": "プラン", + "Plan Details": "プラン詳細", + "Features": "機能", + "Delete Account": "アカウント削除", + "Delete Your Account?": "アカウントを削除しますか?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "この操作は元に戻せません。クラウド上のすべてのデータが完全に削除されます。", + "Delete Permanently": "完全に削除", + "Free Tier": "無料プラン", + "Plus Tier": "Plusプラン", + "Pro Tier": "Proプラン" } diff --git a/apps/readest-app/public/locales/ko/translation.json b/apps/readest-app/public/locales/ko/translation.json index 3d489821..979189d7 100644 --- a/apps/readest-app/public/locales/ko/translation.json +++ b/apps/readest-app/public/locales/ko/translation.json @@ -198,5 +198,39 @@ "Verify token": "토큰 확인", "Sign in with Google": "Google로 로그인", "Sign in with Apple": "Apple로 로그인", - "Sign in with GitHub": "GitHub로 로그인" + "Sign in with GitHub": "GitHub로 로그인", + "Account": "계정", + "Cloud Storage": "클라우드 스토리지", + "Failed to delete user. Please try again later.": "사용자 삭제에 실패했습니다. 나중에 다시 시도해 주세요.", + "Unlimited Offline/Online Reading": "무제한 오프라인/온라인 읽기", + "Unlimited Cloud Sync Devices": "무제한 클라우드 동기화 기기", + "Essential Text-to-Speech Voices": "필수 텍스트 음성 변환 목소리", + "DeepL Free Access": "DeepL 무료 접근", + "Community Support": "커뮤니티 지원", + "500 MB Cloud Sync Space": "500 MB 클라우드 동기화 공간", + "Includes All Free Tier Benefits": "무료 등급의 모든 혜택 포함", + "AI Summaries": "AI 요약", + "AI Translations": "AI 번역", + "Priority Support": "우선 지원", + "DeepL Pro Access": "DeepL 프로 접근", + "Expanded Text-to-Speech Voices": "확장된 텍스트 음성 변환 목소리", + "2000 MB Cloud Sync Space": "2000 MB 클라우드 동기화 공간", + "Includes All Plus Tier Benefits": "플러스 등급의 모든 혜택 포함", + "Unlimited AI Summaries": "무제한 AI 요약", + "Unlimited AI Translations": "무제한 AI 번역", + "Unlimited DeepL Pro Access": "무제한 DeepL 프로 접근", + "Advanced AI Tools": "고급 AI 도구", + "Early Feature Access": "신기능 조기 접근", + "10 GB Cloud Sync Space": "10 GB 클라우드 동기화 공간", + "Loading profile...": "프로필 로딩 중...", + "Plan": "플랜", + "Plan Details": "플랜 세부사항", + "Features": "기능", + "Delete Account": "계정 삭제", + "Delete Your Account?": "계정을 삭제하시겠습니까?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "이 작업은 취소할 수 없습니다. 클라우드에 있는 모든 데이터가 영구적으로 삭제됩니다.", + "Delete Permanently": "영구 삭제", + "Free Tier": "무료 등급", + "Plus Tier": "플러스 등급", + "Pro Tier": "프로 등급" } diff --git a/apps/readest-app/public/locales/pl/translation.json b/apps/readest-app/public/locales/pl/translation.json index 4e45481d..8d3990a4 100644 --- a/apps/readest-app/public/locales/pl/translation.json +++ b/apps/readest-app/public/locales/pl/translation.json @@ -198,5 +198,39 @@ "Verify token": "Weryfikacja tokena", "Sign in with Google": "Zaloguj się za pomocą Google", "Sign in with Apple": "Zaloguj się za pomocą Apple", - "Sign in with GitHub": "Zaloguj się za pomocą GitHub" + "Sign in with GitHub": "Zaloguj się za pomocą GitHub", + "Account": "Konto", + "Cloud Storage": "Przestrzeń w chmurze", + "Failed to delete user. Please try again later.": "Nie udało się usunąć użytkownika. Spróbuj ponownie później.", + "Unlimited Offline/Online Reading": "Nieograniczone czytanie offline/online", + "Unlimited Cloud Sync Devices": "Nieograniczona liczba urządzeń synchronizowanych w chmurze", + "Essential Text-to-Speech Voices": "Podstawowe głosy zamiany tekstu na mowę", + "DeepL Free Access": "Darmowy dostęp do DeepL", + "Community Support": "Wsparcie społeczności", + "500 MB Cloud Sync Space": "500 MB przestrzeni synchronizacji w chmurze", + "Includes All Free Tier Benefits": "Zawiera wszystkie korzyści darmowego planu", + "AI Summaries": "Podsumowania AI", + "AI Translations": "Tłumaczenia AI", + "Priority Support": "Priorytetowe wsparcie", + "DeepL Pro Access": "Dostęp do DeepL Pro", + "Expanded Text-to-Speech Voices": "Rozszerzone głosy zamiany tekstu na mowę", + "2000 MB Cloud Sync Space": "2000 MB przestrzeni synchronizacji w chmurze", + "Includes All Plus Tier Benefits": "Zawiera wszystkie korzyści planu Plus", + "Unlimited AI Summaries": "Nieograniczone podsumowania AI", + "Unlimited AI Translations": "Nieograniczone tłumaczenia AI", + "Unlimited DeepL Pro Access": "Nieograniczony dostęp do DeepL Pro", + "Advanced AI Tools": "Zaawansowane narzędzia AI", + "Early Feature Access": "Wczesny dostęp do nowych funkcji", + "10 GB Cloud Sync Space": "10 GB przestrzeni synchronizacji w chmurze", + "Loading profile...": "Ładowanie profilu...", + "Plan": "Plan", + "Plan Details": "Szczegóły planu", + "Features": "Funkcje", + "Delete Account": "Usuń konto", + "Delete Your Account?": "Usunąć Twoje konto?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "Tej operacji nie można cofnąć. Wszystkie Twoje dane w chmurze zostaną trwale usunięte.", + "Delete Permanently": "Usuń trwale", + "Free Tier": "Plan darmowy", + "Plus Tier": "Plan Plus", + "Pro Tier": "Plan Pro" } diff --git a/apps/readest-app/public/locales/pt/translation.json b/apps/readest-app/public/locales/pt/translation.json index 3dbb9e72..04e907d8 100644 --- a/apps/readest-app/public/locales/pt/translation.json +++ b/apps/readest-app/public/locales/pt/translation.json @@ -198,5 +198,39 @@ "Verify token": "Verificar token", "Sign in with Google": "Entrar com o Google", "Sign in with Apple": "Entrar com o Apple", - "Sign in with GitHub": "Entrar com o GitHub" + "Sign in with GitHub": "Entrar com o GitHub", + "Account": "Conta", + "Cloud Storage": "Armazenamento na nuvem", + "Failed to delete user. Please try again later.": "Falha ao excluir usuário. Por favor, tente novamente mais tarde.", + "Unlimited Offline/Online Reading": "Leitura offline/online ilimitada", + "Unlimited Cloud Sync Devices": "Sincronização ilimitada de dispositivos na nuvem", + "Essential Text-to-Speech Voices": "Vozes essenciais de texto para fala", + "DeepL Free Access": "Acesso gratuito ao DeepL", + "Community Support": "Suporte da comunidade", + "500 MB Cloud Sync Space": "500 MB de espaço de sincronização na nuvem", + "Includes All Free Tier Benefits": "Inclui todos os benefícios do plano gratuito", + "AI Summaries": "Resumos de IA", + "AI Translations": "Traduções de IA", + "Priority Support": "Suporte prioritário", + "DeepL Pro Access": "Acesso ao DeepL Pro", + "Expanded Text-to-Speech Voices": "Vozes ampliadas de texto para fala", + "2000 MB Cloud Sync Space": "2000 MB de espaço de sincronização na nuvem", + "Includes All Plus Tier Benefits": "Inclui todos os benefícios do plano Plus", + "Unlimited AI Summaries": "Resumos de IA ilimitados", + "Unlimited AI Translations": "Traduções de IA ilimitadas", + "Unlimited DeepL Pro Access": "Acesso ilimitado ao DeepL Pro", + "Advanced AI Tools": "Ferramentas avançadas de IA", + "Early Feature Access": "Acesso antecipado a recursos", + "10 GB Cloud Sync Space": "10 GB de espaço de sincronização na nuvem", + "Loading profile...": "Carregando perfil...", + "Plan": "Plano", + "Plan Details": "Detalhes do plano", + "Features": "Recursos", + "Delete Account": "Excluir conta", + "Delete Your Account?": "Excluir sua conta?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "Esta ação não pode ser desfeita. Todos os seus dados na nuvem serão excluídos permanentemente.", + "Delete Permanently": "Excluir permanentemente", + "Free Tier": "Plano gratuito", + "Plus Tier": "Plano Plus", + "Pro Tier": "Plano Pro" } diff --git a/apps/readest-app/public/locales/ru/translation.json b/apps/readest-app/public/locales/ru/translation.json index 1d2e1c86..8014030a 100644 --- a/apps/readest-app/public/locales/ru/translation.json +++ b/apps/readest-app/public/locales/ru/translation.json @@ -198,5 +198,39 @@ "Verify token": "Проверить токен", "Sign in with Google": "Войти через Google", "Sign in with Apple": "Войти через Apple", - "Sign in with GitHub": "Войти через GitHub" + "Sign in with GitHub": "Войти через GitHub", + "Account": "Аккаунт", + "Cloud Storage": "Облачное хранилище", + "Failed to delete user. Please try again later.": "Не удалось удалить пользователя. Пожалуйста, повторите попытку позже.", + "Unlimited Offline/Online Reading": "Безлимитное чтение офлайн/онлайн", + "Unlimited Cloud Sync Devices": "Неограниченное количество устройств для облачной синхронизации", + "Essential Text-to-Speech Voices": "Основные голоса для преобразования текста в речь", + "DeepL Free Access": "Бесплатный доступ к DeepL", + "Community Support": "Поддержка сообщества", + "500 MB Cloud Sync Space": "500 МБ облачного пространства для синхронизации", + "Includes All Free Tier Benefits": "Включает все преимущества бесплатного тарифа", + "AI Summaries": "AI-резюме", + "AI Translations": "AI-переводы", + "Priority Support": "Приоритетная поддержка", + "DeepL Pro Access": "Доступ к DeepL Pro", + "Expanded Text-to-Speech Voices": "Расширенный набор голосов для преобразования текста в речь", + "2000 MB Cloud Sync Space": "2000 МБ облачного пространства для синхронизации", + "Includes All Plus Tier Benefits": "Включает все преимущества тарифа Plus", + "Unlimited AI Summaries": "Безлимитные AI-резюме", + "Unlimited AI Translations": "Безлимитные AI-переводы", + "Unlimited DeepL Pro Access": "Неограниченный доступ к DeepL Pro", + "Advanced AI Tools": "Продвинутые AI-инструменты", + "Early Feature Access": "Ранний доступ к новым функциям", + "10 GB Cloud Sync Space": "10 ГБ облачного пространства для синхронизации", + "Loading profile...": "Загрузка профиля...", + "Plan": "Тариф", + "Plan Details": "Детали тарифа", + "Features": "Функции", + "Delete Account": "Удалить аккаунт", + "Delete Your Account?": "Удалить ваш аккаунт?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "Это действие нельзя отменить. Все ваши данные в облаке будут удалены безвозвратно.", + "Delete Permanently": "Удалить навсегда", + "Free Tier": "Бесплатный тариф", + "Plus Tier": "Тариф Plus", + "Pro Tier": "Тариф Pro" } diff --git a/apps/readest-app/public/locales/tr/translation.json b/apps/readest-app/public/locales/tr/translation.json index 2dbbfada..dc9d68b5 100644 --- a/apps/readest-app/public/locales/tr/translation.json +++ b/apps/readest-app/public/locales/tr/translation.json @@ -198,5 +198,39 @@ "Verify token": "Token'ı doğrula", "Sign in with Google": "Google ile giriş yap", "Sign in with Apple": "Apple ile giriş yap", - "Sign in with GitHub": "GitHub ile giriş yap" + "Sign in with GitHub": "GitHub ile giriş yap", + "Account": "Hesap", + "Cloud Storage": "Bulut Depolama", + "Failed to delete user. Please try again later.": "Kullanıcı silinemedi. Lütfen daha sonra tekrar deneyin.", + "Unlimited Offline/Online Reading": "Sınırsız Çevrimdışı/Çevrimiçi Okuma", + "Unlimited Cloud Sync Devices": "Sınırsız Bulut Senkronizasyon Cihazları", + "Essential Text-to-Speech Voices": "Temel Metinden Sese Dönüştürme Sesleri", + "DeepL Free Access": "DeepL Ücretsiz Erişim", + "Community Support": "Topluluk Desteği", + "500 MB Cloud Sync Space": "500 MB Bulut Senkronizasyon Alanı", + "Includes All Free Tier Benefits": "Tüm Ücretsiz Paket Avantajlarını İçerir", + "AI Summaries": "Yapay Zeka Özetleri", + "AI Translations": "Yapay Zeka Çevirileri", + "Priority Support": "Öncelikli Destek", + "DeepL Pro Access": "DeepL Pro Erişimi", + "Expanded Text-to-Speech Voices": "Genişletilmiş Metinden Sese Dönüştürme Sesleri", + "2000 MB Cloud Sync Space": "2000 MB Bulut Senkronizasyon Alanı", + "Includes All Plus Tier Benefits": "Tüm Plus Paket Avantajlarını İçerir", + "Unlimited AI Summaries": "Sınırsız Yapay Zeka Özetleri", + "Unlimited AI Translations": "Sınırsız Yapay Zeka Çevirileri", + "Unlimited DeepL Pro Access": "Sınırsız DeepL Pro Erişimi", + "Advanced AI Tools": "Gelişmiş Yapay Zeka Araçları", + "Early Feature Access": "Erken Özellik Erişimi", + "10 GB Cloud Sync Space": "10 GB Bulut Senkronizasyon Alanı", + "Loading profile...": "Profil yükleniyor...", + "Plan": "Plan", + "Plan Details": "Plan Detayları", + "Features": "Özellikler", + "Delete Account": "Hesabı Sil", + "Delete Your Account?": "Hesabınızı Silmek İstiyor musunuz?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "Bu işlem geri alınamaz. Buluttaki tüm verileriniz kalıcı olarak silinecektir.", + "Delete Permanently": "Kalıcı Olarak Sil", + "Free Tier": "Ücretsiz Paket", + "Plus Tier": "Plus Paket", + "Pro Tier": "Pro Paket" } diff --git a/apps/readest-app/public/locales/uk/translation.json b/apps/readest-app/public/locales/uk/translation.json index 1fe58227..42555b6c 100644 --- a/apps/readest-app/public/locales/uk/translation.json +++ b/apps/readest-app/public/locales/uk/translation.json @@ -198,5 +198,39 @@ "Verify token": "Перевірити токен", "Sign in with Google": "Увійти через Google", "Sign in with Apple": "Увійти через Apple", - "Sign in with GitHub": "Увійти через GitHub" + "Sign in with GitHub": "Увійти через GitHub", + "Account": "Обліковий запис", + "Cloud Storage": "Хмарне сховище", + "Failed to delete user. Please try again later.": "Не вдалося видалити користувача. Будь ласка, спробуйте пізніше.", + "Unlimited Offline/Online Reading": "Необмежене читання офлайн/онлайн", + "Unlimited Cloud Sync Devices": "Необмежена кількість пристроїв для хмарної синхронізації", + "Essential Text-to-Speech Voices": "Основні голоси для перетворення тексту в мовлення", + "DeepL Free Access": "Безкоштовний доступ до DeepL", + "Community Support": "Підтримка спільноти", + "500 MB Cloud Sync Space": "500 МБ простору для хмарної синхронізації", + "Includes All Free Tier Benefits": "Включає всі переваги безкоштовного тарифу", + "AI Summaries": "AI-резюме", + "AI Translations": "AI-переклади", + "Priority Support": "Пріоритетна підтримка", + "DeepL Pro Access": "Доступ до DeepL Pro", + "Expanded Text-to-Speech Voices": "Розширений набір голосів для перетворення тексту в мовлення", + "2000 MB Cloud Sync Space": "2000 МБ простору для хмарної синхронізації", + "Includes All Plus Tier Benefits": "Включає всі переваги тарифу Plus", + "Unlimited AI Summaries": "Необмежені AI-резюме", + "Unlimited AI Translations": "Необмежені AI-переклади", + "Unlimited DeepL Pro Access": "Необмежений доступ до DeepL Pro", + "Advanced AI Tools": "Розширені AI-інструменти", + "Early Feature Access": "Ранній доступ до нових функцій", + "10 GB Cloud Sync Space": "10 ГБ простору для хмарної синхронізації", + "Loading profile...": "Завантаження профілю...", + "Plan": "Тариф", + "Plan Details": "Деталі тарифу", + "Features": "Функції", + "Delete Account": "Видалити обліковий запис", + "Delete Your Account?": "Видалити ваш обліковий запис?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "Цю дію неможливо скасувати. Всі ваші дані в хмарі будуть повністю видалені.", + "Delete Permanently": "Видалити назавжди", + "Free Tier": "Безкоштовний тариф", + "Plus Tier": "Тариф Plus", + "Pro Tier": "Тариф Pro" } diff --git a/apps/readest-app/public/locales/vi/translation.json b/apps/readest-app/public/locales/vi/translation.json index 3072c70d..8da55e0c 100644 --- a/apps/readest-app/public/locales/vi/translation.json +++ b/apps/readest-app/public/locales/vi/translation.json @@ -198,5 +198,39 @@ "Verify token": "Xác minh mã token", "Sign in with Google": "Đăng nhập với Google", "Sign in with Apple": "Đăng nhập với Apple", - "Sign in with GitHub": "Đăng nhập với GitHub" + "Sign in with GitHub": "Đăng nhập với GitHub", + "Account": "Tài khoản", + "Cloud Storage": "Lưu trữ đám mây", + "Failed to delete user. Please try again later.": "Không thể xóa người dùng. Vui lòng thử lại sau.", + "Unlimited Offline/Online Reading": "Đọc ngoại tuyến/trực tuyến không giới hạn", + "Unlimited Cloud Sync Devices": "Đồng bộ hóa thiết bị đám mây không giới hạn", + "Essential Text-to-Speech Voices": "Giọng nói chuyển văn bản thành giọng nói cơ bản", + "DeepL Free Access": "Truy cập DeepL miễn phí", + "Community Support": "Hỗ trợ cộng đồng", + "500 MB Cloud Sync Space": "500 MB không gian đồng bộ hóa đám mây", + "Includes All Free Tier Benefits": "Bao gồm tất cả lợi ích của gói miễn phí", + "AI Summaries": "Tóm tắt AI", + "AI Translations": "Dịch thuật AI", + "Priority Support": "Hỗ trợ ưu tiên", + "DeepL Pro Access": "Truy cập DeepL Pro", + "Expanded Text-to-Speech Voices": "Giọng nói chuyển văn bản thành giọng nói mở rộng", + "2000 MB Cloud Sync Space": "2000 MB không gian đồng bộ hóa đám mây", + "Includes All Plus Tier Benefits": "Bao gồm tất cả lợi ích của gói Plus", + "Unlimited AI Summaries": "Tóm tắt AI không giới hạn", + "Unlimited AI Translations": "Dịch thuật AI không giới hạn", + "Unlimited DeepL Pro Access": "Truy cập DeepL Pro không giới hạn", + "Advanced AI Tools": "Công cụ AI nâng cao", + "Early Feature Access": "Truy cập tính năng sớm", + "10 GB Cloud Sync Space": "10 GB không gian đồng bộ hóa đám mây", + "Loading profile...": "Đang tải hồ sơ...", + "Plan": "Gói", + "Plan Details": "Chi tiết gói", + "Features": "Tính năng", + "Delete Account": "Xóa tài khoản", + "Delete Your Account?": "Xóa tài khoản của bạn?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "Hành động này không thể hoàn tác. Tất cả dữ liệu của bạn trên đám mây sẽ bị xóa vĩnh viễn.", + "Delete Permanently": "Xóa vĩnh viễn", + "Free Tier": "Gói miễn phí", + "Plus Tier": "Gói Plus", + "Pro Tier": "Gói Pro" } diff --git a/apps/readest-app/public/locales/zh-CN/translation.json b/apps/readest-app/public/locales/zh-CN/translation.json index eddae359..7b9956de 100644 --- a/apps/readest-app/public/locales/zh-CN/translation.json +++ b/apps/readest-app/public/locales/zh-CN/translation.json @@ -198,5 +198,39 @@ "Verify token": "验证令牌", "Sign in with Google": "使用 Google 登录", "Sign in with Apple": "使用 Apple 登录", - "Sign in with GitHub": "使用 GitHub 登录" + "Sign in with GitHub": "使用 GitHub 登录", + "Account": "账户", + "Cloud Storage": "云存储", + "Failed to delete user. Please try again later.": "删除用户失败。请稍后重试。", + "Unlimited Offline/Online Reading": "无限离线/在线阅读", + "Unlimited Cloud Sync Devices": "无限云同步设备", + "Essential Text-to-Speech Voices": "基本文本转语音声音", + "DeepL Free Access": "使用 DeepL 免费版翻译", + "Community Support": "社区支持", + "500 MB Cloud Sync Space": "500 MB 云同步空间", + "Includes All Free Tier Benefits": "包含所有免费版权益", + "AI Summaries": "AI 摘要", + "AI Translations": "AI 翻译", + "Priority Support": "优先支持", + "DeepL Pro Access": "使用 DeepL 专业版翻译", + "Expanded Text-to-Speech Voices": "更多文本转语音声音", + "2000 MB Cloud Sync Space": "2000 MB 云同步空间", + "Includes All Plus Tier Benefits": "包含所有增强版权益", + "Unlimited AI Summaries": "无限使用 AI 摘要", + "Unlimited AI Translations": "无限使用 AI 翻译", + "Unlimited DeepL Pro Access": "无限使用 DeepL 专业版翻译", + "Advanced AI Tools": "高级 AI 工具", + "Early Feature Access": "抢先体验新功能", + "10 GB Cloud Sync Space": "10 GB 云同步空间", + "Loading profile...": "加载个人资料中...", + "Plan": "套餐", + "Plan Details": "套餐详情", + "Features": "功能特性", + "Delete Account": "删除账户", + "Delete Your Account?": "删除您的账户?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "此操作无法撤销。您在云端的所有数据将被永久删除。", + "Delete Permanently": "永久删除", + "Free Tier": "免费版", + "Plus Tier": "增强版", + "Pro Tier": "专业版" } diff --git a/apps/readest-app/public/locales/zh-TW/translation.json b/apps/readest-app/public/locales/zh-TW/translation.json index bb3eca47..58f024f7 100644 --- a/apps/readest-app/public/locales/zh-TW/translation.json +++ b/apps/readest-app/public/locales/zh-TW/translation.json @@ -198,5 +198,39 @@ "Verify token": "驗證令牌", "Sign in with Google": "使用 Google 登入", "Sign in with Apple": "使用 Apple 登入", - "Sign in with GitHub": "使用 GitHub 登入" + "Sign in with GitHub": "使用 GitHub 登入", + "Account": "帳戶", + "Cloud Storage": "雲端儲存空間", + "Failed to delete user. Please try again later.": "刪除使用者失敗。請稍後再試。", + "Unlimited Offline/Online Reading": "無限離線/線上閱讀", + "Unlimited Cloud Sync Devices": "無限雲端同步裝置", + "Essential Text-to-Speech Voices": "基本文字轉語音聲音", + "DeepL Free Access": "DeepL免費存取", + "Community Support": "社群支援", + "500 MB Cloud Sync Space": "500 MB雲端同步空間", + "Includes All Free Tier Benefits": "包含所有免費方案權益", + "AI Summaries": "AI摘要", + "AI Translations": "AI翻譯", + "Priority Support": "優先支援", + "DeepL Pro Access": "DeepL專業版存取", + "Expanded Text-to-Speech Voices": "擴展文字轉語音聲音", + "2000 MB Cloud Sync Space": "2000 MB雲端同步空間", + "Includes All Plus Tier Benefits": "包含所有Plus方案權益", + "Unlimited AI Summaries": "無限AI摘要", + "Unlimited AI Translations": "無限AI翻譯", + "Unlimited DeepL Pro Access": "無限DeepL專業版存取", + "Advanced AI Tools": "進階AI工具", + "Early Feature Access": "搶先體驗新功能", + "10 GB Cloud Sync Space": "10 GB雲端同步空間", + "Loading profile...": "載入個人資料中...", + "Plan": "方案", + "Plan Details": "方案詳情", + "Features": "功能", + "Delete Account": "刪除帳戶", + "Delete Your Account?": "刪除您的帳戶?", + "This action cannot be undone. All your data in the cloud will be permanently deleted.": "此操作無法撤銷。您在雲端的所有資料將被永久刪除。", + "Delete Permanently": "永久刪除", + "Free Tier": "免費方案", + "Plus Tier": "Plus方案", + "Pro Tier": "專業方案" } diff --git a/apps/readest-app/src/app/auth/page.tsx b/apps/readest-app/src/app/auth/page.tsx index 90ae1219..478e59af 100644 --- a/apps/readest-app/src/app/auth/page.tsx +++ b/apps/readest-app/src/app/auth/page.tsx @@ -332,20 +332,16 @@ export default function AuthPage() { Icon={FaGithub} label={_('Sign in with GitHub')} /> - {!appService?.isIOSApp && ( -
-
- -
- )} +
+ ) : ( diff --git a/apps/readest-app/src/app/library/components/SettingsMenu.tsx b/apps/readest-app/src/app/library/components/SettingsMenu.tsx index 5ce03a7c..13f29a08 100644 --- a/apps/readest-app/src/app/library/components/SettingsMenu.tsx +++ b/apps/readest-app/src/app/library/components/SettingsMenu.tsx @@ -13,7 +13,7 @@ import { useEnv } from '@/context/EnvContext'; import { useSettingsStore } from '@/store/settingsStore'; import { useTranslation } from '@/hooks/useTranslation'; import { getStoragePlanData } from '@/utils/access'; -import { navigateToLogin } from '@/utils/nav'; +import { navigateToLogin, navigateToProfile } from '@/utils/nav'; import { QuotaType } from '@/types/user'; import MenuItem from '@/components/MenuItem'; import Quota from '@/components/Quota'; @@ -26,7 +26,7 @@ const SettingsMenu: React.FC = ({ setIsDropdownOpen }) => { const _ = useTranslation(); const router = useRouter(); const { envConfig } = useEnv(); - const { token, user, logout } = useAuth(); + const { token, user } = useAuth(); const { settings, setSettings, saveSettings } = useSettingsStore(); const [quotas, setQuotas] = React.useState([]); const [isAutoUpload, setIsAutoUpload] = useState(settings.autoUpload); @@ -47,11 +47,8 @@ const SettingsMenu: React.FC = ({ setIsDropdownOpen }) => { setIsDropdownOpen?.(false); }; - const handleUserLogout = () => { - logout(); - settings.keepLogin = false; - setSettings(settings); - saveSettings(envConfig, settings); + const handleUserProfile = () => { + navigateToProfile(router); setIsDropdownOpen?.(false); }; @@ -135,8 +132,8 @@ const SettingsMenu: React.FC = ({ setIsDropdownOpen }) => { } >
    - - + +
) : ( diff --git a/apps/readest-app/src/app/user/page.tsx b/apps/readest-app/src/app/user/page.tsx new file mode 100644 index 00000000..7702c340 --- /dev/null +++ b/apps/readest-app/src/app/user/page.tsx @@ -0,0 +1,289 @@ +'use client'; + +import clsx from 'clsx'; +import React, { useState, useEffect } from 'react'; +import Image from 'next/image'; +import { useRouter } from 'next/navigation'; +import { IoArrowBack } from 'react-icons/io5'; +import { PiUserCircle } from 'react-icons/pi'; +import { useEnv } from '@/context/EnvContext'; +import { useAuth } from '@/context/AuthContext'; +import { useTheme } from '@/hooks/useTheme'; +import { useTranslation } from '@/hooks/useTranslation'; +import { useSettingsStore } from '@/store/settingsStore'; +import { QuotaType, UserPlan } from '@/types/user'; +import { getStoragePlanData, getUserPlan } from '@/utils/access'; +import { navigateToLibrary } from '@/utils/nav'; +import { deleteUser } from '@/libs/user'; +import { eventDispatcher } from '@/utils/event'; +import { Toast } from '@/components/Toast'; +import Quota from '@/components/Quota'; + +const ProfilePage = () => { + const _ = useTranslation(); + const router = useRouter(); + const { envConfig, appService } = useEnv(); + const { token, user, logout } = useAuth(); + const { settings, setSettings, saveSettings } = useSettingsStore(); + const [userPlan, setUserPlan] = useState('free'); + const [quotas, setQuotas] = React.useState([]); + const [showConfirmDelete, setShowConfirmDelete] = useState(false); + + useTheme(); + + useEffect(() => { + if (!user || !token) return; + + try { + const userPlan = getUserPlan(token); + const storagePlan = getStoragePlanData(token); + const storageQuota = { + name: _('Cloud Storage'), + tooltip: _('{{percentage}}% of Cloud Storage Used.', { + percentage: Math.round((storagePlan.usage / storagePlan.quota) * 100), + }), + used: Math.round(storagePlan.usage / 1024 / 1024), + total: Math.round(storagePlan.quota / 1024 / 1024), + unit: 'MB', + }; + setUserPlan(userPlan); + setQuotas([storageQuota]); + } catch (error) { + console.error('Error loading user plan data:', error); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [token]); + + const handleGoBack = () => { + navigateToLibrary(router); + }; + + const handleLogout = () => { + logout(); + settings.keepLogin = false; + setSettings(settings); + saveSettings(envConfig, settings); + navigateToLibrary(router); + }; + + const handleDeleteRequest = () => { + setShowConfirmDelete(true); + }; + + const handleCancelDelete = () => { + setShowConfirmDelete(false); + }; + + const handleConfirmDelete = async () => { + try { + await deleteUser(); + handleLogout(); + } catch (error) { + console.error('Error deleting user:', error); + eventDispatcher.dispatch('toast', { + type: 'error', + message: _('Failed to delete user. Please try again later.'), + }); + } + setShowConfirmDelete(false); + }; + + const getPlanDetails = (userPlan: UserPlan) => { + switch (userPlan) { + case 'free': + return { + name: _('Free Tier'), + color: 'bg-gray-200 text-gray-800', + features: [ + _('Unlimited Offline/Online Reading'), + _('Unlimited Cloud Sync Devices'), + _('Essential Text-to-Speech Voices'), + _('DeepL Free Access'), + _('Community Support'), + _('500 MB Cloud Sync Space'), + ], + }; + case 'plus': + return { + name: _('Plus Tier'), + color: 'bg-blue-200 text-blue-800', + features: [ + _('Includes All Free Tier Benefits'), + _('AI Summaries'), + _('AI Translations'), + _('Priority Support'), + _('DeepL Pro Access'), + _('Expanded Text-to-Speech Voices'), + _('2000 MB Cloud Sync Space'), + ], + }; + case 'pro': + return { + name: _('Pro Tier'), + color: 'bg-purple-200 text-purple-800', + features: [ + _('Includes All Plus Tier Benefits'), + _('Unlimited AI Summaries'), + _('Unlimited AI Translations'), + _('Unlimited DeepL Pro Access'), + _('Advanced AI Tools'), + _('Early Feature Access'), + _('10 GB Cloud Sync Space'), + ], + }; + } + }; + + if (!user || !token) { + return ( +
+
+
+
{_('Loading profile...')}
+
+
+
+ ); + } + + const avatarUrl = user?.user_metadata?.['picture'] || user?.user_metadata?.['avatar_url']; + const userFullName = user?.user_metadata?.['full_name'] || '-'; + const userEmail = user?.email || ''; + const planDetails = getPlanDetails(userPlan) || getPlanDetails('free'); + + return ( +
+ +
+
+
+
+
+ {avatarUrl ? ( + {_('User + ) : ( + + )} +
+ +
+

{userFullName}

+

{userEmail}

+
+ + {planDetails.name} {_('Plan')} + +
+
+
+ +
+

{_('Plan Details')}

+
+

{_('Features')}

+
    + {planDetails.features.map((feature, index) => ( +
  • + + + + {feature} +
  • + ))} +
+
+
+ +
+
+ {quotas && quotas.length > 0 ? ( + + ) : ( +
+ )} +
+
+ +
+ + +
+
+
+ + {showConfirmDelete && ( +
+
+

{_('Delete Your Account?')}

+

+ {_( + 'This action cannot be undone. All your data in the cloud will be permanently deleted.', + )} +

+
+ + +
+
+
+ )} +
+ +
+ ); +}; + +export default ProfilePage; diff --git a/apps/readest-app/src/components/Quota.tsx b/apps/readest-app/src/components/Quota.tsx index 0008345e..406bd272 100644 --- a/apps/readest-app/src/components/Quota.tsx +++ b/apps/readest-app/src/components/Quota.tsx @@ -1,3 +1,4 @@ +import clsx from 'clsx'; import React from 'react'; type QuotaProps = { @@ -8,26 +9,48 @@ type QuotaProps = { total: number; unit: string; }[]; + className?: string; + showProgress?: boolean; }; -const Quota: React.FC = ({ quotas }) => { +const Quota: React.FC = ({ quotas, showProgress, className }) => { return ( -
-
- {quotas.map((quota) => ( -
-
-
+
+ {quotas.map((quota) => { + const usagePercentage = (quota.used / quota.total) * 100; + let bgColor = 'bg-green-500'; + if (usagePercentage > 80) { + bgColor = 'bg-red-500'; + } else if (usagePercentage > 50) { + bgColor = 'bg-yellow-500'; + } + + return ( +
+ {showProgress && ( +
+ )} + +
+
{quota.name}
-
- -
- {quota.used} / {quota.total} {quota.unit} +
+ {quota.used} / {quota.total} {quota.unit} +
- ))} -
+ ); + })}
); }; diff --git a/apps/readest-app/src/libs/storage.ts b/apps/readest-app/src/libs/storage.ts index 4291b576..4bbe9cb3 100644 --- a/apps/readest-app/src/libs/storage.ts +++ b/apps/readest-app/src/libs/storage.ts @@ -1,5 +1,6 @@ import { getAPIBaseUrl, isWebAppPlatform } from '@/services/environment'; -import { getAccessToken, getUserID } from '@/utils/access'; +import { getUserID } from '@/utils/access'; +import { fetchWithAuth } from '@/utils/fetch'; import { tauriUpload, tauriDownload, @@ -15,27 +16,6 @@ const API_ENDPOINTS = { delete: getAPIBaseUrl() + '/storage/delete', }; -const fetchWithAuth = async (url: string, options: RequestInit) => { - const token = await getAccessToken(); - if (!token) { - throw new Error('Not authenticated'); - } - const headers = { - ...options.headers, - Authorization: `Bearer ${token}`, - }; - - const response = await fetch(url, { ...options, headers }); - - if (!response.ok) { - const errorData = await response.json(); - console.error('Error:', errorData.error || response.statusText); - throw new Error(errorData.error || 'Request failed'); - } - - return response; -}; - export const createProgressHandler = ( totalFiles: number, completedFilesRef: { count: number }, diff --git a/apps/readest-app/src/libs/user.ts b/apps/readest-app/src/libs/user.ts new file mode 100644 index 00000000..da93b816 --- /dev/null +++ b/apps/readest-app/src/libs/user.ts @@ -0,0 +1,21 @@ +import { getAPIBaseUrl } from '@/services/environment'; +import { getUserID } from '@/utils/access'; +import { fetchWithAuth } from '@/utils/fetch'; + +const API_ENDPOINT = getAPIBaseUrl() + '/user/delete'; + +export const deleteUser = async () => { + try { + const userId = await getUserID(); + if (!userId) { + throw new Error('Not authenticated'); + } + + await fetchWithAuth(API_ENDPOINT, { + method: 'DELETE', + }); + } catch (error) { + console.error('User deletion failed:', error); + throw new Error('User deletion failed'); + } +}; diff --git a/apps/readest-app/src/pages/api/deepl/translate.ts b/apps/readest-app/src/pages/api/deepl/translate.ts index 81168d99..d149c00b 100644 --- a/apps/readest-app/src/pages/api/deepl/translate.ts +++ b/apps/readest-app/src/pages/api/deepl/translate.ts @@ -28,7 +28,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { const { user, token } = await getUserAndToken(req.headers['authorization']); let deeplApiUrl = DEEPL_FREE_API; if (user && token) { - const userPlan = await getUserPlan(token); + const userPlan = getUserPlan(token); if (userPlan !== 'free') deeplApiUrl = DEEPL_PRO_API; } const deeplAuthKey = diff --git a/apps/readest-app/src/pages/api/user/delete.ts b/apps/readest-app/src/pages/api/user/delete.ts new file mode 100644 index 00000000..1c8ede3d --- /dev/null +++ b/apps/readest-app/src/pages/api/user/delete.ts @@ -0,0 +1,30 @@ +import type { NextApiRequest, NextApiResponse } from 'next'; +import { corsAllMethods, runMiddleware } from '@/utils/cors'; +import { createSupabaseAdminClient } from '@/utils/supabase'; +import { validateUserAndToken } from '@/utils/access'; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + await runMiddleware(req, res, corsAllMethods); + + if (req.method !== 'DELETE') { + return res.status(405).json({ error: 'Method not allowed' }); + } + + try { + const { user, token } = await validateUserAndToken(req.headers['authorization']); + if (!user || !token) { + return res.status(403).json({ error: 'Not authenticated' }); + } + + const supabaseAdmin = createSupabaseAdminClient(); + const { error } = await supabaseAdmin.auth.admin.deleteUser(user.id); + if (error) { + return res.status(500).json({ error: error.message }); + } + + res.status(200).json({ message: 'User deleted successfully' }); + } catch (error) { + console.error(error); + return res.status(500).json({ error: 'Something went wrong' }); + } +} diff --git a/apps/readest-app/src/utils/access.ts b/apps/readest-app/src/utils/access.ts index 8f2df135..f815b23a 100644 --- a/apps/readest-app/src/utils/access.ts +++ b/apps/readest-app/src/utils/access.ts @@ -10,7 +10,7 @@ interface Token { [key: string]: string | number; } -export const getUserPlan = async (token: string): Promise => { +export const getUserPlan = (token: string): UserPlan => { const data = jwtDecode(token) || {}; return data['plan'] || 'free'; }; diff --git a/apps/readest-app/src/utils/fetch.ts b/apps/readest-app/src/utils/fetch.ts new file mode 100644 index 00000000..43670fed --- /dev/null +++ b/apps/readest-app/src/utils/fetch.ts @@ -0,0 +1,22 @@ +import { getAccessToken } from './access'; + +export const fetchWithAuth = async (url: string, options: RequestInit) => { + const token = await getAccessToken(); + if (!token) { + throw new Error('Not authenticated'); + } + const headers = { + ...options.headers, + Authorization: `Bearer ${token}`, + }; + + const response = await fetch(url, { ...options, headers }); + + if (!response.ok) { + const errorData = await response.json(); + console.error('Error:', errorData.error || response.statusText); + throw new Error(errorData.error || 'Request failed'); + } + + return response; +}; diff --git a/apps/readest-app/src/utils/nav.ts b/apps/readest-app/src/utils/nav.ts index 4ad98764..d7a6761f 100644 --- a/apps/readest-app/src/utils/nav.ts +++ b/apps/readest-app/src/utils/nav.ts @@ -25,6 +25,10 @@ export const navigateToLogin = (router: ReturnType) => { router.push(`/auth?redirect=${encodeURIComponent(currentPath)}`); }; +export const navigateToProfile = (router: ReturnType) => { + router.push('/user'); +}; + export const navigateToLibrary = ( router: ReturnType, queryParams?: string, diff --git a/apps/readest-app/src/utils/supabase.ts b/apps/readest-app/src/utils/supabase.ts index 70b43211..28ccf0c4 100644 --- a/apps/readest-app/src/utils/supabase.ts +++ b/apps/readest-app/src/utils/supabase.ts @@ -4,6 +4,7 @@ const supabaseUrl = process.env['NEXT_PUBLIC_SUPABASE_URL'] || process.env['NEXT_PUBLIC_DEV_SUPABASE_URL']!; const supabaseAnonKey = process.env['NEXT_PUBLIC_SUPABASE_ANON_KEY'] || process.env['NEXT_PUBLIC_DEV_SUPABASE_ANON_KEY']!; +const supabaseAdminKey = process.env['SUPABASE_ADMIN_KEY'] || ''; export const supabase = createClient(supabaseUrl, supabaseAnonKey); @@ -18,3 +19,13 @@ export const createSupabaseClient = (accessToken?: string) => { }, }); }; + +export const createSupabaseAdminClient = () => { + return createClient(supabaseUrl, supabaseAdminKey, { + auth: { + persistSession: false, + autoRefreshToken: false, + detectSessionInUrl: false, + }, + }); +};