refactor: remove Anki import/export and simplify card system

- Remove Anki apkg import/export functionality
- Remove OCR feature module
- Remove note and note-type modules
- Simplify card/deck modules (remove spaced repetition complexity)
- Update translator and dictionary features
- Clean up unused translations and update i18n files
- Simplify prisma schema
This commit is contained in:
2026-03-17 20:24:42 +08:00
parent 95ce49378b
commit de7c1321c2
77 changed files with 2767 additions and 8107 deletions

View File

@@ -53,7 +53,30 @@
"totalCards": "Total des cartes",
"createdAt": "Créé le",
"actions": "Actions",
"view": "Voir"
"view": "Voir",
"subtitle": "Gérer vos decks d'apprentissage",
"newDeck": "Nouveau deck",
"noDecksYet": "Pas encore de decks",
"loading": "Chargement...",
"deckInfo": "ID: {id} · {totalCards} cartes",
"enterDeckName": "Nom du deck:",
"enterNewName": "Nouveau nom:",
"confirmDelete": "Tapez \"{name}\" pour supprimer:",
"public": "Public",
"private": "Privé",
"setPublic": "Rendre public",
"setPrivate": "Rendre privé",
"importApkg": "Importer APKG",
"exportApkg": "Exporter APKG",
"clickToUpload": "Cliquez pour télécharger",
"apkgFilesOnly": "Fichiers .apkg uniquement",
"parsing": "Analyse...",
"foundDecks": "{count} decks trouvés",
"back": "Retour",
"import": "Importer",
"importing": "Import...",
"exportSuccess": "Export réussi",
"goToDecks": "Aller aux decks"
},
"folder_id": {
"unauthorized": "Vous n'êtes pas le propriétaire de ce dossier",
@@ -106,29 +129,48 @@
"edit": "Modifier",
"delete": "Supprimer",
"permissionDenied": "Vous n'avez pas la permission d'effectuer cette action",
"resetProgress": "Réinitialiser",
"resetProgressTitle": "Réinitialiser la progression du deck",
"resetProgressConfirm": "Cela réinitialisera toutes les cartes de ce deck à l'état neuf. Votre progression d'apprentissage sera perdue. Êtes-vous sûr?",
"resetSuccess": "{count} cartes réinitialisées avec succès",
"resetting": "Réinitialisation en cours...",
"resetProgress": "Réinitialiser progression",
"resetProgressTitle": "Réinitialiser la progression",
"resetProgressConfirm": "Réinitialiser la progression?",
"resetSuccess": "Progression réinitialisée",
"resetting": "Réinitialisation...",
"cancel": "Annuler",
"settings": "Paramètres",
"settingsTitle": "Paramètres du deck",
"newPerDay": "Nouvelles cartes par jour",
"newPerDayHint": "Nombre maximum de nouvelles cartes par jour",
"newPerDay": "Nouvelles par jour",
"newPerDayHint": "Nouvelles cartes par jour",
"revPerDay": "Révisions par jour",
"revPerDayHint": "Nombre maximum de cartes à réviser par jour",
"revPerDayHint": "Révisions par jour",
"save": "Enregistrer",
"saving": "Enregistrement...",
"settingsSaved": "Paramètres enregistrés",
"todayNew": "Nouvelles",
"todayReview": "Révisions",
"todayLearning": "En cours",
"todayNew": "Nouvelles aujourd'hui",
"todayReview": "Révisions aujourd'hui",
"todayLearning": "En apprentissage",
"error": {
"update": "Vous n'avez pas la permission de mettre à jour cette carte.",
"delete": "Vous n'avez pas la permission de supprimer cette carte.",
"add": "Vous n'avez pas la permission d'ajouter des cartes à ce deck."
}
"update": "Pas autorisé à modifier",
"delete": "Pas autorisé à supprimer",
"add": "Pas autorisé à ajouter"
},
"ipaPlaceholder": "Entrer IPA",
"examplePlaceholder": "Entrer exemple",
"wordRequired": "Veuillez entrer un mot",
"definitionRequired": "Veuillez entrer une définition",
"cardAdded": "Carte ajoutée",
"cardType": "Type de carte",
"wordCard": "Carte mot",
"phraseCard": "Carte phrase",
"sentenceCard": "Carte phrase",
"sentence": "Phrase",
"sentencePlaceholder": "Entrer phrase",
"wordPlaceholder": "Entrer mot",
"queryLang": "Langue de requête",
"meanings": "Significations",
"addMeaning": "Ajouter signification",
"partOfSpeech": "Partie du discours",
"deleteConfirm": "Supprimer cette carte?",
"cardDeleted": "Carte supprimée",
"cardUpdated": "Carte mise à jour"
},
"home": {
"title": "Apprendre les langues",
@@ -234,10 +276,10 @@
},
"memorize": {
"deck_selector": {
"selectDeck": "Sélectionner un deck",
"noDecks": "Aucun deck trouvé",
"selectDeck": "Choisir deck",
"noDecks": "Pas de decks",
"goToDecks": "Aller aux decks",
"noCards": "Aucune carte",
"noCards": "Pas de cartes",
"new": "Nouveau",
"learning": "Apprentissage",
"review": "Révision",
@@ -246,29 +288,29 @@
"review": {
"loading": "Chargement...",
"backToDecks": "Retour aux decks",
"allDone": "Terminé !",
"allDoneDesc": "Vous avez révisé toutes les cartes dues.",
"allDone": "Tout terminé!",
"allDoneDesc": "Apprentissage terminé pour aujourd'hui!",
"reviewedCount": "{count} cartes révisées",
"progress": "{current} / {total}",
"nextReview": "Prochaine révision",
"interval": "Intervalle",
"ease": "Facilité",
"lapses": "Oublis",
"showAnswer": "Afficher la réponse",
"lapses": "Erreurs",
"showAnswer": "Montrer réponse",
"again": "Encore",
"hard": "Difficile",
"good": "Bien",
"easy": "Facile",
"now": "maintenant",
"lessThanMinute": "<1 min",
"inMinutes": "{count} min",
"inHours": "{count}h",
"inDays": "{count}j",
"inMonths": "{count}mois",
"minutes": "<1 min",
"days": "{count}j",
"months": "{count}mois",
"minAbbr": "m",
"now": "Maintenant",
"lessThanMinute": "moins d'une minute",
"inMinutes": "dans {n} minute{s}",
"inHours": "dans {n} heure{s}",
"inDays": "dans {n} jour{s}",
"inMonths": "dans {n} mois",
"minutes": "minutes",
"days": "jours",
"months": "mois",
"minAbbr": "min",
"dayAbbr": "j",
"cardTypeNew": "Nouveau",
"cardTypeLearning": "Apprentissage",
@@ -276,14 +318,15 @@
"cardTypeRelearning": "Réapprentissage",
"reverse": "Inverser",
"dictation": "Dictée",
"clickToPlay": "Cliquez pour jouer",
"clickToPlay": "Cliquer pour jouer",
"yourAnswer": "Votre réponse",
"typeWhatYouHear": "Tapez ce que vous entendez",
"correct": "Correct",
"incorrect": "Incorrect"
"correct": "Correct!",
"incorrect": "Incorrect",
"nextCard": "Suivant"
},
"page": {
"unauthorized": "Vous n'êtes pas autorisé à accéder à ce deck"
"unauthorized": "Non autorisé"
}
},
"navbar": {
@@ -297,33 +340,49 @@
"settings": "Paramètres"
},
"ocr": {
"title": "Extraction OCR de vocabulaire",
"description": "Téléchargez des captures d'écran de tableaux de vocabulaire pour extraire les paires mot-définition",
"uploadImage": "Télécharger une image",
"dragDropHint": "Glissez-déposez une image ici, ou cliquez pour sélectionner",
"supportedFormats": "Supportés : JPG, PNG, WebP",
"selectDeck": "Sélectionner un deck",
"chooseDeck": "Choisissez a deck to save the extracted pairs",
"noDecks": "Aucun deck disponible. Please create a deck first.",
"languageHints": "Indices de langue (Optionnel)",
"sourceLanguageHint": "Langue source (ex : Anglais)",
"targetLanguageHint": "Langue cible/traduction (ex : Chinois)",
"process": "Traiter l'image",
"title": "Reconnaissance OCR",
"description": "Extraire le texte des images",
"uploadImage": "Télécharger image",
"dragDropHint": "Glisser-déposer",
"supportedFormats": "Formats: JPG, PNG, WEBP",
"selectDeck": "Choisir deck",
"chooseDeck": "Choisir un deck",
"noDecks": "Pas de decks disponibles",
"languageHints": "Indications de langue",
"sourceLanguageHint": "Langue source",
"targetLanguageHint": "Langue cible",
"process": "Traiter",
"processing": "Traitement...",
"preview": "Aperçu",
"extractedPairs": "Paires extraites",
"word": "Mot",
"definition": "Définition",
"pairsCount": "{count} paires extraites",
"savePairs": "Sauvegarder dans le deck",
"saving": "Sauvegarde...",
"saved": "{count} paires sauvegardées dans {deck}",
"saveFailed": "Échec de la sauvegarde",
"noImage": "Veuillez first upload an image",
"noDeck": "Please select a deck",
"processingFailed": "Échec du traitement OCR",
"tryAgain": "Please try again with a clearer image",
"detectedLanguages": "Détecté : {source} → {target}"
"pairsCount": "{count} paires",
"savePairs": "Enregistrer",
"saving": "Enregistrement...",
"saved": "Enregistré",
"saveFailed": "Échec de l'enregistrement",
"noImage": "Veuillez télécharger une image",
"noDeck": "Veuillez choisir un deck",
"processingFailed": "Traitement échoué",
"tryAgain": "Réessayer",
"detectedLanguages": "Langues détectées",
"uploadSection": "Télécharger image",
"dropOrClick": "Déposer ou cliquer",
"changeImage": "Changer image",
"invalidFileType": "Type de fichier invalide",
"deckSelection": "Choisir deck",
"sourceLanguagePlaceholder": "ex: Anglais",
"targetLanguagePlaceholder": "ex: Français",
"processButton": "Démarrer reconnaissance",
"resultsPreview": "Aperçu des résultats",
"saveButton": "Enregistrer dans le deck",
"ocrSuccess": "OCR réussi",
"ocrFailed": "OCR échoué",
"savedToDeck": "Enregistré dans le deck",
"noResultsToSave": "Pas de résultats",
"detectedSourceLanguage": "Langue source détectée",
"detectedTargetLanguage": "Langue cible détectée"
},
"profile": {
"myProfile": "Mon profil",
@@ -364,12 +423,43 @@
"videoUploadFailed": "Échec du téléchargement de la vidéo",
"subtitleUploadFailed": "Échec du téléchargement des sous-titres",
"subtitleLoadSuccess": "Sous-titres chargés avec succès",
"subtitleLoadFailed": "Échec du chargement des sous-titres"
"subtitleLoadFailed": "Échec du chargement des sous-titres",
"settings": "Paramètres",
"shortcuts": "Raccourcis",
"keyboardShortcuts": "Raccourcis clavier",
"playPause": "Lecture/Pause",
"autoPauseToggle": "Pause auto",
"subtitleSettings": "Paramètres sous-titres",
"fontSize": "Taille police",
"textColor": "Couleur texte",
"backgroundColor": "Couleur fond",
"position": "Position",
"opacity": "Opacité",
"top": "Haut",
"center": "Centre",
"bottom": "Bas"
},
"text_speaker": {
"generateIPA": "Générer l'API",
"viewSavedItems": "Voir les éléments enregistrés",
"confirmDeleteAll": "Êtes-vous sûr de vouloir tout supprimer ? (O/N)"
"confirmDeleteAll": "Êtes-vous sûr de vouloir tout supprimer ? (O/N)",
"saved": "Enregistré",
"clearAll": "Tout effacer",
"language": "Langue",
"customLanguage": "ou entrer une langue...",
"languages": {
"auto": "Auto",
"chinese": "Chinois",
"english": "Anglais",
"japanese": "Japonais",
"korean": "Coréen",
"french": "Français",
"german": "Allemand",
"italian": "Italien",
"spanish": "Espagnol",
"portuguese": "Portugais",
"russian": "Russe"
}
},
"translator": {
"detectLanguage": "détecter la langue",
@@ -403,7 +493,19 @@
"error": "Échec de l'ajout de la paire de texte au dossier"
},
"autoSave": "Sauvegarde automatique",
"customLanguage": "ou tapez la langue..."
"customLanguage": "ou tapez la langue...",
"pleaseLogin": "Connectez-vous pour sauvegarder",
"pleaseCreateDeck": "Créez d'abord un deck",
"noTranslationToSave": "Pas de traduction à sauvegarder",
"noDeckSelected": "Aucun deck sélectionné",
"saveAsCard": "Sauvegarder comme carte",
"selectDeck": "Sélectionner deck",
"front": "Recto",
"back": "Verso",
"cancel": "Annuler",
"save": "Sauvegarder",
"savedToDeck": "Carte sauvegardée dans {deckName}",
"saveFailed": "Échec de la sauvegarde"
},
"dictionary": {
"title": "Dictionnaire",
@@ -448,7 +550,9 @@
"unfavorite": "Retirer des favoris",
"pleaseLogin": "Veuillez vous connecter d'abord",
"sortByFavorites": "Trier par favoris",
"sortByFavoritesActive": "Annuler le tri par favoris"
"sortByFavoritesActive": "Annuler le tri par favoris",
"noDecks": "Pas de decks publics",
"deckInfo": "{userName} · {totalCards} cartes"
},
"exploreDetail": {
"title": "Détails du dossier",
@@ -462,7 +566,8 @@
"unfavorite": "Retirer des favoris",
"favorited": "Ajouté aux favoris",
"unfavorited": "Retiré des favoris",
"pleaseLogin": "Veuillez vous connecter d'abord"
"pleaseLogin": "Veuillez vous connecter d'abord",
"totalCards": "{count} cartes"
},
"favorites": {
"title": "Mes favoris",
@@ -507,7 +612,8 @@
"createdAt": "Créé le",
"actions": "Actions",
"view": "Voir"
}
},
"joined": "Inscrit le"
},
"follow": {
"follow": "Suivre",