feat(update): add a Buzz price alerts panel to the notification bell

P5a of docs/plans/paid-model-price-tracking.md: one surface that answers "what
got cheaper / became free", without a permanent button (the grid filter was
dropped by owner decision, so the panel carries the actions itself).

- price_alert_since records when an alert started, so the panel can say
  "dropped 3 d ago" and count what is new since the user last looked; it is set
  on the first sight of an already-cheap version, preserved while the alert
  stands, and cleared when the price rises back above the threshold
- get_price_alerts() compares the threshold at read time (editing it takes
  effect immediately, no refresh needed) and returns both kinds in one list;
  model_type=None covers every type, which the shared update DB makes a single
  query. "became free" needs no price data, so it is reported even while price
  tracking is off
- GET /api/lm/price-alerts, registered once in MiscRoutes rather than per model
  type, decorating rows best-effort with the local model name and file path from
  the scanner indexes (a cold cache just omits them)
- a third tab in the notification bell: segments for under-threshold and
  became-free, the three states (tracking off / nothing matching / stale), and
  per-row actions (CivitAI always, Open when the model is local)
- two non-permanent entry points share one helper: the controls-bar updates
  dropdown and the global context menu, whose label carries the unread count
- unread state stays client-side (localStorage watermark); the count is fetched
  once on init and only when price tracking is enabled
- the per-type frontend client method is removed as dead code; the per-type
  backend route stays for the companion extension
This commit is contained in:
Will Miao
2026-10-04 15:08:48 +08:00
parent ad2402724b
commit 7ed19c185c
27 changed files with 2142 additions and 86 deletions
+34 -2
View File
@@ -234,6 +234,9 @@
},
"groupByModel": {
"label": "Nach Modell gruppieren"
},
"priceAlerts": {
"label": "[TODO: Translate] Price alerts"
}
},
"header": {
@@ -942,7 +945,9 @@
"action": "Updates",
"menuLabel": "Weitere Update-Optionen anzeigen",
"check": "Updates prüfen",
"checkTooltip": "Die Aktualisierungssuche kann einige Zeit dauern."
"checkTooltip": "Die Aktualisierungssuche kann einige Zeit dauern.",
"priceAlerts": "[TODO: Translate] Price alerts",
"priceAlertsTooltip": "[TODO: Translate] Buzz price alerts for paid versions"
}
},
"bulkOperations": {
@@ -2321,7 +2326,8 @@
"notificationsTitle": "Benachrichtigungszentrum",
"tabs": {
"updates": "Aktualisierungen",
"messages": "Mitteilungen"
"messages": "Mitteilungen",
"priceAlerts": "[TODO: Translate] Price Alerts"
},
"updateAvailable": "Update verfügbar",
"noChangelogAvailable": "Kein detailliertes Changelog verfügbar. Weitere Informationen auf GitHub.",
@@ -2377,6 +2383,32 @@
"shown": "{time} angezeigt",
"dismissed": "{time} geschlossen",
"active": "Aktiv"
},
"priceAlerts": {
"disabled": "[TODO: Translate] CivitAI does not publish prices in its public API, so prices are read from the model page. Turn on price tracking to see them here.",
"openSettings": "[TODO: Translate] Open settings",
"segmentsLabel": "[TODO: Translate] Alert kind",
"segments": {
"belowThreshold": "[TODO: Translate] Under threshold",
"becameFree": "[TODO: Translate] Became free"
},
"thresholdLabel": "[TODO: Translate] Alert threshold: {buzz} Buzz",
"empty": "[TODO: Translate] Nothing is under your price threshold right now.",
"emptyFree": "[TODO: Translate] No version has become free yet.",
"loadFailed": "[TODO: Translate] Could not refresh the alerts; showing the last known list.",
"lastChecked": "[TODO: Translate] Prices last checked {when}",
"justNow": "[TODO: Translate] just now",
"minutesAgo": "[TODO: Translate] {count} min ago",
"hoursAgo": "[TODO: Translate] {count} h ago",
"daysAgo": "[TODO: Translate] {count} d ago",
"freeNow": "[TODO: Translate] Free now",
"blueBuzz": "[TODO: Translate] Blue Buzz OK",
"earlyAccessUntil": "[TODO: Translate] Early access until {date}",
"inLibrary": "[TODO: Translate] In library",
"notInLibrary": "[TODO: Translate] Not in library",
"droppedAgo": "[TODO: Translate] dropped {when}",
"openCivitai": "[TODO: Translate] Open on CivitAI",
"openLocal": "[TODO: Translate] Open"
}
},
"support": {
+34 -2
View File
@@ -234,6 +234,9 @@
},
"groupByModel": {
"label": "Group by Model"
},
"priceAlerts": {
"label": "Price alerts"
}
},
"header": {
@@ -942,7 +945,9 @@
"action": "Updates",
"menuLabel": "Show update options",
"check": "Check updates",
"checkTooltip": "Checking updates may take a while."
"checkTooltip": "Checking updates may take a while.",
"priceAlerts": "Price alerts",
"priceAlertsTooltip": "Buzz price alerts for paid versions"
}
},
"bulkOperations": {
@@ -2321,7 +2326,8 @@
"notificationsTitle": "Notifications",
"tabs": {
"updates": "Updates",
"messages": "Messages"
"messages": "Messages",
"priceAlerts": "Price Alerts"
},
"updateAvailable": "Update Available",
"noChangelogAvailable": "No detailed changelog available. Check GitHub for more information.",
@@ -2377,6 +2383,32 @@
"shown": "Shown {time}",
"dismissed": "Dismissed {time}",
"active": "Active"
},
"priceAlerts": {
"disabled": "CivitAI does not publish prices in its public API, so prices are read from the model page. Turn on price tracking to see them here.",
"openSettings": "Open settings",
"segmentsLabel": "Alert kind",
"segments": {
"belowThreshold": "Under threshold",
"becameFree": "Became free"
},
"thresholdLabel": "Alert threshold: {buzz} Buzz",
"empty": "Nothing is under your price threshold right now.",
"emptyFree": "No version has become free yet.",
"loadFailed": "Could not refresh the alerts; showing the last known list.",
"lastChecked": "Prices last checked {when}",
"justNow": "just now",
"minutesAgo": "{count} min ago",
"hoursAgo": "{count} h ago",
"daysAgo": "{count} d ago",
"freeNow": "Free now",
"blueBuzz": "Blue Buzz OK",
"earlyAccessUntil": "Early access until {date}",
"inLibrary": "In library",
"notInLibrary": "Not in library",
"droppedAgo": "dropped {when}",
"openCivitai": "Open on CivitAI",
"openLocal": "Open"
}
},
"support": {
+34 -2
View File
@@ -234,6 +234,9 @@
},
"groupByModel": {
"label": "Agrupar por modelo"
},
"priceAlerts": {
"label": "[TODO: Translate] Price alerts"
}
},
"header": {
@@ -942,7 +945,9 @@
"action": "Actualizaciones",
"menuLabel": "Mostrar opciones de actualización",
"check": "Buscar actualizaciones",
"checkTooltip": "Comprobar actualizaciones puede tardar."
"checkTooltip": "Comprobar actualizaciones puede tardar.",
"priceAlerts": "[TODO: Translate] Price alerts",
"priceAlertsTooltip": "[TODO: Translate] Buzz price alerts for paid versions"
}
},
"bulkOperations": {
@@ -2321,7 +2326,8 @@
"notificationsTitle": "Centro de notificaciones",
"tabs": {
"updates": "Actualizaciones",
"messages": "Mensajes"
"messages": "Mensajes",
"priceAlerts": "[TODO: Translate] Price Alerts"
},
"updateAvailable": "Actualización disponible",
"noChangelogAvailable": "No hay registro de cambios detallado disponible. Revisa GitHub para más información.",
@@ -2377,6 +2383,32 @@
"shown": "Mostrado {time}",
"dismissed": "Descartado {time}",
"active": "Activo"
},
"priceAlerts": {
"disabled": "[TODO: Translate] CivitAI does not publish prices in its public API, so prices are read from the model page. Turn on price tracking to see them here.",
"openSettings": "[TODO: Translate] Open settings",
"segmentsLabel": "[TODO: Translate] Alert kind",
"segments": {
"belowThreshold": "[TODO: Translate] Under threshold",
"becameFree": "[TODO: Translate] Became free"
},
"thresholdLabel": "[TODO: Translate] Alert threshold: {buzz} Buzz",
"empty": "[TODO: Translate] Nothing is under your price threshold right now.",
"emptyFree": "[TODO: Translate] No version has become free yet.",
"loadFailed": "[TODO: Translate] Could not refresh the alerts; showing the last known list.",
"lastChecked": "[TODO: Translate] Prices last checked {when}",
"justNow": "[TODO: Translate] just now",
"minutesAgo": "[TODO: Translate] {count} min ago",
"hoursAgo": "[TODO: Translate] {count} h ago",
"daysAgo": "[TODO: Translate] {count} d ago",
"freeNow": "[TODO: Translate] Free now",
"blueBuzz": "[TODO: Translate] Blue Buzz OK",
"earlyAccessUntil": "[TODO: Translate] Early access until {date}",
"inLibrary": "[TODO: Translate] In library",
"notInLibrary": "[TODO: Translate] Not in library",
"droppedAgo": "[TODO: Translate] dropped {when}",
"openCivitai": "[TODO: Translate] Open on CivitAI",
"openLocal": "[TODO: Translate] Open"
}
},
"support": {
+34 -2
View File
@@ -234,6 +234,9 @@
},
"groupByModel": {
"label": "Grouper par modèle"
},
"priceAlerts": {
"label": "[TODO: Translate] Price alerts"
}
},
"header": {
@@ -942,7 +945,9 @@
"action": "Mises à jour",
"menuLabel": "Afficher les options de mise à jour",
"check": "Rechercher des mises à jour",
"checkTooltip": "La vérification peut prendre du temps."
"checkTooltip": "La vérification peut prendre du temps.",
"priceAlerts": "[TODO: Translate] Price alerts",
"priceAlertsTooltip": "[TODO: Translate] Buzz price alerts for paid versions"
}
},
"bulkOperations": {
@@ -2321,7 +2326,8 @@
"notificationsTitle": "Notifications",
"tabs": {
"updates": "Mises à jour",
"messages": "Messages"
"messages": "Messages",
"priceAlerts": "[TODO: Translate] Price Alerts"
},
"updateAvailable": "Mise à jour disponible",
"noChangelogAvailable": "Aucun journal des modifications détaillé disponible. Consultez GitHub pour plus d'informations.",
@@ -2377,6 +2383,32 @@
"shown": "Affiché {time}",
"dismissed": "Ignoré {time}",
"active": "Actif"
},
"priceAlerts": {
"disabled": "[TODO: Translate] CivitAI does not publish prices in its public API, so prices are read from the model page. Turn on price tracking to see them here.",
"openSettings": "[TODO: Translate] Open settings",
"segmentsLabel": "[TODO: Translate] Alert kind",
"segments": {
"belowThreshold": "[TODO: Translate] Under threshold",
"becameFree": "[TODO: Translate] Became free"
},
"thresholdLabel": "[TODO: Translate] Alert threshold: {buzz} Buzz",
"empty": "[TODO: Translate] Nothing is under your price threshold right now.",
"emptyFree": "[TODO: Translate] No version has become free yet.",
"loadFailed": "[TODO: Translate] Could not refresh the alerts; showing the last known list.",
"lastChecked": "[TODO: Translate] Prices last checked {when}",
"justNow": "[TODO: Translate] just now",
"minutesAgo": "[TODO: Translate] {count} min ago",
"hoursAgo": "[TODO: Translate] {count} h ago",
"daysAgo": "[TODO: Translate] {count} d ago",
"freeNow": "[TODO: Translate] Free now",
"blueBuzz": "[TODO: Translate] Blue Buzz OK",
"earlyAccessUntil": "[TODO: Translate] Early access until {date}",
"inLibrary": "[TODO: Translate] In library",
"notInLibrary": "[TODO: Translate] Not in library",
"droppedAgo": "[TODO: Translate] dropped {when}",
"openCivitai": "[TODO: Translate] Open on CivitAI",
"openLocal": "[TODO: Translate] Open"
}
},
"support": {
+34 -2
View File
@@ -234,6 +234,9 @@
},
"groupByModel": {
"label": "קיבוץ לפי מודל"
},
"priceAlerts": {
"label": "[TODO: Translate] Price alerts"
}
},
"header": {
@@ -942,7 +945,9 @@
"action": "עדכונים",
"menuLabel": "הצגת אפשרויות עדכון",
"check": "בדוק עדכונים",
"checkTooltip": "בדיקת עדכונים עלולה לקחת זמן."
"checkTooltip": "בדיקת עדכונים עלולה לקחת זמן.",
"priceAlerts": "[TODO: Translate] Price alerts",
"priceAlertsTooltip": "[TODO: Translate] Buzz price alerts for paid versions"
}
},
"bulkOperations": {
@@ -2321,7 +2326,8 @@
"notificationsTitle": "מרכז התראות",
"tabs": {
"updates": "עדכונים",
"messages": "הודעות"
"messages": "הודעות",
"priceAlerts": "[TODO: Translate] Price Alerts"
},
"updateAvailable": "עדכון זמין",
"noChangelogAvailable": "אין יומן שינויים מפורט זמין. בדוק ב-GitHub למידע נוסף.",
@@ -2377,6 +2383,32 @@
"shown": "הוצג {time}",
"dismissed": "הוסר {time}",
"active": "פעיל"
},
"priceAlerts": {
"disabled": "[TODO: Translate] CivitAI does not publish prices in its public API, so prices are read from the model page. Turn on price tracking to see them here.",
"openSettings": "[TODO: Translate] Open settings",
"segmentsLabel": "[TODO: Translate] Alert kind",
"segments": {
"belowThreshold": "[TODO: Translate] Under threshold",
"becameFree": "[TODO: Translate] Became free"
},
"thresholdLabel": "[TODO: Translate] Alert threshold: {buzz} Buzz",
"empty": "[TODO: Translate] Nothing is under your price threshold right now.",
"emptyFree": "[TODO: Translate] No version has become free yet.",
"loadFailed": "[TODO: Translate] Could not refresh the alerts; showing the last known list.",
"lastChecked": "[TODO: Translate] Prices last checked {when}",
"justNow": "[TODO: Translate] just now",
"minutesAgo": "[TODO: Translate] {count} min ago",
"hoursAgo": "[TODO: Translate] {count} h ago",
"daysAgo": "[TODO: Translate] {count} d ago",
"freeNow": "[TODO: Translate] Free now",
"blueBuzz": "[TODO: Translate] Blue Buzz OK",
"earlyAccessUntil": "[TODO: Translate] Early access until {date}",
"inLibrary": "[TODO: Translate] In library",
"notInLibrary": "[TODO: Translate] Not in library",
"droppedAgo": "[TODO: Translate] dropped {when}",
"openCivitai": "[TODO: Translate] Open on CivitAI",
"openLocal": "[TODO: Translate] Open"
}
},
"support": {
+34 -2
View File
@@ -234,6 +234,9 @@
},
"groupByModel": {
"label": "モデルでグループ化"
},
"priceAlerts": {
"label": "[TODO: Translate] Price alerts"
}
},
"header": {
@@ -942,7 +945,9 @@
"action": "アップデート",
"menuLabel": "更新オプションを表示",
"check": "アップデートを確認",
"checkTooltip": "確認には時間がかかる場合があります。"
"checkTooltip": "確認には時間がかかる場合があります。",
"priceAlerts": "[TODO: Translate] Price alerts",
"priceAlertsTooltip": "[TODO: Translate] Buzz price alerts for paid versions"
}
},
"bulkOperations": {
@@ -2321,7 +2326,8 @@
"notificationsTitle": "通知センター",
"tabs": {
"updates": "更新",
"messages": "メッセージ"
"messages": "メッセージ",
"priceAlerts": "[TODO: Translate] Price Alerts"
},
"updateAvailable": "更新が利用可能",
"noChangelogAvailable": "詳細な変更ログは利用できません。詳細はGitHubでご確認ください。",
@@ -2377,6 +2383,32 @@
"shown": "{time} に表示",
"dismissed": "{time} に非表示",
"active": "アクティブ"
},
"priceAlerts": {
"disabled": "[TODO: Translate] CivitAI does not publish prices in its public API, so prices are read from the model page. Turn on price tracking to see them here.",
"openSettings": "[TODO: Translate] Open settings",
"segmentsLabel": "[TODO: Translate] Alert kind",
"segments": {
"belowThreshold": "[TODO: Translate] Under threshold",
"becameFree": "[TODO: Translate] Became free"
},
"thresholdLabel": "[TODO: Translate] Alert threshold: {buzz} Buzz",
"empty": "[TODO: Translate] Nothing is under your price threshold right now.",
"emptyFree": "[TODO: Translate] No version has become free yet.",
"loadFailed": "[TODO: Translate] Could not refresh the alerts; showing the last known list.",
"lastChecked": "[TODO: Translate] Prices last checked {when}",
"justNow": "[TODO: Translate] just now",
"minutesAgo": "[TODO: Translate] {count} min ago",
"hoursAgo": "[TODO: Translate] {count} h ago",
"daysAgo": "[TODO: Translate] {count} d ago",
"freeNow": "[TODO: Translate] Free now",
"blueBuzz": "[TODO: Translate] Blue Buzz OK",
"earlyAccessUntil": "[TODO: Translate] Early access until {date}",
"inLibrary": "[TODO: Translate] In library",
"notInLibrary": "[TODO: Translate] Not in library",
"droppedAgo": "[TODO: Translate] dropped {when}",
"openCivitai": "[TODO: Translate] Open on CivitAI",
"openLocal": "[TODO: Translate] Open"
}
},
"support": {
+34 -2
View File
@@ -234,6 +234,9 @@
},
"groupByModel": {
"label": "모델별 그룹화"
},
"priceAlerts": {
"label": "[TODO: Translate] Price alerts"
}
},
"header": {
@@ -942,7 +945,9 @@
"action": "업데이트",
"menuLabel": "업데이트 옵션 표시",
"check": "업데이트 확인",
"checkTooltip": "업데이트 확인에는 시간이 걸릴 수 있습니다."
"checkTooltip": "업데이트 확인에는 시간이 걸릴 수 있습니다.",
"priceAlerts": "[TODO: Translate] Price alerts",
"priceAlertsTooltip": "[TODO: Translate] Buzz price alerts for paid versions"
}
},
"bulkOperations": {
@@ -2321,7 +2326,8 @@
"notificationsTitle": "알림 센터",
"tabs": {
"updates": "업데이트",
"messages": "메시지"
"messages": "메시지",
"priceAlerts": "[TODO: Translate] Price Alerts"
},
"updateAvailable": "업데이트 사용 가능",
"noChangelogAvailable": "상세한 변경 로그가 없습니다. 더 많은 정보는 GitHub를 확인하세요.",
@@ -2377,6 +2383,32 @@
"shown": "{time}에 표시",
"dismissed": "{time}에 닫힘",
"active": "활성"
},
"priceAlerts": {
"disabled": "[TODO: Translate] CivitAI does not publish prices in its public API, so prices are read from the model page. Turn on price tracking to see them here.",
"openSettings": "[TODO: Translate] Open settings",
"segmentsLabel": "[TODO: Translate] Alert kind",
"segments": {
"belowThreshold": "[TODO: Translate] Under threshold",
"becameFree": "[TODO: Translate] Became free"
},
"thresholdLabel": "[TODO: Translate] Alert threshold: {buzz} Buzz",
"empty": "[TODO: Translate] Nothing is under your price threshold right now.",
"emptyFree": "[TODO: Translate] No version has become free yet.",
"loadFailed": "[TODO: Translate] Could not refresh the alerts; showing the last known list.",
"lastChecked": "[TODO: Translate] Prices last checked {when}",
"justNow": "[TODO: Translate] just now",
"minutesAgo": "[TODO: Translate] {count} min ago",
"hoursAgo": "[TODO: Translate] {count} h ago",
"daysAgo": "[TODO: Translate] {count} d ago",
"freeNow": "[TODO: Translate] Free now",
"blueBuzz": "[TODO: Translate] Blue Buzz OK",
"earlyAccessUntil": "[TODO: Translate] Early access until {date}",
"inLibrary": "[TODO: Translate] In library",
"notInLibrary": "[TODO: Translate] Not in library",
"droppedAgo": "[TODO: Translate] dropped {when}",
"openCivitai": "[TODO: Translate] Open on CivitAI",
"openLocal": "[TODO: Translate] Open"
}
},
"support": {
+34 -2
View File
@@ -234,6 +234,9 @@
},
"groupByModel": {
"label": "Группировать по модели"
},
"priceAlerts": {
"label": "[TODO: Translate] Price alerts"
}
},
"header": {
@@ -942,7 +945,9 @@
"action": "Обновления",
"menuLabel": "Показать параметры обновления",
"check": "Проверить обновления",
"checkTooltip": "Проверка может занять время."
"checkTooltip": "Проверка может занять время.",
"priceAlerts": "[TODO: Translate] Price alerts",
"priceAlertsTooltip": "[TODO: Translate] Buzz price alerts for paid versions"
}
},
"bulkOperations": {
@@ -2321,7 +2326,8 @@
"notificationsTitle": "Центр уведомлений",
"tabs": {
"updates": "Обновления",
"messages": "Сообщения"
"messages": "Сообщения",
"priceAlerts": "[TODO: Translate] Price Alerts"
},
"updateAvailable": "Доступно обновление",
"noChangelogAvailable": "Подробный список изменений недоступен. Проверьте GitHub для получения дополнительной информации.",
@@ -2377,6 +2383,32 @@
"shown": "Показано {time}",
"dismissed": "Закрыто {time}",
"active": "Активно"
},
"priceAlerts": {
"disabled": "[TODO: Translate] CivitAI does not publish prices in its public API, so prices are read from the model page. Turn on price tracking to see them here.",
"openSettings": "[TODO: Translate] Open settings",
"segmentsLabel": "[TODO: Translate] Alert kind",
"segments": {
"belowThreshold": "[TODO: Translate] Under threshold",
"becameFree": "[TODO: Translate] Became free"
},
"thresholdLabel": "[TODO: Translate] Alert threshold: {buzz} Buzz",
"empty": "[TODO: Translate] Nothing is under your price threshold right now.",
"emptyFree": "[TODO: Translate] No version has become free yet.",
"loadFailed": "[TODO: Translate] Could not refresh the alerts; showing the last known list.",
"lastChecked": "[TODO: Translate] Prices last checked {when}",
"justNow": "[TODO: Translate] just now",
"minutesAgo": "[TODO: Translate] {count} min ago",
"hoursAgo": "[TODO: Translate] {count} h ago",
"daysAgo": "[TODO: Translate] {count} d ago",
"freeNow": "[TODO: Translate] Free now",
"blueBuzz": "[TODO: Translate] Blue Buzz OK",
"earlyAccessUntil": "[TODO: Translate] Early access until {date}",
"inLibrary": "[TODO: Translate] In library",
"notInLibrary": "[TODO: Translate] Not in library",
"droppedAgo": "[TODO: Translate] dropped {when}",
"openCivitai": "[TODO: Translate] Open on CivitAI",
"openLocal": "[TODO: Translate] Open"
}
},
"support": {
+34 -2
View File
@@ -234,6 +234,9 @@
},
"groupByModel": {
"label": "按模型分组"
},
"priceAlerts": {
"label": "[TODO: Translate] Price alerts"
}
},
"header": {
@@ -942,7 +945,9 @@
"action": "更新",
"menuLabel": "显示更新选项",
"check": "检查更新",
"checkTooltip": "检查更新可能耗时。"
"checkTooltip": "检查更新可能耗时。",
"priceAlerts": "[TODO: Translate] Price alerts",
"priceAlertsTooltip": "[TODO: Translate] Buzz price alerts for paid versions"
}
},
"bulkOperations": {
@@ -2321,7 +2326,8 @@
"notificationsTitle": "通知中心",
"tabs": {
"updates": "更新",
"messages": "消息"
"messages": "消息",
"priceAlerts": "[TODO: Translate] Price Alerts"
},
"updateAvailable": "更新可用",
"noChangelogAvailable": "没有详细的更新日志可用。请查看 GitHub 以获取更多信息。",
@@ -2377,6 +2383,32 @@
"shown": "{time} 显示",
"dismissed": "{time} 关闭",
"active": "仍在显示"
},
"priceAlerts": {
"disabled": "[TODO: Translate] CivitAI does not publish prices in its public API, so prices are read from the model page. Turn on price tracking to see them here.",
"openSettings": "[TODO: Translate] Open settings",
"segmentsLabel": "[TODO: Translate] Alert kind",
"segments": {
"belowThreshold": "[TODO: Translate] Under threshold",
"becameFree": "[TODO: Translate] Became free"
},
"thresholdLabel": "[TODO: Translate] Alert threshold: {buzz} Buzz",
"empty": "[TODO: Translate] Nothing is under your price threshold right now.",
"emptyFree": "[TODO: Translate] No version has become free yet.",
"loadFailed": "[TODO: Translate] Could not refresh the alerts; showing the last known list.",
"lastChecked": "[TODO: Translate] Prices last checked {when}",
"justNow": "[TODO: Translate] just now",
"minutesAgo": "[TODO: Translate] {count} min ago",
"hoursAgo": "[TODO: Translate] {count} h ago",
"daysAgo": "[TODO: Translate] {count} d ago",
"freeNow": "[TODO: Translate] Free now",
"blueBuzz": "[TODO: Translate] Blue Buzz OK",
"earlyAccessUntil": "[TODO: Translate] Early access until {date}",
"inLibrary": "[TODO: Translate] In library",
"notInLibrary": "[TODO: Translate] Not in library",
"droppedAgo": "[TODO: Translate] dropped {when}",
"openCivitai": "[TODO: Translate] Open on CivitAI",
"openLocal": "[TODO: Translate] Open"
}
},
"support": {
+34 -2
View File
@@ -234,6 +234,9 @@
},
"groupByModel": {
"label": "按模型分組"
},
"priceAlerts": {
"label": "[TODO: Translate] Price alerts"
}
},
"header": {
@@ -942,7 +945,9 @@
"action": "更新",
"menuLabel": "顯示更新選項",
"check": "檢查更新",
"checkTooltip": "檢查更新可能耗時。"
"checkTooltip": "檢查更新可能耗時。",
"priceAlerts": "[TODO: Translate] Price alerts",
"priceAlertsTooltip": "[TODO: Translate] Buzz price alerts for paid versions"
}
},
"bulkOperations": {
@@ -2321,7 +2326,8 @@
"notificationsTitle": "通知中心",
"tabs": {
"updates": "更新",
"messages": "訊息"
"messages": "訊息",
"priceAlerts": "[TODO: Translate] Price Alerts"
},
"updateAvailable": "有新版本可用",
"noChangelogAvailable": "無詳細更新日誌。請至 GitHub 查看更多資訊。",
@@ -2377,6 +2383,32 @@
"shown": "{time} 顯示",
"dismissed": "{time} 關閉",
"active": "仍在顯示"
},
"priceAlerts": {
"disabled": "[TODO: Translate] CivitAI does not publish prices in its public API, so prices are read from the model page. Turn on price tracking to see them here.",
"openSettings": "[TODO: Translate] Open settings",
"segmentsLabel": "[TODO: Translate] Alert kind",
"segments": {
"belowThreshold": "[TODO: Translate] Under threshold",
"becameFree": "[TODO: Translate] Became free"
},
"thresholdLabel": "[TODO: Translate] Alert threshold: {buzz} Buzz",
"empty": "[TODO: Translate] Nothing is under your price threshold right now.",
"emptyFree": "[TODO: Translate] No version has become free yet.",
"loadFailed": "[TODO: Translate] Could not refresh the alerts; showing the last known list.",
"lastChecked": "[TODO: Translate] Prices last checked {when}",
"justNow": "[TODO: Translate] just now",
"minutesAgo": "[TODO: Translate] {count} min ago",
"hoursAgo": "[TODO: Translate] {count} h ago",
"daysAgo": "[TODO: Translate] {count} d ago",
"freeNow": "[TODO: Translate] Free now",
"blueBuzz": "[TODO: Translate] Blue Buzz OK",
"earlyAccessUntil": "[TODO: Translate] Early access until {date}",
"inLibrary": "[TODO: Translate] In library",
"notInLibrary": "[TODO: Translate] Not in library",
"droppedAgo": "[TODO: Translate] dropped {when}",
"openCivitai": "[TODO: Translate] Open on CivitAI",
"openLocal": "[TODO: Translate] Open"
}
},
"support": {