feat: add metadata refresh job to re-download metadata for linked series

Adds a new job type that refreshes metadata from external providers for
all series already linked via approved external_metadata_links. Tracks
and displays per-field diffs (series and book level), respects locked
fields, and provides a detailed change report in the job detail page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-19 09:09:10 +01:00
parent 818bd82e0f
commit 163dc3698c
17 changed files with 1170 additions and 56 deletions

View File

@@ -171,6 +171,8 @@ const fr = {
"jobs.generateThumbnails": "Générer les miniatures",
"jobs.regenerateThumbnails": "Regénérer les miniatures",
"jobs.batchMetadata": "Métadonnées en lot",
"jobs.refreshMetadata": "Rafraîchir métadonnées",
"jobs.refreshMetadataDescription": "Rafraîchit les métadonnées de toutes les séries déjà liées à un fournisseur externe. Re-télécharge les informations depuis le fournisseur et met à jour les séries et livres en base (en respectant les champs verrouillés). Les séries sans lien approuvé sont ignorées. <strong>Requiert une bibliothèque spécifique</strong> (ne fonctionne pas sur \u00ab Toutes les bibliothèques \u00bb).",
"jobs.referenceTitle": "Référence des types de tâches",
"jobs.rebuildDescription": "Scan incrémental : détecte les fichiers ajoutés, modifiés ou supprimés depuis le dernier scan, les indexe et génère les miniatures manquantes. Les données existantes non modifiées sont conservées. C'est l'action la plus courante et la plus rapide.",
"jobs.fullRebuildDescription": "Supprime toutes les données indexées (livres, séries, miniatures) puis effectue un scan complet depuis zéro. Utile si la base de données est désynchronisée ou corrompue. Opération longue et destructive : les statuts de lecture et les métadonnées manuelles seront perdus.",
@@ -183,8 +185,7 @@ const fr = {
"jobsList.library": "Bibliothèque",
"jobsList.type": "Type",
"jobsList.status": "Statut",
"jobsList.files": "Fichiers",
"jobsList.thumbnails": "Miniatures",
"jobsList.stats": "Stats",
"jobsList.duration": "Durée",
"jobsList.created": "Créé",
"jobsList.actions": "Actions",
@@ -193,6 +194,12 @@ const fr = {
"jobRow.showProgress": "Afficher la progression",
"jobRow.hideProgress": "Masquer la progression",
"jobRow.scanned": "{{count}} analysés",
"jobRow.filesIndexed": "{{count}} fichiers indexés",
"jobRow.filesRemoved": "{{count}} fichiers supprimés",
"jobRow.thumbnailsGenerated": "{{count}} miniatures générées",
"jobRow.metadataProcessed": "{{count}} séries traitées",
"jobRow.metadataRefreshed": "{{count}} séries rafraîchies",
"jobRow.errors": "{{count}} erreurs",
"jobRow.view": "Voir",
// Job progress
@@ -232,6 +239,14 @@ const fr = {
"jobDetail.phase2b": "Phase 2b — Génération des miniatures",
"jobDetail.metadataSearch": "Recherche de métadonnées",
"jobDetail.metadataSearchDesc": "Recherche auprès des fournisseurs externes pour chaque série",
"jobDetail.metadataRefresh": "Rafraîchissement des métadonnées",
"jobDetail.metadataRefreshDesc": "Re-téléchargement des métadonnées depuis les fournisseurs pour les séries déjà liées",
"jobDetail.refreshReport": "Rapport de rafraîchissement",
"jobDetail.refreshReportDesc": "{{count}} séries liées traitées",
"jobDetail.refreshed": "Rafraîchies",
"jobDetail.unchanged": "Inchangées",
"jobDetail.refreshChanges": "Détail des changements",
"jobDetail.refreshChangesDesc": "{{count}} séries avec des modifications",
"jobDetail.phase1Desc": "Scan et indexation des fichiers de la bibliothèque",
"jobDetail.phase2aDesc": "Extraction de la première page de chaque archive (nombre de pages + image brute)",
"jobDetail.phase2bDesc": "Génération des miniatures pour les livres analysés",
@@ -271,6 +286,7 @@ const fr = {
"jobType.thumbnail_regenerate": "Régén. miniatures",
"jobType.cbr_to_cbz": "CBR → CBZ",
"jobType.metadata_batch": "Métadonnées en lot",
"jobType.metadata_refresh": "Rafraîchir méta.",
"jobType.rebuildLabel": "Indexation incrémentale",
"jobType.rebuildDesc": "Scanne les fichiers nouveaux/modifiés, les analyse et génère les miniatures manquantes.",
"jobType.full_rebuildLabel": "Réindexation complète",
@@ -283,6 +299,8 @@ const fr = {
"jobType.cbr_to_cbzDesc": "Convertit une archive CBR au format ouvert CBZ.",
"jobType.metadata_batchLabel": "Métadonnées en lot",
"jobType.metadata_batchDesc": "Recherche les métadonnées auprès des fournisseurs externes pour toutes les séries de la bibliothèque et applique automatiquement les correspondances à 100% de confiance.",
"jobType.metadata_refreshLabel": "Rafraîchissement métadonnées",
"jobType.metadata_refreshDesc": "Re-télécharge et met à jour les métadonnées pour toutes les séries déjà liées à un fournisseur externe.",
// Status badges
"statusBadge.extracting_pages": "Extraction des pages",