fix(recipes): distinguish unobtainable LoRAs in recipe status and skip them in syntax

The recipe card pill counted LoRAs deleted from the source (isDeleted) as
available, showing a green 'ready 2/2' for recipes that cannot be fully
reproduced. LoRAs with an unresolvable hash (hashInvalid) were counted as
missing/downloadable even though downloads always fail, and recipe syntax
generation emitted broken tokens for them.

- Four-state status on RecipeCard pill and RecipeTab badge: ready (all in
  library), missing (downloadable, red, keeps the action cue), partial
  (unobtainable entries skipped when used, amber, fa-circle-minus),
  unavailable (nothing usable, gray, fa-ban)
- Pill numerator is now the real in-library count; tooltips spell out
  missing vs unavailable (deleted from source or unresolvable hash)
- get_recipe_syntax_tokens skips hashInvalid entries like deleted ones
  instead of emitting tokens pointing at nonexistent files
- Bulk missing-download manager and recipe context menu exclude
  hashInvalid LoRAs, matching the modal's per-item download block
- New locale keys loraStatus.missingAndUnavailable/partial/noneUsable,
  translated for all 9 non-en locales
This commit is contained in:
Will Miao
2026-08-29 16:41:48 +08:00
parent ebe3df7d22
commit c972c755fc
19 changed files with 258 additions and 40 deletions
+4 -1
View File
@@ -883,7 +883,10 @@
"loraStatus": {
"none": "Aucun LoRA dans cette Recipe",
"allAvailable": "Tous les LoRAs sont disponibles - Prêt à l'emploi",
"missing": "{missing} LoRA(s) manquant(s) sur {total}"
"missing": "{missing} LoRA(s) manquant(s) sur {total}",
"missingAndUnavailable": "{missing} LoRA(s) manquant(s) sur {total}, {unavailable} indisponible(s) (supprimé(s) de la source ou hash irrésolvable)",
"partial": "{unavailable} LoRA(s) indisponible(s) sur {total} (supprimé(s) de la source ou hash irrésolvable) - ignoré(s) lors de l'utilisation de la Recipe",
"noneUsable": "Aucun LoRA utilisable - {unavailable} sur {total} supprimé(s) de la source ou hash irrésolvable"
},
"resources": {
"inLibrary": "Dans la bibliothèque",