diff --git a/processor/internal/i18n/locale/de.json b/processor/internal/i18n/locale/de.json index 2ce7de1a7..1a8d1c763 100644 --- a/processor/internal/i18n/locale/de.json +++ b/processor/internal/i18n/locale/de.json @@ -28,7 +28,7 @@ "size_4": "XL", "size_5": "XXL", "rarity_1": "häufig", - "rarity_2": "selten", + "rarity_2": "seltener", "rarity_3": "selten", "rarity_4": "sehr-rar", "rarity_5": "ultra-rar", @@ -39,9 +39,9 @@ "lure_504": "Magnet Lockmodul", "lure_505": "Regen Lockmodul", "lure_506": "Gold Lockmodul", - "tracking.template_fmt": "vorlage: {0}", + "tracking.template_fmt": "template: {0}", "tracking.clean": "bereinigen", - "tracking.edit": "edit", + "tracking.edit": "bearbeiten", "tracking.summary": "zusammenfassung", "tracking.distance_fmt": "Entfernung: {0}m", "tracking.iv_fmt": "iv: {0}%-{1}%", @@ -51,13 +51,18 @@ "tracking.form_fmt": "Form: {0}", "tracking.size_fmt": "Größe: {0}-{1}", "tracking.rarity_fmt": "Seltenheit: {0}-{1}", - "tracking.weight_fmt": "Gewicht: {0}-{1}g ⚠️ Legacy Filter - Gewicht ist nicht mehr zuverlässig, benutze untrack id:N um diese Filter zu entfernen", + "tracking.weight_fmt": "Gewicht: {0}-{1}g ⚠️ Legacy Filter - Gewicht ist nicht mehr zuverlässig, benutze unbeobachte id:N um diese Filter zu entfernen", "tracking.gender_fmt": "Geschlecht: {0}", "tracking.min_time_fmt": "minimale Zeit: {0}s", "tracking.pvp_ranking": "PVP Rang:", "tracking.pvp_little": "LittleCup", "tracking.pvp_great": "Superliga", "tracking.pvp_ultra": "Hyperliga", + "tracking.pvp_mega_any": "mega", + "tracking.pvp_mega_x": "mega x", + "tracking.pvp_mega_y": "mega y", + "tracking.mega_x_label": "X", + "tracking.mega_y_label": "Y", "tracking.level_cap_fmt": "Level Obergrenze: {0}", "tracking.everything": "_alle_", "tracking.unknown_monster": "unbekanntes Pokémon", @@ -67,31 +72,35 @@ "tracking.all_level_eggs": "alle Raideilevel", "tracking.level_n_eggs": "Level {0} Eier", "tracking.all_level_maxbattles": "alle Dynakampflevel", - "tracking.level_n_maxbattles": "Level {0}Dynakampf", + "tracking.level_n_maxbattles": "Level {0} Dynakampf", "tracking.all_teams_gyms": "alle Teamarenen", - "tracking.team_gyms_fmt": "Arenen", + "tracking.team_gyms_fmt": "{0} Arenen", "tracking.with_move_fmt": "mit Attacke {0}", "tracking.controlled_by_fmt": "kontrolliert von {0}", "tracking.must_be_ex": "muss eine Ex-Raid-Arena sein", "tracking.at_gym_fmt": "an der Arena {0}", - "tracking.at_station_fmt": "an der Kraftquelle", + "tracking.at_station_fmt": "an der Kraftquelle {0}", "tracking.rsvp_without": "ohne rsvp updates", "tracking.rsvp_including": "mit rsvp updates", "tracking.rsvp_only": "nur rsvp", "tracking.reward_fmt": "Belohnung: **{0}**", "tracking.reward_stardust_min_fmt": "{0} oder mehr Sternenstaub", "tracking.reward_stardust": "Sternenstaub", - "tracking.reward_mega_energy": "Mega-Energie", + "tracking.reward_pokecoin_min_fmt": "{0} or more pokecoins", + "tracking.reward_pokecoin": "pokecoins", + "tracking.reward_mega_energy": "Megaenergie", "tracking.reward_mega_energy_fmt": "Megaenergie {0}", "tracking.reward_candy": "Bonbons", - "tracking.reward_candy_fmt": "Bonbon {0}", + "tracking.reward_candy_fmt": "Bonbons {0}", + "tracking.reward_any_pokemon": "any pokemon", + "tracking.reward_any_item": "any item", "tracking.reward_min_fmt": "mindestens {0}", "tracking.grunt_type_fmt": "Rüpel Typ **{0}**", "tracking.min_avg_spawn": "min. Spawns {0}/Stunde", "tracking.lure_type_fmt": "Lockmodul Typ: **{0}**", "tracking.fort_updates_fmt": "Fort Updates: **{0}**", "tracking.including_slot_changes": "inklusive Platzänderungen", - "tracking.including_battle_changes": "inklusive Teamänderungen", + "tracking.including_battle_changes": "inklusive Arenaangriff", "tracking.including_empty": "auch leer", "tracking.any": "_alle_", "tracking.male": "männlich", @@ -100,21 +109,79 @@ "tracking.updated": "Aktualisiert: ", "tracking.new": "Neu: ", "tracking.bulk_changes": "Es wurden viele Änderungen vorgenommen. Weitere Informationen unter {0}{1}.", - "tracking.tracked": "status", + "tracking.tracked": "beobachtet", "tracking.warn_stopped": "Alle Benachrichtigungen sind gestoppt. Benutze {0}start um sie wieder zu aktivieren.", "tracking.warn_no_location": "Du beobachtest mit Entfernung, hast aber keinen Standort gesetzt. Verwende !Standort, um einen zu setzen.", "tracking.warn_no_area": "Du beobachtest mit Gebiet, hast aber kein Gebiet gesetzt. Benutzen !area um einige hinzuzufügen.", "tracking.warn_max_distance": "Die Entfernung wurde auf das Maximum von {0}m begrenzt.", "tracking.template_not_found": "Template \"{0}\" existiert nicht.", "tracking.warn_template_not_found": "Template \"{0}\" für Typ {1}/{2} nicht gefunden. Tracking gespeichert, aber Benachrichtigungen können nicht angezeigt werden.", - "tracking.id_hint": "Um einen bestimmten Eintrag zu entfernen, verwenden seine ID - z.B. `{0}untrack id:45` oder `{0}raid remove id:12`", + "tracking.id_hint": "Um einen bestimmten Eintrag zu entfernen, verwende seine ID - z.B. `{0}unbeobachte id:45` oder `{0}raid entfernen id:12`", + "tracking.id_hint_slash": "Um einen bestimmten Eintrag zu entfernen, verwende `/unbeobachte ` (z.B. `/unbeobachte raid`) und wähle den Typ aus der Liste.", + "tracking.list_attached": "Your tracking list is long ({0} rules) — attached as a file.", "tracking.removed_prefix": "Entfernt: ", "tracking.uid_not_found": "id:{0} nicht gefunden", + "tracking.override_location_fmt": "@ {0}", + "tracking.override_areas_fmt": "in {0}", "cmd.track": "beobachte", "cmd.untrack": "unbeobachte", + "cmd.mute": "stumm", + "cmd.unmute": "lautschalten", + "msg.mute.unavailable": "Die Stummfunktion ist hier nicht aktiviert.", + "msg.mute.usage": "Gültige Befehle sind `{0}stumm [dauer:1h]`", + "msg.mute.usage_pokemon": "Gültige Befehle sind `{0}stumm pokemon [dauer:1h]`", + "msg.mute.usage_gym": "Gültige Befehle sind `{0}stumm arena [dauer:1h]`", + "msg.mute.usage_area": "Gültige Befehle sind `{0}mute gebiet [dauer:1h]`", + "msg.mute.usage_id_scope": "Gültige Befehle sind `{0}mute {0} [dauer:1h]`", + "msg.mute.bad_duration": "Ungültige Dauer: {0}", + "msg.mute.id_not_supported": "`!stumm id:N` / `!stumm id:N` werden noch nicht unterstützt - unterstützte Typen (arena, pokemon, gebiet, pokestop, kraftquelle, alle) funktionieren aktuell. Die regelbasierte Stummschaltung per UID folgt noch.", + "msg.mute.bad_uid": "`{0}` ist keine gültige Tracking-Regel UID. Nutze `!beobachtet` um Tracking-Regel UIDs anzuzeigen.", + "msg.mute.unknown_area": "`{0}` befindet sich nicht in den verfügbaren Gebieten. Nutze `!gebiet` um zu sehen, was stumm geschaltet werden kann.", + "msg.mute.no_pokemon": "Ich kenne kein Pokémon namens `{0}`.", + "msg.mute.everything_label": "alle", + "msg.mute.added": "🔇 stummgeschaltet {0} für {1}.", + "msg.mute.removed": "✅ lautschalten {0}.", + "msg.mute.none_found": "Keine aktive Stummschaltung für {0}.", + "msg.mute.cleared_all": "Entferne {0} aktive Stummschaltungen.", + "msg.unmute.usage": "Gültige Befehle sind `{0}lautschalten ` (oder `{0}lautschalten alle`)", + "msg.unmute.usage_pokemon": "Gültige Befehle sind `{0}lautschalten pokemon `", + "msg.unmute.usage_gym": "Gültige Befehle sind `{0}lautschalten arena `", + "msg.unmute.usage_area": "Gültige Befehle sind `{0}lautschalten gebiet `", + "section.property_mutes": "Eigenschaften der Stummschaltung (gelten für das gesamte Tracking):", + "section.property_mutes.left": "({0} übrig)", + "msg.button.expired": "Dieser Alarm ist abgelaufen.", + "msg.button.unavailable": "Dieser Button ist nicht mehr verfügbar.", + "msg.button.wrong_target": "Dieser Button ist hier nicht anwendbar.", + "msg.button.unauthorized": "Dieser Button ist nicht für dich.", + "msg.button.unidentified": "Ich konnte dich nicht identifizieren, um diesen Klick zu verarbeiten.", + "msg.button.unconfigured": "Dieser Button ist nicht konfiguriert.", + "msg.button.action_failed": "Diese Aktion konnte nicht abgeschlossen werden: {0}", + "msg.button.action_failed_generic": "Diese Aktion konnte nicht abgeschlossen werden.", + "msg.button.cooldown": "Langsamer angehen lassen – versuch es gleich noch einmal.", + "msg.button.actions_not_wired": "Die Button-Aktionen sind hier nicht implementiert.", + "msg.button.not_implemented": "Die {0} Aktionen sind hier nicht implementiert.", + "msg.button.responses_not_wired": "Das Rendern der Antwort ist hier nicht implementiert.", + "msg.button.response_failed": "Konnte diese Antwort nicht rendern: {0}", + "msg.button.done": "Erledigt.", + "msg.button.missing_scope": "Dem Button fehlt ein Scope – Konfigurationsfehler beim Operator.", + "msg.button.missing_target": "Es konnte kein {0} zum Stummschalten für diesen Alarm gefunden werden.", + "msg.button.no_dm_target": "Ich konnte dich nicht identifizieren, um die Nachricht zu senden.", + "msg.button.dm_failed": "Konnte es nicht per Direktnachricht senden: {0}", + "msg.button.unsubscribe_failed": "Abmeldung fehlgeschlagen - bitte versuchen Sie es erneut.", + "msg.button.unsubscribe_already": "Diese Tracking-Regeln wurden bereits entfernt.", + "msg.button.unsubscribed": "✅ Von {0} Tracking-Regel(n) abgemeldet.", + "msg.button.redeliver_sent": "📬 Per Direktnachricht gesendet.", + "msg.mute.scope_gym": "arena", + "msg.mute.scope_pokemon": "pokemon", + "msg.mute.scope_area": "gebiet", + "msg.mute.scope_pokestop": "pokestop", + "msg.mute.scope_station": "kraftquelle", + "msg.mute.scope_tracking": "Tracking-Regel", + "cmd.mute.usage": "**{0}stumm** - Benachrichtigungen stummschalten für eine bestimmte Arena, Pokemon, Gebiet, Pokestop, Kraftquelle, oder alle für ein zeitlich begrenztes Fenster.\\n\\n• `{0}stumm alle [dauer:1h]` - Stummschalten ALLER Alarme für die gegebene Dauer\\n• `{0}stumm arena [dauer:1h]` - Stummschalten der Alarme für eine Arena\\n• `{0}stumm pokemon [dauer:1h]` - Stummschalten der Alarme für eine Pokemon Spezies\\n• `{0}stumm gebiet [dauer:1h]` - Stummschalten der Alarme für ein Gebiet\\n• `{0}stumm pokestop [dauer:1h]` - Stummschalten der Alarme für einen Pokestop\\n• `{0}stumm kraftquelle [dauer:1h]` - Stummschalten der Alarme für eine Kraftquelle\\n\\nDie Dauer beträgt standardmäßig 1 Stunde, wenn sie weggelassen wird. Nutze `{0}lautschalten ` um eine Stummschaltung vorzeitig aufzuheben, oder `{0}beobachtet` um aktive Stummschaltungen anzuzeigen.", + "cmd.track.usage": "**{0}beobachte** - um Pokémon Tracking-Regeln einzurichten.\\n\\n• `{0}beobachte ` - beobachte ein spezifisches Pokemon (per Name oder Dex Id) bei standardmäßig 100m\\n• `{0}beobachte alle` - beobachte jedes Pokemon (Admin zugelassen, siehe `{0}hilfe alle`)\\n• `{0}beobachte iv:100` - nach IV Prozent gefiltert (`iv:90-100` für Bereich, `miniv:90`/`maxiv:99` für eine Begrenzung)\\n• `{0}beobachte wp:1500-2500` - nach WP gefiltert\\n• `{0}beobachte level:25-35` - nach Level gefiltert\\n• `{0}beobachte atk:14-15 def:14-15 sta:14-15` - nach individuellen IV Stats gefiltert\\n• `{0}beobachte e:500` - nur Alarme für 500m Entfernung um den Standort\\n• `{0}beobachte standort:Home e:500` - für 500m Entfernung eines gespeicherten Standorts\\n• `{0}beobachte gebiet:london,paris` - nur in den genannten Gebieten (ersetzt die Standart Gebiete)\\n• `{0}beobachte super5 hyper10` - PVP Filter (super/hyper/little, Rang Schwelle, optional Obergrenze)\\n• `{0}beobachte gen:1 typ:wasser` - Generation und Typ Filter (neben `alle`)\\n• `{0}beobachte seltenheit:ultra-rar` - Seltenheitsfilter\\n• `{0}beobachte bereinigen` / `bearbeiten` - auto-löschen bei despawn / Direktbearbeitung\\n• `{0}beobachte entfernen ` oder `{0}unbeobachte ` - entfernen\\n• `{0}unbeobachte id:42` - entferne ein Regel per Id (siehe `{0}beobachtet` für ids)\\n\\nMehrere Filter werden kombiniert. Siehe `{0}beobachtet` für das, was derzeit aktiv ist.", "cmd.raid": "raid", "cmd.egg": "ei", - "cmd.quest": "Feldforschung", + "cmd.quest": "feldforschung", "cmd.gym": "arena", "cmd.lure": "lockmodul", "cmd.invasion": "invasion", @@ -129,11 +196,11 @@ "cmd.fort": "fort", "cmd.help": "hilfe", "cmd.info": "info", - "cmd.info.poracle.moved": "→ Diese Ansicht ist jetzt unter `!poracle-admin status` verfügbar — bitte verwenden Sie diesen Befehl.", - "cmd.info.config.moved": "→ Diese Ansicht ist jetzt unter `!poracle-admin config` verfügbar — bitte verwenden Sie diesen Befehl.", + "cmd.info.poracle.moved": "→ Diese Ansicht ist jetzt unter `!poracle-admin status` verfügbar - bitte verwenden Sie diesen Befehl.", + "cmd.info.config.moved": "→ Diese Ansicht ist jetzt unter `!poracle-admin config` verfügbar - bitte verwenden Sie diesen Befehl.", "cmd.start": "start", "cmd.stop": "stop", - "cmd.tracked": "status", + "cmd.tracked": "beobachtet", "cmd.poracle": "poracle", "cmd.version": "version", "cmd.enable": "aktivieren", @@ -163,217 +230,18 @@ "cmd.poracle_clean": "poracle-clean", "cmd.poracle_emoji": "poracle-emoji", "cmd.poracle_id": "poracle-id", - "cmd.poracle_admin": "poracle-admin", - "cmd.pa": "pa", - "cmd.poracle_admin.not_admin": "Dieser Befehl ist Administratoren vorbehalten.", - "cmd.poracle_admin.unknown_group": "Unbekannte Untergruppe. Verwenden Sie `!poracle-admin` für die Liste.", - "cmd.poracle_admin.unknown_sub": "Unbekannter Unterbefehl für `{0}`. Verwenden Sie `!poracle-admin {0}` für eine Übersicht.", - "cmd.poracle_admin.help.admin_only": "Dieser Befehl ist Serveradministratoren vorbehalten. Jede Untergruppe führt eine Live-Betriebsaufgabe aus.", - "cmd.poracle_admin.help.groups": "Verfügbare Untergruppen:", - "cmd.poracle_admin.help_intro": "🛠️ Poracle Admin\n\nLive-Betriebsuntergruppen (nur für Administratoren):", - "cmd.poracle_admin.stub": "(noch nicht implementiert)", - "cmd.poracle_admin.group.slash.desc": "Lebenszyklus der Slash-Befehl-Registrierung", - "cmd.poracle_admin.group.reload.desc": "DTS, Geofence oder In-Memory-Zustand neu laden", - "cmd.poracle_admin.group.emoji.desc": "Emoji-Konfiguration auflisten, neu laden oder testen", - "cmd.poracle_admin.group.reconcile.desc": "Discord-Rollen-Abgleich (sofort oder pro Benutzer)", - "cmd.poracle_admin.group.cache.desc": "Cache-Statistiken und Cache leeren", - "cmd.poracle_admin.group.ratelimit.desc": "Nachrichten-Limits prüfen und zurücksetzen", - "cmd.poracle_admin.group.summary.desc": "Zusammenfassungs-Puffer prüfen und manuell ausliefern", - "cmd.poracle_admin.group.status.desc": "Live-Systemzustand anzeigen", - "cmd.poracle_admin.group.maintenance.desc": "Ausgehende Zustellung pausieren/fortsetzen", - "cmd.poracle_admin.group.config.desc": "Effektive Konfiguration mit maskierten Geheimnissen anzeigen", - "cmd.poracle_admin.group.warnings.desc": "Erfasste WARN/ERROR-Logeinträge anzeigen (Startup- und Rolling-Puffer)", - "cmd.poracle_admin.reload.help.intro": "Laufzeitzustand von Festplatte oder Datenbank neu laden.", - "cmd.poracle_admin.reload.dts.desc": "`dts` — DTS-Vorlagen und Partials von der Festplatte neu laden", - "cmd.poracle_admin.reload.geofence.desc": "`geofence` — Geofence-Dateien neu laden und Zustand aktualisieren", - "cmd.poracle_admin.reload.state.desc": "`state` — Tracking-Regeln und Benutzer aus MySQL neu laden (umgeht Entprellung)", - "cmd.poracle_admin.reload.dts.success": "✅ DTS in {0}ms neu geladen ({1} Vorlagen)", - "cmd.poracle_admin.reload.geofence.success": "✅ Geofence in {0}ms neu geladen ({1} Zonen, {2} Tracking-Regeln)", - "cmd.poracle_admin.reload.state.success": "✅ Zustand in {0}ms neu geladen ({1} Tracking-Regeln, {2} aktive Benutzer)", - "cmd.poracle_admin.reload.error": "❌ Neuladen fehlgeschlagen: {0}", - "cmd.poracle_admin.emoji.help.intro": "😀 Emoji-Konfiguration — emoji.json und Discord-Gilden-Emojis verwalten.\n\nUnterbefehle:", - "cmd.poracle_admin.emoji.list.desc": "`list` — Alle konfigurierten Emoji-Schlüssel mit plattformspezifischen Auflösungen auflisten", - "cmd.poracle_admin.emoji.reload.desc": "`reload` — config/emoji.json vom Datenträger neu laden", - "cmd.poracle_admin.emoji.test.desc": "`test ` — Einen Emoji-Schlüssel für die aktuelle Plattform auflösen", - "cmd.poracle_admin.emoji.upload.desc": "`upload [overwrite]` — uicons-basierte Emojis in die Gilde laden und eine neue emoji.json erzeugen (nur Discord)", - "cmd.poracle_admin.emoji.discord_config.desc": "`discord-config` — emoji.json aus dem aktuellen Gilden-Zustand ausgeben, kein Upload (nur Discord)", - "cmd.poracle_admin.emoji.discord_only": "ℹ️ Dieser Unterbefehl benötigt einen Discord-Bot mit Gilden-Zugriff.", - "cmd.poracle_admin.emoji.not_loaded": "ℹ️ Emoji-Konfiguration nicht geladen (DTS-Renderer nicht konfiguriert).", - "cmd.poracle_admin.emoji.list.header": "😀 Emoji-Konfiguration — {0} Schlüssel geladen", - "cmd.poracle_admin.emoji.list.row.key": " {0}:", - "cmd.poracle_admin.emoji.list.row.platform": " {0}: {1}", - "cmd.poracle_admin.emoji.reload.success": "✅ Emoji-Konfiguration neu geladen — {0} Schlüssel (dauerte {1}ms).", - "cmd.poracle_admin.emoji.reload.error": "❌ Emoji-Neuladen fehlgeschlagen: {0}", - "cmd.poracle_admin.emoji.test.success": "🔎 {0} auf {1}: {2}", - "cmd.poracle_admin.emoji.test.not_found": "ℹ️ Emoji-Schlüssel \"{0}\" nicht in der geladenen Konfiguration gefunden.", - "cmd.poracle_admin.emoji.test.usage": "Verwendung: !poracle-admin emoji test ", - "cmd.poracle_admin.reconcile.help.intro": "🔄 Discord-Rollen-Abgleich — sofort auslösen, ohne auf den periodischen Timer zu warten.", - "cmd.poracle_admin.reconcile.run.desc": "`run` — alle Gildenmitglieder jetzt abgleichen (blockiert bis abgeschlossen)", - "cmd.poracle_admin.reconcile.user.desc": "`user ` — einzelnen Discord-Benutzer anhand der Snowflake-ID abgleichen", - "cmd.poracle_admin.reconcile.not_configured": "❌ Discord-Rollen-Abgleich ist nicht konfiguriert (nur Telegram, oder check_role=false).", - "cmd.poracle_admin.reconcile.run.success": "✅ Discord-Rollen-Abgleich abgeschlossen (dauerte {0}ms).", - "cmd.poracle_admin.reconcile.run.error": "❌ Abgleich fehlgeschlagen: {0}", - "cmd.poracle_admin.reconcile.user.success": "✅ discord:user/{0} abgeglichen (dauerte {1}ms).", - "cmd.poracle_admin.reconcile.user.error": "❌ Abgleich von discord:user/{0} fehlgeschlagen: {1}", - "cmd.poracle_admin.reconcile.user.usage": "Verwendung: !poracle-admin reconcile user ", - "cmd.poracle_admin.cache.help.intro": "🗺️ Geocoder-Cache — Zähler abfragen oder In-Memory-Schicht leeren.", - "cmd.poracle_admin.cache.stats.desc": "`stats` — Geocoder-Cache-Statistiken", - "cmd.poracle_admin.cache.clear.desc": "`clear geocoder` — In-Memory-Geocoder-Cache leeren", - "cmd.poracle_admin.cache.not_configured": "Geocoder-Cache ist auf dieser Instanz nicht konfiguriert.", - "cmd.poracle_admin.cache.stats.header": "🗺️ Geocoder-Cache", - "cmd.poracle_admin.cache.stats.row.memory_entries": " Einträge im Arbeitsspeicher: {0}", - "cmd.poracle_admin.cache.stats.row.disk_entries": " Einträge auf Festplatte: {0}", - "cmd.poracle_admin.cache.stats.row.hits_memory": " Treffer (Speicher): {0}", - "cmd.poracle_admin.cache.stats.row.hits_disk": " Treffer (Festplatte): {0}", - "cmd.poracle_admin.cache.stats.row.misses": " Fehlschläge: {0}", - "cmd.poracle_admin.cache.stats.row.hit_rate": " Trefferquote: {0}%", - "cmd.poracle_admin.cache.clear.usage_hint": "Bitte angeben, was geleert werden soll, z.B. `!poracle-admin cache clear geocoder`", - "cmd.poracle_admin.cache.clear.geocoder.success": "✅ Geocoder-Arbeitsspeicher-Cache geleert — {0} Einträge entfernt (Festplatte unberührt).", - "cmd.poracle_admin.ratelimit.help.intro": "🚦 Nachrichten-Limit-Übersicht — Nachrichten- und Zusammenfassungs-Buckets prüfen oder zurücksetzen.", - "cmd.poracle_admin.ratelimit.not_configured": "ℹ️ Nachrichten-Limit-Dienst ist auf dieser Instanz nicht konfiguriert.", - "cmd.poracle_admin.ratelimit.list.desc": "`list` — alle Ziele anzeigen, die aktuell im Limit oder gesperrt sind", - "cmd.poracle_admin.ratelimit.show.desc": "`show ` — Detailzustand für ein Ziel (beide Buckets)", - "cmd.poracle_admin.ratelimit.reset.desc": "`reset ` — Zähler und Verletzungshistorie zurücksetzen", - "cmd.poracle_admin.ratelimit.userlist.desc": "`userlist` — derzeit deaktivierte Benutzer anzeigen (Kurzform für !userlist disabled)", - "cmd.poracle_admin.ratelimit.list.empty": "🟢 Derzeit keine Ziele im Nachrichten-Limit.", - "cmd.poracle_admin.ratelimit.list.header_title": "Aktuell limitierte Ziele", - "cmd.poracle_admin.ratelimit.list.bucket_header": " {0}-Bucket ({1} überschritten / {2} gesperrt):", - "cmd.poracle_admin.ratelimit.list.row": "Anzahl {0}/{1}, {2}", - "cmd.poracle_admin.ratelimit.list.status.banned": "gesperrt für {0}", - "cmd.poracle_admin.ratelimit.list.status.breached": "Fenster zurückgesetzt in {0}", - "cmd.poracle_admin.ratelimit.show.header": "🚦 Nachrichten-Limit-Zustand für {0}", - "cmd.poracle_admin.ratelimit.show.bucket_header": "{0}-Bucket:", - "cmd.poracle_admin.ratelimit.show.empty": "🟢 Kein erfasster Aktivitätsverlauf für {0} in einem der Buckets.", - "cmd.poracle_admin.ratelimit.show.no_data": "(keine Aktivität in diesem Bucket)", - "cmd.poracle_admin.ratelimit.show.no_violations": "Keine Verletzungen.", - "cmd.poracle_admin.ratelimit.show.violations_count": "Verletzungen (24h): {0}", - "cmd.poracle_admin.ratelimit.show.banned_until": "Gesperrt bis: {0} (in {1})", - "cmd.poracle_admin.ratelimit.show.status.under_limit": "unter dem Limit", - "cmd.poracle_admin.ratelimit.show.status.over_limit": "über dem Limit", - "cmd.poracle_admin.ratelimit.show.row.count": " Anzahl: {0} / {1} ({2})\n", - "cmd.poracle_admin.ratelimit.show.row.window": " Fenster: vor {0} geöffnet, setzt zurück in {1}\n", - "cmd.poracle_admin.ratelimit.reset.success": "✅ Nachrichten-Limit-Zustand für {0} zurückgesetzt (Alert- und Zusammenfassungs-Buckets sowie Verletzungen geleert).", - "cmd.poracle_admin.ratelimit.reset.no_state": "ℹ️ Kein Nachrichten-Limit-Zustand zum Zurücksetzen für {0}.", - "cmd.poracle_admin.ratelimit.reset.note": "Hinweis: admin_disable wird NICHT verändert. Wenn der Benutzer durch das Nachrichten-Limit deaktiviert wurde, muss er sich mit !poracle erneut registrieren.", - "cmd.poracle_admin.ratelimit.usage.show": "Verwendung: !poracle-admin ratelimit show ", - "cmd.poracle_admin.ratelimit.usage.reset": "Verwendung: !poracle-admin ratelimit reset ", - "cmd.poracle_admin.ratelimit.userlist.lookup_failed": "❌ Befehl !userlist wurde nicht in der Registrierung gefunden.", - "cmd.poracle_admin.summary.help.intro": "📦 Zusammenfassungs-Puffer — anzeigen, wer Quests gepuffert hat, und sofortiger Versand.", - "cmd.poracle_admin.summary.not_configured": "ℹ️ Zusammenfassungs-Puffer ist auf dieser Instanz nicht konfiguriert.", - "cmd.poracle_admin.summary.list.desc": "`list` — alle Benutzer mit gepufferten Einträgen anzeigen", - "cmd.poracle_admin.summary.show.desc": "`show ` — gepufferte Einträge eines Benutzers ansehen", - "cmd.poracle_admin.summary.fire.desc": "`fire [alertType]` — Puffer eines Benutzers sofort ausliefern", - "cmd.poracle_admin.summary.list.empty": "🟢 Keine Benutzer haben aktuell gepufferte Einträge.", - "cmd.poracle_admin.summary.list.header": "📦 Zusammenfassungs-Puffer — {0} Benutzer mit {1} gepufferten Einträgen", - "cmd.poracle_admin.summary.list.user_header": " {0}", - "cmd.poracle_admin.summary.list.row": " {0}: {1} Einträge (nächste Auslösung: {2})", - "cmd.poracle_admin.summary.list.next_fire.none": "n/v", - "cmd.poracle_admin.summary.show.header": "📦 Zusammenfassungs-Puffer für {0}", - "cmd.poracle_admin.summary.show.empty": "🟢 Keine gepufferten Einträge für {0}.", - "cmd.poracle_admin.summary.show.alert_type": " {0}: {1} Einträge", - "cmd.poracle_admin.summary.show.usage": "Verwendung: !poracle-admin summary show ", - "cmd.poracle_admin.summary.fire.success": "✅ Zusammenfassung für {0} / {1} ausgeliefert — {2} Einträge versendet.", - "cmd.poracle_admin.summary.fire.usage": "Verwendung: !poracle-admin summary fire [alertType]", - "cmd.poracle_admin.summary.show.reward_row": " Belohnungstyp {0}, Belohnung {1}{2} — {3} Stops", - "cmd.poracle_admin.summary.show.reward_more": " ... ({0} weitere Belohnungsgruppen)", - "cmd.poracle_admin.summary.show.form_suffix": " Form {0}", - "cmd.poracle_admin.maintenance.help.intro": "🛠️ **!poracle-admin maintenance** — Live-Steuerung der ausgehenden Zustellung.\n\nUnterbefehle:", - "cmd.poracle_admin.maintenance.no_dispatcher": "ℹ️ Der Dispatcher ist auf dieser Instanz nicht verfügbar.", - "cmd.poracle_admin.maintenance.no_reason": "(kein Grund angegeben)", - "cmd.poracle_admin.maintenance.pause.desc": "`pause [Grund...]` (Alias: `start`) — ausgehende Zustellung anhalten (Webhooks werden weiterhin empfangen, abgeglichen, gerendert und in die Warteschlange aufgenommen)", - "cmd.poracle_admin.maintenance.resume.desc": "`resume` (Alias: `stop`) — Pause aufheben und Warteschlange abarbeiten", - "cmd.poracle_admin.maintenance.status.desc": "`status` — aktuellen Zustand und Warteschlangentiefe anzeigen", - "cmd.poracle_admin.maintenance.pause.new": "🔴 Ausgehende Zustellung pausiert: {0}", - "cmd.poracle_admin.maintenance.pause.detail": "Webhooks werden weiterhin empfangen, abgeglichen, gerendert und in die Warteschlange aufgenommen — der Dispatcher hält sie bis !poracle-admin maintenance resume an.", - "cmd.poracle_admin.maintenance.pause.already": "ℹ️ Bereits pausiert seit {0} (vor {1}): {2}", - "cmd.poracle_admin.maintenance.resume.success": "🟢 Ausgehende Zustellung fortgesetzt (war für {0} pausiert: {1})", - "cmd.poracle_admin.maintenance.resume.detail": "Warteschlange wird abgearbeitet.", - "cmd.poracle_admin.maintenance.resume.not_paused": "ℹ️ Derzeit nicht pausiert.", - "cmd.poracle_admin.maintenance.status.running": "🟢 Zustellung läuft.", - "cmd.poracle_admin.maintenance.status.paused": "🔴 PAUSIERT — {0} (seit {1})", - "cmd.poracle_admin.maintenance.status.queued": "{0} Jobs warten in der Warteschlange (über alle Plattformen — Discord {1}, Telegram {2})", - "cmd.poracle_admin.status.help.intro": "!poracle-admin status — aktuelle Systemübersicht. Mit -v ausführlichere Ausgabe (Discord-Routen-Details, vollständige Webhook-Aufschlüsselung nach Typ).", - "cmd.poracle_admin.status.header": "🛠️ Poracle Admin — Übersicht", - "cmd.poracle_admin.status.paused_banner": "🔴 PAUSIERT — {0} (seit {1})\n Ausgehende Zustellung ist angehalten. Webhooks werden weiterhin empfangen und in die Warteschlange aufgenommen.", - "cmd.poracle_admin.status.value.na": "k.A.", - "cmd.poracle_admin.status.value.none": "keine", - "cmd.poracle_admin.status.section.build": "**Build / Laufzeit**", - "cmd.poracle_admin.status.section.webhooks": "**Webhook-Einlauf**", - "cmd.poracle_admin.status.section.render_queue": "**Render-Warteschlange**", - "cmd.poracle_admin.status.section.delivery": "**Zustellung**", - "cmd.poracle_admin.status.section.discord_rate": "**Discord-Limits**", - "cmd.poracle_admin.status.section.telegram_rate": "**Telegram-Limits**", - "cmd.poracle_admin.status.section.alert_limits": "**Nachrichten-Limits**", - "cmd.poracle_admin.status.section.summary_buffer": "**Zusammenfassungs-Puffer**", - "cmd.poracle_admin.status.label.summary_buffer_totals": "Einträge: {0} in {1} Bucket(s)", - "cmd.poracle_admin.status.label.summary_buffer_top": "Top-Benutzer:", - "cmd.poracle_admin.status.label.summary_buffer_user_row": " {0} ({1}): {2} Einträge", - "cmd.poracle_admin.status.section.tracking": "**Tracking-Übersicht**", - "cmd.poracle_admin.status.section.mysql": "**MySQL-Datenbank**", - "cmd.poracle_admin.status.label.version": "Version: {0} (Commit {1}, erstellt {2})", - "cmd.poracle_admin.status.label.uptime": "Laufzeit: {0}", - "cmd.poracle_admin.status.label.webhooks_rate": "{0} / {1} / {2} pro Minute (letzte 5/15/60 Min)", - "cmd.poracle_admin.status.label.webhooks_by_type": "Nach Typ (letzte 60 Min):", - "cmd.poracle_admin.status.label.delivery_discord": "Discord aktiv: {0}", - "cmd.poracle_admin.status.label.delivery_telegram": "Telegram aktiv: {0}", - "cmd.poracle_admin.status.label.delivery_webhook": "Webhook aktiv: {0}", - "cmd.poracle_admin.status.label.delivery_queue_depth": "Warteschlangentiefe: {0} (Kapazität nicht verfügbar)", - "cmd.poracle_admin.status.label.discord_routes": "Routen nahe dem Limit: {0}", - "cmd.poracle_admin.status.label.discord_global": "Globale Tokens: {0} / {1}", - "cmd.poracle_admin.status.label.discord_429s": "429-Antworten (letzte 5 Min): {0}", - "cmd.poracle_admin.status.label.discord_routes_detail": "Routen nahe dem Limit (Details):", - "cmd.poracle_admin.status.label.telegram_429s": "429-Antworten (letzte 5 Min): {0}", - "cmd.poracle_admin.status.label.telegram_backoff": "Aktuelles Backoff: {0}", - "cmd.poracle_admin.status.label.alert_limits_counts": "Überschritten: Alarme={0}, Zusammenfassungen={1} · Gesperrt: {2}", - "cmd.poracle_admin.status.label.tracking_total": "Tracking-Regeln gesamt: {0}", - "cmd.poracle_admin.status.label.tracking_active_humans": "Aktive Benutzer: {0}", - "cmd.poracle_admin.status.label.tracking_registered_humans": "Registrierte Benutzer: {0}", - "cmd.poracle_admin.status.label.tracking_registered_humans_error": "Registrierte Benutzer: k.A. (Fehler)", - "cmd.poracle_admin.status.label.tracking_type": "{0} → {1}", - "cmd.poracle_admin.status.label.mysql_ping_ok": "Ping: erfolgreich", - "cmd.poracle_admin.status.label.mysql_ping_fail": "Ping: fehlgeschlagen ({0})", - "cmd.poracle_admin.status.label.mysql_pool": "Verbindungen: {0}/{1} offen ({2} in Verwendung, {3} im Leerlauf, Wartezeiten={4})", - "cmd.poracle_admin.status.tracking_type.pokemon": "Pokémon", - "cmd.poracle_admin.status.tracking_type.raid": "Raid", - "cmd.poracle_admin.status.tracking_type.egg": "Ei", - "cmd.poracle_admin.status.tracking_type.quest": "Quest", - "cmd.poracle_admin.status.tracking_type.invasion": "Invasion", - "cmd.poracle_admin.status.tracking_type.lure": "Lockmodul", - "cmd.poracle_admin.status.tracking_type.nest": "Nest", - "cmd.poracle_admin.status.tracking_type.gym": "Arena", - "cmd.poracle_admin.status.tracking_type.fort": "Stop/Arena", - "cmd.poracle_admin.status.tracking_type.maxbattle": "Max-Kampf", - "cmd.poracle_admin.slash.help.intro": "**!poracle-admin slash** — Lebenszyklus der Slash-Befehl-Registrierung.\nUnterbefehle:", - "cmd.poracle_admin.slash.discord_only": "❌ Slash-Befehle sind Discord-exklusiv und können nicht über Telegram verwaltet werden.", - "cmd.poracle_admin.slash.not_configured": "❌ Slash-Befehle sind nicht konfiguriert (Discord deaktiviert oder [discord.slash_commands] enabled=false).", - "cmd.poracle_admin.slash.sync.desc": "aktuellen Befehlssatz an Discord übertragen (fingerabdruckbasierter Cache, überspringt bei unverändertem Stand)", - "cmd.poracle_admin.slash.sync.success": "✅ Slash-Synchronisierung abgeschlossen ({0}ms)", - "cmd.poracle_admin.slash.sync.error": "❌ Slash-Synchronisierung fehlgeschlagen: {0}", - "cmd.poracle_admin.slash.force_resync.desc": "Fingerabdruck-Cache leeren und danach unbedingt übertragen", - "cmd.poracle_admin.slash.force_resync.success": "✅ Erzwungene Neusynchronisierung abgeschlossen ({0}ms)", - "cmd.poracle_admin.slash.force_resync.error": "❌ Erzwungene Neusynchronisierung fehlgeschlagen: {0}", - "cmd.poracle_admin.slash.clear_global.desc": "alle global registrierten Discord-Slash-Befehle entfernen", - "cmd.poracle_admin.slash.clear_global.success": "✅ Globale Slash-Befehle gelöscht.", - "cmd.poracle_admin.slash.clear_global.error": "❌ Globales Löschen fehlgeschlagen: {0}", - "cmd.poracle_admin.slash.clear_guild.desc": "Slash-Befehle von einem Server entfernen (guild_id erforderlich)", - "cmd.poracle_admin.slash.clear_guild.needs_arg": "❌ Verwendung: `!poracle-admin slash clear-guild `", - "cmd.poracle_admin.slash.clear_guild.success": "✅ Slash-Befehle vom Server {0} gelöscht.", - "cmd.poracle_admin.slash.clear_guild.error": "❌ Server-Löschen fehlgeschlagen: {0}", - "cmd.poracle_admin.slash.status.desc": "letzten Synchronisierungszeitstempel und Fingerabdruck je Bereich anzeigen", - "cmd.poracle_admin.slash.status.header": "**Status der Slash-Befehl-Registrierung:**", - "cmd.poracle_admin.slash.status.scope_row": " **{0}**: zuletzt synchronisiert {1} · Fingerabdruck `{2}`", - "cmd.poracle_admin.slash.status.never_synced": "nie", - "cmd.poracle_admin.slash.status.ago": "vor {0}", - "cmd.poracle_admin.slash.status.error": "❌ Statusabfrage fehlgeschlagen: {0}", "arg.remove": "entfernen", "arg.everything": "alle", + "arg.all_pokemon": "all pokemon", + "arg.all_items": "all items", "arg.any": "alle", "arg.clean": "bereinigen", - "arg.edit": "edit", + "arg.edit": "bearbeiten", "arg.individually": "einzeln", "arg.list": "auflisten", "arg.add": "hinzufügen", "arg.show": "zeigen", + "arg.default": "standard", "arg.overview": "übersicht", "arg.dryrun": "trockenlauf", "arg.reset": "zurücksetzen", @@ -386,6 +254,7 @@ "arg.shiny": "schillernd", "arg.gmax": "gmax", "arg.stardust": "sternenstaub", + "arg.pokecoin": "pokecoins", "arg.energy": "energie", "arg.candy": "bonbons", "arg.pvp": "pvp", @@ -404,9 +273,9 @@ "arg.no_rsvp": "kein rsvp", "arg.rsvp_only": "nur rsvp", "arg.slot_changes": "platzänderung", - "arg.battle_changes": "wird angegriffen", + "arg.battle_changes": "arenaangriff", "arg.include_empty": "inklusive leer", - "arg.pokestop": "Pokestop", + "arg.pokestop": "pokestop", "arg.gym": "arena", "arg.station": "kraftquelle", "arg.location": "standort", @@ -415,7 +284,7 @@ "arg.photo": "foto", "arg.name": "name", "arg.description": "beschreibung", - "arg.normal": "Normal", + "arg.normal": "normal", "arg.glacial": "gletscher", "arg.mossy": "moos", "arg.magnetic": "magnet", @@ -452,8 +321,11 @@ "arg.prefix.maxsize": "maxgröße", "arg.prefix.gen": "gen", "arg.prefix.cap": "cap", + "arg.mega": "mega", + "arg.prefix.mega": "mega", "arg.prefix.form": "form", - "arg.prefix.template": "vorlage", + "arg.prefix.costume": "costume", + "arg.prefix.template": "template", "arg.prefix.gym": "arena", "arg.prefix.move": "attacke", "arg.prefix.minspawn": "minspawn", @@ -467,13 +339,17 @@ "arg.prefix.littlehigh": "littlehoch", "arg.prefix.littlecp": "littlewp", "arg.prefix.stardust": "sternenstaub", + "arg.prefix.pokecoin": "pokecoins", "arg.prefix.energy": "energie", "arg.prefix.candy": "bonbons", + "arg.prefix.amount": "menge", "arg.prefix.name": "name", "arg.prefix.user": "benutzer", "arg.prefix.channel": "kanal", "arg.prefix.guild": "gilde", "arg.prefix.language": "sprache", + "arg.prefix.area": "gebiet", + "arg.prefix.location": "standort", "arg.prefix.mon": "mo", "arg.prefix.tue": "di", "arg.prefix.wed": "mi", @@ -483,7 +359,7 @@ "arg.prefix.sun": "so", "arg.prefix.weekday": "werktag", "arg.prefix.weekend": "wochenende", - "arg.prefix.every": "jedes", + "arg.prefix.every": "jeden", "arg.prefix.everyday": "jedentag", "raid.level.legendary": "Legendär", "raid.level.mega": "Mega", @@ -512,8 +388,8 @@ "section.eggs": "** Eier:**", "section.eggs.none": "Es werden keine Eier beobachtet.", "section.quests": "**Feldforschungen:**", - "section.quests.none": "Es werden keine Quests beobachtet.", - "section.invasions": "**Invasions:**", + "section.quests.none": "Es werden keine Feldforschungen beobachtet.", + "section.invasions": "**Invasionen:**", "section.invasions.none": "Es werden keine Team-GO-Rocket-Invasionen beobachtet.", "section.lures": "**Lockmodule:**", "section.lures.none": "Es werden keine Lockmodule beobachtet.", @@ -527,20 +403,25 @@ "section.maxbattles.none": "Es werden keine dynamax Kämpfe beobachtet.", "msg.no_pokemon": "Fehler: Kein gültiges Pokémon angegeben.", "msg.form_not_found": "Form `{0}` nicht erkannt. Verwende `{1}info ` um die verfügbaren Formen zu sehen.", + "msg.costume_not_found": "Costume `{0}` not recognised. Use `{1}info costumes` to see available costumes.", + "msg.no_costume": "no costume", "msg.nothing_to_remove": "Nichts zu entfernen", "msg.no_levels": "Keine Level angegeben", "msg.no_egg_levels": "Fehler: Kein Raid-Ei-Level angegeben.", "msg.no_raid_target": "Fehler: Kein gültiger Raid-Boss oder gültiges Raid-Level angegeben.", "msg.no_lure_type": "Kein Lockmodultyp gefunden", - "msg.no_quest_type": "Fehler: Keine gültige Quest angegeben.", + "msg.no_quest_type": "Fehler: Keine gültige Feldforschung angegeben.", + "msg.quest.amount_not_applicable": "`menge:N` gilt nicht für Pokémon Feldforschungen – bei Pokémon-Belohnungen gibt es keine Mindestmenge.", + "msg.quest.bulk_not_permitted": "You do not have permission to track all pokemon or items at once. Track specific rewards instead.", "msg.removed_n": "Ich habe {0} Einträge entfernt", "msg.egg.usage": "Gültige Befehle sind z.B. `{0}ei level:5`, `{0}ei legendär`, `{0}ei entfernen alle`", "msg.raid.usage": "Gültige Befehle sind z.B. `{0}raid level:5`, `{0}raid pikachu`, `{0}raid entfernen alle`", "msg.track.usage": "Gültige Befehle sind z.B. `{0}beobachte pikachu iv:100`, `{0}beobachte alle iv:90`, `{0}beobachte entfernen pikachu`", "msg.track.everything_no_filters": "Dies würde zu zu vielen Meldungen führen. Du musst zusätzliche Filter wählen, um die Anzahl gültiger Kandidaten zu begrenzen.", "msg.track.invalid_cap": "Diese Level-Obergrenze wird nicht unterstützt. Gültige Werte: {0}", - "msg.quest.usage": "Gültige Befehle sind z.B. `{0}quest pikachu`, `{0}quest sternenstaub:1000`, `{0}quest energie:glurak`", - "msg.quest.edit_summary_conflict": "`edit` und `zusammenfassung` schließen sich gegenseitig aus - wähle eins aus.", + "msg.track.no_mega_form": "⚠️ {0} has no Mega {1} form — this PVP rule will never match.", + "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest pokecoins:10`, `{0}quest energy:charizard`", + "msg.quest.edit_summary_conflict": "`bearbeiten` und `zusammenfassung` schließen sich gegenseitig aus - wähle eins aus.", "msg.summary.usage": "Verwendung: `{0}zusammenfassung Quest [settime |cleartime|jetzt]`", "msg.summary.settime_invalid": "Zeitplaneintrag kann nicht geparst werden `{0}`: {1}", "msg.summary.no_schedule": "Kein Zeitplan für {0} Zusammenfassung gesetzt.", @@ -566,14 +447,36 @@ "msg.fort.usage": "Gültige Befehle sind z.B. `{0}fort pokestop`, `{0}fort alle`, `{0}fort entfernen pokestop`", "msg.location.removed": "Standort entfernt", "msg.location.usage": "Gültige Befehle sind z.B. `{0}standort ,`, `{0}standort `", - "msg.location.specify": "Konnte den Standort nicht verstehen", + "msg.location.specify": "Bitte geben Sie Koordinaten oder eine Adresse an.", "msg.location.set": "Neuer Standort: {0},{1}", "msg.location.current": "Dein aktueller Standort ist {0},{1}", + "msg.location.added": "✅ gespeicherter Standort `{0}` bei {1}, {2}.", + "msg.location.duplicate": "🙅 Sie haben bereits einen gespeicherten Ort namens `{0}`. Entfernen ihn zuerst mit `{1}standort entfernen {0}`.", + "msg.location.list_header": "Deine gespeicherten Standorte:", + "msg.location.list_row": " `{0}`: {1}, {2}", + "msg.location.list_row_with_addr": " `{0}`: {1}, {2} — {3}", + "msg.location.list_empty": "Kein gespeicherten Standorte. Füge einen mit `{0}standort hinzufügen `.", + "msg.location.show_not_found": "🙅 Kein gespeicherter Standort namens `{0}`.", + "msg.location.show": "📍 `{0}` ist bei {1}, {2}.", + "msg.location.show_with_addr": "📍 `{0}` ist bei {1}, {2} — {3}", + "msg.location.no_default": "🙅 Kein standart Standort gesetzt.", + "msg.location.default_removed": "✅ Standart Standort entfernt.", + "msg.location.remove_referenced": "🙅 kann nicht gelöscht werden `{0}` — {1} Tracking-Regel(n) verweisen auf: {2}. Bearbeiten oder entferne diese Regeln zuerst.", + "msg.location.add_usage": "Gültige Befehle sind `{0}standort hinzufügen `", + "msg.location.show_usage": "Gültige Befehle sind `{0}standort zeigen `", + "msg.location.remove_usage": "Gültige Befehle sind `{0}standort entfernen `, `{0}standort entfernen standart`", + "msg.location.geocode_failed": "🙅 Keinen passenden Ort zu `{0}` gefunden.", + "cmd.location.usage": "**{0}standort** - Verwalten den Standardstandort und gespeicherten benannten Standorte.\\n\\n• `{0}standort` — Zeige den aktuellen Standardstandort an.\\n• `{0}standort ` — den Standardstandort setzen\\n• `{0}standort hinzufügen ` — einen benannten Ort speichern (später referenziert als `standort:` bei Trackingregeln)\\n• `{0}standort auflisten` — listet alle gespeicherten Standorte auf\\n• `{0}standort zeigen ` — zeigt einen gespeicherten Standort Coords + Addresse an (nutze `standart` für deinen Standartstandort)\\n• `{0}standort entfernen ` — löscht einen gespeicherten Standort (Verweigert, falls eine Tracking-Regel darauf verweist.)\\n• `{0}standort entfernen standart` — entfernt den Standartstandort", + "msg.override.requires_distance": "🙅 `standort:` benötigt eine `e:` Entfernung - z.B. `standort:Home e:500`.", + "msg.override.area_and_distance": "🙅 `gebiet:` und `e:` schließen sich gegenseitig aus (Gebiet-Modus vs. Entfernung-Modus). Wähle eins.", + "msg.override.area_and_location": "🙅 `gebiet:` und `standort:` schließen sich gegenseitig aus. Wähle eins.", + "msg.override.unknown_location": "🙅 Kein gespeicherter Standort namens `{0}`. Hinzufügen mit `{1}standort hinzufügen {0} `.", + "msg.override.area_not_permitted": "🙅 Gebiet `{0}` Befindet sich nicht in den zulässigen Gebieten. Nutze `{1}gebiet auflisten` um anzuzeigen, was ausgewählt werden kann.", "msg.area.usage": "Gültige Befehle sind `{0}gebiet auflisten`, `{0}gebiet hinzufügen `, `{0}gebiet entfernen `", "msg.area.none_available": "Keine Gebiete verfügbar", "msg.area.available": "**Verfügbare Gebiete:**", - "msg.area.specify_add": "Bitte Gebietsnamen angeben", - "msg.area.specify_remove": "Bitte Gebietsnamen angeben", + "msg.area.specify_add": "Bitte Gebietsnamen zum Hinzufügen angeben", + "msg.area.specify_remove": "Bitte Gebietsnamen zum Entfernen angeben", "msg.area.added": "Hinzugefügte Gebiete: {0}", "msg.area.not_found": "Nicht gefunden: {0}", "msg.area.removed": "Entfernte Gebiete: {0}", @@ -607,23 +510,34 @@ "msg.language.specify": "Bitte gib eine Sprache an!", "msg.language.available": "Verfügbare Sprachen: {0}", "msg.language.unknown": "Poracle unterstützt nur folgende Sprachen: {0}", - "msg.gym.battle_disabled": "Teamänderungs Tracking ist nicht aktiviert", + "msg.gym.battle_disabled": "Arenaangriff Tracking ist nicht aktiviert", "msg.weather.unavailable": "Wetter-Tracking ist über diesen Befehl noch nicht verfügbar", - "msg.help.unknown_topic": "Keine Hilfe verfügbar für '{0}'. Verwende `{1}hilfe` für allgemeine Hilfe.", - "msg.help.no_greeting": "Keine Hilfevorlage konfiguriert. Verwende `{0}hilfe ` für kommandospezifische Hilfe.", - "msg.info.sub.moves": "Attacken", - "msg.info.sub.items": "Items", + "msg.help.unknown_topic": "Keine Hilfe verfügbar für '{0}'. Verwende `{1}help` für allgemeine Hilfe.", + "msg.help.no_greeting": "Keine Hilfevorlage konfiguriert. Verwende `{0}help ` für kommandospezifische Hilfe.", + "msg.help.see_detailed": "💡 Ausführlichere Hilfe ist verfügbar — `{0}hilfe {1}`", + "msg.info.sub.moves": "attacken", + "msg.info.sub.items": "items", "msg.info.sub.shiny": "schillernd", - "msg.info.sub.rarity": "Seltenheit", - "msg.info.sub.weather": "Wetter", + "msg.info.sub.rarity": "seltenheit", + "msg.info.sub.weather": "wetter", "msg.info.sub.poracle": "poracle", "msg.info.sub.config": "config", - "msg.info.sub.translate": "Übersetzen", + "msg.info.sub.translate": "übersetzen", "msg.info.sub.dts": "dts", "msg.info.sub.templates": "templates", - "msg.info.usage": "Gültige Befehle sind `{0}info templates`, `{0}info seltenheit`, `{0}info schillernd`, `{0}info wetter`, `{0}info attacken`, `{0}info items`, `{0}info `", + "msg.info.sub.costumes": "costumes", + "msg.info.sub.forms": "forms", + "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info costumes`, `{0}info `", "msg.info.usage_admin": "Admin: `{0}info poracle`, `{0}info dts`, `{0}info übersetzen `, `{0}info config [suche]`", "msg.info.available_forms": "verfügbare Formen", + "msg.info.more_forms": "More than {0} forms — do {1} for the full list", + "msg.info.recent_forms": "**Recently-seen forms:**", + "msg.info.recent_raid_forms": "**Recently-seen raid forms:**", + "msg.info.available_costumes": "**Recently-seen costumes:**", + "msg.info.recent_raid_costumes": "**Recently-seen raid costumes:**", + "msg.info.costumes.header": "**Costumes** (`costume:` to track):", + "msg.info.no_costume_data": "No costume data loaded", + "msg.info.no_form_data": "No form data for that pokemon.", "msg.info.hundo_cp": "100% IV WP:", "msg.info.dts_summary": "DTS Templates geladen:", "msg.info.pokemon_not_found": "Pokemon nicht gefunden: {0}", @@ -662,9 +576,9 @@ "msg.info.rarity_header": "**Seltenheitsstatistik**", "msg.info.rarity_unavailable": "Seltenheitswert noch nicht berechnet - warte ein paar Minuten und versuche es erneut", "msg.info.weather_unavailable": "Wetterdaten nicht verfügbar", - "msg.info.weather_invalid_coords": "Ungültige Koordinaten. Verwendung: Info Wetter lat,lon", - "msg.info.weather_no_location": "Kein Standort gesetzt. Verwenden Info Wetter lat,lon oder setze zuerst einen Standort", - "msg.info.weather_location": "Wetter {0}, {1}:", + "msg.info.weather_invalid_coords": "Ungültige Koordinaten. Verwendung: info wetter lat,lon", + "msg.info.weather_no_location": "Kein Standort gesetzt. Verwende info wetter lat,lon oder setze zuerst einen Standort", + "msg.info.weather_location": "Wetter bei {0}, {1}:", "msg.info.weather_current": "Aktuelles Wetter: {0}", "msg.info.weather_boosts": "Geboostete Typen: {0}", "msg.info.weather_forecast": "Vorhersage (nächste Stunde): {0}", @@ -689,23 +603,23 @@ "msg.enable.specify": "Bitte Benutzer-IDs angeben", "msg.enable.success": "Aktiviert: {0}", "msg.disable.success": "Deaktiviert: {0}", - "msg.no_permission": "keine Berechtigung dieses Komando zu benutzen", + "msg.no_permission": "keine Berechtigung diesen Befehl zu benutzen", "msg.no_permission.pokemon": "keine Berechtigung Pokémon zu tracken", "msg.no_permission.gym": "keine Berechtigung Arenen zu tracken", "msg.no_permission.invasion": "keine Berechtigung Team-GO-Rocket-Invasionen zu tracken", "msg.no_permission.lure": "keine Berechtigung Lockmodule zu tracken", "msg.no_permission.maxbattle": "keine Berechtigung dynamax Kämpfe zu tracken", "msg.no_permission.fort": "keine Berechtigung Gym und Stop Änderungen zu tracken", - "msg.stop.warn_args": "Der Befehl {0}{1} stoppt alle Warnmeldungen. Ist das gewünscht?", - "msg.stop.success": "Alle Warnmeldungen wurden gestoppt, sie können mit {0}{1} fortgesetzt werden.", - "msg.start.success": "Warnmeldungen wurden wieder aktiviert", + "msg.stop.warn_args": "Der Befehl {0}{1} stoppt alle Alarm Nachrichten. Ist das gewünscht?", + "msg.stop.success": "Alle Alarm Nachrichten wurden gestoppt, sie können mit {0}{1} fortgesetzt werden.", + "msg.start.success": "Alarm Nachrichten wurden wieder aktiviert", "msg.language.changed": "Folgende Sprache wurde eingestellt: {0}", "msg.language.current": "Aktuell eingestellte Sprache: {0}", "msg.location.not_found": "Konnte den Standort nicht verstehen", "msg.location.new": "Neuer Standort", "msg.area.display": "gewähltes Gebiet: {0}", "msg.area.overview_display": "Übersichtsanzeige", - "msg.area.invalid": "Kein gültiges Gebiet. Nutze `{0}{1} list`", + "msg.area.invalid": "Kein gültiges Gebiet. Nutze `{0}{1} auflisten`", "msg.area.current": "Aktuell sind folgende Gebiete festgelegt:", "msg.userlist.registered": "Folgende Nutzer sind bei Poracle registriert:", "msg.userlist.none": "Keine registrierten Benutzer entsprechen Ihren Filtern.", @@ -714,7 +628,7 @@ "msg.dm_only": "Befehle müssen als Direktnachrichten an den Poracle-Bot gesendet werden!", "msg.admin_no_distance": "Warnung: Befehl ohne Distanz erkannt - standard Distanz wird stattdessen verwendet", "msg.not_registered": "Du bist nicht registriert. Bitte registriere dich zuerst.", - "msg.channel_admin_only": "Nur Channel-Administratoren können Befehle in diesem Kanal ausführen. DM dem Bot mit {0}komando, um deine persönlichen Trackings zu verwalten.", + "msg.channel_admin_only": "Nur Channel-Administratoren können Befehle in diesem Kanal ausführen. DM dem Bot mit {0}deinbefehl, um deine persönlichen Trackings zu verwalten.", "msg.backup.invalid_name": "Fügen einen gültigen Backup Namen hinzu (nur: Buchstaben, Zahlen, Bindestriche und Unterstriche)", "msg.backup.need_name": "Dein Backup benötigt einen gültigen Namen (nur: Buchstaben, Zahlen, Bindestriche, Unterstriche)", "msg.restore.no_backups_dir": "Kein Backupverzeichnis gefunden", @@ -735,74 +649,73 @@ "language.pl": "Polnisch", "language.ru": "Russisch", "language.es": "Spanisch", - "language.sv": "Svenska", + "language.sv": "Schwedisch", "language.zh-cn": "Chinesisch (vereinfacht)", "language.ja": "Japanisch", - "msg.help.text": "**verfügbare Commands:**\n{0}track [iv:N] [wp:N] [level:N] [d:N] - Pokemon tracken\n{0}untrack - Pokemon tracking entfernen\n{0}raid [d:N] - Raids tracken\n{0}ei [d:N] - Raideier tracken\n{0}quest - Feldforschungen tracken\n{0}invasion [alle|] - Invasionen tracken\n{0}lockmodul - Lockmodule tracken\n{0}gym [platzänderung] - Arenen tracken\n{0}nest - Nester tracken\n{0}maxbattle - Dynamax Kämpfe tracken\n{0}fort - Fort updates tracken\n{0}tracked - Alle Trackings anzeigen\n{0}skript - Trackings als Commands exportieren\n{0}gebiet [auflisten|hinzufügen|entfernen] - Gebiete organisieren\n{0}standort - Standort setzen\n{0}profile [auflisten|hinzufügen|entfernen|wechseln] - Profile organisieren\n{0}sprache - Sprache wählen\n{0}start / {0}stop - Benachrichtigungen einschalten/abschalten\n{0}version - Version anzeigen", "slash.cmd.version": "version", "slash.desc.version": "Poracle-Version anzeigen", - "slash.cmd.tracked": "tracked", - "slash.desc.tracked": "Deine Tracking-Regeln anzeigen", + "slash.cmd.tracked": "beobachtet", "slash.cmd.help": "hilfe", - "slash.desc.help": "Hilfe anzeigen", "slash.cmd.info": "info", - "slash.desc.info": "Pokemon-Infos, Shinyraten, Seltenheit oder aktuelles Wetter anzeigen", + "slash.cmd.language": "sprache", + "slash.cmd.track": "beobachte", + "slash.cmd.raid": "raid", + "slash.cmd.egg": "ei", + "slash.cmd.quest": "feldforschung", + "slash.cmd.invasion": "invasion", + "slash.cmd.incident": "ereignis", + "slash.cmd.lure": "lockmodul", + "slash.cmd.nest": "nest", + "slash.cmd.maxbattle": "dynamax", + "slash.cmd.gym": "arena", + "slash.cmd.fort": "fort", + "slash.cmd.untrack": "unbeobachte", + "slash.cmd.area": "gebiet", + "slash.cmd.profile": "profil", + "slash.cmd.location": "standort", + "slash.cmd.summary": "zusammenfassung", + "slash.cmd.start": "start", + "slash.cmd.stop": "stop", + "slash.desc.tracked": "Deine Tracking-Regeln anzeigen", + "slash.desc.start": "Benachrichtigungen wieder aktivieren (nach /stop)", + "slash.desc.stop": "Benachrichtigungen pausieren (mit /start fortsetzen)", + "slash.desc.help": "Hilfe anzeigen", + "slash.desc.info": "Deine Bot-Registrierungsinfos anzeigen", "slash.opt.info.pokemon": "pokemon", "slash.opt.info.pokemon.desc": "Typen, Werte, Entwicklungen, Wetterboost und WP-Tabelle eines Pokemon anzeigen", "slash.opt.info.pokemon.name": "name", "slash.opt.info.pokemon.name.desc": "Pokemon-Name (beliebige unterstützte Sprache) oder Pokedex-ID", "slash.opt.info.rarity": "seltenheit", "slash.opt.info.rarity.desc": "Pokemon nach Spawn-Seltenheit gruppiert (häufig → ultra-selten)", - "slash.opt.info.shiny": "shiny", + "slash.opt.info.shiny": "schillernd", "slash.opt.info.shiny.desc": "Beobachtete Shinyraten pro Art anzeigen", "slash.opt.info.weather": "wetter", "slash.opt.info.weather.desc": "Aktuelles Wetter und geboostete Typen für einen Standort", "slash.opt.info.weather.coords": "koordinaten", "slash.opt.info.weather.coords.desc": "lat,lon (Standardmäßig dein gespeicherter Standort)", - "slash.cmd.start": "start", - "slash.desc.start": "Benachrichtigungen wieder aktivieren (nach /stop)", - "slash.cmd.stop": "stop", - "slash.desc.stop": "Benachrichtigungen pausieren (mit /start fortsetzen)", - "slash.cmd.language": "sprache", "slash.desc.language": "Sprache anzeigen oder ändern", - "slash.cmd.track": "track", - "slash.desc.track": "Ein Pokémon verfolgen", - "slash.cmd.raid": "raid", - "slash.desc.raid": "Einen Raidboss oder ein Raid-Level verfolgen", - "slash.cmd.egg": "ei", - "slash.desc.egg": "Ein Ei / Raid-Level verfolgen", - "slash.cmd.quest": "quest", - "slash.desc.quest": "Eine Quest-Belohnung verfolgen", - "slash.cmd.invasion": "invasion", - "slash.desc.invasion": "Eine Team-Rocket-Invasion verfolgen", - "slash.cmd.incident": "ereignis", - "slash.desc.incident": "Einen PokéStop-Vorfall verfolgen (Kecleon, Goldener PokéStop, Showcase…)", - "slash.cmd.lure": "lockmodul", - "slash.desc.lure": "Ein PokéStop-Lockmodul verfolgen", - "slash.cmd.nest": "nest", - "slash.desc.nest": "Ein nistendes Pokémon verfolgen", - "slash.cmd.maxbattle": "dynamax", - "slash.desc.maxbattle": "Einen Dynamax-Kampf verfolgen", - "slash.cmd.gym": "arena", - "slash.desc.gym": "Arena-Änderungen verfolgen (Team / Plätze / Kämpfe)", - "slash.cmd.fort": "fort", - "slash.desc.fort": "PokéStop- oder Arena-Updates verfolgen", - "slash.cmd.untrack": "untrack", + "slash.desc.track": "Beobachte ein Pokemon", + "slash.desc.raid": "Beobachte einen Raidboss oder Raidlevel", + "slash.desc.egg": "Beobachte einen Raidei / Raidlevel", + "slash.desc.quest": "Beobachte eine Feldforschungsbelohnung", + "slash.desc.invasion": "Beobachte eine Team Go Rocket Invasion", + "slash.desc.incident": "Beobachte einen Pokestop Ereignis (Kecleon, Goldstop, Showcase…)", + "slash.desc.lure": "Beobachte ein Pokestop Lockmodul", + "slash.desc.nest": "Beobachte ein nistendes Pokemon", + "slash.desc.maxbattle": "Beobachte ein Giga- Dynamaxkampf", + "slash.desc.gym": "Beobachte Arena Team / Slot / Kampf Änderungen", + "slash.desc.fort": "Beobachte Pokestop oder Arena Updates", "slash.desc.untrack": "Eine Tracking-Regel entfernen", - "slash.cmd.area": "gebiet", "slash.desc.area": "Deine Gebiete verwalten", - "slash.cmd.profile": "profil", "slash.desc.profile": "Deine Profile verwalten", - "slash.cmd.location": "standort", "slash.desc.location": "Deinen Standort festlegen", - "slash.cmd.summary": "zusammenfassung", - "slash.desc.summary": "Geplante Zusammenfassungen verwalten (z. B. Quest)", + "slash.desc.summary": "Deine geplante Zusammenfassungen verwalten (z.B. Feldforschung)", "slash.opt.help.topic": "thema", "slash.opt.help.topic.desc": "Hilfe-Thema", "slash.opt.language.code": "code", "slash.opt.language.code.desc": "Sprachcode", "slash.opt.track.pokemon": "pokemon", - "slash.opt.track.pokemon.desc": "Pokémon zum Verfolgen (oder 'everything')", + "slash.opt.track.pokemon.desc": "Pokémon zum verfolgen (oder 'alle')", "slash.opt.track.iv": "iv", "slash.opt.track.iv.desc": "IV-Filter (z. B. 100, 95, 0-0)", "slash.opt.track.distance": "entfernung", @@ -815,8 +728,8 @@ "slash.opt.track.little_rank.desc": "Bester PVP-Rang in der Little League", "slash.opt.track.clean": "bereinigen", "slash.opt.track.clean.desc": "Benachrichtigung löschen, wenn das Pokémon verschwindet", - "slash.opt.track.template": "vorlage", - "slash.opt.track.template.desc": "DTS-Vorlagenname", + "slash.opt.track.template": "template", + "slash.opt.track.template.desc": "DTS-Templatenname", "slash.opt.track.form": "form", "slash.opt.track.form.desc": "Pokémon-Form", "slash.opt.track.size": "größe", @@ -838,8 +751,8 @@ "slash.opt.raid.distance.desc": "Benachrichtigungsradius in Metern", "slash.opt.raid.clean": "bereinigen", "slash.opt.raid.clean.desc": "Benachrichtigung löschen, wenn der Raid endet", - "slash.opt.raid.template": "vorlage", - "slash.opt.raid.template.desc": "DTS-Vorlagenname", + "slash.opt.raid.template": "template", + "slash.opt.raid.template.desc": "DTS-Templatenname", "slash.choice.raid.clean.yes": "Ja", "slash.choice.raid.level.1": "Stufe 1", "slash.choice.raid.level.3": "Stufe 3", @@ -864,8 +777,8 @@ "slash.opt.egg.distance.desc": "Benachrichtigungsradius in Metern", "slash.opt.egg.clean": "bereinigen", "slash.opt.egg.clean.desc": "Benachrichtigung löschen, wenn das Ei schlüpft", - "slash.opt.egg.template": "vorlage", - "slash.opt.egg.template.desc": "DTS-Vorlagenname", + "slash.opt.egg.template": "template", + "slash.opt.egg.template.desc": "DTS-Templatenname", "slash.choice.egg.clean.yes": "Ja", "slash.choice.egg.level.1": "Stufe 1", "slash.choice.egg.level.3": "Stufe 3", @@ -885,23 +798,23 @@ "slash.opt.quest.pokemon": "pokemon", "slash.opt.quest.pokemon.desc": "Pokémon-Belohnung", "slash.opt.quest.item": "item", - "slash.opt.quest.item.desc": "Item-Belohnung (z. B. Sananabeere)", + "slash.opt.quest.item.desc": "Item-Belohnung (z. B. Goldene Himmihbeere)", "slash.opt.quest.stardust": "sternenstaub", "slash.opt.quest.stardust.desc": "Sternenstaub-Belohnung (Mindestmenge)", "slash.opt.quest.candy": "bonbon", "slash.opt.quest.candy.desc": "Bonbon-Belohnung (Pokémon)", - "slash.opt.quest.mega_energy": "mega_energie", - "slash.opt.quest.mega_energy.desc": "Mega-Energie-Belohnung (Pokémon)", + "slash.opt.quest.mega_energy": "megaenergie", + "slash.opt.quest.mega_energy.desc": "Megaenergie-Belohnung (Pokémon)", "slash.opt.quest.min_amount": "min_menge", "slash.opt.quest.min_amount.desc": "Mindestmenge der Belohnung (nur Item / Bonbon / Mega-Energie)", "slash.opt.quest.distance": "entfernung", "slash.opt.quest.distance.desc": "Benachrichtigungsradius in Metern", "slash.opt.quest.clean": "bereinigen", - "slash.opt.quest.clean.desc": "Benachrichtigung löschen, wenn die Quest abgeschlossen ist", + "slash.opt.quest.clean.desc": "Benachrichtigung löschen, wenn die Feldforschung verschwunden ist", "slash.opt.quest.summary": "zusammenfassung", "slash.opt.quest.summary.desc": "Treffer sammeln und in einem geplanten Batch ausliefern statt sofort zu benachrichtigen", - "slash.opt.quest.template": "vorlage", - "slash.opt.quest.template.desc": "DTS-Vorlagenname", + "slash.opt.quest.template": "template", + "slash.opt.quest.template.desc": "DTS-Templatenname", "slash.choice.quest.clean.yes": "Ja", "slash.choice.quest.summary.yes": "Ja", "slash.opt.invasion.grunt_type": "rüpel_typ", @@ -912,20 +825,20 @@ "slash.opt.invasion.distance.desc": "Benachrichtigungsradius in Metern", "slash.opt.invasion.clean": "bereinigen", "slash.opt.invasion.clean.desc": "Benachrichtigung löschen, wenn die Invasion endet", - "slash.opt.invasion.template": "vorlage", - "slash.opt.invasion.template.desc": "DTS-Vorlagenname", + "slash.opt.invasion.template": "template", + "slash.opt.invasion.template.desc": "DTS-Templatenname", "slash.choice.invasion.clean.yes": "Ja", "slash.choice.invasion.gender.male": "männlich", "slash.choice.invasion.gender.female": "weiblich", "slash.choice.invasion.gender.genderless": "geschlechtslos", "slash.opt.incident.type": "typ", - "slash.opt.incident.type.desc": "PokéStop-Ereignistyp (Kecleon, Goldener PokéStop, Showcase…)", + "slash.opt.incident.type.desc": "PokéStop-Ereignistyp (Kecleon, Goldstop, Showcase…)", "slash.opt.incident.distance": "entfernung", "slash.opt.incident.distance.desc": "Benachrichtigungsradius in Metern", "slash.opt.incident.clean": "bereinigen", "slash.opt.incident.clean.desc": "Benachrichtigung löschen, wenn das Ereignis endet", - "slash.opt.incident.template": "vorlage", - "slash.opt.incident.template.desc": "DTS-Vorlagenname", + "slash.opt.incident.template": "template", + "slash.opt.incident.template.desc": "DTS-Templatenname", "slash.choice.incident.clean.yes": "Ja", "slash.opt.lure.lure_type": "lockmodul", "slash.opt.lure.lure_type.desc": "Lockmodul-Typ", @@ -933,38 +846,38 @@ "slash.opt.lure.distance.desc": "Benachrichtigungsradius in Metern", "slash.opt.lure.clean": "bereinigen", "slash.opt.lure.clean.desc": "Benachrichtigung löschen, wenn das Lockmodul endet", - "slash.opt.lure.template": "vorlage", - "slash.opt.lure.template.desc": "DTS-Vorlagenname", + "slash.opt.lure.template": "template", + "slash.opt.lure.template.desc": "DTS-Templatenname", "slash.choice.lure.clean.yes": "Ja", - "slash.choice.lure.lure_type.normal": "Normales Lockmodul", + "slash.choice.lure.lure_type.normal": "Normales-Lockmodul", "slash.choice.lure.lure_type.glacial": "Gletscher-Lockmodul", "slash.choice.lure.lure_type.mossy": "Moos-Lockmodul", "slash.choice.lure.lure_type.magnetic": "Magnet-Lockmodul", "slash.choice.lure.lure_type.rainy": "Regen-Lockmodul", "slash.choice.lure.lure_type.sparkly": "Gold-Lockmodul", "slash.opt.nest.pokemon": "pokemon", - "slash.opt.nest.pokemon.desc": "Nistendes Pokémon", - "slash.opt.nest.min_spawn_avg": "min_spawns", + "slash.opt.nest.pokemon.desc": "nistendes Pokémon", + "slash.opt.nest.min_spawn_avg": "min_spawn_durchschnitt", "slash.opt.nest.min_spawn_avg.desc": "Mindestanzahl Spawns pro Stunde", "slash.opt.nest.distance": "entfernung", "slash.opt.nest.distance.desc": "Benachrichtigungsradius in Metern", "slash.opt.nest.clean": "bereinigen", "slash.opt.nest.clean.desc": "Benachrichtigung löschen, wenn das Nest endet", - "slash.opt.nest.template": "vorlage", - "slash.opt.nest.template.desc": "DTS-Vorlagenname", + "slash.opt.nest.template": "template", + "slash.opt.nest.template.desc": "DTS-Templatenname", "slash.choice.nest.clean.yes": "Ja", "slash.opt.maxbattle.pokemon": "pokemon", "slash.opt.maxbattle.pokemon.desc": "Dynamax-Kampf-Pokémon", "slash.opt.maxbattle.level": "level", "slash.opt.maxbattle.level.desc": "Kampfstufe (1..6)", - "slash.opt.maxbattle.gmax": "gigadynamax", - "slash.opt.maxbattle.gmax.desc": "Nur Gigadynamax", + "slash.opt.maxbattle.gmax": "gmax", + "slash.opt.maxbattle.gmax.desc": "nur Gigadynamax", "slash.opt.maxbattle.distance": "entfernung", "slash.opt.maxbattle.distance.desc": "Benachrichtigungsradius in Metern", "slash.opt.maxbattle.clean": "bereinigen", "slash.opt.maxbattle.clean.desc": "Benachrichtigung löschen, wenn der Kampf endet", - "slash.opt.maxbattle.template": "vorlage", - "slash.opt.maxbattle.template.desc": "DTS-Vorlagenname", + "slash.opt.maxbattle.template": "template", + "slash.opt.maxbattle.template.desc": "DTS-Templatenname", "slash.choice.maxbattle.clean.yes": "Ja", "slash.choice.maxbattle.level.1": "Stufe 1", "slash.choice.maxbattle.level.2": "Stufe 2", @@ -976,14 +889,14 @@ "slash.opt.gym.team.desc": "Arena-Team, das benachrichtigen soll", "slash.opt.gym.slot_changes": "platzänderungen", "slash.opt.gym.slot_changes.desc": "Bei Änderungen der Platzbesetzung benachrichtigen", - "slash.opt.gym.battle_changes": "wird_angegriffen", + "slash.opt.gym.battle_changes": "arenaangriff", "slash.opt.gym.battle_changes.desc": "Bei Angriff der Arena benachrichtigen", "slash.opt.gym.distance": "entfernung", "slash.opt.gym.distance.desc": "Benachrichtigungsradius in Metern", "slash.opt.gym.clean": "bereinigen", "slash.opt.gym.clean.desc": "Benachrichtigung löschen, wenn sich die Arena erneut ändert", - "slash.opt.gym.template": "vorlage", - "slash.opt.gym.template.desc": "DTS-Vorlagenname", + "slash.opt.gym.template": "template", + "slash.opt.gym.template.desc": "DTS-Templatenname", "slash.choice.gym.clean.yes": "Ja", "slash.choice.gym.team.0": "unumkämpft", "slash.choice.gym.team.1": "Weisheit", @@ -997,61 +910,64 @@ "slash.opt.fort.distance.desc": "Benachrichtigungsradius in Metern", "slash.opt.fort.clean": "bereinigen", "slash.opt.fort.clean.desc": "Benachrichtigung löschen, wenn sich das Fort erneut ändert", - "slash.opt.fort.template": "vorlage", - "slash.opt.fort.template.desc": "DTS-Vorlagenname", + "slash.opt.fort.template": "template", + "slash.opt.fort.template.desc": "DTS-Templatenname", "slash.choice.fort.clean.yes": "Ja", - "slash.choice.fort.fort_type.0": "PokéStop", + "slash.choice.fort.fort_type.0": "Pokestop", "slash.choice.fort.fort_type.1": "Arena", - "slash.autocomplete.untrack.remove_all": "🗑️ ALLE Regeln dieses Typs entfernen", - + "slash.opt.tracker.location": "standort", + "slash.opt.tracker.location.desc": "Verwendet einen gespeicherten Standort anstelle des Standardstandorts (benötigt entfernung):", + "slash.opt.tracker.areas": "gebiet", + "slash.opt.tracker.areas.desc": "auf bestimmte Gebiete beschränken (kommagetrennt)", + "slash.autocomplete.untrack.remove_all": "🗑️ ALLE Trackings dieses Typs entfernen", "slash.opt.untrack.pokemon": "pokemon", - "slash.opt.untrack.pokemon.desc": "Eine Pokémon-Tracking-Regel entfernen", - "slash.opt.untrack.pokemon.tracking": "regel", - "slash.opt.untrack.pokemon.tracking.desc": "Wähle aus deinen bestehenden Pokémon-Tracking-Regeln", + "slash.opt.untrack.pokemon.desc": "Eine Pokémon Tracking entfernen", + "slash.opt.untrack.pokemon.tracking": "beobachtung", + "slash.opt.untrack.pokemon.tracking.desc": "Wähle aus deinen bestehenden Pokémon-Trackings", "slash.opt.untrack.raid": "raid", - "slash.opt.untrack.raid.desc": "Eine Raid-Tracking-Regel entfernen", - "slash.opt.untrack.raid.tracking": "regel", - "slash.opt.untrack.raid.tracking.desc": "Wähle aus deinen bestehenden Raid-Tracking-Regeln", + "slash.opt.untrack.raid.desc": "Eine Raid Tracking entfernen", + "slash.opt.untrack.raid.tracking": "beobachtung", + "slash.opt.untrack.raid.tracking.desc": "Wähle aus deinen bestehenden Raid-Trackings", "slash.opt.untrack.egg": "ei", - "slash.opt.untrack.egg.desc": "Eine Ei-Tracking-Regel entfernen", - "slash.opt.untrack.egg.tracking": "regel", - "slash.opt.untrack.egg.tracking.desc": "Wähle aus deinen bestehenden Ei-Tracking-Regeln", - "slash.opt.untrack.quest": "quest", - "slash.opt.untrack.quest.desc": "Eine Quest-Tracking-Regel entfernen", - "slash.opt.untrack.quest.tracking": "regel", - "slash.opt.untrack.quest.tracking.desc": "Wähle aus deinen bestehenden Quest-Tracking-Regeln", + "slash.opt.untrack.egg.desc": "Eine Ei-Tracking entfernen", + "slash.opt.untrack.egg.tracking": "beobachtung", + "slash.opt.untrack.egg.tracking.desc": "Wähle aus deinen bestehenden Ei-Trackings", + "slash.opt.untrack.quest": "feldforschung", + "slash.opt.untrack.quest.desc": "Eine Feldforschung-Tracking entfernen", + "slash.opt.untrack.quest.tracking": "beobachtung", + "slash.opt.untrack.quest.tracking.desc": "Wähle aus deinen bestehenden Feldforschung-Trackings", "slash.opt.untrack.invasion": "invasion", - "slash.opt.untrack.invasion.desc": "Eine Invasion-Tracking-Regel entfernen", - "slash.opt.untrack.invasion.tracking": "regel", - "slash.opt.untrack.invasion.tracking.desc": "Wähle aus deinen bestehenden Invasion-Tracking-Regeln", + "slash.opt.untrack.invasion.desc": "Eine Invasion Tracking entfernen", + "slash.opt.untrack.invasion.tracking": "beobachtung", + "slash.opt.untrack.invasion.tracking.desc": "Wähle aus deinen bestehenden Invasion-Trackings", "slash.opt.untrack.lure": "lockmodul", - "slash.opt.untrack.lure.desc": "Eine Lockmodul-Tracking-Regel entfernen", - "slash.opt.untrack.lure.tracking": "regel", - "slash.opt.untrack.lure.tracking.desc": "Wähle aus deinen bestehenden Lockmodul-Tracking-Regeln", + "slash.opt.untrack.lure.desc": "Eine Lockmodul-Tracking entfernen", + "slash.opt.untrack.lure.tracking": "beobachtung", + "slash.opt.untrack.lure.tracking.desc": "Wähle aus deinen bestehenden Lockmodul-Trackings", "slash.opt.untrack.nest": "nest", - "slash.opt.untrack.nest.desc": "Eine Nest-Tracking-Regel entfernen", - "slash.opt.untrack.nest.tracking": "regel", - "slash.opt.untrack.nest.tracking.desc": "Wähle aus deinen bestehenden Nest-Tracking-Regeln", + "slash.opt.untrack.nest.desc": "Eine Nest-Tracking entfernen", + "slash.opt.untrack.nest.tracking": "beobachtung", + "slash.opt.untrack.nest.tracking.desc": "Wähle aus deinen bestehenden Nest-Trackings", "slash.opt.untrack.gym": "arena", - "slash.opt.untrack.gym.desc": "Eine Arena-Tracking-Regel entfernen", - "slash.opt.untrack.gym.tracking": "regel", - "slash.opt.untrack.gym.tracking.desc": "Wähle aus deinen bestehenden Arena-Tracking-Regeln", + "slash.opt.untrack.gym.desc": "Eine Arena Tracking entfernen", + "slash.opt.untrack.gym.tracking": "beobachtung", + "slash.opt.untrack.gym.tracking.desc": "Wähle aus deinen bestehenden Arena-Trackings", "slash.opt.untrack.fort": "fort", - "slash.opt.untrack.fort.desc": "Eine Fort-Tracking-Regel entfernen", - "slash.opt.untrack.fort.tracking": "regel", - "slash.opt.untrack.fort.tracking.desc": "Wähle aus deinen bestehenden Fort-Tracking-Regeln", + "slash.opt.untrack.fort.desc": "Eine Fort-Tracking entfernen", + "slash.opt.untrack.fort.tracking": "beobachtung", + "slash.opt.untrack.fort.tracking.desc": "Wähle aus deinen bestehenden Fort-Trackings", "slash.opt.untrack.maxbattle": "dynamax", - "slash.opt.untrack.maxbattle.desc": "Eine Dynamax-Kampf-Tracking-Regel entfernen", - "slash.opt.untrack.maxbattle.tracking": "regel", - "slash.opt.untrack.maxbattle.tracking.desc": "Wähle aus deinen bestehenden Dynamax-Kampf-Tracking-Regeln", + "slash.opt.untrack.maxbattle.desc": "Eine Dynamax-Kampf-Tracking entfernen", + "slash.opt.untrack.maxbattle.tracking": "beobachtung", + "slash.opt.untrack.maxbattle.tracking.desc": "Wähle aus deinen bestehenden Dynamax-Kampf-Trackings", "slash.opt.area.add": "hinzufügen", "slash.opt.area.add.desc": "Ein Gebiet zu deinem Tracking hinzufügen", "slash.opt.area.add.area": "gebiet", - "slash.opt.area.add.area.desc": "Hinzuzufügendes Gebiet", + "slash.opt.area.add.area.desc": "hinzuzufügendes Gebiet", "slash.opt.area.remove": "entfernen", "slash.opt.area.remove.desc": "Ein Gebiet aus deinem Tracking entfernen", "slash.opt.area.remove.area": "gebiet", - "slash.opt.area.remove.area.desc": "Zu entfernendes Gebiet", + "slash.opt.area.remove.area.desc": "zu entfernendes Gebiet", "slash.opt.area.show": "anzeigen", "slash.opt.area.show.desc": "Deine ausgewählten Gebiete anzeigen", "slash.opt.area.list": "auflisten", @@ -1075,50 +991,322 @@ "slash.opt.profile.settime": "settime", "slash.opt.profile.settime.desc": "Aktive Zeiten für das aktuelle Profil festlegen", "slash.opt.profile.settime.times": "zeiten", - "slash.opt.profile.settime.times.desc": "Zeitbereichs-Zeichenkette (z. B. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.profile.settime.times.desc": "Zeitbereichs-Zeichenkette (z. B. mon07:30, wochentag07:30-18:00, wochentag:9-17/2)", "slash.opt.profile.cleartime": "cleartime", "slash.opt.profile.cleartime.desc": "Aktive Zeiten aus dem aktuellen Profil entfernen", "slash.opt.profile.copyto": "kopieren", "slash.opt.profile.copyto.desc": "Tracking dieses Profils in ein anderes Profil kopieren", "slash.opt.profile.copyto.profile": "profil", "slash.opt.profile.copyto.profile.desc": "Zielprofilname oder -nummer", - "slash.opt.location.place": "ort", - "slash.opt.location.place.desc": "Koordinaten (\"51.28, 1.08\") oder ein Ortsname", - "slash.opt.summary.quest": "quest", - "slash.opt.summary.quest.desc": "Quest-Zusammenfassung verwalten", + "slash.opt.location.add": "hinzufügen", + "slash.opt.location.add.desc": "Einen benannten Standort speichern", + "slash.opt.location.add.name": "name", + "slash.opt.location.add.name.desc": "Kurzname für diesen Standort (z.B. Home)", + "slash.opt.location.add.place": "ort", + "slash.opt.location.add.place.desc": "Koordinaten (lat,lon) oder ein Ortsname", + "slash.opt.location.list": "auflisten", + "slash.opt.location.list.desc": "gespeicherte Standorte auflisten", + "slash.opt.location.show": "zeigen", + "slash.opt.location.show.desc": "einen gespeicherten Standort zeigen", + "slash.opt.location.show.name": "name", + "slash.opt.location.show.name.desc": "gespeicherten Standortname", + "slash.opt.location.remove": "entfernen", + "slash.opt.location.remove.desc": "entferne einen gespeicherten Standort", + "slash.opt.location.remove.name": "name", + "slash.opt.location.remove.name.desc": "gespeicherter Standortname (oder \"standart\" um den Standardstandort zu löschen)", + "slash.opt.location.set-default": "setze-standart", + "slash.opt.location.set-default.desc": "Standardstandort setzen", + "slash.opt.location.set-default.place": "ort", + "slash.opt.location.set-default.place.desc": "Koordinaten (lat,lon) oder Addresse um den Standardstandort zu setzen", + "slash.opt.location.remove-default": "entferne-standart", + "slash.opt.location.remove-default.desc": "entferne den Standardstandort", + "slash.opt.summary.quest": "feldforschung", + "slash.opt.summary.quest.desc": "Feldforschung-Zusammenfassung verwalten", "slash.opt.summary.quest.show": "anzeigen", "slash.opt.summary.quest.show.desc": "Zeitplan und aktuelle Pufferanzahl anzeigen", "slash.opt.summary.quest.settime": "settime", - "slash.opt.summary.quest.settime.desc": "Zeitplan für die Quest-Zusammenfassung festlegen", + "slash.opt.summary.quest.settime.desc": "Zeitplan für die Feldforschung-Zusammenfassung festlegen", "slash.opt.summary.quest.settime.times": "zeiten", - "slash.opt.summary.quest.settime.times.desc": "Zeitbereichs-Zeichenkette (z. B. mon07:30, wochentag07:30-18:00, wochentag:9-17/2)", + "slash.opt.summary.quest.settime.times.desc": "Zeitbereichs Zeichenkette (z. B. mon07:30, wochentag07:30-18:00, wochentag:9-17/2)", "slash.opt.summary.quest.cleartime": "cleartime", "slash.opt.summary.quest.cleartime.desc": "Den Zeitplan löschen", "slash.opt.summary.quest.now": "jetzt", - "slash.opt.summary.quest.now.desc": "Die aktuell gepufferten Quests sofort ausliefern", - "cmd.poracle_admin.config.help.intro": "⚙️ Konfigurationsanzeige — Effektive Konfiguration mit maskierten Geheimnissen anzeigen.\nUnterbefehle:", - "cmd.poracle_admin.config.keys.desc": "Abschnittsnamen mit Schlüsselanzahl auflisten", - "cmd.poracle_admin.config.section.desc": "Nur diesen Abschnitt anzeigen (z.B. `!poracle-admin config discord`)", - "cmd.poracle_admin.config.full.desc": "Gesamte Konfiguration anzeigen (alle Abschnitte, Geheimnisse maskiert)", - "cmd.poracle_admin.config.keys.header": "⚙️ Konfigurationsabschnitte:", + "slash.opt.summary.quest.now.desc": "Die aktuell gepufferten Feldforschungen sofort ausliefern", + "error.slash.unregistered_with_channel": "🛑 Bitte zuerst registrieren. Schreib eine DM mit !poracle, oder poste !poracle in {0}.", + "error.slash.unregistered_dm_only": "🛑 Bitte zuerst registrieren. Schreib eine DM mit !poracle.", + "error.slash.track.no_pokemon": "Bitte gib ein Pokémon an, das beobachtet werden soll.", + "error.slash.raid.need_boss_or_level": "Bitte geben entweder einen Boss oder ein Level an.", + "error.slash.raid.boss_and_level": "Bitte geben entweder einen Boss oder ein Level an, nicht beides.", + "error.slash.egg.no_level": "Bitte gebe ein Ei-Level an.", + "error.slash.quest.no_reward": "Bitte gebe genau einen Belohnungstyp an (pokemon, item, sternenstaub, bonbon, oder megaenergie).", + "error.slash.quest.exactly_one_reward": "Bitte gebe genau einen Belohnungstyp an, nicht mehrere: {0}.", + "error.slash.quest.amount_not_applicable": "`min_menge` gilt nicht für Pokemon Feldforschungen. Für sternenstaub, beide `sternenstaub` und `min_menge` landen im selben Feld - wähle was besser passt.", + "error.slash.invasion.no_grunt": "Bitte gebe einen Rüpel-Typ an.", + "error.slash.incident.no_type": "Bitte gebe einen Ereignis-Typ an.", + "error.slash.lure.no_type": "Bitte gebe einen Lockmodul-Typ an.", + "error.slash.nest.no_pokemon": "Bitte gebe ein Pokemon für Nester an.", + "error.slash.maxbattle.no_pokemon": "Bitte gebe ein Pokemon für Dynamax Kämpfe an.", + "error.slash.fort.no_type": "Bitte gebe einen Fort-Typ an (pokestop oder arena).", + "error.slash.untrack.no_subcommand": "Bitte wähle aus, welche Art von Tracking-Regel entfernt werden soll.", + "error.slash.untrack.no_tracking": "Bitte wähle eine Tracking-Regel zum Entfernen aus.", + "error.slash.info.no_subcommand": "Bitte wähle ein Info Unterbefehl (pokemon / seltenheit / schillernd / wetter).", + "error.slash.info.no_pokemon": "Bitte gebe ein Pokemon Namen oder Dex Id an.", + "error.slash.info.unknown_subcommand": "Unbekannter Info Unterbefehl.", + "error.slash.area.no_subcommand": "Bitte wähle einen Gebiet Unterbefehl (hinzufügen / entfernen / zeigen).", + "error.slash.area.no_area": "Bitte gebe einen Gebiet Namen an.", + "error.slash.area.unknown_subcommand": "Unbekannter Gebiet Unterbefehl.", + "error.slash.profile.no_subcommand": "Bitte wähle ein Profil Unterbefehl (auflisten / wechseln / hinzufügen / entfernen / settime / cleartime / copyto).", + "error.slash.profile.no_name": "Bitte gebe einen Profilenamen an.", + "error.slash.profile.no_times": "Bitte gebe einen Zeitbereich an (z.B. mon07:30, wochentag07:30-18:00, wochentag:9-17/2).", + "error.slash.profile.no_target": "Bitte gebe ein Zielprofil für copyto an.", + "error.slash.profile.unknown_subcommand": "Unbekannter Profil Unterbefehl.", + "error.slash.summary.no_alert_type": "Bitte wähle einen Alarm-Typ aus (z.B. feldforschung).", + "error.slash.summary.no_action": "Bitte wähle eine Aktion aus (zeigen / settime / cleartime / jetzt).", + "error.slash.summary.no_times": "Bitte gebe einen Zeitbereich an (z.B. mon07:30, wochentag07:30-18:00, wochentag:9-17/2).", + "error.slash.summary.unknown_action": "Unbekannte Zusammenfassung Aktion.", + "error.slash.location.no_subcommand": "Bitte wähle einen Standort Unterbefehl aus (hinzufügen / auflisten / zeigen / entfernen / entferne-standart).", + "error.slash.location.no_name": "Bitte gebe einen gespeicherten Standortnamen aus.", + "error.slash.location.empty": "Bitte gebe Koordinaten oder einen Ortsnamen an.", + "error.slash.location.unknown_subcommand": "Unbekannter Standort Unterbefehl.", + "error.slash.location.no_geocoder": "Standortnamen lookup ist nicht konfiguriert. Bitte gebe Koordinaten wie 51.28, 1.08 an.", + "error.slash.location.geocode_failed": "Keinen Standort für \"{0}\" gefunden.", + "msg.help.text": "**verfügbare Commands:**\n{0}track [iv:N] [wp:N] [level:N] [e:N] - Pokemon tracken\n{0}untrack - Pokemon tracking entfernen\n{0}raid [e:N] - Raids tracken\n{0}ei [e:N] - Raideier tracken\n{0}quest - Feldforschungen tracken\n{0}invasion [alle|] - Invasionen tracken\n{0}lockmodul - Lockmodule tracken\n{0}gym [platzänderung] - Arenen tracken\n{0}nest - Nester tracken\n{0}maxbattle - Dynamax Kämpfe tracken\n{0}fort - Fort updates tracken\n{0}tracked - Alle Trackings anzeigen\n{0}skript - Trackings als Commands exportieren\n{0}gebiet [auflisten|hinzufügen|entfernen] - Gebiete organisieren\n{0}standort - Standort setzen\n{0}profile [auflisten|hinzufügen|entfernen|wechseln] - Profile organisieren\n{0}sprache - Sprache wählen\n{0}start / {0}stop - Benachrichtigungen einschalten/abschalten\n{0}version - Version anzeigen", + "cmd.poracle_admin": "poracle-admin", + "cmd.pa": "pa", + "cmd.poracle_admin.not_admin": "Dieser Befehl ist Administratoren vorbehalten.", + "cmd.poracle_admin.unknown_group": "Unbekannte Untergruppe, versuche `!poracle-admin` für die Liste.", + "cmd.poracle_admin.unknown_sub": "Unbekannter Unterbefehl für `{0}`. Versuche `!poracle-admin {0}` um zu sehen, was verfügbar ist.", + "cmd.poracle_admin.help.admin_only": "\"Dieser Befehl ist Administratoren vorbehalten. Jede Untergruppe führt eine operative Aufgabe durch.", + "cmd.poracle_admin.help.groups": "Verfügbare Untergruppen:", + "cmd.poracle_admin.help_intro": "🛠️ Poracle Admin\\n\\nUntergruppen für den Live-Betrieb (nur für Administratoren):", + "cmd.poracle_admin.stub": "(noch nicht implementiert)", + "cmd.poracle_admin.group.slash.desc": "Slash-Command Registrierungs-Lebenszyklus", + "cmd.poracle_admin.group.reload.desc": "DTS, Geofence oder In-Memory-Zustand neu laden", + "cmd.poracle_admin.group.emoji.desc": "Emoji-Konfiguration auflisten, neu laden oder testen", + "cmd.poracle_admin.group.reconcile.desc": "Discord Rollen reconciliation (sofort oder pro Benutzer)", + "cmd.poracle_admin.group.cache.desc": "Cache-Statistiken und Cache leeren", + "cmd.poracle_admin.group.ratelimit.desc": "Ratenbegrenzungen für Alert-Buckets überprüfen und zurücksetzen", + "cmd.poracle_admin.group.summary.desc": "Inspektion des Zusammenfassungsbuffers und erzwungener Versand", + "cmd.poracle_admin.group.status.desc": "Live Health Snapshot", + "cmd.poracle_admin.group.maintenance.desc": "ausgehende Zustellung pausieren/fortsetzen", + "cmd.poracle_admin.group.config.desc": "Effektive zusammengeführte Config mit ausgeblendeten Secrets anzeigen", + "cmd.poracle_admin.group.warnings.desc": "erfasste WARN/ERROR-Logeinträge prüfen (Startup + Rollpuffer)", + "cmd.poracle_admin.reload.help.intro": "Laufzeitzustand von Festplatte oder Datenbank neu laden.", + "cmd.poracle_admin.reload.dts.desc": "`dts` - DTS-Templates und Partials von der Festplatte neu laden", + "cmd.poracle_admin.reload.geofence.desc": "`geofence` - Geofence-Dateien neu laden und Status aktualisieren", + "cmd.poracle_admin.reload.state.desc": "`zustand` - Tracking-Regeln und Nutzer aus MySQL neu laden (umgeht Debounce)", + "cmd.poracle_admin.reload.dts.success": "✅ DTS neu laden in {0}ms ({1} Templates)", + "cmd.poracle_admin.reload.geofence.success": "✅ Geofence neu laden in {0}ms ({1} Fences, {2} Tracking Regeln)", + "cmd.poracle_admin.reload.state.success": "✅ Zustand neu laden in {0}ms ({1} Tracking Regeln, {2} aktive Nutzer)", + "cmd.poracle_admin.reload.error": "❌ Reload fehlgeschlagen: {0}", + "cmd.poracle_admin.emoji.help.intro": "😀 Emoji Config - prüfe und verwalte emoji.json + Discord Guild Emojis.\\n\\nUnterbefehle:", + "cmd.poracle_admin.emoji.list.desc": "`List` - alle konfigurierten Emoji-Schlüssel mit plattformspezifischen Auflösungen auflisten", + "cmd.poracle_admin.emoji.reload.desc": "`Reload` - lade Config/emoji.json von der Festplatte neu", + "cmd.poracle_admin.emoji.test.desc": "`Test ` - löse einen Emoji-Schlüssel für die aktuelle Plattform auf", + "cmd.poracle_admin.emoji.upload.desc": "`Upload [überschreiben]` - lade Uicons-basierte Emojis auf den Server hoch und schreibe eine neue emoji.json (nur-Discord)", + "cmd.poracle_admin.emoji.discord_config.desc": "`Discord-Config` - exportiere emoji.json aus den aktuellen Gilden – keine Uploads (nur-Discord)", + "cmd.poracle_admin.emoji.discord_only": "ℹ️ Dieser Unterbefehl erfordert einen Discord-Bot mit Gilden-Zugriff.", + "cmd.poracle_admin.emoji.not_loaded": "ℹ️ Emoji Config nicht geladen (DTS-Renderer nicht konfiguriert).", + "cmd.poracle_admin.emoji.list.header": "😀 Emoji Configuration - {0} Schlüssel geladen", + "cmd.poracle_admin.emoji.list.row.key": " {0}:", + "cmd.poracle_admin.emoji.list.row.platform": " {0}: {1}", + "cmd.poracle_admin.emoji.reload.success": "✅ Emoji Config Reloaded - {0} Schlüssel (dauerten {1}ms).", + "cmd.poracle_admin.emoji.reload.error": "❌ Emoji Reload fehlgeschlagen: {0}", + "cmd.poracle_admin.emoji.test.success": "🔎 {0} auf {1}: {2}", + "cmd.poracle_admin.emoji.test.not_found": "ℹ️ Emoji Schlüssel \\\"{0}\\\" nicht in der geladenen Config gefunden.", + "cmd.poracle_admin.emoji.test.usage": "Verwendung: !poracle-admin emoji test ", + "cmd.poracle_admin.reconcile.help.intro": "🔄 Discord Rollen reconciliation - sofort auslösen, anstatt auf den periodischen Timer zu warten.", + "cmd.poracle_admin.reconcile.run.desc": "`run` - reconcile jetzt alle Guild Mitglieder (blockiert bis zum Abschluss)", + "cmd.poracle_admin.reconcile.user.desc": "`user ` - reconcile einen einzelnen Discord Nutzer nach Snowflake ID", + "cmd.poracle_admin.reconcile.not_configured": "❌ Discord reconciliation ist nicht konfiguriert (nur-Telegram verteilen, oder check_role=false).", + "cmd.poracle_admin.reconcile.run.success": "✅ Discord reconciliation komplett (dauerte {0}ms).", + "cmd.poracle_admin.reconcile.run.error": "❌ Reconciliation fehlgeschlagen: {0}", + "cmd.poracle_admin.reconcile.user.success": "✅ Reconciled Discord:Nutzer/{0} (dauerte {1}ms).", + "cmd.poracle_admin.reconcile.user.error": "❌ Abgleich von Discord:Nutzer fehlgeschlagen/{0}: {1}", + "cmd.poracle_admin.reconcile.user.usage": "Verwendung: !poracle-admin reconcile Nutzer ", + "cmd.poracle_admin.cache.help.intro": "🗺️ Geocoder cache - überprüfe die Zähler oder verwerfen die In-Memory Schicht.", + "cmd.poracle_admin.cache.stats.desc": "`Stats` - Geocoder Cache Statistik", + "cmd.poracle_admin.cache.clear.desc": "`Clear Geocoder` - den In-Memory-Geocoder-Cache löschen", + "cmd.poracle_admin.cache.not_configured": "Geocoder Cache ist auf dieser Instanz nicht konfiguriert.", + "cmd.poracle_admin.cache.stats.header": "🗺️ Geocoder Cache", + "cmd.poracle_admin.cache.stats.row.memory_entries": " Speichereinträge: {0}", + "cmd.poracle_admin.cache.stats.row.disk_entries": " Datenträgereinträge: {0}", + "cmd.poracle_admin.cache.stats.row.hits_memory": " Treffer (Speicher): {0}", + "cmd.poracle_admin.cache.stats.row.hits_disk": " Treffer (Datenträger): {0}", + "cmd.poracle_admin.cache.stats.row.misses": " Fehltreffer: {0}", + "cmd.poracle_admin.cache.stats.row.hit_rate": " Trefferrate: {0}%", + "cmd.poracle_admin.cache.clear.usage_hint": "Gib an, was gelöscht werden soll, z.B. `!poracle-admin cache clear geocoder`", + "cmd.poracle_admin.cache.clear.geocoder.success": "✅ Geocoder Speicher Cache gelöscht - {0} Einträge verworfen (Datenträger unberührt).", + "cmd.poracle_admin.ratelimit.help.intro": "🚦 Ratelimit Selbstbeobachtung - pro Ziel-Alarm- und Zusammenfassungs-Buckets inspizieren oder zurücksetzen.", + "cmd.poracle_admin.ratelimit.not_configured": "ℹ️ Das Alert-Ratelimit ist auf dieser Instanz nicht konfiguriert.", + "cmd.poracle_admin.ratelimit.list.desc": "`List` - alle derzeit kompromittierten oder gesperrten Ziele anzeigen", + "cmd.poracle_admin.ratelimit.show.desc": "`Show ` - detaillierter Status für ein Ziel (beide Buckets)", + "cmd.poracle_admin.ratelimit.reset.desc": "`Reset ` - Zähler und Verletzungshistorie löschen", + "cmd.poracle_admin.ratelimit.userlist.desc": "`Userlist` - aktuell deaktivierte Benutzer anzeigen (Shortcut für !userlist disabled)", + "cmd.poracle_admin.ratelimit.list.empty": "🟢 Derzeit sind keine Ziele ratenbegrenzt.", + "cmd.poracle_admin.ratelimit.list.header_title": "aktuell ratenbegrenzte Ziele", + "cmd.poracle_admin.ratelimit.list.bucket_header": " {0} Bucket ({1} verletzt / {2} gebannt):", + "cmd.poracle_admin.ratelimit.list.row": "gezählt {0}/{1}, {2}", + "cmd.poracle_admin.ratelimit.list.status.banned": "gebannt für {0}", + "cmd.poracle_admin.ratelimit.list.status.breached": "Fenster setzt sich zurück in {0}", + "cmd.poracle_admin.ratelimit.show.header": "🚦 Ratenbegrenzungsstatus für {0}", + "cmd.poracle_admin.ratelimit.show.bucket_header": "{0}-Bucket:", + "cmd.poracle_admin.ratelimit.show.empty": "🟢 Keine aufgezeichnete Aktivität für {0} in einem der beiden Buckets.", + "cmd.poracle_admin.ratelimit.show.no_data": "(keine Aktivität in diesem Bucket)", + "cmd.poracle_admin.ratelimit.show.no_violations": "Keine Verstöße.", + "cmd.poracle_admin.ratelimit.show.violations_count": "Verstöße (24h): {0}", + "cmd.poracle_admin.ratelimit.show.banned_until": "Gebannt bis: {0} (in {1})", + "cmd.poracle_admin.ratelimit.show.status.under_limit": "unterhalb der Grenze", + "cmd.poracle_admin.ratelimit.show.status.over_limit": "oberhalb der Grenze", + "cmd.poracle_admin.ratelimit.show.row.count": " gezählt: {0} / {1} ({2})\\n\n", + "cmd.poracle_admin.ratelimit.show.row.window": " Fenster: vor {0} geöffnet, Resets in {1}\\n\n", + "cmd.poracle_admin.ratelimit.reset.success": "✅ Reset Ratenbegrenzungsstatus für {0} (Warnung gelöscht + Zusammenfassungs Buckets, Verstöße zurückgesetzt).", + "cmd.poracle_admin.ratelimit.reset.no_state": "ℹ️ Kein Ratenbegrenzungsstatus zum Zurücksetzen für {0}.", + "cmd.poracle_admin.ratelimit.reset.note": "Hinweis: admin_disable wird NICHT verändert. Falls der Benutzer durch den Rate-Limiter automatisch deaktiviert wurde, muss er sich weiterhin mittels !poracle erneut registrieren.", + "cmd.poracle_admin.ratelimit.usage.show": "Verwendung: !poracle-admin ratelimit zeigen ", + "cmd.poracle_admin.ratelimit.usage.reset": "Verwendung: !poracle-admin ratelimit zurücksetzen ", + "cmd.poracle_admin.ratelimit.userlist.lookup_failed": "❌ Der Befehl !userlist konnte in der Registrierung nicht gefunden werden.", + "cmd.poracle_admin.summary.help.intro": "📦 Zusammenfassungs-Puffer – überprüfen, wer Quests gepuffert hat und bei Bedarf den Versand erzwingen.", + "cmd.poracle_admin.summary.not_configured": "ℹ️ Der Zusammenfassungs-Puffer ist auf dieser Instanz nicht konfiguriert.", + "cmd.poracle_admin.summary.list.desc": "`List` - alle Benutzer anzeigen, bei denen etwas gepuffert wird", + "cmd.poracle_admin.summary.show.desc": "`Show ` - die gepufferten Einträge eines Benutzers inspizieren", + "cmd.poracle_admin.summary.fire.desc": "`Fire [alertType]` - den Puffer eines Benutzers sofort zwangsweise versenden", + "cmd.poracle_admin.summary.list.empty": "🟢 Keine Benutzer haben etwas gepuffert.", + "cmd.poracle_admin.summary.list.header": "📦 Zusammenfassungs-Puffer - {0} Nutzer mit {1} Puffer Einträgen", + "cmd.poracle_admin.summary.list.user_header": " {0}", + "cmd.poracle_admin.summary.list.row": " {0}: {1} Einträgen (nächstes Versenden: {2})", + "cmd.poracle_admin.summary.list.next_fire.none": "nicht verfügbar", + "cmd.poracle_admin.summary.show.header": "📦 Zusammenfassungs-Puffer für {0}", + "cmd.poracle_admin.summary.show.empty": "🟢 Keine gepufferten Einträge für {0}.", + "cmd.poracle_admin.summary.show.alert_type": " {0}: {1} Einträge", + "cmd.poracle_admin.summary.show.usage": "Verwendung: !poracle-admin zusammenfassung zeigen ", + "cmd.poracle_admin.summary.fire.success": "✅ Versandte Zusammenfassung für {0} / {1} - {2} Eingaben übermittelt.", + "cmd.poracle_admin.summary.fire.usage": "Verwendung: !poracle-admin zusammenfassung fire [alertType]", + "cmd.poracle_admin.summary.show.reward_row": " Belohnungsart {0}, Belohnung {1}{2} - {3} Stops", + "cmd.poracle_admin.summary.show.reward_more": " ... ({0} weitere Belohnungsgruppen)", + "cmd.poracle_admin.summary.show.form_suffix": " Form {0}", + "cmd.poracle_admin.maintenance.help.intro": "🛠️ **!poracle-admin maintenance** - Echtzeitsteuerung der ausgehenden Zustellungen.\\n\\nUnterbefehle:", + "cmd.poracle_admin.maintenance.no_dispatcher": "ℹ️ Der Dispatcher ist auf dieser Instanz nicht verfügbar.", + "cmd.poracle_admin.maintenance.no_reason": "(kein Grund angegeben)", + "cmd.poracle_admin.maintenance.pause.desc": "`Pause [Grund...]` (Alias: `start`) - ausgehende Zustellung anhalten (Webhooks werden weiterhin erfasst, gematcht, gerendert und queued.)", + "cmd.poracle_admin.maintenance.resume.desc": "`Resume` (Alias: `stop`) - eine zuvor gesetzte Pause aufheben und in der Warteschlange befindliche Jobs abarbeiten", + "cmd.poracle_admin.maintenance.status.desc": "`Status` - aktuellen Status (pausiert/laufend) und Warteschlangenlänge anzeigen", + "cmd.poracle_admin.maintenance.pause.new": "🔴 Ausgehende Zustellung pausiert: {0}", + "cmd.poracle_admin.maintenance.pause.detail": "Webhooks werden weiterhin erfasst, gematcht, gerendert und queued - der Dispatcher hält sie zurück, bis !poracle-admin maintenance resume.", + "cmd.poracle_admin.maintenance.pause.already": "ℹ️ Bereits pausiert seit {0} ({1} vor): {2}", + "cmd.poracle_admin.maintenance.resume.success": "🟢 Ausgehende Zustellungen wieder aufgenommen (war pausiert für {0}: {1})", + "cmd.poracle_admin.maintenance.resume.detail": "In der Warteschlange befindliche Nachrichten werden abgearbeitet.", + "cmd.poracle_admin.maintenance.resume.not_paused": "ℹ️ Derzeit nicht pausiert.", + "cmd.poracle_admin.maintenance.status.running": "🟢 Zustellung läuft.", + "cmd.poracle_admin.maintenance.status.paused": "🔴 PAUSIERT - {0} (für {1})", + "cmd.poracle_admin.maintenance.status.queued": "{0} in der Warteschlange befindliche Aufträge (über alle Plattformen hinweg - Discord {1}, Telegram {2})", + "cmd.poracle_admin.status.help.intro": "!poracle-admin status - aktueller Health-Snapshot. Fügen Sie -v für verbose Mode hinzu (Discord-Details pro Route, vollständige Aufschlüsselung der Webhooks nach Typ).", + "cmd.poracle_admin.status.header": "🛠️ Poracle Admin - Status", + "cmd.poracle_admin.status.paused_banner": "🔴 PAUSIERT - {0} (seit {1})\\n Die ausgehenden Zustellungen sind angehalten. Webhooks werden weiterhin erfasset und gequeued.", + "cmd.poracle_admin.status.value.na": "nicht verfügbar", + "cmd.poracle_admin.status.value.none": "keine", + "cmd.poracle_admin.status.section.build": "**Build / Laufzeit**", + "cmd.poracle_admin.status.section.webhooks": "**Webhooks**", + "cmd.poracle_admin.status.section.render_queue": "**Render-Warteschlange**", + "cmd.poracle_admin.status.section.delivery": "**Zustellung**", + "cmd.poracle_admin.status.section.discord_rate": "**Discord Rate**", + "cmd.poracle_admin.status.section.telegram_rate": "**Telegram Rate**", + "cmd.poracle_admin.status.section.alert_limits": "**Nachrichten Limits**", + "cmd.poracle_admin.status.section.summary_buffer": "**Zusammenfassungs-Puffer**", + "cmd.poracle_admin.status.label.summary_buffer_totals": "Einträge: {0} über {1} Bucket(s)", + "cmd.poracle_admin.status.label.summary_buffer_top": "Top Nutzer:", + "cmd.poracle_admin.status.label.summary_buffer_user_row": " {0} ({1}): {2} Einträge", + "cmd.poracle_admin.status.section.tracking": "**Tracking**", + "cmd.poracle_admin.status.section.mysql": "**MySQL**", + "cmd.poracle_admin.status.label.version": "Version: {0} (commit {1}, built {2})", + "cmd.poracle_admin.status.label.uptime": "Laufzeit: {0}", + "cmd.poracle_admin.status.label.webhooks_rate": "{0} / {1} / {2} pro Minute in den letzten 5/15/60 min", + "cmd.poracle_admin.status.label.webhooks_by_type": "Nach Typ (letzten 60 min):", + "cmd.poracle_admin.status.label.delivery_discord": "offenen Nachrichten Discord: {0}", + "cmd.poracle_admin.status.label.delivery_telegram": "offenen Nachrichten Telegram: {0}", + "cmd.poracle_admin.status.label.delivery_webhook": "offenen Nachrichten Webhook: {0}", + "cmd.poracle_admin.status.label.delivery_queue_depth": "Warteschlangenlänge: {0} (Kapazität nicht sichtbar)", + "cmd.poracle_admin.status.label.discord_routes": "Routen nahe des Limits: {0}", + "cmd.poracle_admin.status.label.discord_global": "Globale Tokens: {0} / {1}", + "cmd.poracle_admin.status.label.discord_429s": "429s in den letzten 5 min: {0}", + "cmd.poracle_admin.status.label.discord_routes_detail": "Routen nahe des Limits (Details):", + "cmd.poracle_admin.status.label.telegram_429s": "429s in den letzten 5 min: {0}", + "cmd.poracle_admin.status.label.telegram_backoff": "Aktueller Backoff: {0}", + "cmd.poracle_admin.status.label.alert_limits_counts": "Verletzungen: Alarm={0}, zusammenfassung={1} · Gebannt: {2}", + "cmd.poracle_admin.status.label.tracking_total": "Gesamtregeln für das Tracking: {0}", + "cmd.poracle_admin.status.label.tracking_active_humans": "Aktive Benutzer: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans": "Registrierte Nutzer: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans_error": "Registrierte Nutzer: nicht verfügbar (Fehler)", + "cmd.poracle_admin.status.label.tracking_type": "{0}: {1}", + "cmd.poracle_admin.status.label.mysql_ping_ok": "Ping: OK", + "cmd.poracle_admin.status.label.mysql_ping_fail": "Ping: fehlgeschlagen ({0})", + "cmd.poracle_admin.status.label.mysql_pool": "Verbindungen: {0}/{1} offen ({2} in Benutzung, {3} Leerlauf, wartend={4})", + "cmd.poracle_admin.status.tracking_type.pokemon": "pokemon", + "cmd.poracle_admin.status.tracking_type.raid": "raid", + "cmd.poracle_admin.status.tracking_type.egg": "ei", + "cmd.poracle_admin.status.tracking_type.quest": "feldforschung", + "cmd.poracle_admin.status.tracking_type.invasion": "invasion", + "cmd.poracle_admin.status.tracking_type.lure": "lockmodul", + "cmd.poracle_admin.status.tracking_type.nest": "nest", + "cmd.poracle_admin.status.tracking_type.gym": "arena", + "cmd.poracle_admin.status.tracking_type.fort": "fort", + "cmd.poracle_admin.status.tracking_type.maxbattle": "dynamax", + "cmd.poracle_admin.slash.help.intro": "**!poracle-admin slash** - Slash Befehle Registrierungs-Lebenszyklus.\\nUnterbefehle:", + "cmd.poracle_admin.slash.discord_only": "❌ Slash Befehle sind Discord-exklusiv und können nicht über Telegram verwaltet werden..", + "cmd.poracle_admin.slash.not_configured": "❌ Slash Befehle sind nicht konfiguriert (Discord disabled oder [discord.slash_commands] enabled=false).", + "cmd.poracle_admin.slash.sync.desc": "das aktuelle Befehlsset an Discord übermitteln (fingerprint-cached, überspringen falls unverändert)", + "cmd.poracle_admin.slash.sync.success": "✅ Slash Synchronisierung abgeschlossen ({0}ms)", + "cmd.poracle_admin.slash.sync.error": "❌ Slash Synchronisierung fehlgeschlagen: {0}", + "cmd.poracle_admin.slash.force_resync.desc": "Fingerprint-Cache leeren und bedingungslos pushen", + "cmd.poracle_admin.slash.force_resync.success": "✅ Erzwungene Synchronisierung abgeschlossen ({0}ms)", + "cmd.poracle_admin.slash.force_resync.error": "❌ Erzwungene Synchronisierung fehlgeschlagen: {0}", + "cmd.poracle_admin.slash.clear_global.desc": "alle global registrierten Discord-Slash-Befehle entfernen", + "cmd.poracle_admin.slash.clear_global.success": "✅ Globale Slash Befehle gelöschet.", + "cmd.poracle_admin.slash.clear_global.error": "❌ Löschen der globalen Befehle fehlgeschlagen: {0}", + "cmd.poracle_admin.slash.clear_guild.desc": "Slash-Befehle von einer Gilde entfernen (benötigt Guild_Id arg)", + "cmd.poracle_admin.slash.clear_guild.needs_arg": "❌ Verwendung: `!poracle-admin slash clear-guild `", + "cmd.poracle_admin.slash.clear_guild.success": "✅ Slash Befehle von Guild {0} gelöscht.", + "cmd.poracle_admin.slash.clear_guild.error": "❌ Löschen der Guild Befehle fehlgeschlagen: {0}", + "cmd.poracle_admin.slash.status.desc": "letzte Sync-Zeitstempel und Fingerabdruck pro Scope anzeigen", + "cmd.poracle_admin.slash.status.header": "**Slash Befehl Registrierungsstatus:**", + "cmd.poracle_admin.slash.status.scope_row": " **{0}**: zuletzt synchronisiert {1} · Fingerabdruck `{2}`", + "cmd.poracle_admin.slash.status.never_synced": "nie", + "cmd.poracle_admin.slash.status.ago": "vor {0}", + "cmd.poracle_admin.slash.status.error": "❌ Auslesen des Status fehlgeschlagen: {0}", + "cmd.poracle_admin.config.help.intro": "⚙️ Config Viewer - effektive zusammengeführte Config mit ausgeblendeten Secrets anzeigen.\\nUnterbefehle:", + "cmd.poracle_admin.config.keys.desc": "Bereichnamen mit Schlüsselanzahlen auflisten", + "cmd.poracle_admin.config.section.desc": "nur diesen Bereich anzeigen (z.B. `!poracle-admin config discord`)", + "cmd.poracle_admin.config.full.desc": "vollständige Config anzeigen (alle Bereiche, Secrets ausgeblendet)", + "cmd.poracle_admin.config.keys.header": "⚙️ Config Bereiche:", "cmd.poracle_admin.config.keys.row": " {0}: {1} Schlüssel", - "cmd.poracle_admin.config.unknown_section": "Unbekannter Konfigurationsabschnitt: `{0}`. Verwenden Sie `!poracle-admin config keys` für gültige Abschnitte, oder `!poracle-admin config search ` zum Suchen über alle Abschnitte.", - "cmd.poracle_admin.config.search.desc": "Schlüssel suchen, deren Pfad oder Wert den Begriff enthält (z.B. `!poracle-admin config search dm`)", - "cmd.poracle_admin.config.search.usage": "Verwendung: `!poracle-admin config search ` — z.B. `search dm`, `search shlink`, `search 3030`.", - "cmd.poracle_admin.config.search.header": "🔍 `{0}` — {1} Treffer:", - "cmd.poracle_admin.config.search.no_matches": "Keine Konfigurationsschlüssel oder -werte stimmen mit `{0}` überein.", - "cmd.poracle_admin.config.empty_section": "Abschnitt `{0}` hat keine konfigurierbaren Felder.", - "cmd.poracle_admin.config.not_loaded": "❌ Konfiguration nicht geladen.", - "cmd.poracle_admin.warnings.help.intro": "🛠️ Erfasste Warnungen — In-Memory WARN/ERROR-Logeinträge anzeigen.\n\nUnterbefehle:\n (kein Arg) — Startup- und Recent-Puffer anzeigen\n `startup` — nur den Startup-Puffer anzeigen (erste 200 Einträge, nach dem Start eingefroren)\n `recent` — nur den Rolling-Puffer anzeigen (letzte 50 Einträge)\n `clear` — Rolling-Puffer leeren (Startup-Puffer ist unveränderlich)", - "cmd.poracle_admin.warnings.not_configured": "ℹ️ Log-Puffer ist auf dieser Instanz nicht konfiguriert.", - "cmd.poracle_admin.warnings.section.startup": "🛠️ Erfasste Warnungen — Startup ({0} Einträge)", - "cmd.poracle_admin.warnings.section.recent": "🛠️ Erfasste Warnungen — Recent ({0} Einträge)", - "cmd.poracle_admin.warnings.empty.startup": "🟢 Keine Startup-Warnungen erfasst.", + "cmd.poracle_admin.config.unknown_section": "Unbekannter Config Bereich: `{0}`. Nutze `!poracle-admin config keys` um gültige Bereiche aufzulisten, oder `!poracle-admin config search ` um in allen Bereichen zu suchen.", + "cmd.poracle_admin.config.search.desc": "finde in jedem Bereich Schlüssel, deren Pfad oder Wert den Begriff enthält (z.B. `!poracle-admin config search dm`)", + "cmd.poracle_admin.config.search.usage": "Verwendung: `!poracle-admin config search ` - z.B. `search dm`, `search shlink`, `search 3030`.", + "cmd.poracle_admin.config.search.header": "🔍 `{0}` - {1} Treffer:", + "cmd.poracle_admin.config.search.no_matches": "Keine Configschlüssel oder -werte stimmen überein `{0}`.", + "cmd.poracle_admin.config.empty_section": "Bereich `{0}` hat keine konfigurierbaren Felder.", + "cmd.poracle_admin.config.not_loaded": "❌ Config nicht geladen.", + "cmd.poracle_admin.warnings.help.intro": "🛠️ Erfasste Warnungen- In-Memory WARN/ERROR Logeinträge inspizieren.\\n\\nUnterbefehle:\\n (keine arg) - sowohl Start- als auch aktuelle Puffer anzeigen\\n `startup` - nur den Startpuffer anzeigen (Die ersten 200 Einträge wurden nach der Initialisierung eingefroren.)\\n `recent` - nur den Rolling Buffer anzeigen (letzten 50 Einträge)\\n `clear` - den Rolling Buffer leeren (der Startup ist unveränderlich)", + "cmd.poracle_admin.warnings.not_configured": "ℹ️ Der Log-Puffer ist auf dieser Instanz nicht konfiguriert.", + "cmd.poracle_admin.warnings.section.startup": "🛠️ Erfasste Warnungen - Startup ({0} Einträge)", + "cmd.poracle_admin.warnings.section.recent": "🛠️ Erfasste Warnungen - aktuell ({0} Einträge)", + "cmd.poracle_admin.warnings.empty.startup": "🟢 Keine Startwarnungen erfasst.", "cmd.poracle_admin.warnings.empty.recent": "🟢 Keine aktuellen Warnungen.", "cmd.poracle_admin.warnings.entry_row": " {0} {1} {2} {3}", "cmd.poracle_admin.warnings.cleared": "✅ {0} Einträge aus dem Rolling-Puffer gelöscht (Startup-Puffer nicht betroffen).", - "cmd.poracle_admin.warnings.startup.desc": "`startup` — nur den Startup-Puffer anzeigen (nach dem Start eingefroren)", - "cmd.poracle_admin.warnings.recent.desc": "`recent` — nur den Rolling-Puffer anzeigen (letzte 50 Einträge)", - "cmd.poracle_admin.warnings.clear.desc": "`clear` — Rolling-Puffer leeren", - "cmd.maintenance.active_suffix": "🔧 Wartungsmodus aktiv — Meldungen werden nicht ausgeliefert." + "cmd.poracle_admin.warnings.startup.desc": "`startup` - nur den Startup-Puffer anzeigen (nach dem Start eingefroren)", + "cmd.poracle_admin.warnings.recent.desc": "`recent` - nur den Rolling-Puffer anzeigen (letzte 50 Einträge)", + "cmd.poracle_admin.warnings.clear.desc": "`clear` - Rolling-Puffer leeren", + "cmd.maintenance.active_suffix": "🔧 Wartungsmodus aktiv - Meldungen werden nicht ausgeliefert.", + "showcase_focus_pokemon": "Pokémon", + "showcase_focus_type": "Type", + "showcase_focus_alignment": "Alignment", + "showcase_focus_class": "Class", + "showcase_focus_family": "Family", + "showcase_focus_buddy": "Buddy", + "showcase_focus_generation": "Generation", + "showcase_focus_hatched": "Hatched", + "showcase_focus_mega": "Mega", + "showcase_focus_shiny": "Shiny", + "showcase_class_ultra_beast": "Ultra Beast" } diff --git a/processor/internal/i18n/locale/fr.json b/processor/internal/i18n/locale/fr.json index 155339d25..f62daf992 100644 --- a/processor/internal/i18n/locale/fr.json +++ b/processor/internal/i18n/locale/fr.json @@ -58,6 +58,11 @@ "tracking.pvp_little": "littlepvp", "tracking.pvp_great": "PVP Super", "tracking.pvp_ultra": "PVP Hyper", + "tracking.pvp_mega_any": "mega", + "tracking.pvp_mega_x": "mega x", + "tracking.pvp_mega_y": "mega y", + "tracking.mega_x_label": "X", + "tracking.mega_y_label": "Y", "tracking.level_cap_fmt": "level cap: {0}", "tracking.everything": "Tous", "tracking.unknown_monster": "Pokémon inconnu", @@ -81,10 +86,14 @@ "tracking.reward_fmt": "Reward: **{0}**", "tracking.reward_stardust_min_fmt": "{0} or more stardust", "tracking.reward_stardust": "poussière", + "tracking.reward_pokecoin_min_fmt": "{0} or more pokecoins", + "tracking.reward_pokecoin": "pokecoins", "tracking.reward_mega_energy": "méga énergie", "tracking.reward_mega_energy_fmt": "mega energy {0}", "tracking.reward_candy": "candy", "tracking.reward_candy_fmt": "candy {0}", + "tracking.reward_any_pokemon": "any pokemon", + "tracking.reward_any_item": "any item", "tracking.reward_min_fmt": "minimum {0}", "tracking.grunt_type_fmt": "Grunt type: **{0}**", "tracking.min_avg_spawn": "Min avg. spawn {0}/hour", @@ -108,10 +117,68 @@ "tracking.template_not_found": "Template \"{0}\" does not exist.", "tracking.warn_template_not_found": "Template \"{0}\" not found for type {1}/{2}. Tracking saved but alerts may not render.", "tracking.id_hint": "To remove a specific entry, use its id — e.g. `{0}untrack id:45` or `{0}raid remove id:12`", + "tracking.id_hint_slash": "To remove a specific entry, run `/untrack ` (e.g. `/untrack raid`) and pick it from the list.", + "tracking.list_attached": "Your tracking list is long ({0} rules) — attached as a file.", "tracking.removed_prefix": "Removed: ", "tracking.uid_not_found": "id:{0} not found", + "tracking.override_location_fmt": "@ {0}", + "tracking.override_areas_fmt": "in {0}", "cmd.track": "suivre", "cmd.untrack": "ignorer", + "cmd.mute": "mute", + "cmd.unmute": "unmute", + "msg.mute.unavailable": "Mute feature isn't enabled here.", + "msg.mute.usage": "Valid commands are `{0}mute [duration:1h]`", + "msg.mute.usage_pokemon": "Valid commands are `{0}mute pokemon [duration:1h]`", + "msg.mute.usage_gym": "Valid commands are `{0}mute gym [duration:1h]`", + "msg.mute.usage_area": "Valid commands are `{0}mute area [duration:1h]`", + "msg.mute.usage_id_scope": "Valid commands are `{0}mute {1} [duration:1h]`", + "msg.mute.bad_duration": "Invalid duration: {0}", + "msg.mute.id_not_supported": "`!mute id:N` / `!mute id:N` aren't supported yet — entity scopes (gym, pokemon, area, pokestop, station, everything) work today. Per-rule muting by UID is a follow-up.", + "msg.mute.bad_uid": "`{0}` isn't a valid tracking rule UID. Use `!tracked` to see your rule UIDs.", + "msg.mute.unknown_area": "`{0}` isn't in your available areas. Use `!area` to see what you can mute.", + "msg.mute.no_pokemon": "I don't know a pokemon called `{0}`.", + "msg.mute.everything_label": "everything", + "msg.mute.added": "🔇 Muted {0} for {1}.", + "msg.mute.removed": "✅ Unmuted {0}.", + "msg.mute.none_found": "No active mute for {0}.", + "msg.mute.cleared_all": "Cleared {0} active mutes.", + "msg.unmute.usage": "Valid commands are `{0}unmute `, `{0}unmute all`", + "msg.unmute.usage_pokemon": "Valid commands are `{0}unmute pokemon `", + "msg.unmute.usage_gym": "Valid commands are `{0}unmute gym `", + "msg.unmute.usage_area": "Valid commands are `{0}unmute area `", + "section.property_mutes": "Property mutes (apply across all tracking):", + "section.property_mutes.left": "({0} left)", + "msg.button.expired": "This alert has expired.", + "msg.button.unavailable": "This button is no longer available.", + "msg.button.wrong_target": "This button doesn't apply here.", + "msg.button.unauthorized": "This button isn't for you.", + "msg.button.unidentified": "Couldn't identify you to handle that click.", + "msg.button.unconfigured": "This button isn't configured.", + "msg.button.action_failed": "Couldn't complete that action: {0}", + "msg.button.action_failed_generic": "Couldn't complete that action.", + "msg.button.cooldown": "Slow down — try that again in a moment.", + "msg.button.actions_not_wired": "Button actions aren't wired here.", + "msg.button.not_implemented": "The {0} action isn't implemented yet.", + "msg.button.responses_not_wired": "Response rendering isn't wired here.", + "msg.button.response_failed": "Couldn't render that response: {0}", + "msg.button.done": "Done.", + "msg.button.missing_scope": "Button is missing a scope — operator config bug.", + "msg.button.missing_target": "Couldn't find a {0} to mute on this alert.", + "msg.button.no_dm_target": "Couldn't identify you to send the message.", + "msg.button.dm_failed": "Couldn't send to your DM: {0}", + "msg.button.unsubscribe_failed": "Couldn't unsubscribe — please try again.", + "msg.button.unsubscribe_already": "Those tracking rules were already removed.", + "msg.button.unsubscribed": "✅ Unsubscribed from {0} tracking rule(s).", + "msg.button.redeliver_sent": "📬 Sent to your DM.", + "msg.mute.scope_gym": "gym", + "msg.mute.scope_pokemon": "pokemon", + "msg.mute.scope_area": "area", + "msg.mute.scope_pokestop": "pokestop", + "msg.mute.scope_station": "station", + "msg.mute.scope_tracking": "tracking rule", + "cmd.mute.usage": "**{0}mute** — silence alerts for a specific gym, pokemon, area, pokestop, station, or everything for a time-bounded window.\n\n• `{0}mute everything [duration:1h]` — silence ALL alerts for the given duration\n• `{0}mute gym [duration:1h]` — silence alerts for one gym\n• `{0}mute pokemon [duration:1h]` — silence alerts for one pokemon species\n• `{0}mute area [duration:1h]` — silence alerts in one area\n• `{0}mute pokestop [duration:1h]` — silence alerts for one pokestop\n• `{0}mute station [duration:1h]` — silence alerts for one station\n\nDuration defaults to 1h if omitted. Use `{0}unmute ` to remove a mute early, or `{0}tracked` to see active mutes.", + "cmd.track.usage": "**{0}track** — set up pokemon tracking rules.\n\n• `{0}track ` — track a specific pokemon (by name or dex id) at default 100m\n• `{0}track everything` — track every pokemon (admin-permitted; see `{0}help everything`)\n• `{0}track iv:100` — filter by IV percent (`iv:90-100` for range, `miniv:90`/`maxiv:99` for one-sided)\n• `{0}track cp:1500-2500` — filter by CP\n• `{0}track level:25-35` — filter by level\n• `{0}track atk:14-15 def:14-15 sta:14-15` — filter by individual IV stats\n• `{0}track d:500` — only alert within 500m of your location\n• `{0}track location:Home d:500` — within 500m of a saved location\n• `{0}track area:london,paris` — only in named areas (replaces your default areas)\n• `{0}track great5 ultra10` — PVP filters (great/ultra/little league, rank threshold, optional cap)\n• `{0}track gen:1 type:water` — generation and type filters (alongside `everything`)\n• `{0}track rarity:rare-ultra` — rarity-tier filter\n• `{0}track clean` / `edit` — auto-delete on TTH expiry / edit-in-place\n• `{0}track remove ` or `{0}untrack ` — remove\n• `{0}untrack id:42` — remove one rule by id (see `{0}tracked` for ids)\n\nMultiple filters combine. See `{0}tracked` for what's currently active.", "cmd.raid": "raid", "cmd.egg": "oeuf", "cmd.quest": "quête", @@ -129,6 +196,8 @@ "cmd.fort": "fort", "cmd.help": "aide", "cmd.info": "info", + "cmd.info.poracle.moved": "→ This view has moved to `!poracle-admin status` — please use that instead.", + "cmd.info.config.moved": "→ This view has moved to `!poracle-admin config` — please use that instead.", "cmd.start": "start", "cmd.stop": "stop", "cmd.tracked": "suivi", @@ -163,6 +232,8 @@ "cmd.poracle_id": "poracle-id", "arg.remove": "enlever", "arg.everything": "tous", + "arg.all_pokemon": "all pokemon", + "arg.all_items": "all items", "arg.any": "tout", "arg.clean": "clean", "arg.edit": "edit", @@ -170,6 +241,7 @@ "arg.list": "liste", "arg.add": "ajouter", "arg.show": "afficher", + "arg.default": "default", "arg.overview": "aperçu", "arg.dryrun": "dryrun", "arg.reset": "reset", @@ -182,6 +254,7 @@ "arg.shiny": "chromatique", "arg.gmax": "gmax", "arg.stardust": "poussière", + "arg.pokecoin": "pokecoins", "arg.energy": "énergie", "arg.candy": "bonbon", "arg.pvp": "pvp", @@ -248,7 +321,10 @@ "arg.prefix.maxsize": "maxtaille", "arg.prefix.gen": "gen", "arg.prefix.cap": "cap", + "arg.mega": "mega", + "arg.prefix.mega": "mega", "arg.prefix.form": "forme", + "arg.prefix.costume": "costume", "arg.prefix.template": "modèle", "arg.prefix.gym": "gym", "arg.prefix.move": "attaque", @@ -263,13 +339,17 @@ "arg.prefix.littlehigh": "littlehaut", "arg.prefix.littlecp": "littlepc", "arg.prefix.stardust": "poussière", + "arg.prefix.pokecoin": "pokecoins", "arg.prefix.energy": "énergie", "arg.prefix.candy": "bonbon", + "arg.prefix.amount": "amount", "arg.prefix.name": "nom", "arg.prefix.user": "utilisateur", "arg.prefix.channel": "salon", "arg.prefix.guild": "guilde", "arg.prefix.language": "langue", + "arg.prefix.area": "area", + "arg.prefix.location": "location", "arg.prefix.mon": "lun", "arg.prefix.tue": "mar", "arg.prefix.wed": "mer", @@ -323,21 +403,26 @@ "section.maxbattles.none": "You're not tracking any max battles", "msg.no_pokemon": "Pokémon non trouvé", "msg.form_not_found": "Form `{0}` not recognised. Use `{1}info ` to see available forms.", + "msg.costume_not_found": "Costume `{0}` not recognised. Use `{1}info costumes` to see available costumes.", + "msg.no_costume": "no costume", "msg.nothing_to_remove": "Nothing to remove", "msg.no_levels": "No levels specified", "msg.no_egg_levels": "No egg levels specified", "msg.no_raid_target": "No raid levels or pokemon specified", "msg.no_lure_type": "No lure type specified", "msg.no_quest_type": "No quest type specified", + "msg.quest.amount_not_applicable": "`amount:N` doesn't apply to pokemon quests — pokemon rewards have no minimum amount.", + "msg.quest.bulk_not_permitted": "You do not have permission to track all pokemon or items at once. Track specific rewards instead.", "msg.removed_n": "J'ai retiré {0} entrées", "msg.egg.usage": "Valid commands are e.g. `{0}egg level:5`, `{0}egg legendary`, `{0}egg remove everything`", "msg.raid.usage": "Valid commands are e.g. `{0}raid level:5`, `{0}raid pikachu`, `{0}raid remove everything`", "msg.track.usage": "Valid commands are e.g. `{0}track pikachu iv:100`, `{0}track everything iv:90`, `{0}track remove pikachu`", "msg.track.everything_no_filters": "Cela donnerait beaucoup trop d'alertes. Il faut préciser des filtres supplémentaires pour limiter le nombre de candidats valides.", "msg.track.invalid_cap": "This level cap is not supported, valid choices are: {0}", - "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest energy:charizard`", + "msg.track.no_mega_form": "⚠️ {0} has no Mega {1} form — this PVP rule will never match.", + "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest pokecoins:10`, `{0}quest energy:charizard`", "msg.quest.edit_summary_conflict": "`edit` and `summary` are mutually exclusive — pick one.", - "msg.summary.usage": "Usage: `{0}summary quest [settime |cleartime|now]`", + "msg.summary.usage": "Valid commands are `{0}summary quest`, `{0}summary quest settime `, `{0}summary quest cleartime`, `{0}summary quest now`", "msg.summary.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.summary.no_schedule": "No schedule set for {0} summaries.", "msg.summary.scheduled": "Schedule for {0} summaries: {1}", @@ -360,11 +445,33 @@ "msg.nest.usage": "Valid commands are e.g. `{0}nest pikachu`, `{0}nest everything`, `{0}nest remove pikachu`", "msg.maxbattle.usage": "Valid commands are e.g. `{0}maxbattle pikachu`, `{0}maxbattle level:3`, `{0}maxbattle remove everything`", "msg.fort.usage": "Valid commands are e.g. `{0}fort pokestop`, `{0}fort everything`, `{0}fort remove pokestop`", - "msg.location.removed": "Location removed", - "msg.location.usage": "Valid commands are e.g. `{0}location ,`, `{0}location `", + "msg.location.removed": "✅ Removed saved location `{0}`.", + "msg.location.usage": "Valid commands are `{0}location `, `{0}location add `, `{0}location list`, `{0}location show `, `{0}location remove `, `{0}location remove default`", "msg.location.specify": "Please specify coordinates or an address", "msg.location.set": "Position définie à {0},{1}", "msg.location.current": "Your current location is {0},{1}", + "msg.location.added": "✅ Saved location `{0}` at {1}, {2}.", + "msg.location.duplicate": "🙅 You already have a saved location called `{0}`. Remove it first with `{1}location remove {0}`.", + "msg.location.list_header": "Your saved locations:", + "msg.location.list_row": " `{0}`: {1}, {2}", + "msg.location.list_row_with_addr": " `{0}`: {1}, {2} — {3}", + "msg.location.list_empty": "You have no saved locations. Add one with `{0}location add `.", + "msg.location.show_not_found": "🙅 No saved location called `{0}`.", + "msg.location.show": "📍 `{0}` is at {1}, {2}.", + "msg.location.show_with_addr": "📍 `{0}` is at {1}, {2} — {3}", + "msg.location.no_default": "🙅 No default location set.", + "msg.location.default_removed": "✅ Cleared your default location.", + "msg.location.remove_referenced": "🙅 Cannot remove `{0}` — {1} tracking rule(s) reference it: {2}. Edit or remove those rules first.", + "msg.location.add_usage": "Valid commands are `{0}location add `", + "msg.location.show_usage": "Valid commands are `{0}location show `", + "msg.location.remove_usage": "Valid commands are `{0}location remove `, `{0}location remove default`", + "msg.location.geocode_failed": "🙅 Couldn't find a place matching `{0}`.", + "cmd.location.usage": "**{0}location** — manage your default location and saved named locations.\n\n• `{0}location` — show your current default location\n• `{0}location ` — set your default location\n• `{0}location add ` — save a named location (referenced later as `location:` on tracking rules)\n• `{0}location list` — list all your saved locations\n• `{0}location show ` — show one saved location's coords + address (use `default` for your default)\n• `{0}location remove ` — delete a saved location (refuses if any tracking rule references it)\n• `{0}location remove default` — clear your default location", + "msg.override.requires_distance": "🙅 `location:` needs a `d:` distance — e.g. `location:Home d:500`.", + "msg.override.area_and_distance": "🙅 `area:` and `d:` are mutually exclusive (area-mode vs distance-mode). Pick one.", + "msg.override.area_and_location": "🙅 `area:` and `location:` are mutually exclusive. Pick one.", + "msg.override.unknown_location": "🙅 No saved location called `{0}`. Add it with `{1}location add {0} `.", + "msg.override.area_not_permitted": "🙅 Area `{0}` is not in your allowed areas. Use `{1}area list` to see what you can pick.", "msg.area.usage": "Valid commands are `{0}area list`, `{0}area add `, `{0}area remove `", "msg.area.none_available": "No areas available", "msg.area.available": "**Available areas:**", @@ -382,14 +489,14 @@ "msg.profile.deleted": "Profile {0} deleted", "msg.profile.not_found": "Profil non trouvé", "msg.profile.cannot_delete_1": "Cannot delete profile 1", - "msg.profile.hours_usage": "Usage: profile hours ", + "msg.profile.hours_usage": "Valid commands are `{0}profile hours `", "msg.profile.hours_invalid_json": "Invalid JSON for active hours", "msg.profile.hours_set": "Active hours updated for profile {0}", "msg.profile.hours_cleared": "Active hours cleared for profile {0}", - "msg.profile.settime_usage": "Usage: profile settime mon09:00 tue18:30 weekday09:00 weekend10:00", + "msg.profile.settime_usage": "Valid commands are `{0}profile settime mon09:00 tue18:30 weekday09:00 weekend10:00`", "msg.profile.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.profile.copied": "Profil courant copié vers : {0}", - "msg.profile.copyto_usage": "Usage: profile copyto ", + "msg.profile.copyto_usage": "Valid commands are `{0}profile copyto `", "msg.profile.copy_invalid": "Les profils suivants sont invalides : {0}", "msg.profile.usage": "Valid commands are `{0}profile `, `{0}profile list`, `{0}profile add `, `{0}profile remove `, `{0}profile settime `, `{0}profile copyto `", "msg.profile.list_header": "Les profils configurés sont :", @@ -407,6 +514,7 @@ "msg.weather.unavailable": "Weather tracking is not yet available via this command", "msg.help.unknown_topic": "No help available for '{0}'. Use `{1}help` for general help.", "msg.help.no_greeting": "No help template configured. Use `{0}help ` for command-specific help.", + "msg.help.see_detailed": "💡 More detailed help is available — `{0}help {1}`", "msg.info.sub.moves": "moves", "msg.info.sub.items": "items", "msg.info.sub.shiny": "shiny", @@ -417,9 +525,19 @@ "msg.info.sub.translate": "translate", "msg.info.sub.dts": "dts", "msg.info.sub.templates": "templates", - "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info `", + "msg.info.sub.costumes": "costumes", + "msg.info.sub.forms": "forms", + "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info costumes`, `{0}info `", "msg.info.usage_admin": "Admin: `{0}info poracle`, `{0}info dts`, `{0}info translate `, `{0}info config [search]`", "msg.info.available_forms": "Formes disponibles", + "msg.info.more_forms": "More than {0} forms — do {1} for the full list", + "msg.info.recent_forms": "**Recently-seen forms:**", + "msg.info.recent_raid_forms": "**Recently-seen raid forms:**", + "msg.info.available_costumes": "**Recently-seen costumes:**", + "msg.info.recent_raid_costumes": "**Recently-seen raid costumes:**", + "msg.info.costumes.header": "**Costumes** (`costume:` to track):", + "msg.info.no_costume_data": "No costume data loaded", + "msg.info.no_form_data": "No form data for that pokemon.", "msg.info.hundo_cp": "100% IV CP:", "msg.info.dts_summary": "DTS Templates loaded:", "msg.info.pokemon_not_found": "Pokemon not found: {0}", @@ -534,5 +652,661 @@ "language.sv": "Svenska", "language.zh-cn": "Chinois (simplifié)", "language.ja": "Japonais", - "msg.help.text": "**Available commands:**\n{0}track [iv:N] [cp:N] [level:N] [d:N] — Track pokemon\n{0}untrack — Remove pokemon tracking\n{0}raid [d:N] — Track raids\n{0}egg [d:N] — Track eggs\n{0}quest — Track quests\n{0}invasion [everything|] — Track invasions\n{0}lure — Track lures\n{0}gym [slot_changes] — Track gyms\n{0}nest — Track nests\n{0}maxbattle — Track max battles\n{0}fort — Track fort updates\n{0}tracked — Show all tracking\n{0}script — Export tracking as commands\n{0}area [list|add|remove] — Manage areas\n{0}location — Set location\n{0}profile [list|add|remove|switch] — Manage profiles\n{0}language — Set language\n{0}start / {0}stop — Enable/disable alerts\n{0}version — Show version" + "slash.cmd.version": "version", + "slash.desc.version": "Show Poracle version", + "slash.cmd.tracked": "tracked", + "slash.cmd.help": "help", + "slash.cmd.info": "info", + "slash.cmd.language": "language", + "slash.cmd.track": "track", + "slash.cmd.raid": "raid", + "slash.cmd.egg": "egg", + "slash.cmd.quest": "quest", + "slash.cmd.invasion": "invasion", + "slash.cmd.incident": "incident", + "slash.cmd.lure": "lure", + "slash.cmd.nest": "nest", + "slash.cmd.maxbattle": "maxbattle", + "slash.cmd.gym": "gym", + "slash.cmd.fort": "fort", + "slash.cmd.untrack": "untrack", + "slash.cmd.area": "area", + "slash.cmd.profile": "profile", + "slash.cmd.location": "location", + "slash.cmd.summary": "summary", + "slash.cmd.start": "start", + "slash.cmd.stop": "stop", + "slash.desc.tracked": "List your tracking rules", + "slash.desc.start": "Resume alert delivery (after /stop)", + "slash.desc.stop": "Pause alert delivery (resume with /start)", + "slash.desc.help": "Show help", + "slash.desc.info": "Look up pokemon info, shiny rates, rarity tiers, or current weather", + "slash.opt.info.pokemon": "pokemon", + "slash.opt.info.pokemon.desc": "Show types, stats, evolutions, weather boost and CP table for a pokemon", + "slash.opt.info.pokemon.name": "name", + "slash.opt.info.pokemon.name.desc": "Pokemon name (any supported language) or dex id", + "slash.opt.info.rarity": "rarity", + "slash.opt.info.rarity.desc": "List pokemon by spawn rarity tier (common → ultra-rare)", + "slash.opt.info.shiny": "shiny", + "slash.opt.info.shiny.desc": "Show observed shiny rates per species", + "slash.opt.info.weather": "weather", + "slash.opt.info.weather.desc": "Show current weather and boosted types for a location", + "slash.opt.info.weather.coords": "coords", + "slash.opt.info.weather.coords.desc": "lat,lon (defaults to your saved location)", + "slash.desc.language": "Show or set your language", + "slash.desc.track": "Track a Pokemon", + "slash.desc.raid": "Track a raid boss or raid level", + "slash.desc.egg": "Track an egg / raid level", + "slash.desc.quest": "Track a quest reward", + "slash.desc.invasion": "Track a Team Rocket invasion", + "slash.desc.incident": "Track a pokestop incident (Kecleon, Gold Pokestop, Showcase…)", + "slash.desc.lure": "Track a pokestop lure", + "slash.desc.nest": "Track a nesting pokemon", + "slash.desc.maxbattle": "Track a max (Dynamax) battle", + "slash.desc.gym": "Track gym team / slot / battle changes", + "slash.desc.fort": "Track pokestop or gym updates", + "slash.desc.untrack": "Remove a tracking rule", + "slash.desc.area": "Manage your areas", + "slash.desc.profile": "Manage your profiles", + "slash.desc.location": "Manage your saved locations", + "slash.desc.summary": "Manage scheduled summary digests (e.g. quest)", + "slash.opt.help.topic": "topic", + "slash.opt.help.topic.desc": "Help topic", + "slash.opt.language.code": "code", + "slash.opt.language.code.desc": "Language code", + "slash.opt.track.pokemon": "pokemon", + "slash.opt.track.pokemon.desc": "Pokemon to track (or 'everything')", + "slash.opt.track.iv": "iv", + "slash.opt.track.iv.desc": "IV filter (e.g. 100, 95, 0-0)", + "slash.opt.track.distance": "distance", + "slash.opt.track.distance.desc": "Alert radius in metres", + "slash.opt.track.great_rank": "great_rank", + "slash.opt.track.great_rank.desc": "Top PVP rank in the Great League", + "slash.opt.track.ultra_rank": "ultra_rank", + "slash.opt.track.ultra_rank.desc": "Top PVP rank in the Ultra League", + "slash.opt.track.little_rank": "little_rank", + "slash.opt.track.little_rank.desc": "Top PVP rank in the Little League", + "slash.opt.track.clean": "clean", + "slash.opt.track.clean.desc": "Auto-delete the alert when the pokemon despawns", + "slash.opt.track.template": "template", + "slash.opt.track.template.desc": "DTS template name", + "slash.opt.track.form": "form", + "slash.opt.track.form.desc": "Pokemon form", + "slash.opt.track.size": "size", + "slash.opt.track.size.desc": "Pokemon size class", + "slash.choice.track.clean.yes": "Yes", + "slash.choice.track.size.all": "All sizes", + "slash.choice.track.size.xxs": "XXS", + "slash.choice.track.size.xs": "XS", + "slash.choice.track.size.m": "M", + "slash.choice.track.size.xl": "XL", + "slash.choice.track.size.xxl": "XXL", + "slash.opt.raid.boss": "boss", + "slash.opt.raid.boss.desc": "Raid boss pokemon", + "slash.opt.raid.level": "level", + "slash.opt.raid.level.desc": "Raid level", + "slash.opt.raid.team": "team", + "slash.opt.raid.team.desc": "Required gym-control team", + "slash.opt.raid.distance": "distance", + "slash.opt.raid.distance.desc": "Alert radius in metres", + "slash.opt.raid.clean": "clean", + "slash.opt.raid.clean.desc": "Auto-delete the alert when the raid expires", + "slash.opt.raid.template": "template", + "slash.opt.raid.template.desc": "DTS template name", + "slash.choice.raid.clean.yes": "Yes", + "slash.choice.raid.level.1": "Tier 1", + "slash.choice.raid.level.3": "Tier 3", + "slash.choice.raid.level.5": "Tier 5", + "slash.choice.raid.level.6": "Tier 6", + "slash.choice.raid.level.mega": "Mega", + "slash.choice.raid.level.legendary": "Legendary", + "slash.choice.raid.level.shadow1": "Shadow Tier 1", + "slash.choice.raid.level.shadow3": "Shadow Tier 3", + "slash.choice.raid.level.shadow5": "Shadow Tier 5", + "slash.choice.raid.level.ultra beast": "Ultra Beast", + "slash.choice.raid.level.everything": "Everything", + "slash.choice.raid.team.0": "Harmony", + "slash.choice.raid.team.1": "Mystic", + "slash.choice.raid.team.2": "Valor", + "slash.choice.raid.team.3": "Instinct", + "slash.opt.egg.level": "level", + "slash.opt.egg.level.desc": "Egg / raid level", + "slash.opt.egg.team": "team", + "slash.opt.egg.team.desc": "Required gym-control team", + "slash.opt.egg.distance": "distance", + "slash.opt.egg.distance.desc": "Alert radius in metres", + "slash.opt.egg.clean": "clean", + "slash.opt.egg.clean.desc": "Auto-delete the alert when the egg hatches", + "slash.opt.egg.template": "template", + "slash.opt.egg.template.desc": "DTS template name", + "slash.choice.egg.clean.yes": "Yes", + "slash.choice.egg.level.1": "Tier 1", + "slash.choice.egg.level.3": "Tier 3", + "slash.choice.egg.level.5": "Tier 5", + "slash.choice.egg.level.6": "Tier 6", + "slash.choice.egg.level.mega": "Mega", + "slash.choice.egg.level.legendary": "Legendary", + "slash.choice.egg.level.shadow1": "Shadow Tier 1", + "slash.choice.egg.level.shadow3": "Shadow Tier 3", + "slash.choice.egg.level.shadow5": "Shadow Tier 5", + "slash.choice.egg.level.ultra beast": "Ultra Beast", + "slash.choice.egg.level.everything": "Everything", + "slash.choice.egg.team.0": "Harmony", + "slash.choice.egg.team.1": "Mystic", + "slash.choice.egg.team.2": "Valor", + "slash.choice.egg.team.3": "Instinct", + "slash.opt.quest.pokemon": "pokemon", + "slash.opt.quest.pokemon.desc": "Pokemon reward", + "slash.opt.quest.item": "item", + "slash.opt.quest.item.desc": "Item reward (e.g. golden razz berry)", + "slash.opt.quest.stardust": "stardust", + "slash.opt.quest.stardust.desc": "Stardust reward (minimum amount)", + "slash.opt.quest.candy": "candy", + "slash.opt.quest.candy.desc": "Candy reward pokemon", + "slash.opt.quest.mega_energy": "mega_energy", + "slash.opt.quest.mega_energy.desc": "Mega energy reward pokemon", + "slash.opt.quest.min_amount": "min_amount", + "slash.opt.quest.min_amount.desc": "Minimum reward amount (item / candy / mega_energy only)", + "slash.opt.quest.distance": "distance", + "slash.opt.quest.distance.desc": "Alert radius in metres", + "slash.opt.quest.clean": "clean", + "slash.opt.quest.clean.desc": "Auto-delete the alert when the quest is completed", + "slash.opt.quest.summary": "summary", + "slash.opt.quest.summary.desc": "Buffer matches and dispatch in a scheduled batch instead of alerting immediately", + "slash.opt.quest.template": "template", + "slash.opt.quest.template.desc": "DTS template name", + "slash.choice.quest.clean.yes": "Yes", + "slash.choice.quest.summary.yes": "Yes", + "slash.opt.invasion.grunt_type": "grunt_type", + "slash.opt.invasion.grunt_type.desc": "Grunt type (Fire, Water…), boss (Giovanni…), or incident (Kecleon…)", + "slash.opt.invasion.gender": "gender", + "slash.opt.invasion.gender.desc": "Filter by grunt gender", + "slash.opt.invasion.distance": "distance", + "slash.opt.invasion.distance.desc": "Alert radius in metres", + "slash.opt.invasion.clean": "clean", + "slash.opt.invasion.clean.desc": "Auto-delete the alert when the invasion expires", + "slash.opt.invasion.template": "template", + "slash.opt.invasion.template.desc": "DTS template name", + "slash.choice.invasion.clean.yes": "Yes", + "slash.choice.invasion.gender.male": "Male", + "slash.choice.invasion.gender.female": "Female", + "slash.choice.invasion.gender.genderless": "Genderless", + "slash.opt.incident.type": "type", + "slash.opt.incident.type.desc": "Pokestop incident type (Kecleon, Gold Pokestop, Showcase…)", + "slash.opt.incident.distance": "distance", + "slash.opt.incident.distance.desc": "Alert radius in metres", + "slash.opt.incident.clean": "clean", + "slash.opt.incident.clean.desc": "Auto-delete the alert when the incident expires", + "slash.opt.incident.template": "template", + "slash.opt.incident.template.desc": "DTS template name", + "slash.choice.incident.clean.yes": "Yes", + "slash.opt.lure.lure_type": "lure_type", + "slash.opt.lure.lure_type.desc": "Lure type", + "slash.opt.lure.distance": "distance", + "slash.opt.lure.distance.desc": "Alert radius in metres", + "slash.opt.lure.clean": "clean", + "slash.opt.lure.clean.desc": "Auto-delete the alert when the lure expires", + "slash.opt.lure.template": "template", + "slash.opt.lure.template.desc": "DTS template name", + "slash.choice.lure.clean.yes": "Yes", + "slash.choice.lure.lure_type.normal": "Normal", + "slash.choice.lure.lure_type.glacial": "Glacial", + "slash.choice.lure.lure_type.mossy": "Mossy", + "slash.choice.lure.lure_type.magnetic": "Magnetic", + "slash.choice.lure.lure_type.rainy": "Rainy", + "slash.choice.lure.lure_type.sparkly": "Sparkly", + "slash.opt.nest.pokemon": "pokemon", + "slash.opt.nest.pokemon.desc": "Nesting pokemon", + "slash.opt.nest.min_spawn_avg": "min_spawn_avg", + "slash.opt.nest.min_spawn_avg.desc": "Minimum spawns per hour", + "slash.opt.nest.distance": "distance", + "slash.opt.nest.distance.desc": "Alert radius in metres", + "slash.opt.nest.clean": "clean", + "slash.opt.nest.clean.desc": "Auto-delete the alert when the nest expires", + "slash.opt.nest.template": "template", + "slash.opt.nest.template.desc": "DTS template name", + "slash.choice.nest.clean.yes": "Yes", + "slash.opt.maxbattle.pokemon": "pokemon", + "slash.opt.maxbattle.pokemon.desc": "Max battle pokemon", + "slash.opt.maxbattle.level": "level", + "slash.opt.maxbattle.level.desc": "Battle level (1..6)", + "slash.opt.maxbattle.gmax": "gmax", + "slash.opt.maxbattle.gmax.desc": "Gigantamax only", + "slash.opt.maxbattle.distance": "distance", + "slash.opt.maxbattle.distance.desc": "Alert radius in metres", + "slash.opt.maxbattle.clean": "clean", + "slash.opt.maxbattle.clean.desc": "Auto-delete the alert when the battle ends", + "slash.opt.maxbattle.template": "template", + "slash.opt.maxbattle.template.desc": "DTS template name", + "slash.choice.maxbattle.clean.yes": "Yes", + "slash.choice.maxbattle.level.1": "Level 1", + "slash.choice.maxbattle.level.2": "Level 2", + "slash.choice.maxbattle.level.3": "Level 3", + "slash.choice.maxbattle.level.4": "Level 4", + "slash.choice.maxbattle.level.5": "Level 5", + "slash.choice.maxbattle.level.6": "Level 6", + "slash.opt.gym.team": "team", + "slash.opt.gym.team.desc": "Gym-control team to alert on", + "slash.opt.gym.slot_changes": "slot_changes", + "slash.opt.gym.slot_changes.desc": "Alert on slot composition changes", + "slash.opt.gym.battle_changes": "battle_changes", + "slash.opt.gym.battle_changes.desc": "Alert on battle state changes", + "slash.opt.gym.distance": "distance", + "slash.opt.gym.distance.desc": "Alert radius in metres", + "slash.opt.gym.clean": "clean", + "slash.opt.gym.clean.desc": "Auto-delete the alert when the gym state changes", + "slash.opt.gym.template": "template", + "slash.opt.gym.template.desc": "DTS template name", + "slash.choice.gym.clean.yes": "Yes", + "slash.choice.gym.team.0": "Harmony", + "slash.choice.gym.team.1": "Mystic", + "slash.choice.gym.team.2": "Valor", + "slash.choice.gym.team.3": "Instinct", + "slash.opt.fort.fort_type": "fort_type", + "slash.opt.fort.fort_type.desc": "Fort type to track", + "slash.opt.fort.include_empty": "include_empty", + "slash.opt.fort.include_empty.desc": "Alert on empty/unowned forts", + "slash.opt.fort.distance": "distance", + "slash.opt.fort.distance.desc": "Alert radius in metres", + "slash.opt.fort.clean": "clean", + "slash.opt.fort.clean.desc": "Auto-delete the alert when the fort changes again", + "slash.opt.fort.template": "template", + "slash.opt.fort.template.desc": "DTS template name", + "slash.choice.fort.clean.yes": "Yes", + "slash.choice.fort.fort_type.0": "Pokestop", + "slash.choice.fort.fort_type.1": "Gym", + "slash.opt.tracker.location": "location", + "slash.opt.tracker.location.desc": "Use a saved location instead of your default (requires distance:)", + "slash.opt.tracker.areas": "areas", + "slash.opt.tracker.areas.desc": "Restrict to specific areas (comma-separated)", + "slash.autocomplete.untrack.remove_all": "🗑️ Remove ALL rules of this type", + "slash.opt.untrack.pokemon": "pokemon", + "slash.opt.untrack.pokemon.desc": "Remove a pokemon tracking rule", + "slash.opt.untrack.pokemon.tracking": "tracking", + "slash.opt.untrack.pokemon.tracking.desc": "Pick from your existing pokemon tracking rules", + "slash.opt.untrack.raid": "raid", + "slash.opt.untrack.raid.desc": "Remove a raid tracking rule", + "slash.opt.untrack.raid.tracking": "tracking", + "slash.opt.untrack.raid.tracking.desc": "Pick from your existing raid tracking rules", + "slash.opt.untrack.egg": "egg", + "slash.opt.untrack.egg.desc": "Remove an egg tracking rule", + "slash.opt.untrack.egg.tracking": "tracking", + "slash.opt.untrack.egg.tracking.desc": "Pick from your existing egg tracking rules", + "slash.opt.untrack.quest": "quest", + "slash.opt.untrack.quest.desc": "Remove a quest tracking rule", + "slash.opt.untrack.quest.tracking": "tracking", + "slash.opt.untrack.quest.tracking.desc": "Pick from your existing quest tracking rules", + "slash.opt.untrack.invasion": "invasion", + "slash.opt.untrack.invasion.desc": "Remove an invasion tracking rule", + "slash.opt.untrack.invasion.tracking": "tracking", + "slash.opt.untrack.invasion.tracking.desc": "Pick from your existing invasion tracking rules", + "slash.opt.untrack.lure": "lure", + "slash.opt.untrack.lure.desc": "Remove a lure tracking rule", + "slash.opt.untrack.lure.tracking": "tracking", + "slash.opt.untrack.lure.tracking.desc": "Pick from your existing lure tracking rules", + "slash.opt.untrack.nest": "nest", + "slash.opt.untrack.nest.desc": "Remove a nest tracking rule", + "slash.opt.untrack.nest.tracking": "tracking", + "slash.opt.untrack.nest.tracking.desc": "Pick from your existing nest tracking rules", + "slash.opt.untrack.gym": "gym", + "slash.opt.untrack.gym.desc": "Remove a gym tracking rule", + "slash.opt.untrack.gym.tracking": "tracking", + "slash.opt.untrack.gym.tracking.desc": "Pick from your existing gym tracking rules", + "slash.opt.untrack.fort": "fort", + "slash.opt.untrack.fort.desc": "Remove a fort tracking rule", + "slash.opt.untrack.fort.tracking": "tracking", + "slash.opt.untrack.fort.tracking.desc": "Pick from your existing fort tracking rules", + "slash.opt.untrack.maxbattle": "maxbattle", + "slash.opt.untrack.maxbattle.desc": "Remove a maxbattle tracking rule", + "slash.opt.untrack.maxbattle.tracking": "tracking", + "slash.opt.untrack.maxbattle.tracking.desc": "Pick from your existing maxbattle tracking rules", + "slash.opt.area.add": "add", + "slash.opt.area.add.desc": "Add an area to your tracking", + "slash.opt.area.add.area": "area", + "slash.opt.area.add.area.desc": "Area to add", + "slash.opt.area.remove": "remove", + "slash.opt.area.remove.desc": "Remove an area from your tracking", + "slash.opt.area.remove.area": "area", + "slash.opt.area.remove.area.desc": "Area to remove", + "slash.opt.area.show": "show", + "slash.opt.area.show.desc": "Show your selected areas", + "slash.opt.area.list": "list", + "slash.opt.area.list.desc": "List every area available to you (✓ = already added)", + "slash.opt.area.overview": "overview", + "slash.opt.area.overview.desc": "Map overview of every area available to you", + "slash.opt.profile.list": "list", + "slash.opt.profile.list.desc": "List your profiles", + "slash.opt.profile.change": "change", + "slash.opt.profile.change.desc": "Switch active profile", + "slash.opt.profile.change.name": "name", + "slash.opt.profile.change.name.desc": "Profile name", + "slash.opt.profile.create": "create", + "slash.opt.profile.create.desc": "Create a new profile", + "slash.opt.profile.create.name": "name", + "slash.opt.profile.create.name.desc": "Profile name", + "slash.opt.profile.delete": "delete", + "slash.opt.profile.delete.desc": "Delete a profile", + "slash.opt.profile.delete.name": "name", + "slash.opt.profile.delete.name.desc": "Profile name", + "slash.opt.profile.settime": "settime", + "slash.opt.profile.settime.desc": "Set active-hours for the current profile", + "slash.opt.profile.settime.times": "times", + "slash.opt.profile.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.profile.cleartime": "cleartime", + "slash.opt.profile.cleartime.desc": "Clear active-hours from the current profile", + "slash.opt.profile.copyto": "copyto", + "slash.opt.profile.copyto.desc": "Copy this profile's tracking to another profile", + "slash.opt.profile.copyto.profile": "profile", + "slash.opt.profile.copyto.profile.desc": "Target profile name or number", + "slash.opt.location.add": "add", + "slash.opt.location.add.desc": "Save a named location", + "slash.opt.location.add.name": "name", + "slash.opt.location.add.name.desc": "Short name for this location (e.g. Home)", + "slash.opt.location.add.place": "place", + "slash.opt.location.add.place.desc": "Coordinates (lat,lon) or a place name", + "slash.opt.location.list": "list", + "slash.opt.location.list.desc": "List your saved locations", + "slash.opt.location.show": "show", + "slash.opt.location.show.desc": "Show one saved location", + "slash.opt.location.show.name": "name", + "slash.opt.location.show.name.desc": "Saved-location name", + "slash.opt.location.remove": "remove", + "slash.opt.location.remove.desc": "Remove a saved location", + "slash.opt.location.remove.name": "name", + "slash.opt.location.remove.name.desc": "Saved-location name (or \"default\" to clear your default location)", + "slash.opt.location.set-default": "set-default", + "slash.opt.location.set-default.desc": "Set your default location", + "slash.opt.location.set-default.place": "place", + "slash.opt.location.set-default.place.desc": "Coordinates (lat,lon) or address to set as your default location", + "slash.opt.location.remove-default": "remove-default", + "slash.opt.location.remove-default.desc": "Clear your default location", + "slash.opt.summary.quest": "quest", + "slash.opt.summary.quest.desc": "Manage quest-summary buffering", + "slash.opt.summary.quest.show": "show", + "slash.opt.summary.quest.show.desc": "Show schedule and current buffer count", + "slash.opt.summary.quest.settime": "settime", + "slash.opt.summary.quest.settime.desc": "Set the active-hours schedule for the quest summary", + "slash.opt.summary.quest.settime.times": "times", + "slash.opt.summary.quest.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.summary.quest.cleartime": "cleartime", + "slash.opt.summary.quest.cleartime.desc": "Clear the active-hours schedule", + "slash.opt.summary.quest.now": "now", + "slash.opt.summary.quest.now.desc": "Force-dispatch the currently-buffered quests", + "error.slash.unregistered_with_channel": "🛑 You need to register first. DM me with !poracle, or run !poracle in {0}.", + "error.slash.unregistered_dm_only": "🛑 You need to register first. DM me with !poracle.", + "error.slash.track.no_pokemon": "Please specify a Pokemon to track.", + "error.slash.raid.need_boss_or_level": "Please specify either a boss or a level.", + "error.slash.raid.boss_and_level": "Please specify either a boss OR a level, not both.", + "error.slash.egg.no_level": "Please specify an egg level.", + "error.slash.quest.no_reward": "Please specify exactly one reward type (pokemon, item, stardust, candy, or mega_energy).", + "error.slash.quest.exactly_one_reward": "Please specify exactly one reward type, not multiple: {0}.", + "error.slash.quest.amount_not_applicable": "`min_amount` doesn't apply to pokemon quests. For stardust, both `stardust` and `min_amount` end up in the same field — pick whichever reads better.", + "error.slash.invasion.no_grunt": "Please specify a grunt type.", + "error.slash.incident.no_type": "Please specify an incident type.", + "error.slash.lure.no_type": "Please specify a lure type.", + "error.slash.nest.no_pokemon": "Please specify a Pokemon for the nest.", + "error.slash.maxbattle.no_pokemon": "Please specify a Pokemon for the max battle.", + "error.slash.fort.no_type": "Please specify a fort type (pokestop or gym).", + "error.slash.untrack.no_subcommand": "Please choose what kind of tracking rule to remove.", + "error.slash.untrack.no_tracking": "Please pick a tracking rule to remove.", + "error.slash.info.no_subcommand": "Please choose an info sub-command (pokemon / rarity / shiny / weather).", + "error.slash.info.no_pokemon": "Please specify a pokemon name or dex id.", + "error.slash.info.unknown_subcommand": "Unknown info sub-command.", + "error.slash.area.no_subcommand": "Please choose an area sub-command (add / remove / show).", + "error.slash.area.no_area": "Please specify an area name.", + "error.slash.area.unknown_subcommand": "Unknown area sub-command.", + "error.slash.profile.no_subcommand": "Please choose a profile sub-command (list / change / create / delete / settime / cleartime / copyto).", + "error.slash.profile.no_name": "Please specify a profile name.", + "error.slash.profile.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.profile.no_target": "Please specify a target profile to copy to.", + "error.slash.profile.unknown_subcommand": "Unknown profile sub-command.", + "error.slash.summary.no_alert_type": "Please choose an alert type (e.g. quest).", + "error.slash.summary.no_action": "Please choose an action (show / settime / cleartime / now).", + "error.slash.summary.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.summary.unknown_action": "Unknown summary action.", + "error.slash.location.no_subcommand": "Please choose a location sub-command (add / list / show / remove / remove-default).", + "error.slash.location.no_name": "Please specify a saved-location name.", + "error.slash.location.empty": "Please specify coordinates or a place name.", + "error.slash.location.unknown_subcommand": "Unknown location sub-command.", + "error.slash.location.no_geocoder": "Place-name lookup is not configured. Please provide coordinates like 51.28, 1.08.", + "error.slash.location.geocode_failed": "Could not find a location for \"{0}\".", + "msg.help.text": "**Available commands:**\n{0}track [iv:N] [cp:N] [level:N] [d:N] — Track pokemon\n{0}untrack — Remove pokemon tracking\n{0}raid [d:N] — Track raids\n{0}egg [d:N] — Track eggs\n{0}quest — Track quests\n{0}invasion [everything|] — Track invasions\n{0}lure — Track lures\n{0}gym [slot_changes] — Track gyms\n{0}nest — Track nests\n{0}maxbattle — Track max battles\n{0}fort — Track fort updates\n{0}tracked — Show all tracking\n{0}script — Export tracking as commands\n{0}area [list|add|remove] — Manage areas\n{0}location — Set location\n{0}profile [list|add|remove|switch] — Manage profiles\n{0}language — Set language\n{0}start / {0}stop — Enable/disable alerts\n{0}version — Show version", + "cmd.poracle_admin": "poracle-admin", + "cmd.pa": "pa", + "cmd.poracle_admin.not_admin": "This command is reserved for administrators.", + "cmd.poracle_admin.unknown_group": "Unknown subgroup. Try `!poracle-admin` for the list.", + "cmd.poracle_admin.unknown_sub": "Unknown subcommand for `{0}`. Try `!poracle-admin {0}` to see what's available.", + "cmd.poracle_admin.help.admin_only": "This command is reserved for server administrators. Each subgroup performs a live operations task.", + "cmd.poracle_admin.help.groups": "Available subgroups:", + "cmd.poracle_admin.help_intro": "🛠️ Poracle Admin\n\nLive operations subgroups (administrators only):", + "cmd.poracle_admin.stub": "(not yet implemented)", + "cmd.poracle_admin.group.slash.desc": "slash-command registration lifecycle", + "cmd.poracle_admin.group.reload.desc": "reload DTS, geofence, or in-memory state", + "cmd.poracle_admin.group.emoji.desc": "list, reload, or test emoji config", + "cmd.poracle_admin.group.reconcile.desc": "Discord role reconciliation (immediate or per-user)", + "cmd.poracle_admin.group.cache.desc": "cache stats and clear", + "cmd.poracle_admin.group.ratelimit.desc": "inspect and reset alert-bucket rate limits", + "cmd.poracle_admin.group.summary.desc": "summary buffer inspection and forced dispatch", + "cmd.poracle_admin.group.status.desc": "live health snapshot", + "cmd.poracle_admin.group.maintenance.desc": "pause/resume outbound delivery", + "cmd.poracle_admin.group.config.desc": "view effective merged config with secrets redacted", + "cmd.poracle_admin.group.warnings.desc": "inspect captured WARN/ERROR log entries (startup + rolling buffers)", + "cmd.poracle_admin.reload.help.intro": "Reload runtime state from disk or database.", + "cmd.poracle_admin.reload.dts.desc": "`dts` — reload DTS templates and partials from disk", + "cmd.poracle_admin.reload.geofence.desc": "`geofence` — reload geofence files and refresh state", + "cmd.poracle_admin.reload.state.desc": "`state` — reload tracking rules and humans from MySQL (bypasses debounce)", + "cmd.poracle_admin.reload.dts.success": "✅ DTS reloaded in {0}ms ({1} templates)", + "cmd.poracle_admin.reload.geofence.success": "✅ Geofence reloaded in {0}ms ({1} fences, {2} tracking rules)", + "cmd.poracle_admin.reload.state.success": "✅ State reloaded in {0}ms ({1} tracking rules, {2} active humans)", + "cmd.poracle_admin.reload.error": "❌ Reload failed: {0}", + "cmd.poracle_admin.emoji.help.intro": "😀 Emoji config — inspect and manage emoji.json + Discord guild emojis.\n\nSubcommands:", + "cmd.poracle_admin.emoji.list.desc": "`list` — list all configured emoji keys with per-platform resolutions", + "cmd.poracle_admin.emoji.reload.desc": "`reload` — reload config/emoji.json from disk", + "cmd.poracle_admin.emoji.test.desc": "`test ` — resolve one emoji key for the current platform", + "cmd.poracle_admin.emoji.upload.desc": "`upload [overwrite]` — upload uicons-based emojis to the guild and write a new emoji.json (Discord-only)", + "cmd.poracle_admin.emoji.discord_config.desc": "`discord-config` — dump emoji.json from the current guild state, no uploads (Discord-only)", + "cmd.poracle_admin.emoji.discord_only": "ℹ️ This subcommand requires a Discord bot with guild access.", + "cmd.poracle_admin.emoji.not_loaded": "ℹ️ Emoji config not loaded (DTS renderer not configured).", + "cmd.poracle_admin.emoji.list.header": "😀 Emoji configuration — {0} keys loaded", + "cmd.poracle_admin.emoji.list.row.key": " {0}:", + "cmd.poracle_admin.emoji.list.row.platform": " {0}: {1}", + "cmd.poracle_admin.emoji.reload.success": "✅ Emoji config reloaded — {0} keys (took {1}ms).", + "cmd.poracle_admin.emoji.reload.error": "❌ Emoji reload failed: {0}", + "cmd.poracle_admin.emoji.test.success": "🔎 {0} on {1}: {2}", + "cmd.poracle_admin.emoji.test.not_found": "ℹ️ Emoji key \"{0}\" not found in the loaded config.", + "cmd.poracle_admin.emoji.test.usage": "Usage: !poracle-admin emoji test ", + "cmd.poracle_admin.reconcile.help.intro": "🔄 Discord role reconciliation — trigger immediately instead of waiting for the periodic timer.", + "cmd.poracle_admin.reconcile.run.desc": "`run` — reconcile all guild members now (blocks until complete)", + "cmd.poracle_admin.reconcile.user.desc": "`user ` — reconcile a single Discord user by snowflake ID", + "cmd.poracle_admin.reconcile.not_configured": "❌ Discord reconciliation is not configured (Telegram-only deploy, or check_role=false).", + "cmd.poracle_admin.reconcile.run.success": "✅ Discord reconciliation complete (took {0}ms).", + "cmd.poracle_admin.reconcile.run.error": "❌ Reconciliation failed: {0}", + "cmd.poracle_admin.reconcile.user.success": "✅ Reconciled discord:user/{0} (took {1}ms).", + "cmd.poracle_admin.reconcile.user.error": "❌ Failed to reconcile discord:user/{0}: {1}", + "cmd.poracle_admin.reconcile.user.usage": "Usage: !poracle-admin reconcile user ", + "cmd.poracle_admin.cache.help.intro": "🗺️ Geocoder cache — inspect counters or drop the in-memory layer.", + "cmd.poracle_admin.cache.stats.desc": "`stats` — geocoder cache stats", + "cmd.poracle_admin.cache.clear.desc": "`clear geocoder` — drop the in-memory geocoder cache", + "cmd.poracle_admin.cache.not_configured": "Geocoder cache is not configured on this instance.", + "cmd.poracle_admin.cache.stats.header": "🗺️ Geocoder cache", + "cmd.poracle_admin.cache.stats.row.memory_entries": " Memory entries: {0}", + "cmd.poracle_admin.cache.stats.row.disk_entries": " Disk entries: {0}", + "cmd.poracle_admin.cache.stats.row.hits_memory": " Hits (memory): {0}", + "cmd.poracle_admin.cache.stats.row.hits_disk": " Hits (disk): {0}", + "cmd.poracle_admin.cache.stats.row.misses": " Misses: {0}", + "cmd.poracle_admin.cache.stats.row.hit_rate": " Hit rate: {0}%", + "cmd.poracle_admin.cache.clear.usage_hint": "Specify what to clear, e.g. `!poracle-admin cache clear geocoder`", + "cmd.poracle_admin.cache.clear.geocoder.success": "✅ Geocoder memory cache cleared — {0} entries dropped (disk untouched).", + "cmd.poracle_admin.ratelimit.help.intro": "🚦 Rate-limit introspection — inspect or reset per-destination alert and summary buckets.", + "cmd.poracle_admin.ratelimit.not_configured": "ℹ️ Alert rate limiter is not configured on this instance.", + "cmd.poracle_admin.ratelimit.list.desc": "`list` — show all targets currently breached or banned", + "cmd.poracle_admin.ratelimit.show.desc": "`show ` — detailed state for one target (both buckets)", + "cmd.poracle_admin.ratelimit.reset.desc": "`reset ` — clear counters and violation history", + "cmd.poracle_admin.ratelimit.userlist.desc": "`userlist` — show currently disabled users (shortcut for !userlist disabled)", + "cmd.poracle_admin.ratelimit.list.empty": "🟢 No targets currently rate-limited.", + "cmd.poracle_admin.ratelimit.list.header_title": "Currently rate-limited targets", + "cmd.poracle_admin.ratelimit.list.bucket_header": " {0} bucket ({1} breached / {2} banned):", + "cmd.poracle_admin.ratelimit.list.row": "count {0}/{1}, {2}", + "cmd.poracle_admin.ratelimit.list.status.banned": "banned for {0}", + "cmd.poracle_admin.ratelimit.list.status.breached": "window resets in {0}", + "cmd.poracle_admin.ratelimit.show.header": "🚦 Rate-limit state for {0}", + "cmd.poracle_admin.ratelimit.show.bucket_header": "{0} bucket:", + "cmd.poracle_admin.ratelimit.show.empty": "🟢 No recorded activity for {0} in either bucket.", + "cmd.poracle_admin.ratelimit.show.no_data": "(no activity in this bucket)", + "cmd.poracle_admin.ratelimit.show.no_violations": "No violations.", + "cmd.poracle_admin.ratelimit.show.violations_count": "Violations (24h): {0}", + "cmd.poracle_admin.ratelimit.show.banned_until": "Banned until: {0} (in {1})", + "cmd.poracle_admin.ratelimit.show.status.under_limit": "under limit", + "cmd.poracle_admin.ratelimit.show.status.over_limit": "over limit", + "cmd.poracle_admin.ratelimit.show.row.count": " Count: {0} / {1} ({2})\n", + "cmd.poracle_admin.ratelimit.show.row.window": " Window: opened {0} ago, resets in {1}\n", + "cmd.poracle_admin.ratelimit.reset.success": "✅ Reset rate-limit state for {0} (cleared alert + summary buckets, violations reset).", + "cmd.poracle_admin.ratelimit.reset.no_state": "ℹ️ No rate-limit state to reset for {0}.", + "cmd.poracle_admin.ratelimit.reset.note": "Note: admin_disable is NOT touched. If the user was auto-disabled by the rate-limiter, they still need to !poracle to re-register.", + "cmd.poracle_admin.ratelimit.usage.show": "Usage: !poracle-admin ratelimit show ", + "cmd.poracle_admin.ratelimit.usage.reset": "Usage: !poracle-admin ratelimit reset ", + "cmd.poracle_admin.ratelimit.userlist.lookup_failed": "❌ Could not find !userlist command in the registry.", + "cmd.poracle_admin.summary.help.intro": "📦 Summary buffer — inspect who has quests buffered and force-dispatch on demand.", + "cmd.poracle_admin.summary.not_configured": "ℹ️ Summary buffer is not configured on this instance.", + "cmd.poracle_admin.summary.list.desc": "`list` — show all users with anything buffered", + "cmd.poracle_admin.summary.show.desc": "`show ` — inspect one user's buffered entries", + "cmd.poracle_admin.summary.fire.desc": "`fire [alertType]` — force-dispatch a user's buffer immediately", + "cmd.poracle_admin.summary.list.empty": "🟢 No users have anything buffered.", + "cmd.poracle_admin.summary.list.header": "📦 Summary buffer — {0} users with {1} buffered entries", + "cmd.poracle_admin.summary.list.user_header": " {0}", + "cmd.poracle_admin.summary.list.row": " {0}: {1} entries (next fires: {2})", + "cmd.poracle_admin.summary.list.next_fire.none": "n/a", + "cmd.poracle_admin.summary.show.header": "📦 Summary buffer for {0}", + "cmd.poracle_admin.summary.show.empty": "🟢 No buffered entries for {0}.", + "cmd.poracle_admin.summary.show.alert_type": " {0}: {1} entries", + "cmd.poracle_admin.summary.show.usage": "Usage: !poracle-admin summary show ", + "cmd.poracle_admin.summary.fire.success": "✅ Dispatched summary for {0} / {1} — {2} entries delivered.", + "cmd.poracle_admin.summary.fire.usage": "Usage: !poracle-admin summary fire [alertType]", + "cmd.poracle_admin.summary.show.reward_row": " Reward type {0}, reward {1}{2} — {3} stops", + "cmd.poracle_admin.summary.show.reward_more": " ... ({0} more reward groups)", + "cmd.poracle_admin.summary.show.form_suffix": " form {0}", + "cmd.poracle_admin.maintenance.help.intro": "🛠️ **!poracle-admin maintenance** — live control over outbound delivery.\n\nSubcommands:", + "cmd.poracle_admin.maintenance.no_dispatcher": "ℹ️ Dispatcher is not available on this instance.", + "cmd.poracle_admin.maintenance.no_reason": "(no reason given)", + "cmd.poracle_admin.maintenance.pause.desc": "`pause [reason...]` (alias: `start`) — halt outbound delivery (webhooks still ingest, match, render, and queue)", + "cmd.poracle_admin.maintenance.resume.desc": "`resume` (alias: `stop`) — lift a previous pause and drain queued jobs", + "cmd.poracle_admin.maintenance.status.desc": "`status` — show current paused/running state and queue depth", + "cmd.poracle_admin.maintenance.pause.new": "🔴 Outbound delivery paused: {0}", + "cmd.poracle_admin.maintenance.pause.detail": "Webhooks still ingest, match, render, and queue — the dispatcher holds them until !poracle-admin maintenance resume.", + "cmd.poracle_admin.maintenance.pause.already": "ℹ️ Already paused since {0} ({1} ago): {2}", + "cmd.poracle_admin.maintenance.resume.success": "🟢 Outbound delivery resumed (was paused for {0}: {1})", + "cmd.poracle_admin.maintenance.resume.detail": "Queued messages are draining.", + "cmd.poracle_admin.maintenance.resume.not_paused": "ℹ️ Not currently paused.", + "cmd.poracle_admin.maintenance.status.running": "🟢 Delivery is running.", + "cmd.poracle_admin.maintenance.status.paused": "🔴 PAUSED — {0} (for {1})", + "cmd.poracle_admin.maintenance.status.queued": "{0} jobs queued waiting (across all platforms — Discord {1}, Telegram {2})", + "cmd.poracle_admin.status.help.intro": "!poracle-admin status — current health snapshot. Add -v for verbose mode (per-route Discord detail, full webhook per-type breakdown).", + "cmd.poracle_admin.status.header": "🛠️ Poracle Admin — Status", + "cmd.poracle_admin.status.paused_banner": "🔴 PAUSED — {0} (since {1} ago)\n Outbound delivery is held. Webhooks still ingest and queue.", + "cmd.poracle_admin.status.value.na": "n/a", + "cmd.poracle_admin.status.value.none": "none", + "cmd.poracle_admin.status.section.build": "**Build / Uptime**", + "cmd.poracle_admin.status.section.webhooks": "**Webhooks**", + "cmd.poracle_admin.status.section.render_queue": "**Render queue**", + "cmd.poracle_admin.status.section.delivery": "**Delivery**", + "cmd.poracle_admin.status.section.discord_rate": "**Discord rate**", + "cmd.poracle_admin.status.section.telegram_rate": "**Telegram rate**", + "cmd.poracle_admin.status.section.alert_limits": "**Alert limits**", + "cmd.poracle_admin.status.section.summary_buffer": "**Summary buffer**", + "cmd.poracle_admin.status.label.summary_buffer_totals": "Entries: {0} across {1} bucket(s)", + "cmd.poracle_admin.status.label.summary_buffer_top": "Top users:", + "cmd.poracle_admin.status.label.summary_buffer_user_row": " {0} ({1}): {2} entries", + "cmd.poracle_admin.status.section.tracking": "**Tracking**", + "cmd.poracle_admin.status.section.mysql": "**MySQL**", + "cmd.poracle_admin.status.label.version": "Version: {0} (commit {1}, built {2})", + "cmd.poracle_admin.status.label.uptime": "Uptime: {0}", + "cmd.poracle_admin.status.label.webhooks_rate": "{0} / {1} / {2} per min over last 5/15/60 min", + "cmd.poracle_admin.status.label.webhooks_by_type": "By type (last 60 min):", + "cmd.poracle_admin.status.label.delivery_discord": "Discord in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_telegram": "Telegram in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_webhook": "Webhook in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_queue_depth": "Queue depth: {0} (capacity not exposed)", + "cmd.poracle_admin.status.label.discord_routes": "Routes near limit: {0}", + "cmd.poracle_admin.status.label.discord_global": "Global tokens: {0} / {1}", + "cmd.poracle_admin.status.label.discord_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.discord_routes_detail": "Routes near limit (detail):", + "cmd.poracle_admin.status.label.telegram_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.telegram_backoff": "Current backoff: {0}", + "cmd.poracle_admin.status.label.alert_limits_counts": "Breached: alert={0}, summary={1} · Banned: {2}", + "cmd.poracle_admin.status.label.tracking_total": "Total tracking rules: {0}", + "cmd.poracle_admin.status.label.tracking_active_humans": "Active humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans": "Registered humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans_error": "Registered humans: n/a (error)", + "cmd.poracle_admin.status.label.tracking_type": "{0}: {1}", + "cmd.poracle_admin.status.label.mysql_ping_ok": "Ping: ok", + "cmd.poracle_admin.status.label.mysql_ping_fail": "Ping: failed ({0})", + "cmd.poracle_admin.status.label.mysql_pool": "Connections: {0}/{1} open ({2} in use, {3} idle, waits={4})", + "cmd.poracle_admin.status.tracking_type.pokemon": "pokemon", + "cmd.poracle_admin.status.tracking_type.raid": "raid", + "cmd.poracle_admin.status.tracking_type.egg": "egg", + "cmd.poracle_admin.status.tracking_type.quest": "quest", + "cmd.poracle_admin.status.tracking_type.invasion": "invasion", + "cmd.poracle_admin.status.tracking_type.lure": "lure", + "cmd.poracle_admin.status.tracking_type.nest": "nest", + "cmd.poracle_admin.status.tracking_type.gym": "gym", + "cmd.poracle_admin.status.tracking_type.fort": "fort", + "cmd.poracle_admin.status.tracking_type.maxbattle": "maxbattle", + "cmd.poracle_admin.slash.help.intro": "**!poracle-admin slash** — slash-command registration lifecycle.\nSubcommands:", + "cmd.poracle_admin.slash.discord_only": "❌ Slash commands are Discord-only and cannot be managed from Telegram.", + "cmd.poracle_admin.slash.not_configured": "❌ Slash commands are not configured (Discord disabled or [discord.slash_commands] enabled=false).", + "cmd.poracle_admin.slash.sync.desc": "push the current command set to Discord (fingerprint-cached, skips if unchanged)", + "cmd.poracle_admin.slash.sync.success": "✅ Slash sync complete ({0}ms)", + "cmd.poracle_admin.slash.sync.error": "❌ Slash sync failed: {0}", + "cmd.poracle_admin.slash.force_resync.desc": "clear fingerprint cache and push unconditionally", + "cmd.poracle_admin.slash.force_resync.success": "✅ Force-resync complete ({0}ms)", + "cmd.poracle_admin.slash.force_resync.error": "❌ Force-resync failed: {0}", + "cmd.poracle_admin.slash.clear_global.desc": "remove all globally-registered Discord slash commands", + "cmd.poracle_admin.slash.clear_global.success": "✅ Global slash commands cleared.", + "cmd.poracle_admin.slash.clear_global.error": "❌ Clear global failed: {0}", + "cmd.poracle_admin.slash.clear_guild.desc": "remove slash commands from one guild (requires guild_id arg)", + "cmd.poracle_admin.slash.clear_guild.needs_arg": "❌ Usage: `!poracle-admin slash clear-guild `", + "cmd.poracle_admin.slash.clear_guild.success": "✅ Slash commands cleared from guild {0}.", + "cmd.poracle_admin.slash.clear_guild.error": "❌ Clear guild failed: {0}", + "cmd.poracle_admin.slash.status.desc": "show last sync timestamp and fingerprint per scope", + "cmd.poracle_admin.slash.status.header": "**Slash command registration status:**", + "cmd.poracle_admin.slash.status.scope_row": " **{0}**: last synced {1} · fingerprint `{2}`", + "cmd.poracle_admin.slash.status.never_synced": "never", + "cmd.poracle_admin.slash.status.ago": "{0} ago", + "cmd.poracle_admin.slash.status.error": "❌ Status read failed: {0}", + "cmd.poracle_admin.config.help.intro": "⚙️ Config viewer — show effective merged config with secrets redacted.\nSubcommands:", + "cmd.poracle_admin.config.keys.desc": "list section names with key counts", + "cmd.poracle_admin.config.section.desc": "show just that section (e.g. `!poracle-admin config discord`)", + "cmd.poracle_admin.config.full.desc": "show the full config (all sections, secrets redacted)", + "cmd.poracle_admin.config.keys.header": "⚙️ Config sections:", + "cmd.poracle_admin.config.keys.row": " {0}: {1} keys", + "cmd.poracle_admin.config.unknown_section": "Unknown config section: `{0}`. Use `!poracle-admin config keys` to list valid sections, or `!poracle-admin config search ` to search across all sections.", + "cmd.poracle_admin.config.search.desc": "find keys whose path or value contains the term across every section (e.g. `!poracle-admin config search dm`)", + "cmd.poracle_admin.config.search.usage": "Usage: `!poracle-admin config search ` — e.g. `search dm`, `search shlink`, `search 3030`.", + "cmd.poracle_admin.config.search.header": "🔍 `{0}` — {1} match(es):", + "cmd.poracle_admin.config.search.no_matches": "No config keys or values match `{0}`.", + "cmd.poracle_admin.config.empty_section": "Section `{0}` has no configurable fields.", + "cmd.poracle_admin.config.not_loaded": "❌ Config not loaded.", + "cmd.poracle_admin.warnings.help.intro": "🛠️ Captured warnings — inspect in-memory WARN/ERROR log entries.\n\nSubcommands:\n (no arg) — show both startup and recent buffers\n `startup` — show only the startup buffer (first 200 entries, frozen after init)\n `recent` — show only the rolling buffer (last 50 entries)\n `clear` — empty the rolling buffer (startup is immutable)", + "cmd.poracle_admin.warnings.not_configured": "ℹ️ Log buffer is not configured on this instance.", + "cmd.poracle_admin.warnings.section.startup": "🛠️ Captured warnings — startup ({0} entries)", + "cmd.poracle_admin.warnings.section.recent": "🛠️ Captured warnings — recent ({0} entries)", + "cmd.poracle_admin.warnings.empty.startup": "🟢 No startup warnings captured.", + "cmd.poracle_admin.warnings.empty.recent": "🟢 No recent warnings.", + "cmd.poracle_admin.warnings.entry_row": " {0} {1} {2} {3}", + "cmd.poracle_admin.warnings.cleared": "✅ Cleared {0} entries from the rolling buffer (startup buffer is unaffected).", + "cmd.poracle_admin.warnings.startup.desc": "`startup` — show only the startup buffer (frozen after init)", + "cmd.poracle_admin.warnings.recent.desc": "`recent` — show only the rolling buffer (last 50 entries)", + "cmd.poracle_admin.warnings.clear.desc": "`clear` — empty the rolling buffer", + "cmd.maintenance.active_suffix": "🔧 Maintenance mode is active — alerts are not being delivered.", + "showcase_focus_pokemon": "Pokémon", + "showcase_focus_type": "Type", + "showcase_focus_alignment": "Alignment", + "showcase_focus_class": "Class", + "showcase_focus_family": "Family", + "showcase_focus_buddy": "Buddy", + "showcase_focus_generation": "Generation", + "showcase_focus_hatched": "Hatched", + "showcase_focus_mega": "Mega", + "showcase_focus_shiny": "Shiny", + "showcase_class_ultra_beast": "Ultra Beast" } diff --git a/processor/internal/i18n/locale/it.json b/processor/internal/i18n/locale/it.json index ba30c3859..1209db856 100644 --- a/processor/internal/i18n/locale/it.json +++ b/processor/internal/i18n/locale/it.json @@ -58,6 +58,11 @@ "tracking.pvp_little": "littlepvp", "tracking.pvp_great": "greatpvp", "tracking.pvp_ultra": "ultrapvp", + "tracking.pvp_mega_any": "mega", + "tracking.pvp_mega_x": "mega x", + "tracking.pvp_mega_y": "mega y", + "tracking.mega_x_label": "X", + "tracking.mega_y_label": "Y", "tracking.level_cap_fmt": "level cap: {0}", "tracking.everything": "Tutto", "tracking.unknown_monster": "Unknown monster", @@ -81,10 +86,14 @@ "tracking.reward_fmt": "Reward: **{0}**", "tracking.reward_stardust_min_fmt": "{0} or more stardust", "tracking.reward_stardust": "polvere di stelle", + "tracking.reward_pokecoin_min_fmt": "{0} or more pokecoins", + "tracking.reward_pokecoin": "pokecoins", "tracking.reward_mega_energy": "mega energia", "tracking.reward_mega_energy_fmt": "mega energy {0}", "tracking.reward_candy": "candy", "tracking.reward_candy_fmt": "candy {0}", + "tracking.reward_any_pokemon": "any pokemon", + "tracking.reward_any_item": "any item", "tracking.reward_min_fmt": "minimum {0}", "tracking.grunt_type_fmt": "Grunt type: **{0}**", "tracking.min_avg_spawn": "Min avg. spawn {0}/hour", @@ -108,10 +117,68 @@ "tracking.template_not_found": "Template \"{0}\" does not exist.", "tracking.warn_template_not_found": "Template \"{0}\" not found for type {1}/{2}. Tracking saved but alerts may not render.", "tracking.id_hint": "To remove a specific entry, use its id — e.g. `{0}untrack id:45` or `{0}raid remove id:12`", + "tracking.id_hint_slash": "To remove a specific entry, run `/untrack ` (e.g. `/untrack raid`) and pick it from the list.", + "tracking.list_attached": "Your tracking list is long ({0} rules) — attached as a file.", "tracking.removed_prefix": "Removed: ", "tracking.uid_not_found": "id:{0} not found", + "tracking.override_location_fmt": "@ {0}", + "tracking.override_areas_fmt": "in {0}", "cmd.track": "trova", "cmd.untrack": "basta", + "cmd.mute": "mute", + "cmd.unmute": "unmute", + "msg.mute.unavailable": "Mute feature isn't enabled here.", + "msg.mute.usage": "Valid commands are `{0}mute [duration:1h]`", + "msg.mute.usage_pokemon": "Valid commands are `{0}mute pokemon [duration:1h]`", + "msg.mute.usage_gym": "Valid commands are `{0}mute gym [duration:1h]`", + "msg.mute.usage_area": "Valid commands are `{0}mute area [duration:1h]`", + "msg.mute.usage_id_scope": "Valid commands are `{0}mute {1} [duration:1h]`", + "msg.mute.bad_duration": "Invalid duration: {0}", + "msg.mute.id_not_supported": "`!mute id:N` / `!mute id:N` aren't supported yet — entity scopes (gym, pokemon, area, pokestop, station, everything) work today. Per-rule muting by UID is a follow-up.", + "msg.mute.bad_uid": "`{0}` isn't a valid tracking rule UID. Use `!tracked` to see your rule UIDs.", + "msg.mute.unknown_area": "`{0}` isn't in your available areas. Use `!area` to see what you can mute.", + "msg.mute.no_pokemon": "I don't know a pokemon called `{0}`.", + "msg.mute.everything_label": "everything", + "msg.mute.added": "🔇 Muted {0} for {1}.", + "msg.mute.removed": "✅ Unmuted {0}.", + "msg.mute.none_found": "No active mute for {0}.", + "msg.mute.cleared_all": "Cleared {0} active mutes.", + "msg.unmute.usage": "Valid commands are `{0}unmute `, `{0}unmute all`", + "msg.unmute.usage_pokemon": "Valid commands are `{0}unmute pokemon `", + "msg.unmute.usage_gym": "Valid commands are `{0}unmute gym `", + "msg.unmute.usage_area": "Valid commands are `{0}unmute area `", + "section.property_mutes": "Property mutes (apply across all tracking):", + "section.property_mutes.left": "({0} left)", + "msg.button.expired": "This alert has expired.", + "msg.button.unavailable": "This button is no longer available.", + "msg.button.wrong_target": "This button doesn't apply here.", + "msg.button.unauthorized": "This button isn't for you.", + "msg.button.unidentified": "Couldn't identify you to handle that click.", + "msg.button.unconfigured": "This button isn't configured.", + "msg.button.action_failed": "Couldn't complete that action: {0}", + "msg.button.action_failed_generic": "Couldn't complete that action.", + "msg.button.cooldown": "Slow down — try that again in a moment.", + "msg.button.actions_not_wired": "Button actions aren't wired here.", + "msg.button.not_implemented": "The {0} action isn't implemented yet.", + "msg.button.responses_not_wired": "Response rendering isn't wired here.", + "msg.button.response_failed": "Couldn't render that response: {0}", + "msg.button.done": "Done.", + "msg.button.missing_scope": "Button is missing a scope — operator config bug.", + "msg.button.missing_target": "Couldn't find a {0} to mute on this alert.", + "msg.button.no_dm_target": "Couldn't identify you to send the message.", + "msg.button.dm_failed": "Couldn't send to your DM: {0}", + "msg.button.unsubscribe_failed": "Couldn't unsubscribe — please try again.", + "msg.button.unsubscribe_already": "Those tracking rules were already removed.", + "msg.button.unsubscribed": "✅ Unsubscribed from {0} tracking rule(s).", + "msg.button.redeliver_sent": "📬 Sent to your DM.", + "msg.mute.scope_gym": "gym", + "msg.mute.scope_pokemon": "pokemon", + "msg.mute.scope_area": "area", + "msg.mute.scope_pokestop": "pokestop", + "msg.mute.scope_station": "station", + "msg.mute.scope_tracking": "tracking rule", + "cmd.mute.usage": "**{0}mute** — silence alerts for a specific gym, pokemon, area, pokestop, station, or everything for a time-bounded window.\n\n• `{0}mute everything [duration:1h]` — silence ALL alerts for the given duration\n• `{0}mute gym [duration:1h]` — silence alerts for one gym\n• `{0}mute pokemon [duration:1h]` — silence alerts for one pokemon species\n• `{0}mute area [duration:1h]` — silence alerts in one area\n• `{0}mute pokestop [duration:1h]` — silence alerts for one pokestop\n• `{0}mute station [duration:1h]` — silence alerts for one station\n\nDuration defaults to 1h if omitted. Use `{0}unmute ` to remove a mute early, or `{0}tracked` to see active mutes.", + "cmd.track.usage": "**{0}track** — set up pokemon tracking rules.\n\n• `{0}track ` — track a specific pokemon (by name or dex id) at default 100m\n• `{0}track everything` — track every pokemon (admin-permitted; see `{0}help everything`)\n• `{0}track iv:100` — filter by IV percent (`iv:90-100` for range, `miniv:90`/`maxiv:99` for one-sided)\n• `{0}track cp:1500-2500` — filter by CP\n• `{0}track level:25-35` — filter by level\n• `{0}track atk:14-15 def:14-15 sta:14-15` — filter by individual IV stats\n• `{0}track d:500` — only alert within 500m of your location\n• `{0}track location:Home d:500` — within 500m of a saved location\n• `{0}track area:london,paris` — only in named areas (replaces your default areas)\n• `{0}track great5 ultra10` — PVP filters (great/ultra/little league, rank threshold, optional cap)\n• `{0}track gen:1 type:water` — generation and type filters (alongside `everything`)\n• `{0}track rarity:rare-ultra` — rarity-tier filter\n• `{0}track clean` / `edit` — auto-delete on TTH expiry / edit-in-place\n• `{0}track remove ` or `{0}untrack ` — remove\n• `{0}untrack id:42` — remove one rule by id (see `{0}tracked` for ids)\n\nMultiple filters combine. See `{0}tracked` for what's currently active.", "cmd.raid": "raid", "cmd.egg": "uovo", "cmd.quest": "quest", @@ -129,6 +196,8 @@ "cmd.fort": "fort", "cmd.help": "aiuto", "cmd.info": "info", + "cmd.info.poracle.moved": "→ This view has moved to `!poracle-admin status` — please use that instead.", + "cmd.info.config.moved": "→ This view has moved to `!poracle-admin config` — please use that instead.", "cmd.start": "start", "cmd.stop": "stop", "cmd.tracked": "tracciati", @@ -163,6 +232,8 @@ "cmd.poracle_id": "poracle-id", "arg.remove": "rimuovi", "arg.everything": "tutto", + "arg.all_pokemon": "all pokemon", + "arg.all_items": "all items", "arg.any": "qualsiasi", "arg.clean": "pulito", "arg.edit": "edit", @@ -170,6 +241,7 @@ "arg.list": "lista", "arg.add": "aggiungi", "arg.show": "mostra", + "arg.default": "default", "arg.overview": "panoramica", "arg.dryrun": "dryrun", "arg.reset": "reset", @@ -182,6 +254,7 @@ "arg.shiny": "shiny", "arg.gmax": "gmax", "arg.stardust": "polvere di stelle", + "arg.pokecoin": "pokecoins", "arg.energy": "energia", "arg.candy": "caramella", "arg.pvp": "pvp", @@ -248,7 +321,10 @@ "arg.prefix.maxsize": "maxtaglia", "arg.prefix.gen": "gen", "arg.prefix.cap": "cap", + "arg.mega": "mega", + "arg.prefix.mega": "mega", "arg.prefix.form": "forma", + "arg.prefix.costume": "costume", "arg.prefix.template": "modello", "arg.prefix.gym": "gym", "arg.prefix.move": "mossa", @@ -263,13 +339,17 @@ "arg.prefix.littlehigh": "littlealto", "arg.prefix.littlecp": "littlepl", "arg.prefix.stardust": "polvere", + "arg.prefix.pokecoin": "pokecoins", "arg.prefix.energy": "energia", "arg.prefix.candy": "caramella", + "arg.prefix.amount": "amount", "arg.prefix.name": "nome", "arg.prefix.user": "utente", "arg.prefix.channel": "canale", "arg.prefix.guild": "gilda", "arg.prefix.language": "lingua", + "arg.prefix.area": "area", + "arg.prefix.location": "location", "arg.prefix.mon": "lun", "arg.prefix.tue": "mar", "arg.prefix.wed": "mer", @@ -323,21 +403,26 @@ "section.maxbattles.none": "You're not tracking any max battles", "msg.no_pokemon": "Nessun pokemon trovato", "msg.form_not_found": "Form `{0}` not recognised. Use `{1}info ` to see available forms.", + "msg.costume_not_found": "Costume `{0}` not recognised. Use `{1}info costumes` to see available costumes.", + "msg.no_costume": "no costume", "msg.nothing_to_remove": "Nothing to remove", "msg.no_levels": "No levels specified", "msg.no_egg_levels": "No egg levels specified", "msg.no_raid_target": "No raid levels or pokemon specified", "msg.no_lure_type": "No lure type specified", "msg.no_quest_type": "No quest type specified", + "msg.quest.amount_not_applicable": "`amount:N` doesn't apply to pokemon quests — pokemon rewards have no minimum amount.", + "msg.quest.bulk_not_permitted": "You do not have permission to track all pokemon or items at once. Track specific rewards instead.", "msg.removed_n": "Removed {0} tracking rules", "msg.egg.usage": "Valid commands are e.g. `{0}egg level:5`, `{0}egg legendary`, `{0}egg remove everything`", "msg.raid.usage": "Valid commands are e.g. `{0}raid level:5`, `{0}raid pikachu`, `{0}raid remove everything`", "msg.track.usage": "Valid commands are e.g. `{0}track pikachu iv:100`, `{0}track everything iv:90`, `{0}track remove pikachu`", "msg.track.everything_no_filters": "This would result in too many alerts. You need to provide additional filters to limit the number of valid candidates.", "msg.track.invalid_cap": "This level cap is not supported, valid choices are: {0}", - "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest energy:charizard`", + "msg.track.no_mega_form": "⚠️ {0} has no Mega {1} form — this PVP rule will never match.", + "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest pokecoins:10`, `{0}quest energy:charizard`", "msg.quest.edit_summary_conflict": "`edit` and `summary` are mutually exclusive — pick one.", - "msg.summary.usage": "Usage: `{0}summary quest [settime |cleartime|now]`", + "msg.summary.usage": "Valid commands are `{0}summary quest`, `{0}summary quest settime `, `{0}summary quest cleartime`, `{0}summary quest now`", "msg.summary.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.summary.no_schedule": "No schedule set for {0} summaries.", "msg.summary.scheduled": "Schedule for {0} summaries: {1}", @@ -360,11 +445,33 @@ "msg.nest.usage": "Valid commands are e.g. `{0}nest pikachu`, `{0}nest everything`, `{0}nest remove pikachu`", "msg.maxbattle.usage": "Valid commands are e.g. `{0}maxbattle pikachu`, `{0}maxbattle level:3`, `{0}maxbattle remove everything`", "msg.fort.usage": "Valid commands are e.g. `{0}fort pokestop`, `{0}fort everything`, `{0}fort remove pokestop`", - "msg.location.removed": "Location removed", - "msg.location.usage": "Valid commands are e.g. `{0}location ,`, `{0}location `", + "msg.location.removed": "✅ Removed saved location `{0}`.", + "msg.location.usage": "Valid commands are `{0}location `, `{0}location add `, `{0}location list`, `{0}location show `, `{0}location remove `, `{0}location remove default`", "msg.location.specify": "Please specify coordinates or an address", "msg.location.set": "Location set to {0},{1}", "msg.location.current": "Your current location is {0},{1}", + "msg.location.added": "✅ Saved location `{0}` at {1}, {2}.", + "msg.location.duplicate": "🙅 You already have a saved location called `{0}`. Remove it first with `{1}location remove {0}`.", + "msg.location.list_header": "Your saved locations:", + "msg.location.list_row": " `{0}`: {1}, {2}", + "msg.location.list_row_with_addr": " `{0}`: {1}, {2} — {3}", + "msg.location.list_empty": "You have no saved locations. Add one with `{0}location add `.", + "msg.location.show_not_found": "🙅 No saved location called `{0}`.", + "msg.location.show": "📍 `{0}` is at {1}, {2}.", + "msg.location.show_with_addr": "📍 `{0}` is at {1}, {2} — {3}", + "msg.location.no_default": "🙅 No default location set.", + "msg.location.default_removed": "✅ Cleared your default location.", + "msg.location.remove_referenced": "🙅 Cannot remove `{0}` — {1} tracking rule(s) reference it: {2}. Edit or remove those rules first.", + "msg.location.add_usage": "Valid commands are `{0}location add `", + "msg.location.show_usage": "Valid commands are `{0}location show `", + "msg.location.remove_usage": "Valid commands are `{0}location remove `, `{0}location remove default`", + "msg.location.geocode_failed": "🙅 Couldn't find a place matching `{0}`.", + "cmd.location.usage": "**{0}location** — manage your default location and saved named locations.\n\n• `{0}location` — show your current default location\n• `{0}location ` — set your default location\n• `{0}location add ` — save a named location (referenced later as `location:` on tracking rules)\n• `{0}location list` — list all your saved locations\n• `{0}location show ` — show one saved location's coords + address (use `default` for your default)\n• `{0}location remove ` — delete a saved location (refuses if any tracking rule references it)\n• `{0}location remove default` — clear your default location", + "msg.override.requires_distance": "🙅 `location:` needs a `d:` distance — e.g. `location:Home d:500`.", + "msg.override.area_and_distance": "🙅 `area:` and `d:` are mutually exclusive (area-mode vs distance-mode). Pick one.", + "msg.override.area_and_location": "🙅 `area:` and `location:` are mutually exclusive. Pick one.", + "msg.override.unknown_location": "🙅 No saved location called `{0}`. Add it with `{1}location add {0} `.", + "msg.override.area_not_permitted": "🙅 Area `{0}` is not in your allowed areas. Use `{1}area list` to see what you can pick.", "msg.area.usage": "Valid commands are `{0}area list`, `{0}area add `, `{0}area remove `", "msg.area.none_available": "No areas available", "msg.area.available": "**Available areas:**", @@ -382,14 +489,14 @@ "msg.profile.deleted": "Profile {0} deleted", "msg.profile.not_found": "Non posso trovare quel profilo", "msg.profile.cannot_delete_1": "Cannot delete profile 1", - "msg.profile.hours_usage": "Usage: profile hours ", + "msg.profile.hours_usage": "Valid commands are `{0}profile hours `", "msg.profile.hours_invalid_json": "Invalid JSON for active hours", "msg.profile.hours_set": "Active hours updated for profile {0}", "msg.profile.hours_cleared": "Active hours cleared for profile {0}", - "msg.profile.settime_usage": "Usage: profile settime mon09:00 tue18:30 weekday09:00 weekend10:00", + "msg.profile.settime_usage": "Valid commands are `{0}profile settime mon09:00 tue18:30 weekday09:00 weekend10:00`", "msg.profile.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.profile.copied": "Current profile copied to: {0}", - "msg.profile.copyto_usage": "Usage: profile copyto ", + "msg.profile.copyto_usage": "Valid commands are `{0}profile copyto `", "msg.profile.copy_invalid": "These profiles were invalid: {0}", "msg.profile.usage": "Valid commands are `{0}profile `, `{0}profile list`, `{0}profile add `, `{0}profile remove `, `{0}profile settime `, `{0}profile copyto `", "msg.profile.list_header": "I profili attualmente configurati sono:", @@ -407,6 +514,7 @@ "msg.weather.unavailable": "Weather tracking is not yet available via this command", "msg.help.unknown_topic": "No help available for '{0}'. Use `{1}help` for general help.", "msg.help.no_greeting": "No help template configured. Use `{0}help ` for command-specific help.", + "msg.help.see_detailed": "💡 More detailed help is available — `{0}help {1}`", "msg.info.sub.moves": "moves", "msg.info.sub.items": "items", "msg.info.sub.shiny": "shiny", @@ -417,9 +525,19 @@ "msg.info.sub.translate": "translate", "msg.info.sub.dts": "dts", "msg.info.sub.templates": "templates", - "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info `", + "msg.info.sub.costumes": "costumes", + "msg.info.sub.forms": "forms", + "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info costumes`, `{0}info `", "msg.info.usage_admin": "Admin: `{0}info poracle`, `{0}info dts`, `{0}info translate `, `{0}info config [search]`", "msg.info.available_forms": "Available forms:", + "msg.info.more_forms": "More than {0} forms — do {1} for the full list", + "msg.info.recent_forms": "**Recently-seen forms:**", + "msg.info.recent_raid_forms": "**Recently-seen raid forms:**", + "msg.info.available_costumes": "**Recently-seen costumes:**", + "msg.info.recent_raid_costumes": "**Recently-seen raid costumes:**", + "msg.info.costumes.header": "**Costumes** (`costume:` to track):", + "msg.info.no_costume_data": "No costume data loaded", + "msg.info.no_form_data": "No form data for that pokemon.", "msg.info.hundo_cp": "100% IV CP:", "msg.info.dts_summary": "DTS Templates loaded:", "msg.info.pokemon_not_found": "Pokemon not found: {0}", @@ -534,5 +652,661 @@ "language.sv": "Svenska", "language.zh-cn": "Cinese (semplificato)", "language.ja": "Giapponese", - "msg.help.text": "**Available commands:**\n{0}track [iv:N] [cp:N] [level:N] [d:N] — Track pokemon\n{0}untrack — Remove pokemon tracking\n{0}raid [d:N] — Track raids\n{0}egg [d:N] — Track eggs\n{0}quest — Track quests\n{0}invasion [everything|] — Track invasions\n{0}lure — Track lures\n{0}gym [slot_changes] — Track gyms\n{0}nest — Track nests\n{0}maxbattle — Track max battles\n{0}fort — Track fort updates\n{0}tracked — Show all tracking\n{0}script — Export tracking as commands\n{0}area [list|add|remove] — Manage areas\n{0}location — Set location\n{0}profile [list|add|remove|switch] — Manage profiles\n{0}language — Set language\n{0}start / {0}stop — Enable/disable alerts\n{0}version — Show version" + "slash.cmd.version": "version", + "slash.desc.version": "Show Poracle version", + "slash.cmd.tracked": "tracked", + "slash.cmd.help": "help", + "slash.cmd.info": "info", + "slash.cmd.language": "language", + "slash.cmd.track": "track", + "slash.cmd.raid": "raid", + "slash.cmd.egg": "egg", + "slash.cmd.quest": "quest", + "slash.cmd.invasion": "invasion", + "slash.cmd.incident": "incident", + "slash.cmd.lure": "lure", + "slash.cmd.nest": "nest", + "slash.cmd.maxbattle": "maxbattle", + "slash.cmd.gym": "gym", + "slash.cmd.fort": "fort", + "slash.cmd.untrack": "untrack", + "slash.cmd.area": "area", + "slash.cmd.profile": "profile", + "slash.cmd.location": "location", + "slash.cmd.summary": "summary", + "slash.cmd.start": "start", + "slash.cmd.stop": "stop", + "slash.desc.tracked": "List your tracking rules", + "slash.desc.start": "Resume alert delivery (after /stop)", + "slash.desc.stop": "Pause alert delivery (resume with /start)", + "slash.desc.help": "Show help", + "slash.desc.info": "Look up pokemon info, shiny rates, rarity tiers, or current weather", + "slash.opt.info.pokemon": "pokemon", + "slash.opt.info.pokemon.desc": "Show types, stats, evolutions, weather boost and CP table for a pokemon", + "slash.opt.info.pokemon.name": "name", + "slash.opt.info.pokemon.name.desc": "Pokemon name (any supported language) or dex id", + "slash.opt.info.rarity": "rarity", + "slash.opt.info.rarity.desc": "List pokemon by spawn rarity tier (common → ultra-rare)", + "slash.opt.info.shiny": "shiny", + "slash.opt.info.shiny.desc": "Show observed shiny rates per species", + "slash.opt.info.weather": "weather", + "slash.opt.info.weather.desc": "Show current weather and boosted types for a location", + "slash.opt.info.weather.coords": "coords", + "slash.opt.info.weather.coords.desc": "lat,lon (defaults to your saved location)", + "slash.desc.language": "Show or set your language", + "slash.desc.track": "Track a Pokemon", + "slash.desc.raid": "Track a raid boss or raid level", + "slash.desc.egg": "Track an egg / raid level", + "slash.desc.quest": "Track a quest reward", + "slash.desc.invasion": "Track a Team Rocket invasion", + "slash.desc.incident": "Track a pokestop incident (Kecleon, Gold Pokestop, Showcase…)", + "slash.desc.lure": "Track a pokestop lure", + "slash.desc.nest": "Track a nesting pokemon", + "slash.desc.maxbattle": "Track a max (Dynamax) battle", + "slash.desc.gym": "Track gym team / slot / battle changes", + "slash.desc.fort": "Track pokestop or gym updates", + "slash.desc.untrack": "Remove a tracking rule", + "slash.desc.area": "Manage your areas", + "slash.desc.profile": "Manage your profiles", + "slash.desc.location": "Manage your saved locations", + "slash.desc.summary": "Manage scheduled summary digests (e.g. quest)", + "slash.opt.help.topic": "topic", + "slash.opt.help.topic.desc": "Help topic", + "slash.opt.language.code": "code", + "slash.opt.language.code.desc": "Language code", + "slash.opt.track.pokemon": "pokemon", + "slash.opt.track.pokemon.desc": "Pokemon to track (or 'everything')", + "slash.opt.track.iv": "iv", + "slash.opt.track.iv.desc": "IV filter (e.g. 100, 95, 0-0)", + "slash.opt.track.distance": "distance", + "slash.opt.track.distance.desc": "Alert radius in metres", + "slash.opt.track.great_rank": "great_rank", + "slash.opt.track.great_rank.desc": "Top PVP rank in the Great League", + "slash.opt.track.ultra_rank": "ultra_rank", + "slash.opt.track.ultra_rank.desc": "Top PVP rank in the Ultra League", + "slash.opt.track.little_rank": "little_rank", + "slash.opt.track.little_rank.desc": "Top PVP rank in the Little League", + "slash.opt.track.clean": "clean", + "slash.opt.track.clean.desc": "Auto-delete the alert when the pokemon despawns", + "slash.opt.track.template": "template", + "slash.opt.track.template.desc": "DTS template name", + "slash.opt.track.form": "form", + "slash.opt.track.form.desc": "Pokemon form", + "slash.opt.track.size": "size", + "slash.opt.track.size.desc": "Pokemon size class", + "slash.choice.track.clean.yes": "Yes", + "slash.choice.track.size.all": "All sizes", + "slash.choice.track.size.xxs": "XXS", + "slash.choice.track.size.xs": "XS", + "slash.choice.track.size.m": "M", + "slash.choice.track.size.xl": "XL", + "slash.choice.track.size.xxl": "XXL", + "slash.opt.raid.boss": "boss", + "slash.opt.raid.boss.desc": "Raid boss pokemon", + "slash.opt.raid.level": "level", + "slash.opt.raid.level.desc": "Raid level", + "slash.opt.raid.team": "team", + "slash.opt.raid.team.desc": "Required gym-control team", + "slash.opt.raid.distance": "distance", + "slash.opt.raid.distance.desc": "Alert radius in metres", + "slash.opt.raid.clean": "clean", + "slash.opt.raid.clean.desc": "Auto-delete the alert when the raid expires", + "slash.opt.raid.template": "template", + "slash.opt.raid.template.desc": "DTS template name", + "slash.choice.raid.clean.yes": "Yes", + "slash.choice.raid.level.1": "Tier 1", + "slash.choice.raid.level.3": "Tier 3", + "slash.choice.raid.level.5": "Tier 5", + "slash.choice.raid.level.6": "Tier 6", + "slash.choice.raid.level.mega": "Mega", + "slash.choice.raid.level.legendary": "Legendary", + "slash.choice.raid.level.shadow1": "Shadow Tier 1", + "slash.choice.raid.level.shadow3": "Shadow Tier 3", + "slash.choice.raid.level.shadow5": "Shadow Tier 5", + "slash.choice.raid.level.ultra beast": "Ultra Beast", + "slash.choice.raid.level.everything": "Everything", + "slash.choice.raid.team.0": "Harmony", + "slash.choice.raid.team.1": "Mystic", + "slash.choice.raid.team.2": "Valor", + "slash.choice.raid.team.3": "Instinct", + "slash.opt.egg.level": "level", + "slash.opt.egg.level.desc": "Egg / raid level", + "slash.opt.egg.team": "team", + "slash.opt.egg.team.desc": "Required gym-control team", + "slash.opt.egg.distance": "distance", + "slash.opt.egg.distance.desc": "Alert radius in metres", + "slash.opt.egg.clean": "clean", + "slash.opt.egg.clean.desc": "Auto-delete the alert when the egg hatches", + "slash.opt.egg.template": "template", + "slash.opt.egg.template.desc": "DTS template name", + "slash.choice.egg.clean.yes": "Yes", + "slash.choice.egg.level.1": "Tier 1", + "slash.choice.egg.level.3": "Tier 3", + "slash.choice.egg.level.5": "Tier 5", + "slash.choice.egg.level.6": "Tier 6", + "slash.choice.egg.level.mega": "Mega", + "slash.choice.egg.level.legendary": "Legendary", + "slash.choice.egg.level.shadow1": "Shadow Tier 1", + "slash.choice.egg.level.shadow3": "Shadow Tier 3", + "slash.choice.egg.level.shadow5": "Shadow Tier 5", + "slash.choice.egg.level.ultra beast": "Ultra Beast", + "slash.choice.egg.level.everything": "Everything", + "slash.choice.egg.team.0": "Harmony", + "slash.choice.egg.team.1": "Mystic", + "slash.choice.egg.team.2": "Valor", + "slash.choice.egg.team.3": "Instinct", + "slash.opt.quest.pokemon": "pokemon", + "slash.opt.quest.pokemon.desc": "Pokemon reward", + "slash.opt.quest.item": "item", + "slash.opt.quest.item.desc": "Item reward (e.g. golden razz berry)", + "slash.opt.quest.stardust": "stardust", + "slash.opt.quest.stardust.desc": "Stardust reward (minimum amount)", + "slash.opt.quest.candy": "candy", + "slash.opt.quest.candy.desc": "Candy reward pokemon", + "slash.opt.quest.mega_energy": "mega_energy", + "slash.opt.quest.mega_energy.desc": "Mega energy reward pokemon", + "slash.opt.quest.min_amount": "min_amount", + "slash.opt.quest.min_amount.desc": "Minimum reward amount (item / candy / mega_energy only)", + "slash.opt.quest.distance": "distance", + "slash.opt.quest.distance.desc": "Alert radius in metres", + "slash.opt.quest.clean": "clean", + "slash.opt.quest.clean.desc": "Auto-delete the alert when the quest is completed", + "slash.opt.quest.summary": "summary", + "slash.opt.quest.summary.desc": "Buffer matches and dispatch in a scheduled batch instead of alerting immediately", + "slash.opt.quest.template": "template", + "slash.opt.quest.template.desc": "DTS template name", + "slash.choice.quest.clean.yes": "Yes", + "slash.choice.quest.summary.yes": "Yes", + "slash.opt.invasion.grunt_type": "grunt_type", + "slash.opt.invasion.grunt_type.desc": "Grunt type (Fire, Water…), boss (Giovanni…), or incident (Kecleon…)", + "slash.opt.invasion.gender": "gender", + "slash.opt.invasion.gender.desc": "Filter by grunt gender", + "slash.opt.invasion.distance": "distance", + "slash.opt.invasion.distance.desc": "Alert radius in metres", + "slash.opt.invasion.clean": "clean", + "slash.opt.invasion.clean.desc": "Auto-delete the alert when the invasion expires", + "slash.opt.invasion.template": "template", + "slash.opt.invasion.template.desc": "DTS template name", + "slash.choice.invasion.clean.yes": "Yes", + "slash.choice.invasion.gender.male": "Male", + "slash.choice.invasion.gender.female": "Female", + "slash.choice.invasion.gender.genderless": "Genderless", + "slash.opt.incident.type": "type", + "slash.opt.incident.type.desc": "Pokestop incident type (Kecleon, Gold Pokestop, Showcase…)", + "slash.opt.incident.distance": "distance", + "slash.opt.incident.distance.desc": "Alert radius in metres", + "slash.opt.incident.clean": "clean", + "slash.opt.incident.clean.desc": "Auto-delete the alert when the incident expires", + "slash.opt.incident.template": "template", + "slash.opt.incident.template.desc": "DTS template name", + "slash.choice.incident.clean.yes": "Yes", + "slash.opt.lure.lure_type": "lure_type", + "slash.opt.lure.lure_type.desc": "Lure type", + "slash.opt.lure.distance": "distance", + "slash.opt.lure.distance.desc": "Alert radius in metres", + "slash.opt.lure.clean": "clean", + "slash.opt.lure.clean.desc": "Auto-delete the alert when the lure expires", + "slash.opt.lure.template": "template", + "slash.opt.lure.template.desc": "DTS template name", + "slash.choice.lure.clean.yes": "Yes", + "slash.choice.lure.lure_type.normal": "Normal", + "slash.choice.lure.lure_type.glacial": "Glacial", + "slash.choice.lure.lure_type.mossy": "Mossy", + "slash.choice.lure.lure_type.magnetic": "Magnetic", + "slash.choice.lure.lure_type.rainy": "Rainy", + "slash.choice.lure.lure_type.sparkly": "Sparkly", + "slash.opt.nest.pokemon": "pokemon", + "slash.opt.nest.pokemon.desc": "Nesting pokemon", + "slash.opt.nest.min_spawn_avg": "min_spawn_avg", + "slash.opt.nest.min_spawn_avg.desc": "Minimum spawns per hour", + "slash.opt.nest.distance": "distance", + "slash.opt.nest.distance.desc": "Alert radius in metres", + "slash.opt.nest.clean": "clean", + "slash.opt.nest.clean.desc": "Auto-delete the alert when the nest expires", + "slash.opt.nest.template": "template", + "slash.opt.nest.template.desc": "DTS template name", + "slash.choice.nest.clean.yes": "Yes", + "slash.opt.maxbattle.pokemon": "pokemon", + "slash.opt.maxbattle.pokemon.desc": "Max battle pokemon", + "slash.opt.maxbattle.level": "level", + "slash.opt.maxbattle.level.desc": "Battle level (1..6)", + "slash.opt.maxbattle.gmax": "gmax", + "slash.opt.maxbattle.gmax.desc": "Gigantamax only", + "slash.opt.maxbattle.distance": "distance", + "slash.opt.maxbattle.distance.desc": "Alert radius in metres", + "slash.opt.maxbattle.clean": "clean", + "slash.opt.maxbattle.clean.desc": "Auto-delete the alert when the battle ends", + "slash.opt.maxbattle.template": "template", + "slash.opt.maxbattle.template.desc": "DTS template name", + "slash.choice.maxbattle.clean.yes": "Yes", + "slash.choice.maxbattle.level.1": "Level 1", + "slash.choice.maxbattle.level.2": "Level 2", + "slash.choice.maxbattle.level.3": "Level 3", + "slash.choice.maxbattle.level.4": "Level 4", + "slash.choice.maxbattle.level.5": "Level 5", + "slash.choice.maxbattle.level.6": "Level 6", + "slash.opt.gym.team": "team", + "slash.opt.gym.team.desc": "Gym-control team to alert on", + "slash.opt.gym.slot_changes": "slot_changes", + "slash.opt.gym.slot_changes.desc": "Alert on slot composition changes", + "slash.opt.gym.battle_changes": "battle_changes", + "slash.opt.gym.battle_changes.desc": "Alert on battle state changes", + "slash.opt.gym.distance": "distance", + "slash.opt.gym.distance.desc": "Alert radius in metres", + "slash.opt.gym.clean": "clean", + "slash.opt.gym.clean.desc": "Auto-delete the alert when the gym state changes", + "slash.opt.gym.template": "template", + "slash.opt.gym.template.desc": "DTS template name", + "slash.choice.gym.clean.yes": "Yes", + "slash.choice.gym.team.0": "Harmony", + "slash.choice.gym.team.1": "Mystic", + "slash.choice.gym.team.2": "Valor", + "slash.choice.gym.team.3": "Instinct", + "slash.opt.fort.fort_type": "fort_type", + "slash.opt.fort.fort_type.desc": "Fort type to track", + "slash.opt.fort.include_empty": "include_empty", + "slash.opt.fort.include_empty.desc": "Alert on empty/unowned forts", + "slash.opt.fort.distance": "distance", + "slash.opt.fort.distance.desc": "Alert radius in metres", + "slash.opt.fort.clean": "clean", + "slash.opt.fort.clean.desc": "Auto-delete the alert when the fort changes again", + "slash.opt.fort.template": "template", + "slash.opt.fort.template.desc": "DTS template name", + "slash.choice.fort.clean.yes": "Yes", + "slash.choice.fort.fort_type.0": "Pokestop", + "slash.choice.fort.fort_type.1": "Gym", + "slash.opt.tracker.location": "location", + "slash.opt.tracker.location.desc": "Use a saved location instead of your default (requires distance:)", + "slash.opt.tracker.areas": "areas", + "slash.opt.tracker.areas.desc": "Restrict to specific areas (comma-separated)", + "slash.autocomplete.untrack.remove_all": "🗑️ Remove ALL rules of this type", + "slash.opt.untrack.pokemon": "pokemon", + "slash.opt.untrack.pokemon.desc": "Remove a pokemon tracking rule", + "slash.opt.untrack.pokemon.tracking": "tracking", + "slash.opt.untrack.pokemon.tracking.desc": "Pick from your existing pokemon tracking rules", + "slash.opt.untrack.raid": "raid", + "slash.opt.untrack.raid.desc": "Remove a raid tracking rule", + "slash.opt.untrack.raid.tracking": "tracking", + "slash.opt.untrack.raid.tracking.desc": "Pick from your existing raid tracking rules", + "slash.opt.untrack.egg": "egg", + "slash.opt.untrack.egg.desc": "Remove an egg tracking rule", + "slash.opt.untrack.egg.tracking": "tracking", + "slash.opt.untrack.egg.tracking.desc": "Pick from your existing egg tracking rules", + "slash.opt.untrack.quest": "quest", + "slash.opt.untrack.quest.desc": "Remove a quest tracking rule", + "slash.opt.untrack.quest.tracking": "tracking", + "slash.opt.untrack.quest.tracking.desc": "Pick from your existing quest tracking rules", + "slash.opt.untrack.invasion": "invasion", + "slash.opt.untrack.invasion.desc": "Remove an invasion tracking rule", + "slash.opt.untrack.invasion.tracking": "tracking", + "slash.opt.untrack.invasion.tracking.desc": "Pick from your existing invasion tracking rules", + "slash.opt.untrack.lure": "lure", + "slash.opt.untrack.lure.desc": "Remove a lure tracking rule", + "slash.opt.untrack.lure.tracking": "tracking", + "slash.opt.untrack.lure.tracking.desc": "Pick from your existing lure tracking rules", + "slash.opt.untrack.nest": "nest", + "slash.opt.untrack.nest.desc": "Remove a nest tracking rule", + "slash.opt.untrack.nest.tracking": "tracking", + "slash.opt.untrack.nest.tracking.desc": "Pick from your existing nest tracking rules", + "slash.opt.untrack.gym": "gym", + "slash.opt.untrack.gym.desc": "Remove a gym tracking rule", + "slash.opt.untrack.gym.tracking": "tracking", + "slash.opt.untrack.gym.tracking.desc": "Pick from your existing gym tracking rules", + "slash.opt.untrack.fort": "fort", + "slash.opt.untrack.fort.desc": "Remove a fort tracking rule", + "slash.opt.untrack.fort.tracking": "tracking", + "slash.opt.untrack.fort.tracking.desc": "Pick from your existing fort tracking rules", + "slash.opt.untrack.maxbattle": "maxbattle", + "slash.opt.untrack.maxbattle.desc": "Remove a maxbattle tracking rule", + "slash.opt.untrack.maxbattle.tracking": "tracking", + "slash.opt.untrack.maxbattle.tracking.desc": "Pick from your existing maxbattle tracking rules", + "slash.opt.area.add": "add", + "slash.opt.area.add.desc": "Add an area to your tracking", + "slash.opt.area.add.area": "area", + "slash.opt.area.add.area.desc": "Area to add", + "slash.opt.area.remove": "remove", + "slash.opt.area.remove.desc": "Remove an area from your tracking", + "slash.opt.area.remove.area": "area", + "slash.opt.area.remove.area.desc": "Area to remove", + "slash.opt.area.show": "show", + "slash.opt.area.show.desc": "Show your selected areas", + "slash.opt.area.list": "list", + "slash.opt.area.list.desc": "List every area available to you (✓ = already added)", + "slash.opt.area.overview": "overview", + "slash.opt.area.overview.desc": "Map overview of every area available to you", + "slash.opt.profile.list": "list", + "slash.opt.profile.list.desc": "List your profiles", + "slash.opt.profile.change": "change", + "slash.opt.profile.change.desc": "Switch active profile", + "slash.opt.profile.change.name": "name", + "slash.opt.profile.change.name.desc": "Profile name", + "slash.opt.profile.create": "create", + "slash.opt.profile.create.desc": "Create a new profile", + "slash.opt.profile.create.name": "name", + "slash.opt.profile.create.name.desc": "Profile name", + "slash.opt.profile.delete": "delete", + "slash.opt.profile.delete.desc": "Delete a profile", + "slash.opt.profile.delete.name": "name", + "slash.opt.profile.delete.name.desc": "Profile name", + "slash.opt.profile.settime": "settime", + "slash.opt.profile.settime.desc": "Set active-hours for the current profile", + "slash.opt.profile.settime.times": "times", + "slash.opt.profile.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.profile.cleartime": "cleartime", + "slash.opt.profile.cleartime.desc": "Clear active-hours from the current profile", + "slash.opt.profile.copyto": "copyto", + "slash.opt.profile.copyto.desc": "Copy this profile's tracking to another profile", + "slash.opt.profile.copyto.profile": "profile", + "slash.opt.profile.copyto.profile.desc": "Target profile name or number", + "slash.opt.location.add": "add", + "slash.opt.location.add.desc": "Save a named location", + "slash.opt.location.add.name": "name", + "slash.opt.location.add.name.desc": "Short name for this location (e.g. Home)", + "slash.opt.location.add.place": "place", + "slash.opt.location.add.place.desc": "Coordinates (lat,lon) or a place name", + "slash.opt.location.list": "list", + "slash.opt.location.list.desc": "List your saved locations", + "slash.opt.location.show": "show", + "slash.opt.location.show.desc": "Show one saved location", + "slash.opt.location.show.name": "name", + "slash.opt.location.show.name.desc": "Saved-location name", + "slash.opt.location.remove": "remove", + "slash.opt.location.remove.desc": "Remove a saved location", + "slash.opt.location.remove.name": "name", + "slash.opt.location.remove.name.desc": "Saved-location name (or \"default\" to clear your default location)", + "slash.opt.location.set-default": "set-default", + "slash.opt.location.set-default.desc": "Set your default location", + "slash.opt.location.set-default.place": "place", + "slash.opt.location.set-default.place.desc": "Coordinates (lat,lon) or address to set as your default location", + "slash.opt.location.remove-default": "remove-default", + "slash.opt.location.remove-default.desc": "Clear your default location", + "slash.opt.summary.quest": "quest", + "slash.opt.summary.quest.desc": "Manage quest-summary buffering", + "slash.opt.summary.quest.show": "show", + "slash.opt.summary.quest.show.desc": "Show schedule and current buffer count", + "slash.opt.summary.quest.settime": "settime", + "slash.opt.summary.quest.settime.desc": "Set the active-hours schedule for the quest summary", + "slash.opt.summary.quest.settime.times": "times", + "slash.opt.summary.quest.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.summary.quest.cleartime": "cleartime", + "slash.opt.summary.quest.cleartime.desc": "Clear the active-hours schedule", + "slash.opt.summary.quest.now": "now", + "slash.opt.summary.quest.now.desc": "Force-dispatch the currently-buffered quests", + "error.slash.unregistered_with_channel": "🛑 You need to register first. DM me with !poracle, or run !poracle in {0}.", + "error.slash.unregistered_dm_only": "🛑 You need to register first. DM me with !poracle.", + "error.slash.track.no_pokemon": "Please specify a Pokemon to track.", + "error.slash.raid.need_boss_or_level": "Please specify either a boss or a level.", + "error.slash.raid.boss_and_level": "Please specify either a boss OR a level, not both.", + "error.slash.egg.no_level": "Please specify an egg level.", + "error.slash.quest.no_reward": "Please specify exactly one reward type (pokemon, item, stardust, candy, or mega_energy).", + "error.slash.quest.exactly_one_reward": "Please specify exactly one reward type, not multiple: {0}.", + "error.slash.quest.amount_not_applicable": "`min_amount` doesn't apply to pokemon quests. For stardust, both `stardust` and `min_amount` end up in the same field — pick whichever reads better.", + "error.slash.invasion.no_grunt": "Please specify a grunt type.", + "error.slash.incident.no_type": "Please specify an incident type.", + "error.slash.lure.no_type": "Please specify a lure type.", + "error.slash.nest.no_pokemon": "Please specify a Pokemon for the nest.", + "error.slash.maxbattle.no_pokemon": "Please specify a Pokemon for the max battle.", + "error.slash.fort.no_type": "Please specify a fort type (pokestop or gym).", + "error.slash.untrack.no_subcommand": "Please choose what kind of tracking rule to remove.", + "error.slash.untrack.no_tracking": "Please pick a tracking rule to remove.", + "error.slash.info.no_subcommand": "Please choose an info sub-command (pokemon / rarity / shiny / weather).", + "error.slash.info.no_pokemon": "Please specify a pokemon name or dex id.", + "error.slash.info.unknown_subcommand": "Unknown info sub-command.", + "error.slash.area.no_subcommand": "Please choose an area sub-command (add / remove / show).", + "error.slash.area.no_area": "Please specify an area name.", + "error.slash.area.unknown_subcommand": "Unknown area sub-command.", + "error.slash.profile.no_subcommand": "Please choose a profile sub-command (list / change / create / delete / settime / cleartime / copyto).", + "error.slash.profile.no_name": "Please specify a profile name.", + "error.slash.profile.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.profile.no_target": "Please specify a target profile to copy to.", + "error.slash.profile.unknown_subcommand": "Unknown profile sub-command.", + "error.slash.summary.no_alert_type": "Please choose an alert type (e.g. quest).", + "error.slash.summary.no_action": "Please choose an action (show / settime / cleartime / now).", + "error.slash.summary.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.summary.unknown_action": "Unknown summary action.", + "error.slash.location.no_subcommand": "Please choose a location sub-command (add / list / show / remove / remove-default).", + "error.slash.location.no_name": "Please specify a saved-location name.", + "error.slash.location.empty": "Please specify coordinates or a place name.", + "error.slash.location.unknown_subcommand": "Unknown location sub-command.", + "error.slash.location.no_geocoder": "Place-name lookup is not configured. Please provide coordinates like 51.28, 1.08.", + "error.slash.location.geocode_failed": "Could not find a location for \"{0}\".", + "msg.help.text": "**Available commands:**\n{0}track [iv:N] [cp:N] [level:N] [d:N] — Track pokemon\n{0}untrack — Remove pokemon tracking\n{0}raid [d:N] — Track raids\n{0}egg [d:N] — Track eggs\n{0}quest — Track quests\n{0}invasion [everything|] — Track invasions\n{0}lure — Track lures\n{0}gym [slot_changes] — Track gyms\n{0}nest — Track nests\n{0}maxbattle — Track max battles\n{0}fort — Track fort updates\n{0}tracked — Show all tracking\n{0}script — Export tracking as commands\n{0}area [list|add|remove] — Manage areas\n{0}location — Set location\n{0}profile [list|add|remove|switch] — Manage profiles\n{0}language — Set language\n{0}start / {0}stop — Enable/disable alerts\n{0}version — Show version", + "cmd.poracle_admin": "poracle-admin", + "cmd.pa": "pa", + "cmd.poracle_admin.not_admin": "This command is reserved for administrators.", + "cmd.poracle_admin.unknown_group": "Unknown subgroup. Try `!poracle-admin` for the list.", + "cmd.poracle_admin.unknown_sub": "Unknown subcommand for `{0}`. Try `!poracle-admin {0}` to see what's available.", + "cmd.poracle_admin.help.admin_only": "This command is reserved for server administrators. Each subgroup performs a live operations task.", + "cmd.poracle_admin.help.groups": "Available subgroups:", + "cmd.poracle_admin.help_intro": "🛠️ Poracle Admin\n\nLive operations subgroups (administrators only):", + "cmd.poracle_admin.stub": "(not yet implemented)", + "cmd.poracle_admin.group.slash.desc": "slash-command registration lifecycle", + "cmd.poracle_admin.group.reload.desc": "reload DTS, geofence, or in-memory state", + "cmd.poracle_admin.group.emoji.desc": "list, reload, or test emoji config", + "cmd.poracle_admin.group.reconcile.desc": "Discord role reconciliation (immediate or per-user)", + "cmd.poracle_admin.group.cache.desc": "cache stats and clear", + "cmd.poracle_admin.group.ratelimit.desc": "inspect and reset alert-bucket rate limits", + "cmd.poracle_admin.group.summary.desc": "summary buffer inspection and forced dispatch", + "cmd.poracle_admin.group.status.desc": "live health snapshot", + "cmd.poracle_admin.group.maintenance.desc": "pause/resume outbound delivery", + "cmd.poracle_admin.group.config.desc": "view effective merged config with secrets redacted", + "cmd.poracle_admin.group.warnings.desc": "inspect captured WARN/ERROR log entries (startup + rolling buffers)", + "cmd.poracle_admin.reload.help.intro": "Reload runtime state from disk or database.", + "cmd.poracle_admin.reload.dts.desc": "`dts` — reload DTS templates and partials from disk", + "cmd.poracle_admin.reload.geofence.desc": "`geofence` — reload geofence files and refresh state", + "cmd.poracle_admin.reload.state.desc": "`state` — reload tracking rules and humans from MySQL (bypasses debounce)", + "cmd.poracle_admin.reload.dts.success": "✅ DTS reloaded in {0}ms ({1} templates)", + "cmd.poracle_admin.reload.geofence.success": "✅ Geofence reloaded in {0}ms ({1} fences, {2} tracking rules)", + "cmd.poracle_admin.reload.state.success": "✅ State reloaded in {0}ms ({1} tracking rules, {2} active humans)", + "cmd.poracle_admin.reload.error": "❌ Reload failed: {0}", + "cmd.poracle_admin.emoji.help.intro": "😀 Emoji config — inspect and manage emoji.json + Discord guild emojis.\n\nSubcommands:", + "cmd.poracle_admin.emoji.list.desc": "`list` — list all configured emoji keys with per-platform resolutions", + "cmd.poracle_admin.emoji.reload.desc": "`reload` — reload config/emoji.json from disk", + "cmd.poracle_admin.emoji.test.desc": "`test ` — resolve one emoji key for the current platform", + "cmd.poracle_admin.emoji.upload.desc": "`upload [overwrite]` — upload uicons-based emojis to the guild and write a new emoji.json (Discord-only)", + "cmd.poracle_admin.emoji.discord_config.desc": "`discord-config` — dump emoji.json from the current guild state, no uploads (Discord-only)", + "cmd.poracle_admin.emoji.discord_only": "ℹ️ This subcommand requires a Discord bot with guild access.", + "cmd.poracle_admin.emoji.not_loaded": "ℹ️ Emoji config not loaded (DTS renderer not configured).", + "cmd.poracle_admin.emoji.list.header": "😀 Emoji configuration — {0} keys loaded", + "cmd.poracle_admin.emoji.list.row.key": " {0}:", + "cmd.poracle_admin.emoji.list.row.platform": " {0}: {1}", + "cmd.poracle_admin.emoji.reload.success": "✅ Emoji config reloaded — {0} keys (took {1}ms).", + "cmd.poracle_admin.emoji.reload.error": "❌ Emoji reload failed: {0}", + "cmd.poracle_admin.emoji.test.success": "🔎 {0} on {1}: {2}", + "cmd.poracle_admin.emoji.test.not_found": "ℹ️ Emoji key \"{0}\" not found in the loaded config.", + "cmd.poracle_admin.emoji.test.usage": "Usage: !poracle-admin emoji test ", + "cmd.poracle_admin.reconcile.help.intro": "🔄 Discord role reconciliation — trigger immediately instead of waiting for the periodic timer.", + "cmd.poracle_admin.reconcile.run.desc": "`run` — reconcile all guild members now (blocks until complete)", + "cmd.poracle_admin.reconcile.user.desc": "`user ` — reconcile a single Discord user by snowflake ID", + "cmd.poracle_admin.reconcile.not_configured": "❌ Discord reconciliation is not configured (Telegram-only deploy, or check_role=false).", + "cmd.poracle_admin.reconcile.run.success": "✅ Discord reconciliation complete (took {0}ms).", + "cmd.poracle_admin.reconcile.run.error": "❌ Reconciliation failed: {0}", + "cmd.poracle_admin.reconcile.user.success": "✅ Reconciled discord:user/{0} (took {1}ms).", + "cmd.poracle_admin.reconcile.user.error": "❌ Failed to reconcile discord:user/{0}: {1}", + "cmd.poracle_admin.reconcile.user.usage": "Usage: !poracle-admin reconcile user ", + "cmd.poracle_admin.cache.help.intro": "🗺️ Geocoder cache — inspect counters or drop the in-memory layer.", + "cmd.poracle_admin.cache.stats.desc": "`stats` — geocoder cache stats", + "cmd.poracle_admin.cache.clear.desc": "`clear geocoder` — drop the in-memory geocoder cache", + "cmd.poracle_admin.cache.not_configured": "Geocoder cache is not configured on this instance.", + "cmd.poracle_admin.cache.stats.header": "🗺️ Geocoder cache", + "cmd.poracle_admin.cache.stats.row.memory_entries": " Memory entries: {0}", + "cmd.poracle_admin.cache.stats.row.disk_entries": " Disk entries: {0}", + "cmd.poracle_admin.cache.stats.row.hits_memory": " Hits (memory): {0}", + "cmd.poracle_admin.cache.stats.row.hits_disk": " Hits (disk): {0}", + "cmd.poracle_admin.cache.stats.row.misses": " Misses: {0}", + "cmd.poracle_admin.cache.stats.row.hit_rate": " Hit rate: {0}%", + "cmd.poracle_admin.cache.clear.usage_hint": "Specify what to clear, e.g. `!poracle-admin cache clear geocoder`", + "cmd.poracle_admin.cache.clear.geocoder.success": "✅ Geocoder memory cache cleared — {0} entries dropped (disk untouched).", + "cmd.poracle_admin.ratelimit.help.intro": "🚦 Rate-limit introspection — inspect or reset per-destination alert and summary buckets.", + "cmd.poracle_admin.ratelimit.not_configured": "ℹ️ Alert rate limiter is not configured on this instance.", + "cmd.poracle_admin.ratelimit.list.desc": "`list` — show all targets currently breached or banned", + "cmd.poracle_admin.ratelimit.show.desc": "`show ` — detailed state for one target (both buckets)", + "cmd.poracle_admin.ratelimit.reset.desc": "`reset ` — clear counters and violation history", + "cmd.poracle_admin.ratelimit.userlist.desc": "`userlist` — show currently disabled users (shortcut for !userlist disabled)", + "cmd.poracle_admin.ratelimit.list.empty": "🟢 No targets currently rate-limited.", + "cmd.poracle_admin.ratelimit.list.header_title": "Currently rate-limited targets", + "cmd.poracle_admin.ratelimit.list.bucket_header": " {0} bucket ({1} breached / {2} banned):", + "cmd.poracle_admin.ratelimit.list.row": "count {0}/{1}, {2}", + "cmd.poracle_admin.ratelimit.list.status.banned": "banned for {0}", + "cmd.poracle_admin.ratelimit.list.status.breached": "window resets in {0}", + "cmd.poracle_admin.ratelimit.show.header": "🚦 Rate-limit state for {0}", + "cmd.poracle_admin.ratelimit.show.bucket_header": "{0} bucket:", + "cmd.poracle_admin.ratelimit.show.empty": "🟢 No recorded activity for {0} in either bucket.", + "cmd.poracle_admin.ratelimit.show.no_data": "(no activity in this bucket)", + "cmd.poracle_admin.ratelimit.show.no_violations": "No violations.", + "cmd.poracle_admin.ratelimit.show.violations_count": "Violations (24h): {0}", + "cmd.poracle_admin.ratelimit.show.banned_until": "Banned until: {0} (in {1})", + "cmd.poracle_admin.ratelimit.show.status.under_limit": "under limit", + "cmd.poracle_admin.ratelimit.show.status.over_limit": "over limit", + "cmd.poracle_admin.ratelimit.show.row.count": " Count: {0} / {1} ({2})\n", + "cmd.poracle_admin.ratelimit.show.row.window": " Window: opened {0} ago, resets in {1}\n", + "cmd.poracle_admin.ratelimit.reset.success": "✅ Reset rate-limit state for {0} (cleared alert + summary buckets, violations reset).", + "cmd.poracle_admin.ratelimit.reset.no_state": "ℹ️ No rate-limit state to reset for {0}.", + "cmd.poracle_admin.ratelimit.reset.note": "Note: admin_disable is NOT touched. If the user was auto-disabled by the rate-limiter, they still need to !poracle to re-register.", + "cmd.poracle_admin.ratelimit.usage.show": "Usage: !poracle-admin ratelimit show ", + "cmd.poracle_admin.ratelimit.usage.reset": "Usage: !poracle-admin ratelimit reset ", + "cmd.poracle_admin.ratelimit.userlist.lookup_failed": "❌ Could not find !userlist command in the registry.", + "cmd.poracle_admin.summary.help.intro": "📦 Summary buffer — inspect who has quests buffered and force-dispatch on demand.", + "cmd.poracle_admin.summary.not_configured": "ℹ️ Summary buffer is not configured on this instance.", + "cmd.poracle_admin.summary.list.desc": "`list` — show all users with anything buffered", + "cmd.poracle_admin.summary.show.desc": "`show ` — inspect one user's buffered entries", + "cmd.poracle_admin.summary.fire.desc": "`fire [alertType]` — force-dispatch a user's buffer immediately", + "cmd.poracle_admin.summary.list.empty": "🟢 No users have anything buffered.", + "cmd.poracle_admin.summary.list.header": "📦 Summary buffer — {0} users with {1} buffered entries", + "cmd.poracle_admin.summary.list.user_header": " {0}", + "cmd.poracle_admin.summary.list.row": " {0}: {1} entries (next fires: {2})", + "cmd.poracle_admin.summary.list.next_fire.none": "n/a", + "cmd.poracle_admin.summary.show.header": "📦 Summary buffer for {0}", + "cmd.poracle_admin.summary.show.empty": "🟢 No buffered entries for {0}.", + "cmd.poracle_admin.summary.show.alert_type": " {0}: {1} entries", + "cmd.poracle_admin.summary.show.usage": "Usage: !poracle-admin summary show ", + "cmd.poracle_admin.summary.fire.success": "✅ Dispatched summary for {0} / {1} — {2} entries delivered.", + "cmd.poracle_admin.summary.fire.usage": "Usage: !poracle-admin summary fire [alertType]", + "cmd.poracle_admin.summary.show.reward_row": " Reward type {0}, reward {1}{2} — {3} stops", + "cmd.poracle_admin.summary.show.reward_more": " ... ({0} more reward groups)", + "cmd.poracle_admin.summary.show.form_suffix": " form {0}", + "cmd.poracle_admin.maintenance.help.intro": "🛠️ **!poracle-admin maintenance** — live control over outbound delivery.\n\nSubcommands:", + "cmd.poracle_admin.maintenance.no_dispatcher": "ℹ️ Dispatcher is not available on this instance.", + "cmd.poracle_admin.maintenance.no_reason": "(no reason given)", + "cmd.poracle_admin.maintenance.pause.desc": "`pause [reason...]` (alias: `start`) — halt outbound delivery (webhooks still ingest, match, render, and queue)", + "cmd.poracle_admin.maintenance.resume.desc": "`resume` (alias: `stop`) — lift a previous pause and drain queued jobs", + "cmd.poracle_admin.maintenance.status.desc": "`status` — show current paused/running state and queue depth", + "cmd.poracle_admin.maintenance.pause.new": "🔴 Outbound delivery paused: {0}", + "cmd.poracle_admin.maintenance.pause.detail": "Webhooks still ingest, match, render, and queue — the dispatcher holds them until !poracle-admin maintenance resume.", + "cmd.poracle_admin.maintenance.pause.already": "ℹ️ Already paused since {0} ({1} ago): {2}", + "cmd.poracle_admin.maintenance.resume.success": "🟢 Outbound delivery resumed (was paused for {0}: {1})", + "cmd.poracle_admin.maintenance.resume.detail": "Queued messages are draining.", + "cmd.poracle_admin.maintenance.resume.not_paused": "ℹ️ Not currently paused.", + "cmd.poracle_admin.maintenance.status.running": "🟢 Delivery is running.", + "cmd.poracle_admin.maintenance.status.paused": "🔴 PAUSED — {0} (for {1})", + "cmd.poracle_admin.maintenance.status.queued": "{0} jobs queued waiting (across all platforms — Discord {1}, Telegram {2})", + "cmd.poracle_admin.status.help.intro": "!poracle-admin status — current health snapshot. Add -v for verbose mode (per-route Discord detail, full webhook per-type breakdown).", + "cmd.poracle_admin.status.header": "🛠️ Poracle Admin — Status", + "cmd.poracle_admin.status.paused_banner": "🔴 PAUSED — {0} (since {1} ago)\n Outbound delivery is held. Webhooks still ingest and queue.", + "cmd.poracle_admin.status.value.na": "n/a", + "cmd.poracle_admin.status.value.none": "none", + "cmd.poracle_admin.status.section.build": "**Build / Uptime**", + "cmd.poracle_admin.status.section.webhooks": "**Webhooks**", + "cmd.poracle_admin.status.section.render_queue": "**Render queue**", + "cmd.poracle_admin.status.section.delivery": "**Delivery**", + "cmd.poracle_admin.status.section.discord_rate": "**Discord rate**", + "cmd.poracle_admin.status.section.telegram_rate": "**Telegram rate**", + "cmd.poracle_admin.status.section.alert_limits": "**Alert limits**", + "cmd.poracle_admin.status.section.summary_buffer": "**Summary buffer**", + "cmd.poracle_admin.status.label.summary_buffer_totals": "Entries: {0} across {1} bucket(s)", + "cmd.poracle_admin.status.label.summary_buffer_top": "Top users:", + "cmd.poracle_admin.status.label.summary_buffer_user_row": " {0} ({1}): {2} entries", + "cmd.poracle_admin.status.section.tracking": "**Tracking**", + "cmd.poracle_admin.status.section.mysql": "**MySQL**", + "cmd.poracle_admin.status.label.version": "Version: {0} (commit {1}, built {2})", + "cmd.poracle_admin.status.label.uptime": "Uptime: {0}", + "cmd.poracle_admin.status.label.webhooks_rate": "{0} / {1} / {2} per min over last 5/15/60 min", + "cmd.poracle_admin.status.label.webhooks_by_type": "By type (last 60 min):", + "cmd.poracle_admin.status.label.delivery_discord": "Discord in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_telegram": "Telegram in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_webhook": "Webhook in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_queue_depth": "Queue depth: {0} (capacity not exposed)", + "cmd.poracle_admin.status.label.discord_routes": "Routes near limit: {0}", + "cmd.poracle_admin.status.label.discord_global": "Global tokens: {0} / {1}", + "cmd.poracle_admin.status.label.discord_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.discord_routes_detail": "Routes near limit (detail):", + "cmd.poracle_admin.status.label.telegram_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.telegram_backoff": "Current backoff: {0}", + "cmd.poracle_admin.status.label.alert_limits_counts": "Breached: alert={0}, summary={1} · Banned: {2}", + "cmd.poracle_admin.status.label.tracking_total": "Total tracking rules: {0}", + "cmd.poracle_admin.status.label.tracking_active_humans": "Active humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans": "Registered humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans_error": "Registered humans: n/a (error)", + "cmd.poracle_admin.status.label.tracking_type": "{0}: {1}", + "cmd.poracle_admin.status.label.mysql_ping_ok": "Ping: ok", + "cmd.poracle_admin.status.label.mysql_ping_fail": "Ping: failed ({0})", + "cmd.poracle_admin.status.label.mysql_pool": "Connections: {0}/{1} open ({2} in use, {3} idle, waits={4})", + "cmd.poracle_admin.status.tracking_type.pokemon": "pokemon", + "cmd.poracle_admin.status.tracking_type.raid": "raid", + "cmd.poracle_admin.status.tracking_type.egg": "egg", + "cmd.poracle_admin.status.tracking_type.quest": "quest", + "cmd.poracle_admin.status.tracking_type.invasion": "invasion", + "cmd.poracle_admin.status.tracking_type.lure": "lure", + "cmd.poracle_admin.status.tracking_type.nest": "nest", + "cmd.poracle_admin.status.tracking_type.gym": "gym", + "cmd.poracle_admin.status.tracking_type.fort": "fort", + "cmd.poracle_admin.status.tracking_type.maxbattle": "maxbattle", + "cmd.poracle_admin.slash.help.intro": "**!poracle-admin slash** — slash-command registration lifecycle.\nSubcommands:", + "cmd.poracle_admin.slash.discord_only": "❌ Slash commands are Discord-only and cannot be managed from Telegram.", + "cmd.poracle_admin.slash.not_configured": "❌ Slash commands are not configured (Discord disabled or [discord.slash_commands] enabled=false).", + "cmd.poracle_admin.slash.sync.desc": "push the current command set to Discord (fingerprint-cached, skips if unchanged)", + "cmd.poracle_admin.slash.sync.success": "✅ Slash sync complete ({0}ms)", + "cmd.poracle_admin.slash.sync.error": "❌ Slash sync failed: {0}", + "cmd.poracle_admin.slash.force_resync.desc": "clear fingerprint cache and push unconditionally", + "cmd.poracle_admin.slash.force_resync.success": "✅ Force-resync complete ({0}ms)", + "cmd.poracle_admin.slash.force_resync.error": "❌ Force-resync failed: {0}", + "cmd.poracle_admin.slash.clear_global.desc": "remove all globally-registered Discord slash commands", + "cmd.poracle_admin.slash.clear_global.success": "✅ Global slash commands cleared.", + "cmd.poracle_admin.slash.clear_global.error": "❌ Clear global failed: {0}", + "cmd.poracle_admin.slash.clear_guild.desc": "remove slash commands from one guild (requires guild_id arg)", + "cmd.poracle_admin.slash.clear_guild.needs_arg": "❌ Usage: `!poracle-admin slash clear-guild `", + "cmd.poracle_admin.slash.clear_guild.success": "✅ Slash commands cleared from guild {0}.", + "cmd.poracle_admin.slash.clear_guild.error": "❌ Clear guild failed: {0}", + "cmd.poracle_admin.slash.status.desc": "show last sync timestamp and fingerprint per scope", + "cmd.poracle_admin.slash.status.header": "**Slash command registration status:**", + "cmd.poracle_admin.slash.status.scope_row": " **{0}**: last synced {1} · fingerprint `{2}`", + "cmd.poracle_admin.slash.status.never_synced": "never", + "cmd.poracle_admin.slash.status.ago": "{0} ago", + "cmd.poracle_admin.slash.status.error": "❌ Status read failed: {0}", + "cmd.poracle_admin.config.help.intro": "⚙️ Config viewer — show effective merged config with secrets redacted.\nSubcommands:", + "cmd.poracle_admin.config.keys.desc": "list section names with key counts", + "cmd.poracle_admin.config.section.desc": "show just that section (e.g. `!poracle-admin config discord`)", + "cmd.poracle_admin.config.full.desc": "show the full config (all sections, secrets redacted)", + "cmd.poracle_admin.config.keys.header": "⚙️ Config sections:", + "cmd.poracle_admin.config.keys.row": " {0}: {1} keys", + "cmd.poracle_admin.config.unknown_section": "Unknown config section: `{0}`. Use `!poracle-admin config keys` to list valid sections, or `!poracle-admin config search ` to search across all sections.", + "cmd.poracle_admin.config.search.desc": "find keys whose path or value contains the term across every section (e.g. `!poracle-admin config search dm`)", + "cmd.poracle_admin.config.search.usage": "Usage: `!poracle-admin config search ` — e.g. `search dm`, `search shlink`, `search 3030`.", + "cmd.poracle_admin.config.search.header": "🔍 `{0}` — {1} match(es):", + "cmd.poracle_admin.config.search.no_matches": "No config keys or values match `{0}`.", + "cmd.poracle_admin.config.empty_section": "Section `{0}` has no configurable fields.", + "cmd.poracle_admin.config.not_loaded": "❌ Config not loaded.", + "cmd.poracle_admin.warnings.help.intro": "🛠️ Captured warnings — inspect in-memory WARN/ERROR log entries.\n\nSubcommands:\n (no arg) — show both startup and recent buffers\n `startup` — show only the startup buffer (first 200 entries, frozen after init)\n `recent` — show only the rolling buffer (last 50 entries)\n `clear` — empty the rolling buffer (startup is immutable)", + "cmd.poracle_admin.warnings.not_configured": "ℹ️ Log buffer is not configured on this instance.", + "cmd.poracle_admin.warnings.section.startup": "🛠️ Captured warnings — startup ({0} entries)", + "cmd.poracle_admin.warnings.section.recent": "🛠️ Captured warnings — recent ({0} entries)", + "cmd.poracle_admin.warnings.empty.startup": "🟢 No startup warnings captured.", + "cmd.poracle_admin.warnings.empty.recent": "🟢 No recent warnings.", + "cmd.poracle_admin.warnings.entry_row": " {0} {1} {2} {3}", + "cmd.poracle_admin.warnings.cleared": "✅ Cleared {0} entries from the rolling buffer (startup buffer is unaffected).", + "cmd.poracle_admin.warnings.startup.desc": "`startup` — show only the startup buffer (frozen after init)", + "cmd.poracle_admin.warnings.recent.desc": "`recent` — show only the rolling buffer (last 50 entries)", + "cmd.poracle_admin.warnings.clear.desc": "`clear` — empty the rolling buffer", + "cmd.maintenance.active_suffix": "🔧 Maintenance mode is active — alerts are not being delivered.", + "showcase_focus_pokemon": "Pokémon", + "showcase_focus_type": "Type", + "showcase_focus_alignment": "Alignment", + "showcase_focus_class": "Class", + "showcase_focus_family": "Family", + "showcase_focus_buddy": "Buddy", + "showcase_focus_generation": "Generation", + "showcase_focus_hatched": "Hatched", + "showcase_focus_mega": "Mega", + "showcase_focus_shiny": "Shiny", + "showcase_class_ultra_beast": "Ultra Beast" } diff --git a/processor/internal/i18n/locale/ja.json b/processor/internal/i18n/locale/ja.json index ba47b6779..a58474d52 100644 --- a/processor/internal/i18n/locale/ja.json +++ b/processor/internal/i18n/locale/ja.json @@ -58,6 +58,11 @@ "tracking.pvp_little": "リトルPVP", "tracking.pvp_great": "スーパーPVP", "tracking.pvp_ultra": "ハイパーPVP", + "tracking.pvp_mega_any": "mega", + "tracking.pvp_mega_x": "mega x", + "tracking.pvp_mega_y": "mega y", + "tracking.mega_x_label": "X", + "tracking.mega_y_label": "Y", "tracking.level_cap_fmt": "レベル上限: {0}", "tracking.everything": "すべて", "tracking.unknown_monster": "不明なポケモン", @@ -81,10 +86,14 @@ "tracking.reward_fmt": "報酬: **{0}**", "tracking.reward_stardust_min_fmt": "ほしのすな {0} 以上", "tracking.reward_stardust": "ほしのすな", + "tracking.reward_pokecoin_min_fmt": "{0} or more pokecoins", + "tracking.reward_pokecoin": "pokecoins", "tracking.reward_mega_energy": "メガエナジー", "tracking.reward_mega_energy_fmt": "メガエナジー {0}", "tracking.reward_candy": "アメ", "tracking.reward_candy_fmt": "アメ {0}", + "tracking.reward_any_pokemon": "any pokemon", + "tracking.reward_any_item": "any item", "tracking.reward_min_fmt": "最小 {0}", "tracking.grunt_type_fmt": "したっぱタイプ: **{0}**", "tracking.min_avg_spawn": "最小平均出現: {0}/時", @@ -108,10 +117,68 @@ "tracking.template_not_found": "テンプレート \"{0}\" は存在しません。", "tracking.warn_template_not_found": "タイプ {1}/{2} のテンプレート \"{0}\" が見つかりません。追跡は保存されましたがアラートが描画されない可能性があります。", "tracking.id_hint": "特定の項目を削除するには id を使用してください — 例: `{0}untrack id:45` または `{0}raid remove id:12`", + "tracking.id_hint_slash": "To remove a specific entry, run `/untrack ` (e.g. `/untrack raid`) and pick it from the list.", + "tracking.list_attached": "Your tracking list is long ({0} rules) — attached as a file.", "tracking.removed_prefix": "削除: ", "tracking.uid_not_found": "id:{0} が見つかりません", + "tracking.override_location_fmt": "@ {0}", + "tracking.override_areas_fmt": "in {0}", "cmd.track": "track", "cmd.untrack": "untrack", + "cmd.mute": "mute", + "cmd.unmute": "unmute", + "msg.mute.unavailable": "Mute feature isn't enabled here.", + "msg.mute.usage": "Valid commands are `{0}mute [duration:1h]`", + "msg.mute.usage_pokemon": "Valid commands are `{0}mute pokemon [duration:1h]`", + "msg.mute.usage_gym": "Valid commands are `{0}mute gym [duration:1h]`", + "msg.mute.usage_area": "Valid commands are `{0}mute area [duration:1h]`", + "msg.mute.usage_id_scope": "Valid commands are `{0}mute {1} [duration:1h]`", + "msg.mute.bad_duration": "Invalid duration: {0}", + "msg.mute.id_not_supported": "`!mute id:N` / `!mute id:N` aren't supported yet — entity scopes (gym, pokemon, area, pokestop, station, everything) work today. Per-rule muting by UID is a follow-up.", + "msg.mute.bad_uid": "`{0}` isn't a valid tracking rule UID. Use `!tracked` to see your rule UIDs.", + "msg.mute.unknown_area": "`{0}` isn't in your available areas. Use `!area` to see what you can mute.", + "msg.mute.no_pokemon": "I don't know a pokemon called `{0}`.", + "msg.mute.everything_label": "everything", + "msg.mute.added": "🔇 Muted {0} for {1}.", + "msg.mute.removed": "✅ Unmuted {0}.", + "msg.mute.none_found": "No active mute for {0}.", + "msg.mute.cleared_all": "Cleared {0} active mutes.", + "msg.unmute.usage": "Valid commands are `{0}unmute `, `{0}unmute all`", + "msg.unmute.usage_pokemon": "Valid commands are `{0}unmute pokemon `", + "msg.unmute.usage_gym": "Valid commands are `{0}unmute gym `", + "msg.unmute.usage_area": "Valid commands are `{0}unmute area `", + "section.property_mutes": "Property mutes (apply across all tracking):", + "section.property_mutes.left": "({0} left)", + "msg.button.expired": "This alert has expired.", + "msg.button.unavailable": "This button is no longer available.", + "msg.button.wrong_target": "This button doesn't apply here.", + "msg.button.unauthorized": "This button isn't for you.", + "msg.button.unidentified": "Couldn't identify you to handle that click.", + "msg.button.unconfigured": "This button isn't configured.", + "msg.button.action_failed": "Couldn't complete that action: {0}", + "msg.button.action_failed_generic": "Couldn't complete that action.", + "msg.button.cooldown": "Slow down — try that again in a moment.", + "msg.button.actions_not_wired": "Button actions aren't wired here.", + "msg.button.not_implemented": "The {0} action isn't implemented yet.", + "msg.button.responses_not_wired": "Response rendering isn't wired here.", + "msg.button.response_failed": "Couldn't render that response: {0}", + "msg.button.done": "Done.", + "msg.button.missing_scope": "Button is missing a scope — operator config bug.", + "msg.button.missing_target": "Couldn't find a {0} to mute on this alert.", + "msg.button.no_dm_target": "Couldn't identify you to send the message.", + "msg.button.dm_failed": "Couldn't send to your DM: {0}", + "msg.button.unsubscribe_failed": "Couldn't unsubscribe — please try again.", + "msg.button.unsubscribe_already": "Those tracking rules were already removed.", + "msg.button.unsubscribed": "✅ Unsubscribed from {0} tracking rule(s).", + "msg.button.redeliver_sent": "📬 Sent to your DM.", + "msg.mute.scope_gym": "gym", + "msg.mute.scope_pokemon": "pokemon", + "msg.mute.scope_area": "area", + "msg.mute.scope_pokestop": "pokestop", + "msg.mute.scope_station": "station", + "msg.mute.scope_tracking": "tracking rule", + "cmd.mute.usage": "**{0}mute** — silence alerts for a specific gym, pokemon, area, pokestop, station, or everything for a time-bounded window.\n\n• `{0}mute everything [duration:1h]` — silence ALL alerts for the given duration\n• `{0}mute gym [duration:1h]` — silence alerts for one gym\n• `{0}mute pokemon [duration:1h]` — silence alerts for one pokemon species\n• `{0}mute area [duration:1h]` — silence alerts in one area\n• `{0}mute pokestop [duration:1h]` — silence alerts for one pokestop\n• `{0}mute station [duration:1h]` — silence alerts for one station\n\nDuration defaults to 1h if omitted. Use `{0}unmute ` to remove a mute early, or `{0}tracked` to see active mutes.", + "cmd.track.usage": "**{0}track** — set up pokemon tracking rules.\n\n• `{0}track ` — track a specific pokemon (by name or dex id) at default 100m\n• `{0}track everything` — track every pokemon (admin-permitted; see `{0}help everything`)\n• `{0}track iv:100` — filter by IV percent (`iv:90-100` for range, `miniv:90`/`maxiv:99` for one-sided)\n• `{0}track cp:1500-2500` — filter by CP\n• `{0}track level:25-35` — filter by level\n• `{0}track atk:14-15 def:14-15 sta:14-15` — filter by individual IV stats\n• `{0}track d:500` — only alert within 500m of your location\n• `{0}track location:Home d:500` — within 500m of a saved location\n• `{0}track area:london,paris` — only in named areas (replaces your default areas)\n• `{0}track great5 ultra10` — PVP filters (great/ultra/little league, rank threshold, optional cap)\n• `{0}track gen:1 type:water` — generation and type filters (alongside `everything`)\n• `{0}track rarity:rare-ultra` — rarity-tier filter\n• `{0}track clean` / `edit` — auto-delete on TTH expiry / edit-in-place\n• `{0}track remove ` or `{0}untrack ` — remove\n• `{0}untrack id:42` — remove one rule by id (see `{0}tracked` for ids)\n\nMultiple filters combine. See `{0}tracked` for what's currently active.", "cmd.raid": "raid", "cmd.egg": "egg", "cmd.quest": "quest", @@ -129,6 +196,8 @@ "cmd.fort": "fort", "cmd.help": "help", "cmd.info": "info", + "cmd.info.poracle.moved": "→ This view has moved to `!poracle-admin status` — please use that instead.", + "cmd.info.config.moved": "→ This view has moved to `!poracle-admin config` — please use that instead.", "cmd.start": "start", "cmd.stop": "stop", "cmd.tracked": "tracked", @@ -163,6 +232,8 @@ "cmd.poracle_id": "poracle-id", "arg.remove": "remove", "arg.everything": "everything", + "arg.all_pokemon": "all pokemon", + "arg.all_items": "all items", "arg.any": "any", "arg.clean": "clean", "arg.edit": "edit", @@ -170,6 +241,7 @@ "arg.list": "list", "arg.add": "add", "arg.show": "show", + "arg.default": "default", "arg.overview": "overview", "arg.dryrun": "dryrun", "arg.reset": "reset", @@ -182,6 +254,7 @@ "arg.shiny": "shiny", "arg.gmax": "gmax", "arg.stardust": "stardust", + "arg.pokecoin": "pokecoins", "arg.energy": "energy", "arg.candy": "candy", "arg.pvp": "pvp", @@ -248,7 +321,10 @@ "arg.prefix.maxsize": "maxsize", "arg.prefix.gen": "gen", "arg.prefix.cap": "cap", + "arg.mega": "mega", + "arg.prefix.mega": "mega", "arg.prefix.form": "form", + "arg.prefix.costume": "costume", "arg.prefix.template": "template", "arg.prefix.gym": "gym", "arg.prefix.move": "move", @@ -263,13 +339,17 @@ "arg.prefix.littlehigh": "littlehigh", "arg.prefix.littlecp": "littlecp", "arg.prefix.stardust": "stardust", + "arg.prefix.pokecoin": "pokecoins", "arg.prefix.energy": "energy", "arg.prefix.candy": "candy", + "arg.prefix.amount": "amount", "arg.prefix.name": "name", "arg.prefix.user": "user", "arg.prefix.channel": "channel", "arg.prefix.guild": "guild", "arg.prefix.language": "language", + "arg.prefix.area": "area", + "arg.prefix.location": "location", "arg.prefix.mon": "mon", "arg.prefix.tue": "tue", "arg.prefix.wed": "wed", @@ -323,21 +403,26 @@ "section.maxbattles.none": "マックスバトルを追跡していません", "msg.no_pokemon": "ポケモンが指定されていません", "msg.form_not_found": "Form `{0}` not recognised. Use `{1}info ` to see available forms.", + "msg.costume_not_found": "Costume `{0}` not recognised. Use `{1}info costumes` to see available costumes.", + "msg.no_costume": "no costume", "msg.nothing_to_remove": "削除する項目がありません", "msg.no_levels": "レベルが指定されていません", "msg.no_egg_levels": "タマゴのレベルが指定されていません", "msg.no_raid_target": "レイドのレベルまたはポケモンが指定されていません", "msg.no_lure_type": "ルアータイプが指定されていません", "msg.no_quest_type": "タスクタイプが指定されていません", + "msg.quest.amount_not_applicable": "`amount:N` doesn't apply to pokemon quests — pokemon rewards have no minimum amount.", + "msg.quest.bulk_not_permitted": "You do not have permission to track all pokemon or items at once. Track specific rewards instead.", "msg.removed_n": "{0} 件の追跡ルールを削除しました", "msg.egg.usage": "有効なコマンド例: `{0}egg level:5`、`{0}egg legendary`、`{0}egg remove everything`", "msg.raid.usage": "有効なコマンド例: `{0}raid level:5`、`{0}raid pikachu`、`{0}raid remove everything`", "msg.track.usage": "有効なコマンド例: `{0}track pikachu iv:100`、`{0}track everything iv:90`、`{0}track remove pikachu`", "msg.track.everything_no_filters": "アラート数が多すぎます。候補数を絞るための追加フィルターが必要です。", "msg.track.invalid_cap": "このレベル上限はサポートされていません。有効な値: {0}", - "msg.quest.usage": "有効なコマンド例: `{0}quest pikachu`、`{0}quest stardust:1000`、`{0}quest energy:charizard`", + "msg.track.no_mega_form": "⚠️ {0} has no Mega {1} form — this PVP rule will never match.", + "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest pokecoins:10`, `{0}quest energy:charizard`", "msg.quest.edit_summary_conflict": "`edit` and `summary` are mutually exclusive — pick one.", - "msg.summary.usage": "Usage: `{0}summary quest [settime |cleartime|now]`", + "msg.summary.usage": "Valid commands are `{0}summary quest`, `{0}summary quest settime `, `{0}summary quest cleartime`, `{0}summary quest now`", "msg.summary.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.summary.no_schedule": "No schedule set for {0} summaries.", "msg.summary.scheduled": "Schedule for {0} summaries: {1}", @@ -360,11 +445,33 @@ "msg.nest.usage": "有効なコマンド例: `{0}nest pikachu`、`{0}nest everything`、`{0}nest remove pikachu`", "msg.maxbattle.usage": "有効なコマンド例: `{0}maxbattle pikachu`、`{0}maxbattle level:3`、`{0}maxbattle remove everything`", "msg.fort.usage": "有効なコマンド例: `{0}fort pokestop`、`{0}fort everything`、`{0}fort remove pokestop`", - "msg.location.removed": "位置を削除しました", - "msg.location.usage": "有効なコマンド例: `{0}location <緯度>,<経度>`、`{0}location <住所>`", + "msg.location.removed": "✅ Removed saved location `{0}`.", + "msg.location.usage": "Valid commands are `{0}location `, `{0}location add `, `{0}location list`, `{0}location show `, `{0}location remove `, `{0}location remove default`", "msg.location.specify": "座標または住所を指定してください", "msg.location.set": "位置を {0},{1} に設定しました", "msg.location.current": "Your current location is {0},{1}", + "msg.location.added": "✅ Saved location `{0}` at {1}, {2}.", + "msg.location.duplicate": "🙅 You already have a saved location called `{0}`. Remove it first with `{1}location remove {0}`.", + "msg.location.list_header": "Your saved locations:", + "msg.location.list_row": " `{0}`: {1}, {2}", + "msg.location.list_row_with_addr": " `{0}`: {1}, {2} — {3}", + "msg.location.list_empty": "You have no saved locations. Add one with `{0}location add `.", + "msg.location.show_not_found": "🙅 No saved location called `{0}`.", + "msg.location.show": "📍 `{0}` is at {1}, {2}.", + "msg.location.show_with_addr": "📍 `{0}` is at {1}, {2} — {3}", + "msg.location.no_default": "🙅 No default location set.", + "msg.location.default_removed": "✅ Cleared your default location.", + "msg.location.remove_referenced": "🙅 Cannot remove `{0}` — {1} tracking rule(s) reference it: {2}. Edit or remove those rules first.", + "msg.location.add_usage": "Valid commands are `{0}location add `", + "msg.location.show_usage": "Valid commands are `{0}location show `", + "msg.location.remove_usage": "Valid commands are `{0}location remove `, `{0}location remove default`", + "msg.location.geocode_failed": "🙅 Couldn't find a place matching `{0}`.", + "cmd.location.usage": "**{0}location** — manage your default location and saved named locations.\n\n• `{0}location` — show your current default location\n• `{0}location ` — set your default location\n• `{0}location add ` — save a named location (referenced later as `location:` on tracking rules)\n• `{0}location list` — list all your saved locations\n• `{0}location show ` — show one saved location's coords + address (use `default` for your default)\n• `{0}location remove ` — delete a saved location (refuses if any tracking rule references it)\n• `{0}location remove default` — clear your default location", + "msg.override.requires_distance": "🙅 `location:` needs a `d:` distance — e.g. `location:Home d:500`.", + "msg.override.area_and_distance": "🙅 `area:` and `d:` are mutually exclusive (area-mode vs distance-mode). Pick one.", + "msg.override.area_and_location": "🙅 `area:` and `location:` are mutually exclusive. Pick one.", + "msg.override.unknown_location": "🙅 No saved location called `{0}`. Add it with `{1}location add {0} `.", + "msg.override.area_not_permitted": "🙅 Area `{0}` is not in your allowed areas. Use `{1}area list` to see what you can pick.", "msg.area.usage": "Valid commands are `{0}area list`, `{0}area add `, `{0}area remove `", "msg.area.none_available": "利用可能なエリアがありません", "msg.area.available": "**利用可能なエリア:**", @@ -382,14 +489,14 @@ "msg.profile.deleted": "プロファイル {0} を削除しました", "msg.profile.not_found": "プロファイルが見つかりません", "msg.profile.cannot_delete_1": "プロファイル 1 は削除できません", - "msg.profile.hours_usage": "使用法: profile hours <プロファイル番号> ", + "msg.profile.hours_usage": "Valid commands are `{0}profile hours `", "msg.profile.hours_invalid_json": "有効時間の JSON が無効です", "msg.profile.hours_set": "プロファイル {0} の有効時間を更新しました", "msg.profile.hours_cleared": "Active hours cleared for profile {0}", - "msg.profile.settime_usage": "使用法: profile settime mon09:00 tue18:30 weekday09:00 weekend10:00", + "msg.profile.settime_usage": "Valid commands are `{0}profile settime mon09:00 tue18:30 weekday09:00 weekend10:00`", "msg.profile.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.profile.copied": "現在のプロファイルを {0} にコピーしました", - "msg.profile.copyto_usage": "使用法: profile copyto <名前|all>", + "msg.profile.copyto_usage": "Valid commands are `{0}profile copyto `", "msg.profile.copy_invalid": "これらのプロファイルは無効でした: {0}", "msg.profile.usage": "有効なコマンド: `{0}profile <名前>`、`{0}profile list`、`{0}profile add <名前>`、`{0}profile remove <名前>`、`{0}profile settime <時間指定>`、`{0}profile copyto <名前>`", "msg.profile.list_header": "現在設定されているプロファイル:", @@ -407,6 +514,7 @@ "msg.weather.unavailable": "このコマンドでは天気追跡はまだ利用できません", "msg.help.unknown_topic": "'{0}' のヘルプはありません。一般的なヘルプは `{1}help` を使用してください。", "msg.help.no_greeting": "ヘルプテンプレートが設定されていません。コマンド別ヘルプは `{0}help <コマンド>` を使用してください。", + "msg.help.see_detailed": "💡 More detailed help is available — `{0}help {1}`", "msg.info.sub.moves": "技", "msg.info.sub.items": "アイテム", "msg.info.sub.shiny": "色違い", @@ -417,9 +525,19 @@ "msg.info.sub.translate": "翻訳", "msg.info.sub.dts": "dts", "msg.info.sub.templates": "テンプレート", - "msg.info.usage": "有効なコマンド: `{0}info templates`、`{0}info rarity`、`{0}info shiny`、`{0}info weather`、`{0}info moves`、`{0}info items`、`{0}info <ポケモン>`", + "msg.info.sub.costumes": "costumes", + "msg.info.sub.forms": "forms", + "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info costumes`, `{0}info `", "msg.info.usage_admin": "Admin: `{0}info poracle`, `{0}info dts`, `{0}info translate `, `{0}info config [search]`", "msg.info.available_forms": "利用可能なフォーム:", + "msg.info.more_forms": "More than {0} forms — do {1} for the full list", + "msg.info.recent_forms": "**Recently-seen forms:**", + "msg.info.recent_raid_forms": "**Recently-seen raid forms:**", + "msg.info.available_costumes": "**Recently-seen costumes:**", + "msg.info.recent_raid_costumes": "**Recently-seen raid costumes:**", + "msg.info.costumes.header": "**Costumes** (`costume:` to track):", + "msg.info.no_costume_data": "No costume data loaded", + "msg.info.no_form_data": "No form data for that pokemon.", "msg.info.hundo_cp": "100% IV CP:", "msg.info.dts_summary": "読み込まれた DTS テンプレート:", "msg.info.pokemon_not_found": "ポケモンが見つかりません: {0}", @@ -534,5 +652,661 @@ "language.sv": "スウェーデン語", "language.zh-cn": "中国語(簡体字)", "language.ja": "日本語", - "msg.help.text": "**利用可能なコマンド:**\n{0}track <ポケモン> [iv:N] [cp:N] [level:N] [d:N] — ポケモンを追跡\n{0}untrack <ポケモン> — ポケモンの追跡を解除\n{0}raid <ポケモン|level:N|legendary> [d:N] — レイドを追跡\n{0}egg [d:N] — タマゴを追跡\n{0}quest <ポケモン|stardust|energy:ポケモン|candy:ポケモン> — タスクを追跡\n{0}invasion [everything|<タイプ>] — 襲撃を追跡\n{0}lure <タイプ|everything> — ルアーを追跡\n{0}gym <チーム|everything> [slot_changes] — ジムを追跡\n{0}nest <ポケモン|everything> — 巣を追跡\n{0}maxbattle <ポケモン|level:N> — マックスバトルを追跡\n{0}fort — フォート更新を追跡\n{0}tracked — 追跡を表示\n{0}script — 追跡をコマンドとしてエクスポート\n{0}area [list|add|remove] — エリアを管理\n{0}location <緯度,経度> — 位置を設定\n{0}profile [list|add|remove|switch] — プロファイルを管理\n{0}language <コード> — 言語を設定\n{0}start / {0}stop — アラートの有効化/無効化\n{0}version — バージョン表示" + "slash.cmd.version": "version", + "slash.desc.version": "Show Poracle version", + "slash.cmd.tracked": "tracked", + "slash.cmd.help": "help", + "slash.cmd.info": "info", + "slash.cmd.language": "language", + "slash.cmd.track": "track", + "slash.cmd.raid": "raid", + "slash.cmd.egg": "egg", + "slash.cmd.quest": "quest", + "slash.cmd.invasion": "invasion", + "slash.cmd.incident": "incident", + "slash.cmd.lure": "lure", + "slash.cmd.nest": "nest", + "slash.cmd.maxbattle": "maxbattle", + "slash.cmd.gym": "gym", + "slash.cmd.fort": "fort", + "slash.cmd.untrack": "untrack", + "slash.cmd.area": "area", + "slash.cmd.profile": "profile", + "slash.cmd.location": "location", + "slash.cmd.summary": "summary", + "slash.cmd.start": "start", + "slash.cmd.stop": "stop", + "slash.desc.tracked": "List your tracking rules", + "slash.desc.start": "Resume alert delivery (after /stop)", + "slash.desc.stop": "Pause alert delivery (resume with /start)", + "slash.desc.help": "Show help", + "slash.desc.info": "Look up pokemon info, shiny rates, rarity tiers, or current weather", + "slash.opt.info.pokemon": "pokemon", + "slash.opt.info.pokemon.desc": "Show types, stats, evolutions, weather boost and CP table for a pokemon", + "slash.opt.info.pokemon.name": "name", + "slash.opt.info.pokemon.name.desc": "Pokemon name (any supported language) or dex id", + "slash.opt.info.rarity": "rarity", + "slash.opt.info.rarity.desc": "List pokemon by spawn rarity tier (common → ultra-rare)", + "slash.opt.info.shiny": "shiny", + "slash.opt.info.shiny.desc": "Show observed shiny rates per species", + "slash.opt.info.weather": "weather", + "slash.opt.info.weather.desc": "Show current weather and boosted types for a location", + "slash.opt.info.weather.coords": "coords", + "slash.opt.info.weather.coords.desc": "lat,lon (defaults to your saved location)", + "slash.desc.language": "Show or set your language", + "slash.desc.track": "Track a Pokemon", + "slash.desc.raid": "Track a raid boss or raid level", + "slash.desc.egg": "Track an egg / raid level", + "slash.desc.quest": "Track a quest reward", + "slash.desc.invasion": "Track a Team Rocket invasion", + "slash.desc.incident": "Track a pokestop incident (Kecleon, Gold Pokestop, Showcase…)", + "slash.desc.lure": "Track a pokestop lure", + "slash.desc.nest": "Track a nesting pokemon", + "slash.desc.maxbattle": "Track a max (Dynamax) battle", + "slash.desc.gym": "Track gym team / slot / battle changes", + "slash.desc.fort": "Track pokestop or gym updates", + "slash.desc.untrack": "Remove a tracking rule", + "slash.desc.area": "Manage your areas", + "slash.desc.profile": "Manage your profiles", + "slash.desc.location": "Manage your saved locations", + "slash.desc.summary": "Manage scheduled summary digests (e.g. quest)", + "slash.opt.help.topic": "topic", + "slash.opt.help.topic.desc": "Help topic", + "slash.opt.language.code": "code", + "slash.opt.language.code.desc": "Language code", + "slash.opt.track.pokemon": "pokemon", + "slash.opt.track.pokemon.desc": "Pokemon to track (or 'everything')", + "slash.opt.track.iv": "iv", + "slash.opt.track.iv.desc": "IV filter (e.g. 100, 95, 0-0)", + "slash.opt.track.distance": "distance", + "slash.opt.track.distance.desc": "Alert radius in metres", + "slash.opt.track.great_rank": "great_rank", + "slash.opt.track.great_rank.desc": "Top PVP rank in the Great League", + "slash.opt.track.ultra_rank": "ultra_rank", + "slash.opt.track.ultra_rank.desc": "Top PVP rank in the Ultra League", + "slash.opt.track.little_rank": "little_rank", + "slash.opt.track.little_rank.desc": "Top PVP rank in the Little League", + "slash.opt.track.clean": "clean", + "slash.opt.track.clean.desc": "Auto-delete the alert when the pokemon despawns", + "slash.opt.track.template": "template", + "slash.opt.track.template.desc": "DTS template name", + "slash.opt.track.form": "form", + "slash.opt.track.form.desc": "Pokemon form", + "slash.opt.track.size": "size", + "slash.opt.track.size.desc": "Pokemon size class", + "slash.choice.track.clean.yes": "Yes", + "slash.choice.track.size.all": "All sizes", + "slash.choice.track.size.xxs": "XXS", + "slash.choice.track.size.xs": "XS", + "slash.choice.track.size.m": "M", + "slash.choice.track.size.xl": "XL", + "slash.choice.track.size.xxl": "XXL", + "slash.opt.raid.boss": "boss", + "slash.opt.raid.boss.desc": "Raid boss pokemon", + "slash.opt.raid.level": "level", + "slash.opt.raid.level.desc": "Raid level", + "slash.opt.raid.team": "team", + "slash.opt.raid.team.desc": "Required gym-control team", + "slash.opt.raid.distance": "distance", + "slash.opt.raid.distance.desc": "Alert radius in metres", + "slash.opt.raid.clean": "clean", + "slash.opt.raid.clean.desc": "Auto-delete the alert when the raid expires", + "slash.opt.raid.template": "template", + "slash.opt.raid.template.desc": "DTS template name", + "slash.choice.raid.clean.yes": "Yes", + "slash.choice.raid.level.1": "Tier 1", + "slash.choice.raid.level.3": "Tier 3", + "slash.choice.raid.level.5": "Tier 5", + "slash.choice.raid.level.6": "Tier 6", + "slash.choice.raid.level.mega": "Mega", + "slash.choice.raid.level.legendary": "Legendary", + "slash.choice.raid.level.shadow1": "Shadow Tier 1", + "slash.choice.raid.level.shadow3": "Shadow Tier 3", + "slash.choice.raid.level.shadow5": "Shadow Tier 5", + "slash.choice.raid.level.ultra beast": "Ultra Beast", + "slash.choice.raid.level.everything": "Everything", + "slash.choice.raid.team.0": "Harmony", + "slash.choice.raid.team.1": "Mystic", + "slash.choice.raid.team.2": "Valor", + "slash.choice.raid.team.3": "Instinct", + "slash.opt.egg.level": "level", + "slash.opt.egg.level.desc": "Egg / raid level", + "slash.opt.egg.team": "team", + "slash.opt.egg.team.desc": "Required gym-control team", + "slash.opt.egg.distance": "distance", + "slash.opt.egg.distance.desc": "Alert radius in metres", + "slash.opt.egg.clean": "clean", + "slash.opt.egg.clean.desc": "Auto-delete the alert when the egg hatches", + "slash.opt.egg.template": "template", + "slash.opt.egg.template.desc": "DTS template name", + "slash.choice.egg.clean.yes": "Yes", + "slash.choice.egg.level.1": "Tier 1", + "slash.choice.egg.level.3": "Tier 3", + "slash.choice.egg.level.5": "Tier 5", + "slash.choice.egg.level.6": "Tier 6", + "slash.choice.egg.level.mega": "Mega", + "slash.choice.egg.level.legendary": "Legendary", + "slash.choice.egg.level.shadow1": "Shadow Tier 1", + "slash.choice.egg.level.shadow3": "Shadow Tier 3", + "slash.choice.egg.level.shadow5": "Shadow Tier 5", + "slash.choice.egg.level.ultra beast": "Ultra Beast", + "slash.choice.egg.level.everything": "Everything", + "slash.choice.egg.team.0": "Harmony", + "slash.choice.egg.team.1": "Mystic", + "slash.choice.egg.team.2": "Valor", + "slash.choice.egg.team.3": "Instinct", + "slash.opt.quest.pokemon": "pokemon", + "slash.opt.quest.pokemon.desc": "Pokemon reward", + "slash.opt.quest.item": "item", + "slash.opt.quest.item.desc": "Item reward (e.g. golden razz berry)", + "slash.opt.quest.stardust": "stardust", + "slash.opt.quest.stardust.desc": "Stardust reward (minimum amount)", + "slash.opt.quest.candy": "candy", + "slash.opt.quest.candy.desc": "Candy reward pokemon", + "slash.opt.quest.mega_energy": "mega_energy", + "slash.opt.quest.mega_energy.desc": "Mega energy reward pokemon", + "slash.opt.quest.min_amount": "min_amount", + "slash.opt.quest.min_amount.desc": "Minimum reward amount (item / candy / mega_energy only)", + "slash.opt.quest.distance": "distance", + "slash.opt.quest.distance.desc": "Alert radius in metres", + "slash.opt.quest.clean": "clean", + "slash.opt.quest.clean.desc": "Auto-delete the alert when the quest is completed", + "slash.opt.quest.summary": "summary", + "slash.opt.quest.summary.desc": "Buffer matches and dispatch in a scheduled batch instead of alerting immediately", + "slash.opt.quest.template": "template", + "slash.opt.quest.template.desc": "DTS template name", + "slash.choice.quest.clean.yes": "Yes", + "slash.choice.quest.summary.yes": "Yes", + "slash.opt.invasion.grunt_type": "grunt_type", + "slash.opt.invasion.grunt_type.desc": "Grunt type (Fire, Water…), boss (Giovanni…), or incident (Kecleon…)", + "slash.opt.invasion.gender": "gender", + "slash.opt.invasion.gender.desc": "Filter by grunt gender", + "slash.opt.invasion.distance": "distance", + "slash.opt.invasion.distance.desc": "Alert radius in metres", + "slash.opt.invasion.clean": "clean", + "slash.opt.invasion.clean.desc": "Auto-delete the alert when the invasion expires", + "slash.opt.invasion.template": "template", + "slash.opt.invasion.template.desc": "DTS template name", + "slash.choice.invasion.clean.yes": "Yes", + "slash.choice.invasion.gender.male": "Male", + "slash.choice.invasion.gender.female": "Female", + "slash.choice.invasion.gender.genderless": "Genderless", + "slash.opt.incident.type": "type", + "slash.opt.incident.type.desc": "Pokestop incident type (Kecleon, Gold Pokestop, Showcase…)", + "slash.opt.incident.distance": "distance", + "slash.opt.incident.distance.desc": "Alert radius in metres", + "slash.opt.incident.clean": "clean", + "slash.opt.incident.clean.desc": "Auto-delete the alert when the incident expires", + "slash.opt.incident.template": "template", + "slash.opt.incident.template.desc": "DTS template name", + "slash.choice.incident.clean.yes": "Yes", + "slash.opt.lure.lure_type": "lure_type", + "slash.opt.lure.lure_type.desc": "Lure type", + "slash.opt.lure.distance": "distance", + "slash.opt.lure.distance.desc": "Alert radius in metres", + "slash.opt.lure.clean": "clean", + "slash.opt.lure.clean.desc": "Auto-delete the alert when the lure expires", + "slash.opt.lure.template": "template", + "slash.opt.lure.template.desc": "DTS template name", + "slash.choice.lure.clean.yes": "Yes", + "slash.choice.lure.lure_type.normal": "Normal", + "slash.choice.lure.lure_type.glacial": "Glacial", + "slash.choice.lure.lure_type.mossy": "Mossy", + "slash.choice.lure.lure_type.magnetic": "Magnetic", + "slash.choice.lure.lure_type.rainy": "Rainy", + "slash.choice.lure.lure_type.sparkly": "Sparkly", + "slash.opt.nest.pokemon": "pokemon", + "slash.opt.nest.pokemon.desc": "Nesting pokemon", + "slash.opt.nest.min_spawn_avg": "min_spawn_avg", + "slash.opt.nest.min_spawn_avg.desc": "Minimum spawns per hour", + "slash.opt.nest.distance": "distance", + "slash.opt.nest.distance.desc": "Alert radius in metres", + "slash.opt.nest.clean": "clean", + "slash.opt.nest.clean.desc": "Auto-delete the alert when the nest expires", + "slash.opt.nest.template": "template", + "slash.opt.nest.template.desc": "DTS template name", + "slash.choice.nest.clean.yes": "Yes", + "slash.opt.maxbattle.pokemon": "pokemon", + "slash.opt.maxbattle.pokemon.desc": "Max battle pokemon", + "slash.opt.maxbattle.level": "level", + "slash.opt.maxbattle.level.desc": "Battle level (1..6)", + "slash.opt.maxbattle.gmax": "gmax", + "slash.opt.maxbattle.gmax.desc": "Gigantamax only", + "slash.opt.maxbattle.distance": "distance", + "slash.opt.maxbattle.distance.desc": "Alert radius in metres", + "slash.opt.maxbattle.clean": "clean", + "slash.opt.maxbattle.clean.desc": "Auto-delete the alert when the battle ends", + "slash.opt.maxbattle.template": "template", + "slash.opt.maxbattle.template.desc": "DTS template name", + "slash.choice.maxbattle.clean.yes": "Yes", + "slash.choice.maxbattle.level.1": "Level 1", + "slash.choice.maxbattle.level.2": "Level 2", + "slash.choice.maxbattle.level.3": "Level 3", + "slash.choice.maxbattle.level.4": "Level 4", + "slash.choice.maxbattle.level.5": "Level 5", + "slash.choice.maxbattle.level.6": "Level 6", + "slash.opt.gym.team": "team", + "slash.opt.gym.team.desc": "Gym-control team to alert on", + "slash.opt.gym.slot_changes": "slot_changes", + "slash.opt.gym.slot_changes.desc": "Alert on slot composition changes", + "slash.opt.gym.battle_changes": "battle_changes", + "slash.opt.gym.battle_changes.desc": "Alert on battle state changes", + "slash.opt.gym.distance": "distance", + "slash.opt.gym.distance.desc": "Alert radius in metres", + "slash.opt.gym.clean": "clean", + "slash.opt.gym.clean.desc": "Auto-delete the alert when the gym state changes", + "slash.opt.gym.template": "template", + "slash.opt.gym.template.desc": "DTS template name", + "slash.choice.gym.clean.yes": "Yes", + "slash.choice.gym.team.0": "Harmony", + "slash.choice.gym.team.1": "Mystic", + "slash.choice.gym.team.2": "Valor", + "slash.choice.gym.team.3": "Instinct", + "slash.opt.fort.fort_type": "fort_type", + "slash.opt.fort.fort_type.desc": "Fort type to track", + "slash.opt.fort.include_empty": "include_empty", + "slash.opt.fort.include_empty.desc": "Alert on empty/unowned forts", + "slash.opt.fort.distance": "distance", + "slash.opt.fort.distance.desc": "Alert radius in metres", + "slash.opt.fort.clean": "clean", + "slash.opt.fort.clean.desc": "Auto-delete the alert when the fort changes again", + "slash.opt.fort.template": "template", + "slash.opt.fort.template.desc": "DTS template name", + "slash.choice.fort.clean.yes": "Yes", + "slash.choice.fort.fort_type.0": "Pokestop", + "slash.choice.fort.fort_type.1": "Gym", + "slash.opt.tracker.location": "location", + "slash.opt.tracker.location.desc": "Use a saved location instead of your default (requires distance:)", + "slash.opt.tracker.areas": "areas", + "slash.opt.tracker.areas.desc": "Restrict to specific areas (comma-separated)", + "slash.autocomplete.untrack.remove_all": "🗑️ Remove ALL rules of this type", + "slash.opt.untrack.pokemon": "pokemon", + "slash.opt.untrack.pokemon.desc": "Remove a pokemon tracking rule", + "slash.opt.untrack.pokemon.tracking": "tracking", + "slash.opt.untrack.pokemon.tracking.desc": "Pick from your existing pokemon tracking rules", + "slash.opt.untrack.raid": "raid", + "slash.opt.untrack.raid.desc": "Remove a raid tracking rule", + "slash.opt.untrack.raid.tracking": "tracking", + "slash.opt.untrack.raid.tracking.desc": "Pick from your existing raid tracking rules", + "slash.opt.untrack.egg": "egg", + "slash.opt.untrack.egg.desc": "Remove an egg tracking rule", + "slash.opt.untrack.egg.tracking": "tracking", + "slash.opt.untrack.egg.tracking.desc": "Pick from your existing egg tracking rules", + "slash.opt.untrack.quest": "quest", + "slash.opt.untrack.quest.desc": "Remove a quest tracking rule", + "slash.opt.untrack.quest.tracking": "tracking", + "slash.opt.untrack.quest.tracking.desc": "Pick from your existing quest tracking rules", + "slash.opt.untrack.invasion": "invasion", + "slash.opt.untrack.invasion.desc": "Remove an invasion tracking rule", + "slash.opt.untrack.invasion.tracking": "tracking", + "slash.opt.untrack.invasion.tracking.desc": "Pick from your existing invasion tracking rules", + "slash.opt.untrack.lure": "lure", + "slash.opt.untrack.lure.desc": "Remove a lure tracking rule", + "slash.opt.untrack.lure.tracking": "tracking", + "slash.opt.untrack.lure.tracking.desc": "Pick from your existing lure tracking rules", + "slash.opt.untrack.nest": "nest", + "slash.opt.untrack.nest.desc": "Remove a nest tracking rule", + "slash.opt.untrack.nest.tracking": "tracking", + "slash.opt.untrack.nest.tracking.desc": "Pick from your existing nest tracking rules", + "slash.opt.untrack.gym": "gym", + "slash.opt.untrack.gym.desc": "Remove a gym tracking rule", + "slash.opt.untrack.gym.tracking": "tracking", + "slash.opt.untrack.gym.tracking.desc": "Pick from your existing gym tracking rules", + "slash.opt.untrack.fort": "fort", + "slash.opt.untrack.fort.desc": "Remove a fort tracking rule", + "slash.opt.untrack.fort.tracking": "tracking", + "slash.opt.untrack.fort.tracking.desc": "Pick from your existing fort tracking rules", + "slash.opt.untrack.maxbattle": "maxbattle", + "slash.opt.untrack.maxbattle.desc": "Remove a maxbattle tracking rule", + "slash.opt.untrack.maxbattle.tracking": "tracking", + "slash.opt.untrack.maxbattle.tracking.desc": "Pick from your existing maxbattle tracking rules", + "slash.opt.area.add": "add", + "slash.opt.area.add.desc": "Add an area to your tracking", + "slash.opt.area.add.area": "area", + "slash.opt.area.add.area.desc": "Area to add", + "slash.opt.area.remove": "remove", + "slash.opt.area.remove.desc": "Remove an area from your tracking", + "slash.opt.area.remove.area": "area", + "slash.opt.area.remove.area.desc": "Area to remove", + "slash.opt.area.show": "show", + "slash.opt.area.show.desc": "Show your selected areas", + "slash.opt.area.list": "list", + "slash.opt.area.list.desc": "List every area available to you (✓ = already added)", + "slash.opt.area.overview": "overview", + "slash.opt.area.overview.desc": "Map overview of every area available to you", + "slash.opt.profile.list": "list", + "slash.opt.profile.list.desc": "List your profiles", + "slash.opt.profile.change": "change", + "slash.opt.profile.change.desc": "Switch active profile", + "slash.opt.profile.change.name": "name", + "slash.opt.profile.change.name.desc": "Profile name", + "slash.opt.profile.create": "create", + "slash.opt.profile.create.desc": "Create a new profile", + "slash.opt.profile.create.name": "name", + "slash.opt.profile.create.name.desc": "Profile name", + "slash.opt.profile.delete": "delete", + "slash.opt.profile.delete.desc": "Delete a profile", + "slash.opt.profile.delete.name": "name", + "slash.opt.profile.delete.name.desc": "Profile name", + "slash.opt.profile.settime": "settime", + "slash.opt.profile.settime.desc": "Set active-hours for the current profile", + "slash.opt.profile.settime.times": "times", + "slash.opt.profile.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.profile.cleartime": "cleartime", + "slash.opt.profile.cleartime.desc": "Clear active-hours from the current profile", + "slash.opt.profile.copyto": "copyto", + "slash.opt.profile.copyto.desc": "Copy this profile's tracking to another profile", + "slash.opt.profile.copyto.profile": "profile", + "slash.opt.profile.copyto.profile.desc": "Target profile name or number", + "slash.opt.location.add": "add", + "slash.opt.location.add.desc": "Save a named location", + "slash.opt.location.add.name": "name", + "slash.opt.location.add.name.desc": "Short name for this location (e.g. Home)", + "slash.opt.location.add.place": "place", + "slash.opt.location.add.place.desc": "Coordinates (lat,lon) or a place name", + "slash.opt.location.list": "list", + "slash.opt.location.list.desc": "List your saved locations", + "slash.opt.location.show": "show", + "slash.opt.location.show.desc": "Show one saved location", + "slash.opt.location.show.name": "name", + "slash.opt.location.show.name.desc": "Saved-location name", + "slash.opt.location.remove": "remove", + "slash.opt.location.remove.desc": "Remove a saved location", + "slash.opt.location.remove.name": "name", + "slash.opt.location.remove.name.desc": "Saved-location name (or \"default\" to clear your default location)", + "slash.opt.location.set-default": "set-default", + "slash.opt.location.set-default.desc": "Set your default location", + "slash.opt.location.set-default.place": "place", + "slash.opt.location.set-default.place.desc": "Coordinates (lat,lon) or address to set as your default location", + "slash.opt.location.remove-default": "remove-default", + "slash.opt.location.remove-default.desc": "Clear your default location", + "slash.opt.summary.quest": "quest", + "slash.opt.summary.quest.desc": "Manage quest-summary buffering", + "slash.opt.summary.quest.show": "show", + "slash.opt.summary.quest.show.desc": "Show schedule and current buffer count", + "slash.opt.summary.quest.settime": "settime", + "slash.opt.summary.quest.settime.desc": "Set the active-hours schedule for the quest summary", + "slash.opt.summary.quest.settime.times": "times", + "slash.opt.summary.quest.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.summary.quest.cleartime": "cleartime", + "slash.opt.summary.quest.cleartime.desc": "Clear the active-hours schedule", + "slash.opt.summary.quest.now": "now", + "slash.opt.summary.quest.now.desc": "Force-dispatch the currently-buffered quests", + "error.slash.unregistered_with_channel": "🛑 You need to register first. DM me with !poracle, or run !poracle in {0}.", + "error.slash.unregistered_dm_only": "🛑 You need to register first. DM me with !poracle.", + "error.slash.track.no_pokemon": "Please specify a Pokemon to track.", + "error.slash.raid.need_boss_or_level": "Please specify either a boss or a level.", + "error.slash.raid.boss_and_level": "Please specify either a boss OR a level, not both.", + "error.slash.egg.no_level": "Please specify an egg level.", + "error.slash.quest.no_reward": "Please specify exactly one reward type (pokemon, item, stardust, candy, or mega_energy).", + "error.slash.quest.exactly_one_reward": "Please specify exactly one reward type, not multiple: {0}.", + "error.slash.quest.amount_not_applicable": "`min_amount` doesn't apply to pokemon quests. For stardust, both `stardust` and `min_amount` end up in the same field — pick whichever reads better.", + "error.slash.invasion.no_grunt": "Please specify a grunt type.", + "error.slash.incident.no_type": "Please specify an incident type.", + "error.slash.lure.no_type": "Please specify a lure type.", + "error.slash.nest.no_pokemon": "Please specify a Pokemon for the nest.", + "error.slash.maxbattle.no_pokemon": "Please specify a Pokemon for the max battle.", + "error.slash.fort.no_type": "Please specify a fort type (pokestop or gym).", + "error.slash.untrack.no_subcommand": "Please choose what kind of tracking rule to remove.", + "error.slash.untrack.no_tracking": "Please pick a tracking rule to remove.", + "error.slash.info.no_subcommand": "Please choose an info sub-command (pokemon / rarity / shiny / weather).", + "error.slash.info.no_pokemon": "Please specify a pokemon name or dex id.", + "error.slash.info.unknown_subcommand": "Unknown info sub-command.", + "error.slash.area.no_subcommand": "Please choose an area sub-command (add / remove / show).", + "error.slash.area.no_area": "Please specify an area name.", + "error.slash.area.unknown_subcommand": "Unknown area sub-command.", + "error.slash.profile.no_subcommand": "Please choose a profile sub-command (list / change / create / delete / settime / cleartime / copyto).", + "error.slash.profile.no_name": "Please specify a profile name.", + "error.slash.profile.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.profile.no_target": "Please specify a target profile to copy to.", + "error.slash.profile.unknown_subcommand": "Unknown profile sub-command.", + "error.slash.summary.no_alert_type": "Please choose an alert type (e.g. quest).", + "error.slash.summary.no_action": "Please choose an action (show / settime / cleartime / now).", + "error.slash.summary.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.summary.unknown_action": "Unknown summary action.", + "error.slash.location.no_subcommand": "Please choose a location sub-command (add / list / show / remove / remove-default).", + "error.slash.location.no_name": "Please specify a saved-location name.", + "error.slash.location.empty": "Please specify coordinates or a place name.", + "error.slash.location.unknown_subcommand": "Unknown location sub-command.", + "error.slash.location.no_geocoder": "Place-name lookup is not configured. Please provide coordinates like 51.28, 1.08.", + "error.slash.location.geocode_failed": "Could not find a location for \"{0}\".", + "msg.help.text": "**利用可能なコマンド:**\n{0}track <ポケモン> [iv:N] [cp:N] [level:N] [d:N] — ポケモンを追跡\n{0}untrack <ポケモン> — ポケモンの追跡を解除\n{0}raid <ポケモン|level:N|legendary> [d:N] — レイドを追跡\n{0}egg [d:N] — タマゴを追跡\n{0}quest <ポケモン|stardust|energy:ポケモン|candy:ポケモン> — タスクを追跡\n{0}invasion [everything|<タイプ>] — 襲撃を追跡\n{0}lure <タイプ|everything> — ルアーを追跡\n{0}gym <チーム|everything> [slot_changes] — ジムを追跡\n{0}nest <ポケモン|everything> — 巣を追跡\n{0}maxbattle <ポケモン|level:N> — マックスバトルを追跡\n{0}fort — フォート更新を追跡\n{0}tracked — 追跡を表示\n{0}script — 追跡をコマンドとしてエクスポート\n{0}area [list|add|remove] — エリアを管理\n{0}location <緯度,経度> — 位置を設定\n{0}profile [list|add|remove|switch] — プロファイルを管理\n{0}language <コード> — 言語を設定\n{0}start / {0}stop — アラートの有効化/無効化\n{0}version — バージョン表示", + "cmd.poracle_admin": "poracle-admin", + "cmd.pa": "pa", + "cmd.poracle_admin.not_admin": "This command is reserved for administrators.", + "cmd.poracle_admin.unknown_group": "Unknown subgroup. Try `!poracle-admin` for the list.", + "cmd.poracle_admin.unknown_sub": "Unknown subcommand for `{0}`. Try `!poracle-admin {0}` to see what's available.", + "cmd.poracle_admin.help.admin_only": "This command is reserved for server administrators. Each subgroup performs a live operations task.", + "cmd.poracle_admin.help.groups": "Available subgroups:", + "cmd.poracle_admin.help_intro": "🛠️ Poracle Admin\n\nLive operations subgroups (administrators only):", + "cmd.poracle_admin.stub": "(not yet implemented)", + "cmd.poracle_admin.group.slash.desc": "slash-command registration lifecycle", + "cmd.poracle_admin.group.reload.desc": "reload DTS, geofence, or in-memory state", + "cmd.poracle_admin.group.emoji.desc": "list, reload, or test emoji config", + "cmd.poracle_admin.group.reconcile.desc": "Discord role reconciliation (immediate or per-user)", + "cmd.poracle_admin.group.cache.desc": "cache stats and clear", + "cmd.poracle_admin.group.ratelimit.desc": "inspect and reset alert-bucket rate limits", + "cmd.poracle_admin.group.summary.desc": "summary buffer inspection and forced dispatch", + "cmd.poracle_admin.group.status.desc": "live health snapshot", + "cmd.poracle_admin.group.maintenance.desc": "pause/resume outbound delivery", + "cmd.poracle_admin.group.config.desc": "view effective merged config with secrets redacted", + "cmd.poracle_admin.group.warnings.desc": "inspect captured WARN/ERROR log entries (startup + rolling buffers)", + "cmd.poracle_admin.reload.help.intro": "Reload runtime state from disk or database.", + "cmd.poracle_admin.reload.dts.desc": "`dts` — reload DTS templates and partials from disk", + "cmd.poracle_admin.reload.geofence.desc": "`geofence` — reload geofence files and refresh state", + "cmd.poracle_admin.reload.state.desc": "`state` — reload tracking rules and humans from MySQL (bypasses debounce)", + "cmd.poracle_admin.reload.dts.success": "✅ DTS reloaded in {0}ms ({1} templates)", + "cmd.poracle_admin.reload.geofence.success": "✅ Geofence reloaded in {0}ms ({1} fences, {2} tracking rules)", + "cmd.poracle_admin.reload.state.success": "✅ State reloaded in {0}ms ({1} tracking rules, {2} active humans)", + "cmd.poracle_admin.reload.error": "❌ Reload failed: {0}", + "cmd.poracle_admin.emoji.help.intro": "😀 Emoji config — inspect and manage emoji.json + Discord guild emojis.\n\nSubcommands:", + "cmd.poracle_admin.emoji.list.desc": "`list` — list all configured emoji keys with per-platform resolutions", + "cmd.poracle_admin.emoji.reload.desc": "`reload` — reload config/emoji.json from disk", + "cmd.poracle_admin.emoji.test.desc": "`test ` — resolve one emoji key for the current platform", + "cmd.poracle_admin.emoji.upload.desc": "`upload [overwrite]` — upload uicons-based emojis to the guild and write a new emoji.json (Discord-only)", + "cmd.poracle_admin.emoji.discord_config.desc": "`discord-config` — dump emoji.json from the current guild state, no uploads (Discord-only)", + "cmd.poracle_admin.emoji.discord_only": "ℹ️ This subcommand requires a Discord bot with guild access.", + "cmd.poracle_admin.emoji.not_loaded": "ℹ️ Emoji config not loaded (DTS renderer not configured).", + "cmd.poracle_admin.emoji.list.header": "😀 Emoji configuration — {0} keys loaded", + "cmd.poracle_admin.emoji.list.row.key": " {0}:", + "cmd.poracle_admin.emoji.list.row.platform": " {0}: {1}", + "cmd.poracle_admin.emoji.reload.success": "✅ Emoji config reloaded — {0} keys (took {1}ms).", + "cmd.poracle_admin.emoji.reload.error": "❌ Emoji reload failed: {0}", + "cmd.poracle_admin.emoji.test.success": "🔎 {0} on {1}: {2}", + "cmd.poracle_admin.emoji.test.not_found": "ℹ️ Emoji key \"{0}\" not found in the loaded config.", + "cmd.poracle_admin.emoji.test.usage": "Usage: !poracle-admin emoji test ", + "cmd.poracle_admin.reconcile.help.intro": "🔄 Discord role reconciliation — trigger immediately instead of waiting for the periodic timer.", + "cmd.poracle_admin.reconcile.run.desc": "`run` — reconcile all guild members now (blocks until complete)", + "cmd.poracle_admin.reconcile.user.desc": "`user ` — reconcile a single Discord user by snowflake ID", + "cmd.poracle_admin.reconcile.not_configured": "❌ Discord reconciliation is not configured (Telegram-only deploy, or check_role=false).", + "cmd.poracle_admin.reconcile.run.success": "✅ Discord reconciliation complete (took {0}ms).", + "cmd.poracle_admin.reconcile.run.error": "❌ Reconciliation failed: {0}", + "cmd.poracle_admin.reconcile.user.success": "✅ Reconciled discord:user/{0} (took {1}ms).", + "cmd.poracle_admin.reconcile.user.error": "❌ Failed to reconcile discord:user/{0}: {1}", + "cmd.poracle_admin.reconcile.user.usage": "Usage: !poracle-admin reconcile user ", + "cmd.poracle_admin.cache.help.intro": "🗺️ Geocoder cache — inspect counters or drop the in-memory layer.", + "cmd.poracle_admin.cache.stats.desc": "`stats` — geocoder cache stats", + "cmd.poracle_admin.cache.clear.desc": "`clear geocoder` — drop the in-memory geocoder cache", + "cmd.poracle_admin.cache.not_configured": "Geocoder cache is not configured on this instance.", + "cmd.poracle_admin.cache.stats.header": "🗺️ Geocoder cache", + "cmd.poracle_admin.cache.stats.row.memory_entries": " Memory entries: {0}", + "cmd.poracle_admin.cache.stats.row.disk_entries": " Disk entries: {0}", + "cmd.poracle_admin.cache.stats.row.hits_memory": " Hits (memory): {0}", + "cmd.poracle_admin.cache.stats.row.hits_disk": " Hits (disk): {0}", + "cmd.poracle_admin.cache.stats.row.misses": " Misses: {0}", + "cmd.poracle_admin.cache.stats.row.hit_rate": " Hit rate: {0}%", + "cmd.poracle_admin.cache.clear.usage_hint": "Specify what to clear, e.g. `!poracle-admin cache clear geocoder`", + "cmd.poracle_admin.cache.clear.geocoder.success": "✅ Geocoder memory cache cleared — {0} entries dropped (disk untouched).", + "cmd.poracle_admin.ratelimit.help.intro": "🚦 Rate-limit introspection — inspect or reset per-destination alert and summary buckets.", + "cmd.poracle_admin.ratelimit.not_configured": "ℹ️ Alert rate limiter is not configured on this instance.", + "cmd.poracle_admin.ratelimit.list.desc": "`list` — show all targets currently breached or banned", + "cmd.poracle_admin.ratelimit.show.desc": "`show ` — detailed state for one target (both buckets)", + "cmd.poracle_admin.ratelimit.reset.desc": "`reset ` — clear counters and violation history", + "cmd.poracle_admin.ratelimit.userlist.desc": "`userlist` — show currently disabled users (shortcut for !userlist disabled)", + "cmd.poracle_admin.ratelimit.list.empty": "🟢 No targets currently rate-limited.", + "cmd.poracle_admin.ratelimit.list.header_title": "Currently rate-limited targets", + "cmd.poracle_admin.ratelimit.list.bucket_header": " {0} bucket ({1} breached / {2} banned):", + "cmd.poracle_admin.ratelimit.list.row": "count {0}/{1}, {2}", + "cmd.poracle_admin.ratelimit.list.status.banned": "banned for {0}", + "cmd.poracle_admin.ratelimit.list.status.breached": "window resets in {0}", + "cmd.poracle_admin.ratelimit.show.header": "🚦 Rate-limit state for {0}", + "cmd.poracle_admin.ratelimit.show.bucket_header": "{0} bucket:", + "cmd.poracle_admin.ratelimit.show.empty": "🟢 No recorded activity for {0} in either bucket.", + "cmd.poracle_admin.ratelimit.show.no_data": "(no activity in this bucket)", + "cmd.poracle_admin.ratelimit.show.no_violations": "No violations.", + "cmd.poracle_admin.ratelimit.show.violations_count": "Violations (24h): {0}", + "cmd.poracle_admin.ratelimit.show.banned_until": "Banned until: {0} (in {1})", + "cmd.poracle_admin.ratelimit.show.status.under_limit": "under limit", + "cmd.poracle_admin.ratelimit.show.status.over_limit": "over limit", + "cmd.poracle_admin.ratelimit.show.row.count": " Count: {0} / {1} ({2})\n", + "cmd.poracle_admin.ratelimit.show.row.window": " Window: opened {0} ago, resets in {1}\n", + "cmd.poracle_admin.ratelimit.reset.success": "✅ Reset rate-limit state for {0} (cleared alert + summary buckets, violations reset).", + "cmd.poracle_admin.ratelimit.reset.no_state": "ℹ️ No rate-limit state to reset for {0}.", + "cmd.poracle_admin.ratelimit.reset.note": "Note: admin_disable is NOT touched. If the user was auto-disabled by the rate-limiter, they still need to !poracle to re-register.", + "cmd.poracle_admin.ratelimit.usage.show": "Usage: !poracle-admin ratelimit show ", + "cmd.poracle_admin.ratelimit.usage.reset": "Usage: !poracle-admin ratelimit reset ", + "cmd.poracle_admin.ratelimit.userlist.lookup_failed": "❌ Could not find !userlist command in the registry.", + "cmd.poracle_admin.summary.help.intro": "📦 Summary buffer — inspect who has quests buffered and force-dispatch on demand.", + "cmd.poracle_admin.summary.not_configured": "ℹ️ Summary buffer is not configured on this instance.", + "cmd.poracle_admin.summary.list.desc": "`list` — show all users with anything buffered", + "cmd.poracle_admin.summary.show.desc": "`show ` — inspect one user's buffered entries", + "cmd.poracle_admin.summary.fire.desc": "`fire [alertType]` — force-dispatch a user's buffer immediately", + "cmd.poracle_admin.summary.list.empty": "🟢 No users have anything buffered.", + "cmd.poracle_admin.summary.list.header": "📦 Summary buffer — {0} users with {1} buffered entries", + "cmd.poracle_admin.summary.list.user_header": " {0}", + "cmd.poracle_admin.summary.list.row": " {0}: {1} entries (next fires: {2})", + "cmd.poracle_admin.summary.list.next_fire.none": "n/a", + "cmd.poracle_admin.summary.show.header": "📦 Summary buffer for {0}", + "cmd.poracle_admin.summary.show.empty": "🟢 No buffered entries for {0}.", + "cmd.poracle_admin.summary.show.alert_type": " {0}: {1} entries", + "cmd.poracle_admin.summary.show.usage": "Usage: !poracle-admin summary show ", + "cmd.poracle_admin.summary.fire.success": "✅ Dispatched summary for {0} / {1} — {2} entries delivered.", + "cmd.poracle_admin.summary.fire.usage": "Usage: !poracle-admin summary fire [alertType]", + "cmd.poracle_admin.summary.show.reward_row": " Reward type {0}, reward {1}{2} — {3} stops", + "cmd.poracle_admin.summary.show.reward_more": " ... ({0} more reward groups)", + "cmd.poracle_admin.summary.show.form_suffix": " form {0}", + "cmd.poracle_admin.maintenance.help.intro": "🛠️ **!poracle-admin maintenance** — live control over outbound delivery.\n\nSubcommands:", + "cmd.poracle_admin.maintenance.no_dispatcher": "ℹ️ Dispatcher is not available on this instance.", + "cmd.poracle_admin.maintenance.no_reason": "(no reason given)", + "cmd.poracle_admin.maintenance.pause.desc": "`pause [reason...]` (alias: `start`) — halt outbound delivery (webhooks still ingest, match, render, and queue)", + "cmd.poracle_admin.maintenance.resume.desc": "`resume` (alias: `stop`) — lift a previous pause and drain queued jobs", + "cmd.poracle_admin.maintenance.status.desc": "`status` — show current paused/running state and queue depth", + "cmd.poracle_admin.maintenance.pause.new": "🔴 Outbound delivery paused: {0}", + "cmd.poracle_admin.maintenance.pause.detail": "Webhooks still ingest, match, render, and queue — the dispatcher holds them until !poracle-admin maintenance resume.", + "cmd.poracle_admin.maintenance.pause.already": "ℹ️ Already paused since {0} ({1} ago): {2}", + "cmd.poracle_admin.maintenance.resume.success": "🟢 Outbound delivery resumed (was paused for {0}: {1})", + "cmd.poracle_admin.maintenance.resume.detail": "Queued messages are draining.", + "cmd.poracle_admin.maintenance.resume.not_paused": "ℹ️ Not currently paused.", + "cmd.poracle_admin.maintenance.status.running": "🟢 Delivery is running.", + "cmd.poracle_admin.maintenance.status.paused": "🔴 PAUSED — {0} (for {1})", + "cmd.poracle_admin.maintenance.status.queued": "{0} jobs queued waiting (across all platforms — Discord {1}, Telegram {2})", + "cmd.poracle_admin.status.help.intro": "!poracle-admin status — current health snapshot. Add -v for verbose mode (per-route Discord detail, full webhook per-type breakdown).", + "cmd.poracle_admin.status.header": "🛠️ Poracle Admin — Status", + "cmd.poracle_admin.status.paused_banner": "🔴 PAUSED — {0} (since {1} ago)\n Outbound delivery is held. Webhooks still ingest and queue.", + "cmd.poracle_admin.status.value.na": "n/a", + "cmd.poracle_admin.status.value.none": "none", + "cmd.poracle_admin.status.section.build": "**Build / Uptime**", + "cmd.poracle_admin.status.section.webhooks": "**Webhooks**", + "cmd.poracle_admin.status.section.render_queue": "**Render queue**", + "cmd.poracle_admin.status.section.delivery": "**Delivery**", + "cmd.poracle_admin.status.section.discord_rate": "**Discord rate**", + "cmd.poracle_admin.status.section.telegram_rate": "**Telegram rate**", + "cmd.poracle_admin.status.section.alert_limits": "**Alert limits**", + "cmd.poracle_admin.status.section.summary_buffer": "**Summary buffer**", + "cmd.poracle_admin.status.label.summary_buffer_totals": "Entries: {0} across {1} bucket(s)", + "cmd.poracle_admin.status.label.summary_buffer_top": "Top users:", + "cmd.poracle_admin.status.label.summary_buffer_user_row": " {0} ({1}): {2} entries", + "cmd.poracle_admin.status.section.tracking": "**Tracking**", + "cmd.poracle_admin.status.section.mysql": "**MySQL**", + "cmd.poracle_admin.status.label.version": "Version: {0} (commit {1}, built {2})", + "cmd.poracle_admin.status.label.uptime": "Uptime: {0}", + "cmd.poracle_admin.status.label.webhooks_rate": "{0} / {1} / {2} per min over last 5/15/60 min", + "cmd.poracle_admin.status.label.webhooks_by_type": "By type (last 60 min):", + "cmd.poracle_admin.status.label.delivery_discord": "Discord in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_telegram": "Telegram in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_webhook": "Webhook in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_queue_depth": "Queue depth: {0} (capacity not exposed)", + "cmd.poracle_admin.status.label.discord_routes": "Routes near limit: {0}", + "cmd.poracle_admin.status.label.discord_global": "Global tokens: {0} / {1}", + "cmd.poracle_admin.status.label.discord_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.discord_routes_detail": "Routes near limit (detail):", + "cmd.poracle_admin.status.label.telegram_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.telegram_backoff": "Current backoff: {0}", + "cmd.poracle_admin.status.label.alert_limits_counts": "Breached: alert={0}, summary={1} · Banned: {2}", + "cmd.poracle_admin.status.label.tracking_total": "Total tracking rules: {0}", + "cmd.poracle_admin.status.label.tracking_active_humans": "Active humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans": "Registered humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans_error": "Registered humans: n/a (error)", + "cmd.poracle_admin.status.label.tracking_type": "{0}: {1}", + "cmd.poracle_admin.status.label.mysql_ping_ok": "Ping: ok", + "cmd.poracle_admin.status.label.mysql_ping_fail": "Ping: failed ({0})", + "cmd.poracle_admin.status.label.mysql_pool": "Connections: {0}/{1} open ({2} in use, {3} idle, waits={4})", + "cmd.poracle_admin.status.tracking_type.pokemon": "pokemon", + "cmd.poracle_admin.status.tracking_type.raid": "raid", + "cmd.poracle_admin.status.tracking_type.egg": "egg", + "cmd.poracle_admin.status.tracking_type.quest": "quest", + "cmd.poracle_admin.status.tracking_type.invasion": "invasion", + "cmd.poracle_admin.status.tracking_type.lure": "lure", + "cmd.poracle_admin.status.tracking_type.nest": "nest", + "cmd.poracle_admin.status.tracking_type.gym": "gym", + "cmd.poracle_admin.status.tracking_type.fort": "fort", + "cmd.poracle_admin.status.tracking_type.maxbattle": "maxbattle", + "cmd.poracle_admin.slash.help.intro": "**!poracle-admin slash** — slash-command registration lifecycle.\nSubcommands:", + "cmd.poracle_admin.slash.discord_only": "❌ Slash commands are Discord-only and cannot be managed from Telegram.", + "cmd.poracle_admin.slash.not_configured": "❌ Slash commands are not configured (Discord disabled or [discord.slash_commands] enabled=false).", + "cmd.poracle_admin.slash.sync.desc": "push the current command set to Discord (fingerprint-cached, skips if unchanged)", + "cmd.poracle_admin.slash.sync.success": "✅ Slash sync complete ({0}ms)", + "cmd.poracle_admin.slash.sync.error": "❌ Slash sync failed: {0}", + "cmd.poracle_admin.slash.force_resync.desc": "clear fingerprint cache and push unconditionally", + "cmd.poracle_admin.slash.force_resync.success": "✅ Force-resync complete ({0}ms)", + "cmd.poracle_admin.slash.force_resync.error": "❌ Force-resync failed: {0}", + "cmd.poracle_admin.slash.clear_global.desc": "remove all globally-registered Discord slash commands", + "cmd.poracle_admin.slash.clear_global.success": "✅ Global slash commands cleared.", + "cmd.poracle_admin.slash.clear_global.error": "❌ Clear global failed: {0}", + "cmd.poracle_admin.slash.clear_guild.desc": "remove slash commands from one guild (requires guild_id arg)", + "cmd.poracle_admin.slash.clear_guild.needs_arg": "❌ Usage: `!poracle-admin slash clear-guild `", + "cmd.poracle_admin.slash.clear_guild.success": "✅ Slash commands cleared from guild {0}.", + "cmd.poracle_admin.slash.clear_guild.error": "❌ Clear guild failed: {0}", + "cmd.poracle_admin.slash.status.desc": "show last sync timestamp and fingerprint per scope", + "cmd.poracle_admin.slash.status.header": "**Slash command registration status:**", + "cmd.poracle_admin.slash.status.scope_row": " **{0}**: last synced {1} · fingerprint `{2}`", + "cmd.poracle_admin.slash.status.never_synced": "never", + "cmd.poracle_admin.slash.status.ago": "{0} ago", + "cmd.poracle_admin.slash.status.error": "❌ Status read failed: {0}", + "cmd.poracle_admin.config.help.intro": "⚙️ Config viewer — show effective merged config with secrets redacted.\nSubcommands:", + "cmd.poracle_admin.config.keys.desc": "list section names with key counts", + "cmd.poracle_admin.config.section.desc": "show just that section (e.g. `!poracle-admin config discord`)", + "cmd.poracle_admin.config.full.desc": "show the full config (all sections, secrets redacted)", + "cmd.poracle_admin.config.keys.header": "⚙️ Config sections:", + "cmd.poracle_admin.config.keys.row": " {0}: {1} keys", + "cmd.poracle_admin.config.unknown_section": "Unknown config section: `{0}`. Use `!poracle-admin config keys` to list valid sections, or `!poracle-admin config search ` to search across all sections.", + "cmd.poracle_admin.config.search.desc": "find keys whose path or value contains the term across every section (e.g. `!poracle-admin config search dm`)", + "cmd.poracle_admin.config.search.usage": "Usage: `!poracle-admin config search ` — e.g. `search dm`, `search shlink`, `search 3030`.", + "cmd.poracle_admin.config.search.header": "🔍 `{0}` — {1} match(es):", + "cmd.poracle_admin.config.search.no_matches": "No config keys or values match `{0}`.", + "cmd.poracle_admin.config.empty_section": "Section `{0}` has no configurable fields.", + "cmd.poracle_admin.config.not_loaded": "❌ Config not loaded.", + "cmd.poracle_admin.warnings.help.intro": "🛠️ Captured warnings — inspect in-memory WARN/ERROR log entries.\n\nSubcommands:\n (no arg) — show both startup and recent buffers\n `startup` — show only the startup buffer (first 200 entries, frozen after init)\n `recent` — show only the rolling buffer (last 50 entries)\n `clear` — empty the rolling buffer (startup is immutable)", + "cmd.poracle_admin.warnings.not_configured": "ℹ️ Log buffer is not configured on this instance.", + "cmd.poracle_admin.warnings.section.startup": "🛠️ Captured warnings — startup ({0} entries)", + "cmd.poracle_admin.warnings.section.recent": "🛠️ Captured warnings — recent ({0} entries)", + "cmd.poracle_admin.warnings.empty.startup": "🟢 No startup warnings captured.", + "cmd.poracle_admin.warnings.empty.recent": "🟢 No recent warnings.", + "cmd.poracle_admin.warnings.entry_row": " {0} {1} {2} {3}", + "cmd.poracle_admin.warnings.cleared": "✅ Cleared {0} entries from the rolling buffer (startup buffer is unaffected).", + "cmd.poracle_admin.warnings.startup.desc": "`startup` — show only the startup buffer (frozen after init)", + "cmd.poracle_admin.warnings.recent.desc": "`recent` — show only the rolling buffer (last 50 entries)", + "cmd.poracle_admin.warnings.clear.desc": "`clear` — empty the rolling buffer", + "cmd.maintenance.active_suffix": "🔧 Maintenance mode is active — alerts are not being delivered.", + "showcase_focus_pokemon": "Pokémon", + "showcase_focus_type": "Type", + "showcase_focus_alignment": "Alignment", + "showcase_focus_class": "Class", + "showcase_focus_family": "Family", + "showcase_focus_buddy": "Buddy", + "showcase_focus_generation": "Generation", + "showcase_focus_hatched": "Hatched", + "showcase_focus_mega": "Mega", + "showcase_focus_shiny": "Shiny", + "showcase_class_ultra_beast": "Ultra Beast" } diff --git a/processor/internal/i18n/locale/nb-no.json b/processor/internal/i18n/locale/nb-no.json index ff0b3cc57..a435b9065 100644 --- a/processor/internal/i18n/locale/nb-no.json +++ b/processor/internal/i18n/locale/nb-no.json @@ -58,6 +58,11 @@ "tracking.pvp_little": "littlepvp", "tracking.pvp_great": "greatpvp", "tracking.pvp_ultra": "ultrapvp", + "tracking.pvp_mega_any": "mega", + "tracking.pvp_mega_x": "mega x", + "tracking.pvp_mega_y": "mega y", + "tracking.mega_x_label": "X", + "tracking.mega_y_label": "Y", "tracking.level_cap_fmt": "level cap: {0}", "tracking.everything": "Alt", "tracking.unknown_monster": "Unknown monster", @@ -81,10 +86,14 @@ "tracking.reward_fmt": "Reward: **{0}**", "tracking.reward_stardust_min_fmt": "{0} or more stardust", "tracking.reward_stardust": "stardust", + "tracking.reward_pokecoin_min_fmt": "{0} or more pokecoins", + "tracking.reward_pokecoin": "pokecoins", "tracking.reward_mega_energy": "mega energy", "tracking.reward_mega_energy_fmt": "mega energy {0}", "tracking.reward_candy": "candy", "tracking.reward_candy_fmt": "candy {0}", + "tracking.reward_any_pokemon": "any pokemon", + "tracking.reward_any_item": "any item", "tracking.reward_min_fmt": "minimum {0}", "tracking.grunt_type_fmt": "Grunt type: **{0}**", "tracking.min_avg_spawn": "Min avg. spawn {0}/hour", @@ -108,10 +117,68 @@ "tracking.template_not_found": "Template \"{0}\" does not exist.", "tracking.warn_template_not_found": "Template \"{0}\" not found for type {1}/{2}. Tracking saved but alerts may not render.", "tracking.id_hint": "To remove a specific entry, use its id — e.g. `{0}untrack id:45` or `{0}raid remove id:12`", + "tracking.id_hint_slash": "To remove a specific entry, run `/untrack ` (e.g. `/untrack raid`) and pick it from the list.", + "tracking.list_attached": "Your tracking list is long ({0} rules) — attached as a file.", "tracking.removed_prefix": "Removed: ", "tracking.uid_not_found": "id:{0} not found", + "tracking.override_location_fmt": "@ {0}", + "tracking.override_areas_fmt": "in {0}", "cmd.track": "track", "cmd.untrack": "untrack", + "cmd.mute": "mute", + "cmd.unmute": "unmute", + "msg.mute.unavailable": "Mute feature isn't enabled here.", + "msg.mute.usage": "Valid commands are `{0}mute [duration:1h]`", + "msg.mute.usage_pokemon": "Valid commands are `{0}mute pokemon [duration:1h]`", + "msg.mute.usage_gym": "Valid commands are `{0}mute gym [duration:1h]`", + "msg.mute.usage_area": "Valid commands are `{0}mute area [duration:1h]`", + "msg.mute.usage_id_scope": "Valid commands are `{0}mute {1} [duration:1h]`", + "msg.mute.bad_duration": "Invalid duration: {0}", + "msg.mute.id_not_supported": "`!mute id:N` / `!mute id:N` aren't supported yet — entity scopes (gym, pokemon, area, pokestop, station, everything) work today. Per-rule muting by UID is a follow-up.", + "msg.mute.bad_uid": "`{0}` isn't a valid tracking rule UID. Use `!tracked` to see your rule UIDs.", + "msg.mute.unknown_area": "`{0}` isn't in your available areas. Use `!area` to see what you can mute.", + "msg.mute.no_pokemon": "I don't know a pokemon called `{0}`.", + "msg.mute.everything_label": "everything", + "msg.mute.added": "🔇 Muted {0} for {1}.", + "msg.mute.removed": "✅ Unmuted {0}.", + "msg.mute.none_found": "No active mute for {0}.", + "msg.mute.cleared_all": "Cleared {0} active mutes.", + "msg.unmute.usage": "Valid commands are `{0}unmute `, `{0}unmute all`", + "msg.unmute.usage_pokemon": "Valid commands are `{0}unmute pokemon `", + "msg.unmute.usage_gym": "Valid commands are `{0}unmute gym `", + "msg.unmute.usage_area": "Valid commands are `{0}unmute area `", + "section.property_mutes": "Property mutes (apply across all tracking):", + "section.property_mutes.left": "({0} left)", + "msg.button.expired": "This alert has expired.", + "msg.button.unavailable": "This button is no longer available.", + "msg.button.wrong_target": "This button doesn't apply here.", + "msg.button.unauthorized": "This button isn't for you.", + "msg.button.unidentified": "Couldn't identify you to handle that click.", + "msg.button.unconfigured": "This button isn't configured.", + "msg.button.action_failed": "Couldn't complete that action: {0}", + "msg.button.action_failed_generic": "Couldn't complete that action.", + "msg.button.cooldown": "Slow down — try that again in a moment.", + "msg.button.actions_not_wired": "Button actions aren't wired here.", + "msg.button.not_implemented": "The {0} action isn't implemented yet.", + "msg.button.responses_not_wired": "Response rendering isn't wired here.", + "msg.button.response_failed": "Couldn't render that response: {0}", + "msg.button.done": "Done.", + "msg.button.missing_scope": "Button is missing a scope — operator config bug.", + "msg.button.missing_target": "Couldn't find a {0} to mute on this alert.", + "msg.button.no_dm_target": "Couldn't identify you to send the message.", + "msg.button.dm_failed": "Couldn't send to your DM: {0}", + "msg.button.unsubscribe_failed": "Couldn't unsubscribe — please try again.", + "msg.button.unsubscribe_already": "Those tracking rules were already removed.", + "msg.button.unsubscribed": "✅ Unsubscribed from {0} tracking rule(s).", + "msg.button.redeliver_sent": "📬 Sent to your DM.", + "msg.mute.scope_gym": "gym", + "msg.mute.scope_pokemon": "pokemon", + "msg.mute.scope_area": "area", + "msg.mute.scope_pokestop": "pokestop", + "msg.mute.scope_station": "station", + "msg.mute.scope_tracking": "tracking rule", + "cmd.mute.usage": "**{0}mute** — silence alerts for a specific gym, pokemon, area, pokestop, station, or everything for a time-bounded window.\n\n• `{0}mute everything [duration:1h]` — silence ALL alerts for the given duration\n• `{0}mute gym [duration:1h]` — silence alerts for one gym\n• `{0}mute pokemon [duration:1h]` — silence alerts for one pokemon species\n• `{0}mute area [duration:1h]` — silence alerts in one area\n• `{0}mute pokestop [duration:1h]` — silence alerts for one pokestop\n• `{0}mute station [duration:1h]` — silence alerts for one station\n\nDuration defaults to 1h if omitted. Use `{0}unmute ` to remove a mute early, or `{0}tracked` to see active mutes.", + "cmd.track.usage": "**{0}track** — set up pokemon tracking rules.\n\n• `{0}track ` — track a specific pokemon (by name or dex id) at default 100m\n• `{0}track everything` — track every pokemon (admin-permitted; see `{0}help everything`)\n• `{0}track iv:100` — filter by IV percent (`iv:90-100` for range, `miniv:90`/`maxiv:99` for one-sided)\n• `{0}track cp:1500-2500` — filter by CP\n• `{0}track level:25-35` — filter by level\n• `{0}track atk:14-15 def:14-15 sta:14-15` — filter by individual IV stats\n• `{0}track d:500` — only alert within 500m of your location\n• `{0}track location:Home d:500` — within 500m of a saved location\n• `{0}track area:london,paris` — only in named areas (replaces your default areas)\n• `{0}track great5 ultra10` — PVP filters (great/ultra/little league, rank threshold, optional cap)\n• `{0}track gen:1 type:water` — generation and type filters (alongside `everything`)\n• `{0}track rarity:rare-ultra` — rarity-tier filter\n• `{0}track clean` / `edit` — auto-delete on TTH expiry / edit-in-place\n• `{0}track remove ` or `{0}untrack ` — remove\n• `{0}untrack id:42` — remove one rule by id (see `{0}tracked` for ids)\n\nMultiple filters combine. See `{0}tracked` for what's currently active.", "cmd.raid": "raid", "cmd.egg": "egg", "cmd.quest": "quest", @@ -129,6 +196,8 @@ "cmd.fort": "fort", "cmd.help": "help", "cmd.info": "info", + "cmd.info.poracle.moved": "→ This view has moved to `!poracle-admin status` — please use that instead.", + "cmd.info.config.moved": "→ This view has moved to `!poracle-admin config` — please use that instead.", "cmd.start": "start", "cmd.stop": "stop", "cmd.tracked": "tracked", @@ -163,6 +232,8 @@ "cmd.poracle_id": "poracle-id", "arg.remove": "remove", "arg.everything": "everything", + "arg.all_pokemon": "all pokemon", + "arg.all_items": "all items", "arg.any": "any", "arg.clean": "clean", "arg.edit": "edit", @@ -170,6 +241,7 @@ "arg.list": "list", "arg.add": "add", "arg.show": "show", + "arg.default": "default", "arg.overview": "overview", "arg.dryrun": "dryrun", "arg.reset": "reset", @@ -182,6 +254,7 @@ "arg.shiny": "shiny", "arg.gmax": "gmax", "arg.stardust": "stardust", + "arg.pokecoin": "pokecoins", "arg.energy": "energy", "arg.candy": "candy", "arg.pvp": "pvp", @@ -248,7 +321,10 @@ "arg.prefix.maxsize": "maxsize", "arg.prefix.gen": "gen", "arg.prefix.cap": "cap", + "arg.mega": "mega", + "arg.prefix.mega": "mega", "arg.prefix.form": "form", + "arg.prefix.costume": "costume", "arg.prefix.template": "template", "arg.prefix.gym": "gym", "arg.prefix.move": "move", @@ -263,13 +339,17 @@ "arg.prefix.littlehigh": "littlehigh", "arg.prefix.littlecp": "littlecp", "arg.prefix.stardust": "stardust", + "arg.prefix.pokecoin": "pokecoins", "arg.prefix.energy": "energy", "arg.prefix.candy": "candy", + "arg.prefix.amount": "amount", "arg.prefix.name": "name", "arg.prefix.user": "user", "arg.prefix.channel": "channel", "arg.prefix.guild": "guild", "arg.prefix.language": "language", + "arg.prefix.area": "area", + "arg.prefix.location": "location", "arg.prefix.mon": "mon", "arg.prefix.tue": "tue", "arg.prefix.wed": "wed", @@ -323,21 +403,26 @@ "section.maxbattles.none": "You're not tracking any max battles", "msg.no_pokemon": "Ingen Pokémon ble funnet", "msg.form_not_found": "Form `{0}` not recognised. Use `{1}info ` to see available forms.", + "msg.costume_not_found": "Costume `{0}` not recognised. Use `{1}info costumes` to see available costumes.", + "msg.no_costume": "no costume", "msg.nothing_to_remove": "Nothing to remove", "msg.no_levels": "No levels specified", "msg.no_egg_levels": "No egg levels specified", "msg.no_raid_target": "No raid levels or pokemon specified", "msg.no_lure_type": "No lure type specified", "msg.no_quest_type": "No quest type specified", + "msg.quest.amount_not_applicable": "`amount:N` doesn't apply to pokemon quests — pokemon rewards have no minimum amount.", + "msg.quest.bulk_not_permitted": "You do not have permission to track all pokemon or items at once. Track specific rewards instead.", "msg.removed_n": "Jeg fjernet {0} varslinger", "msg.egg.usage": "Valid commands are e.g. `{0}egg level:5`, `{0}egg legendary`, `{0}egg remove everything`", "msg.raid.usage": "Valid commands are e.g. `{0}raid level:5`, `{0}raid pikachu`, `{0}raid remove everything`", "msg.track.usage": "Valid commands are e.g. `{0}track pikachu iv:100`, `{0}track everything iv:90`, `{0}track remove pikachu`", "msg.track.everything_no_filters": "Denne kommandoen ville ført til alt for mange varsler, legg inn mer filtrering for å begrense mulige varsler.", "msg.track.invalid_cap": "This level cap is not supported, valid choices are: {0}", - "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest energy:charizard`", + "msg.track.no_mega_form": "⚠️ {0} has no Mega {1} form — this PVP rule will never match.", + "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest pokecoins:10`, `{0}quest energy:charizard`", "msg.quest.edit_summary_conflict": "`edit` and `summary` are mutually exclusive — pick one.", - "msg.summary.usage": "Usage: `{0}summary quest [settime |cleartime|now]`", + "msg.summary.usage": "Valid commands are `{0}summary quest`, `{0}summary quest settime `, `{0}summary quest cleartime`, `{0}summary quest now`", "msg.summary.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.summary.no_schedule": "No schedule set for {0} summaries.", "msg.summary.scheduled": "Schedule for {0} summaries: {1}", @@ -360,11 +445,33 @@ "msg.nest.usage": "Valid commands are e.g. `{0}nest pikachu`, `{0}nest everything`, `{0}nest remove pikachu`", "msg.maxbattle.usage": "Valid commands are e.g. `{0}maxbattle pikachu`, `{0}maxbattle level:3`, `{0}maxbattle remove everything`", "msg.fort.usage": "Valid commands are e.g. `{0}fort pokestop`, `{0}fort everything`, `{0}fort remove pokestop`", - "msg.location.removed": "Location removed", - "msg.location.usage": "Valid commands are e.g. `{0}location ,`, `{0}location `", + "msg.location.removed": "✅ Removed saved location `{0}`.", + "msg.location.usage": "Valid commands are `{0}location `, `{0}location add `, `{0}location list`, `{0}location show `, `{0}location remove `, `{0}location remove default`", "msg.location.specify": "Please specify coordinates or an address", "msg.location.set": "Location set to {0},{1}", "msg.location.current": "Your current location is {0},{1}", + "msg.location.added": "✅ Saved location `{0}` at {1}, {2}.", + "msg.location.duplicate": "🙅 You already have a saved location called `{0}`. Remove it first with `{1}location remove {0}`.", + "msg.location.list_header": "Your saved locations:", + "msg.location.list_row": " `{0}`: {1}, {2}", + "msg.location.list_row_with_addr": " `{0}`: {1}, {2} — {3}", + "msg.location.list_empty": "You have no saved locations. Add one with `{0}location add `.", + "msg.location.show_not_found": "🙅 No saved location called `{0}`.", + "msg.location.show": "📍 `{0}` is at {1}, {2}.", + "msg.location.show_with_addr": "📍 `{0}` is at {1}, {2} — {3}", + "msg.location.no_default": "🙅 No default location set.", + "msg.location.default_removed": "✅ Cleared your default location.", + "msg.location.remove_referenced": "🙅 Cannot remove `{0}` — {1} tracking rule(s) reference it: {2}. Edit or remove those rules first.", + "msg.location.add_usage": "Valid commands are `{0}location add `", + "msg.location.show_usage": "Valid commands are `{0}location show `", + "msg.location.remove_usage": "Valid commands are `{0}location remove `, `{0}location remove default`", + "msg.location.geocode_failed": "🙅 Couldn't find a place matching `{0}`.", + "cmd.location.usage": "**{0}location** — manage your default location and saved named locations.\n\n• `{0}location` — show your current default location\n• `{0}location ` — set your default location\n• `{0}location add ` — save a named location (referenced later as `location:` on tracking rules)\n• `{0}location list` — list all your saved locations\n• `{0}location show ` — show one saved location's coords + address (use `default` for your default)\n• `{0}location remove ` — delete a saved location (refuses if any tracking rule references it)\n• `{0}location remove default` — clear your default location", + "msg.override.requires_distance": "🙅 `location:` needs a `d:` distance — e.g. `location:Home d:500`.", + "msg.override.area_and_distance": "🙅 `area:` and `d:` are mutually exclusive (area-mode vs distance-mode). Pick one.", + "msg.override.area_and_location": "🙅 `area:` and `location:` are mutually exclusive. Pick one.", + "msg.override.unknown_location": "🙅 No saved location called `{0}`. Add it with `{1}location add {0} `.", + "msg.override.area_not_permitted": "🙅 Area `{0}` is not in your allowed areas. Use `{1}area list` to see what you can pick.", "msg.area.usage": "Valid commands are `{0}area list`, `{0}area add `, `{0}area remove `", "msg.area.none_available": "No areas available", "msg.area.available": "**Available areas:**", @@ -382,14 +489,14 @@ "msg.profile.deleted": "Profile {0} deleted", "msg.profile.not_found": "Ukjent profil", "msg.profile.cannot_delete_1": "Cannot delete profile 1", - "msg.profile.hours_usage": "Usage: profile hours ", + "msg.profile.hours_usage": "Valid commands are `{0}profile hours `", "msg.profile.hours_invalid_json": "Invalid JSON for active hours", "msg.profile.hours_set": "Active hours updated for profile {0}", "msg.profile.hours_cleared": "Active hours cleared for profile {0}", - "msg.profile.settime_usage": "Usage: profile settime mon09:00 tue18:30 weekday09:00 weekend10:00", + "msg.profile.settime_usage": "Valid commands are `{0}profile settime mon09:00 tue18:30 weekday09:00 weekend10:00`", "msg.profile.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.profile.copied": "Current profile copied to: {0}", - "msg.profile.copyto_usage": "Usage: profile copyto ", + "msg.profile.copyto_usage": "Valid commands are `{0}profile copyto `", "msg.profile.copy_invalid": "These profiles were invalid: {0}", "msg.profile.usage": "Valid commands are `{0}profile `, `{0}profile list`, `{0}profile add `, `{0}profile remove `, `{0}profile settime `, `{0}profile copyto `", "msg.profile.list_header": "Du har følgende profiler:", @@ -407,6 +514,7 @@ "msg.weather.unavailable": "Weather tracking is not yet available via this command", "msg.help.unknown_topic": "No help available for '{0}'. Use `{1}help` for general help.", "msg.help.no_greeting": "No help template configured. Use `{0}help ` for command-specific help.", + "msg.help.see_detailed": "💡 More detailed help is available — `{0}help {1}`", "msg.info.sub.moves": "moves", "msg.info.sub.items": "items", "msg.info.sub.shiny": "shiny", @@ -417,9 +525,19 @@ "msg.info.sub.translate": "translate", "msg.info.sub.dts": "dts", "msg.info.sub.templates": "templates", - "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info `", + "msg.info.sub.costumes": "costumes", + "msg.info.sub.forms": "forms", + "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info costumes`, `{0}info `", "msg.info.usage_admin": "Admin: `{0}info poracle`, `{0}info dts`, `{0}info translate `, `{0}info config [search]`", "msg.info.available_forms": "Available forms:", + "msg.info.more_forms": "More than {0} forms — do {1} for the full list", + "msg.info.recent_forms": "**Recently-seen forms:**", + "msg.info.recent_raid_forms": "**Recently-seen raid forms:**", + "msg.info.available_costumes": "**Recently-seen costumes:**", + "msg.info.recent_raid_costumes": "**Recently-seen raid costumes:**", + "msg.info.costumes.header": "**Costumes** (`costume:` to track):", + "msg.info.no_costume_data": "No costume data loaded", + "msg.info.no_form_data": "No form data for that pokemon.", "msg.info.hundo_cp": "100% IV CP:", "msg.info.dts_summary": "DTS Templates loaded:", "msg.info.pokemon_not_found": "Pokemon not found: {0}", @@ -534,5 +652,661 @@ "language.sv": "Svenska", "language.zh-cn": "Kinesisk (forenklet)", "language.ja": "Japansk", - "msg.help.text": "**Available commands:**\n{0}track [iv:N] [cp:N] [level:N] [d:N] — Track pokemon\n{0}untrack — Remove pokemon tracking\n{0}raid [d:N] — Track raids\n{0}egg [d:N] — Track eggs\n{0}quest — Track quests\n{0}invasion [everything|] — Track invasions\n{0}lure — Track lures\n{0}gym [slot_changes] — Track gyms\n{0}nest — Track nests\n{0}maxbattle — Track max battles\n{0}fort — Track fort updates\n{0}tracked — Show all tracking\n{0}script — Export tracking as commands\n{0}area [list|add|remove] — Manage areas\n{0}location — Set location\n{0}profile [list|add|remove|switch] — Manage profiles\n{0}language — Set language\n{0}start / {0}stop — Enable/disable alerts\n{0}version — Show version" + "slash.cmd.version": "version", + "slash.desc.version": "Show Poracle version", + "slash.cmd.tracked": "tracked", + "slash.cmd.help": "help", + "slash.cmd.info": "info", + "slash.cmd.language": "language", + "slash.cmd.track": "track", + "slash.cmd.raid": "raid", + "slash.cmd.egg": "egg", + "slash.cmd.quest": "quest", + "slash.cmd.invasion": "invasion", + "slash.cmd.incident": "incident", + "slash.cmd.lure": "lure", + "slash.cmd.nest": "nest", + "slash.cmd.maxbattle": "maxbattle", + "slash.cmd.gym": "gym", + "slash.cmd.fort": "fort", + "slash.cmd.untrack": "untrack", + "slash.cmd.area": "area", + "slash.cmd.profile": "profile", + "slash.cmd.location": "location", + "slash.cmd.summary": "summary", + "slash.cmd.start": "start", + "slash.cmd.stop": "stop", + "slash.desc.tracked": "List your tracking rules", + "slash.desc.start": "Resume alert delivery (after /stop)", + "slash.desc.stop": "Pause alert delivery (resume with /start)", + "slash.desc.help": "Show help", + "slash.desc.info": "Look up pokemon info, shiny rates, rarity tiers, or current weather", + "slash.opt.info.pokemon": "pokemon", + "slash.opt.info.pokemon.desc": "Show types, stats, evolutions, weather boost and CP table for a pokemon", + "slash.opt.info.pokemon.name": "name", + "slash.opt.info.pokemon.name.desc": "Pokemon name (any supported language) or dex id", + "slash.opt.info.rarity": "rarity", + "slash.opt.info.rarity.desc": "List pokemon by spawn rarity tier (common → ultra-rare)", + "slash.opt.info.shiny": "shiny", + "slash.opt.info.shiny.desc": "Show observed shiny rates per species", + "slash.opt.info.weather": "weather", + "slash.opt.info.weather.desc": "Show current weather and boosted types for a location", + "slash.opt.info.weather.coords": "coords", + "slash.opt.info.weather.coords.desc": "lat,lon (defaults to your saved location)", + "slash.desc.language": "Show or set your language", + "slash.desc.track": "Track a Pokemon", + "slash.desc.raid": "Track a raid boss or raid level", + "slash.desc.egg": "Track an egg / raid level", + "slash.desc.quest": "Track a quest reward", + "slash.desc.invasion": "Track a Team Rocket invasion", + "slash.desc.incident": "Track a pokestop incident (Kecleon, Gold Pokestop, Showcase…)", + "slash.desc.lure": "Track a pokestop lure", + "slash.desc.nest": "Track a nesting pokemon", + "slash.desc.maxbattle": "Track a max (Dynamax) battle", + "slash.desc.gym": "Track gym team / slot / battle changes", + "slash.desc.fort": "Track pokestop or gym updates", + "slash.desc.untrack": "Remove a tracking rule", + "slash.desc.area": "Manage your areas", + "slash.desc.profile": "Manage your profiles", + "slash.desc.location": "Manage your saved locations", + "slash.desc.summary": "Manage scheduled summary digests (e.g. quest)", + "slash.opt.help.topic": "topic", + "slash.opt.help.topic.desc": "Help topic", + "slash.opt.language.code": "code", + "slash.opt.language.code.desc": "Language code", + "slash.opt.track.pokemon": "pokemon", + "slash.opt.track.pokemon.desc": "Pokemon to track (or 'everything')", + "slash.opt.track.iv": "iv", + "slash.opt.track.iv.desc": "IV filter (e.g. 100, 95, 0-0)", + "slash.opt.track.distance": "distance", + "slash.opt.track.distance.desc": "Alert radius in metres", + "slash.opt.track.great_rank": "great_rank", + "slash.opt.track.great_rank.desc": "Top PVP rank in the Great League", + "slash.opt.track.ultra_rank": "ultra_rank", + "slash.opt.track.ultra_rank.desc": "Top PVP rank in the Ultra League", + "slash.opt.track.little_rank": "little_rank", + "slash.opt.track.little_rank.desc": "Top PVP rank in the Little League", + "slash.opt.track.clean": "clean", + "slash.opt.track.clean.desc": "Auto-delete the alert when the pokemon despawns", + "slash.opt.track.template": "template", + "slash.opt.track.template.desc": "DTS template name", + "slash.opt.track.form": "form", + "slash.opt.track.form.desc": "Pokemon form", + "slash.opt.track.size": "size", + "slash.opt.track.size.desc": "Pokemon size class", + "slash.choice.track.clean.yes": "Yes", + "slash.choice.track.size.all": "All sizes", + "slash.choice.track.size.xxs": "XXS", + "slash.choice.track.size.xs": "XS", + "slash.choice.track.size.m": "M", + "slash.choice.track.size.xl": "XL", + "slash.choice.track.size.xxl": "XXL", + "slash.opt.raid.boss": "boss", + "slash.opt.raid.boss.desc": "Raid boss pokemon", + "slash.opt.raid.level": "level", + "slash.opt.raid.level.desc": "Raid level", + "slash.opt.raid.team": "team", + "slash.opt.raid.team.desc": "Required gym-control team", + "slash.opt.raid.distance": "distance", + "slash.opt.raid.distance.desc": "Alert radius in metres", + "slash.opt.raid.clean": "clean", + "slash.opt.raid.clean.desc": "Auto-delete the alert when the raid expires", + "slash.opt.raid.template": "template", + "slash.opt.raid.template.desc": "DTS template name", + "slash.choice.raid.clean.yes": "Yes", + "slash.choice.raid.level.1": "Tier 1", + "slash.choice.raid.level.3": "Tier 3", + "slash.choice.raid.level.5": "Tier 5", + "slash.choice.raid.level.6": "Tier 6", + "slash.choice.raid.level.mega": "Mega", + "slash.choice.raid.level.legendary": "Legendary", + "slash.choice.raid.level.shadow1": "Shadow Tier 1", + "slash.choice.raid.level.shadow3": "Shadow Tier 3", + "slash.choice.raid.level.shadow5": "Shadow Tier 5", + "slash.choice.raid.level.ultra beast": "Ultra Beast", + "slash.choice.raid.level.everything": "Everything", + "slash.choice.raid.team.0": "Harmony", + "slash.choice.raid.team.1": "Mystic", + "slash.choice.raid.team.2": "Valor", + "slash.choice.raid.team.3": "Instinct", + "slash.opt.egg.level": "level", + "slash.opt.egg.level.desc": "Egg / raid level", + "slash.opt.egg.team": "team", + "slash.opt.egg.team.desc": "Required gym-control team", + "slash.opt.egg.distance": "distance", + "slash.opt.egg.distance.desc": "Alert radius in metres", + "slash.opt.egg.clean": "clean", + "slash.opt.egg.clean.desc": "Auto-delete the alert when the egg hatches", + "slash.opt.egg.template": "template", + "slash.opt.egg.template.desc": "DTS template name", + "slash.choice.egg.clean.yes": "Yes", + "slash.choice.egg.level.1": "Tier 1", + "slash.choice.egg.level.3": "Tier 3", + "slash.choice.egg.level.5": "Tier 5", + "slash.choice.egg.level.6": "Tier 6", + "slash.choice.egg.level.mega": "Mega", + "slash.choice.egg.level.legendary": "Legendary", + "slash.choice.egg.level.shadow1": "Shadow Tier 1", + "slash.choice.egg.level.shadow3": "Shadow Tier 3", + "slash.choice.egg.level.shadow5": "Shadow Tier 5", + "slash.choice.egg.level.ultra beast": "Ultra Beast", + "slash.choice.egg.level.everything": "Everything", + "slash.choice.egg.team.0": "Harmony", + "slash.choice.egg.team.1": "Mystic", + "slash.choice.egg.team.2": "Valor", + "slash.choice.egg.team.3": "Instinct", + "slash.opt.quest.pokemon": "pokemon", + "slash.opt.quest.pokemon.desc": "Pokemon reward", + "slash.opt.quest.item": "item", + "slash.opt.quest.item.desc": "Item reward (e.g. golden razz berry)", + "slash.opt.quest.stardust": "stardust", + "slash.opt.quest.stardust.desc": "Stardust reward (minimum amount)", + "slash.opt.quest.candy": "candy", + "slash.opt.quest.candy.desc": "Candy reward pokemon", + "slash.opt.quest.mega_energy": "mega_energy", + "slash.opt.quest.mega_energy.desc": "Mega energy reward pokemon", + "slash.opt.quest.min_amount": "min_amount", + "slash.opt.quest.min_amount.desc": "Minimum reward amount (item / candy / mega_energy only)", + "slash.opt.quest.distance": "distance", + "slash.opt.quest.distance.desc": "Alert radius in metres", + "slash.opt.quest.clean": "clean", + "slash.opt.quest.clean.desc": "Auto-delete the alert when the quest is completed", + "slash.opt.quest.summary": "summary", + "slash.opt.quest.summary.desc": "Buffer matches and dispatch in a scheduled batch instead of alerting immediately", + "slash.opt.quest.template": "template", + "slash.opt.quest.template.desc": "DTS template name", + "slash.choice.quest.clean.yes": "Yes", + "slash.choice.quest.summary.yes": "Yes", + "slash.opt.invasion.grunt_type": "grunt_type", + "slash.opt.invasion.grunt_type.desc": "Grunt type (Fire, Water…), boss (Giovanni…), or incident (Kecleon…)", + "slash.opt.invasion.gender": "gender", + "slash.opt.invasion.gender.desc": "Filter by grunt gender", + "slash.opt.invasion.distance": "distance", + "slash.opt.invasion.distance.desc": "Alert radius in metres", + "slash.opt.invasion.clean": "clean", + "slash.opt.invasion.clean.desc": "Auto-delete the alert when the invasion expires", + "slash.opt.invasion.template": "template", + "slash.opt.invasion.template.desc": "DTS template name", + "slash.choice.invasion.clean.yes": "Yes", + "slash.choice.invasion.gender.male": "Male", + "slash.choice.invasion.gender.female": "Female", + "slash.choice.invasion.gender.genderless": "Genderless", + "slash.opt.incident.type": "type", + "slash.opt.incident.type.desc": "Pokestop incident type (Kecleon, Gold Pokestop, Showcase…)", + "slash.opt.incident.distance": "distance", + "slash.opt.incident.distance.desc": "Alert radius in metres", + "slash.opt.incident.clean": "clean", + "slash.opt.incident.clean.desc": "Auto-delete the alert when the incident expires", + "slash.opt.incident.template": "template", + "slash.opt.incident.template.desc": "DTS template name", + "slash.choice.incident.clean.yes": "Yes", + "slash.opt.lure.lure_type": "lure_type", + "slash.opt.lure.lure_type.desc": "Lure type", + "slash.opt.lure.distance": "distance", + "slash.opt.lure.distance.desc": "Alert radius in metres", + "slash.opt.lure.clean": "clean", + "slash.opt.lure.clean.desc": "Auto-delete the alert when the lure expires", + "slash.opt.lure.template": "template", + "slash.opt.lure.template.desc": "DTS template name", + "slash.choice.lure.clean.yes": "Yes", + "slash.choice.lure.lure_type.normal": "Normal", + "slash.choice.lure.lure_type.glacial": "Glacial", + "slash.choice.lure.lure_type.mossy": "Mossy", + "slash.choice.lure.lure_type.magnetic": "Magnetic", + "slash.choice.lure.lure_type.rainy": "Rainy", + "slash.choice.lure.lure_type.sparkly": "Sparkly", + "slash.opt.nest.pokemon": "pokemon", + "slash.opt.nest.pokemon.desc": "Nesting pokemon", + "slash.opt.nest.min_spawn_avg": "min_spawn_avg", + "slash.opt.nest.min_spawn_avg.desc": "Minimum spawns per hour", + "slash.opt.nest.distance": "distance", + "slash.opt.nest.distance.desc": "Alert radius in metres", + "slash.opt.nest.clean": "clean", + "slash.opt.nest.clean.desc": "Auto-delete the alert when the nest expires", + "slash.opt.nest.template": "template", + "slash.opt.nest.template.desc": "DTS template name", + "slash.choice.nest.clean.yes": "Yes", + "slash.opt.maxbattle.pokemon": "pokemon", + "slash.opt.maxbattle.pokemon.desc": "Max battle pokemon", + "slash.opt.maxbattle.level": "level", + "slash.opt.maxbattle.level.desc": "Battle level (1..6)", + "slash.opt.maxbattle.gmax": "gmax", + "slash.opt.maxbattle.gmax.desc": "Gigantamax only", + "slash.opt.maxbattle.distance": "distance", + "slash.opt.maxbattle.distance.desc": "Alert radius in metres", + "slash.opt.maxbattle.clean": "clean", + "slash.opt.maxbattle.clean.desc": "Auto-delete the alert when the battle ends", + "slash.opt.maxbattle.template": "template", + "slash.opt.maxbattle.template.desc": "DTS template name", + "slash.choice.maxbattle.clean.yes": "Yes", + "slash.choice.maxbattle.level.1": "Level 1", + "slash.choice.maxbattle.level.2": "Level 2", + "slash.choice.maxbattle.level.3": "Level 3", + "slash.choice.maxbattle.level.4": "Level 4", + "slash.choice.maxbattle.level.5": "Level 5", + "slash.choice.maxbattle.level.6": "Level 6", + "slash.opt.gym.team": "team", + "slash.opt.gym.team.desc": "Gym-control team to alert on", + "slash.opt.gym.slot_changes": "slot_changes", + "slash.opt.gym.slot_changes.desc": "Alert on slot composition changes", + "slash.opt.gym.battle_changes": "battle_changes", + "slash.opt.gym.battle_changes.desc": "Alert on battle state changes", + "slash.opt.gym.distance": "distance", + "slash.opt.gym.distance.desc": "Alert radius in metres", + "slash.opt.gym.clean": "clean", + "slash.opt.gym.clean.desc": "Auto-delete the alert when the gym state changes", + "slash.opt.gym.template": "template", + "slash.opt.gym.template.desc": "DTS template name", + "slash.choice.gym.clean.yes": "Yes", + "slash.choice.gym.team.0": "Harmony", + "slash.choice.gym.team.1": "Mystic", + "slash.choice.gym.team.2": "Valor", + "slash.choice.gym.team.3": "Instinct", + "slash.opt.fort.fort_type": "fort_type", + "slash.opt.fort.fort_type.desc": "Fort type to track", + "slash.opt.fort.include_empty": "include_empty", + "slash.opt.fort.include_empty.desc": "Alert on empty/unowned forts", + "slash.opt.fort.distance": "distance", + "slash.opt.fort.distance.desc": "Alert radius in metres", + "slash.opt.fort.clean": "clean", + "slash.opt.fort.clean.desc": "Auto-delete the alert when the fort changes again", + "slash.opt.fort.template": "template", + "slash.opt.fort.template.desc": "DTS template name", + "slash.choice.fort.clean.yes": "Yes", + "slash.choice.fort.fort_type.0": "Pokestop", + "slash.choice.fort.fort_type.1": "Gym", + "slash.opt.tracker.location": "location", + "slash.opt.tracker.location.desc": "Use a saved location instead of your default (requires distance:)", + "slash.opt.tracker.areas": "areas", + "slash.opt.tracker.areas.desc": "Restrict to specific areas (comma-separated)", + "slash.autocomplete.untrack.remove_all": "🗑️ Remove ALL rules of this type", + "slash.opt.untrack.pokemon": "pokemon", + "slash.opt.untrack.pokemon.desc": "Remove a pokemon tracking rule", + "slash.opt.untrack.pokemon.tracking": "tracking", + "slash.opt.untrack.pokemon.tracking.desc": "Pick from your existing pokemon tracking rules", + "slash.opt.untrack.raid": "raid", + "slash.opt.untrack.raid.desc": "Remove a raid tracking rule", + "slash.opt.untrack.raid.tracking": "tracking", + "slash.opt.untrack.raid.tracking.desc": "Pick from your existing raid tracking rules", + "slash.opt.untrack.egg": "egg", + "slash.opt.untrack.egg.desc": "Remove an egg tracking rule", + "slash.opt.untrack.egg.tracking": "tracking", + "slash.opt.untrack.egg.tracking.desc": "Pick from your existing egg tracking rules", + "slash.opt.untrack.quest": "quest", + "slash.opt.untrack.quest.desc": "Remove a quest tracking rule", + "slash.opt.untrack.quest.tracking": "tracking", + "slash.opt.untrack.quest.tracking.desc": "Pick from your existing quest tracking rules", + "slash.opt.untrack.invasion": "invasion", + "slash.opt.untrack.invasion.desc": "Remove an invasion tracking rule", + "slash.opt.untrack.invasion.tracking": "tracking", + "slash.opt.untrack.invasion.tracking.desc": "Pick from your existing invasion tracking rules", + "slash.opt.untrack.lure": "lure", + "slash.opt.untrack.lure.desc": "Remove a lure tracking rule", + "slash.opt.untrack.lure.tracking": "tracking", + "slash.opt.untrack.lure.tracking.desc": "Pick from your existing lure tracking rules", + "slash.opt.untrack.nest": "nest", + "slash.opt.untrack.nest.desc": "Remove a nest tracking rule", + "slash.opt.untrack.nest.tracking": "tracking", + "slash.opt.untrack.nest.tracking.desc": "Pick from your existing nest tracking rules", + "slash.opt.untrack.gym": "gym", + "slash.opt.untrack.gym.desc": "Remove a gym tracking rule", + "slash.opt.untrack.gym.tracking": "tracking", + "slash.opt.untrack.gym.tracking.desc": "Pick from your existing gym tracking rules", + "slash.opt.untrack.fort": "fort", + "slash.opt.untrack.fort.desc": "Remove a fort tracking rule", + "slash.opt.untrack.fort.tracking": "tracking", + "slash.opt.untrack.fort.tracking.desc": "Pick from your existing fort tracking rules", + "slash.opt.untrack.maxbattle": "maxbattle", + "slash.opt.untrack.maxbattle.desc": "Remove a maxbattle tracking rule", + "slash.opt.untrack.maxbattle.tracking": "tracking", + "slash.opt.untrack.maxbattle.tracking.desc": "Pick from your existing maxbattle tracking rules", + "slash.opt.area.add": "add", + "slash.opt.area.add.desc": "Add an area to your tracking", + "slash.opt.area.add.area": "area", + "slash.opt.area.add.area.desc": "Area to add", + "slash.opt.area.remove": "remove", + "slash.opt.area.remove.desc": "Remove an area from your tracking", + "slash.opt.area.remove.area": "area", + "slash.opt.area.remove.area.desc": "Area to remove", + "slash.opt.area.show": "show", + "slash.opt.area.show.desc": "Show your selected areas", + "slash.opt.area.list": "list", + "slash.opt.area.list.desc": "List every area available to you (✓ = already added)", + "slash.opt.area.overview": "overview", + "slash.opt.area.overview.desc": "Map overview of every area available to you", + "slash.opt.profile.list": "list", + "slash.opt.profile.list.desc": "List your profiles", + "slash.opt.profile.change": "change", + "slash.opt.profile.change.desc": "Switch active profile", + "slash.opt.profile.change.name": "name", + "slash.opt.profile.change.name.desc": "Profile name", + "slash.opt.profile.create": "create", + "slash.opt.profile.create.desc": "Create a new profile", + "slash.opt.profile.create.name": "name", + "slash.opt.profile.create.name.desc": "Profile name", + "slash.opt.profile.delete": "delete", + "slash.opt.profile.delete.desc": "Delete a profile", + "slash.opt.profile.delete.name": "name", + "slash.opt.profile.delete.name.desc": "Profile name", + "slash.opt.profile.settime": "settime", + "slash.opt.profile.settime.desc": "Set active-hours for the current profile", + "slash.opt.profile.settime.times": "times", + "slash.opt.profile.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.profile.cleartime": "cleartime", + "slash.opt.profile.cleartime.desc": "Clear active-hours from the current profile", + "slash.opt.profile.copyto": "copyto", + "slash.opt.profile.copyto.desc": "Copy this profile's tracking to another profile", + "slash.opt.profile.copyto.profile": "profile", + "slash.opt.profile.copyto.profile.desc": "Target profile name or number", + "slash.opt.location.add": "add", + "slash.opt.location.add.desc": "Save a named location", + "slash.opt.location.add.name": "name", + "slash.opt.location.add.name.desc": "Short name for this location (e.g. Home)", + "slash.opt.location.add.place": "place", + "slash.opt.location.add.place.desc": "Coordinates (lat,lon) or a place name", + "slash.opt.location.list": "list", + "slash.opt.location.list.desc": "List your saved locations", + "slash.opt.location.show": "show", + "slash.opt.location.show.desc": "Show one saved location", + "slash.opt.location.show.name": "name", + "slash.opt.location.show.name.desc": "Saved-location name", + "slash.opt.location.remove": "remove", + "slash.opt.location.remove.desc": "Remove a saved location", + "slash.opt.location.remove.name": "name", + "slash.opt.location.remove.name.desc": "Saved-location name (or \"default\" to clear your default location)", + "slash.opt.location.set-default": "set-default", + "slash.opt.location.set-default.desc": "Set your default location", + "slash.opt.location.set-default.place": "place", + "slash.opt.location.set-default.place.desc": "Coordinates (lat,lon) or address to set as your default location", + "slash.opt.location.remove-default": "remove-default", + "slash.opt.location.remove-default.desc": "Clear your default location", + "slash.opt.summary.quest": "quest", + "slash.opt.summary.quest.desc": "Manage quest-summary buffering", + "slash.opt.summary.quest.show": "show", + "slash.opt.summary.quest.show.desc": "Show schedule and current buffer count", + "slash.opt.summary.quest.settime": "settime", + "slash.opt.summary.quest.settime.desc": "Set the active-hours schedule for the quest summary", + "slash.opt.summary.quest.settime.times": "times", + "slash.opt.summary.quest.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.summary.quest.cleartime": "cleartime", + "slash.opt.summary.quest.cleartime.desc": "Clear the active-hours schedule", + "slash.opt.summary.quest.now": "now", + "slash.opt.summary.quest.now.desc": "Force-dispatch the currently-buffered quests", + "error.slash.unregistered_with_channel": "🛑 You need to register first. DM me with !poracle, or run !poracle in {0}.", + "error.slash.unregistered_dm_only": "🛑 You need to register first. DM me with !poracle.", + "error.slash.track.no_pokemon": "Please specify a Pokemon to track.", + "error.slash.raid.need_boss_or_level": "Please specify either a boss or a level.", + "error.slash.raid.boss_and_level": "Please specify either a boss OR a level, not both.", + "error.slash.egg.no_level": "Please specify an egg level.", + "error.slash.quest.no_reward": "Please specify exactly one reward type (pokemon, item, stardust, candy, or mega_energy).", + "error.slash.quest.exactly_one_reward": "Please specify exactly one reward type, not multiple: {0}.", + "error.slash.quest.amount_not_applicable": "`min_amount` doesn't apply to pokemon quests. For stardust, both `stardust` and `min_amount` end up in the same field — pick whichever reads better.", + "error.slash.invasion.no_grunt": "Please specify a grunt type.", + "error.slash.incident.no_type": "Please specify an incident type.", + "error.slash.lure.no_type": "Please specify a lure type.", + "error.slash.nest.no_pokemon": "Please specify a Pokemon for the nest.", + "error.slash.maxbattle.no_pokemon": "Please specify a Pokemon for the max battle.", + "error.slash.fort.no_type": "Please specify a fort type (pokestop or gym).", + "error.slash.untrack.no_subcommand": "Please choose what kind of tracking rule to remove.", + "error.slash.untrack.no_tracking": "Please pick a tracking rule to remove.", + "error.slash.info.no_subcommand": "Please choose an info sub-command (pokemon / rarity / shiny / weather).", + "error.slash.info.no_pokemon": "Please specify a pokemon name or dex id.", + "error.slash.info.unknown_subcommand": "Unknown info sub-command.", + "error.slash.area.no_subcommand": "Please choose an area sub-command (add / remove / show).", + "error.slash.area.no_area": "Please specify an area name.", + "error.slash.area.unknown_subcommand": "Unknown area sub-command.", + "error.slash.profile.no_subcommand": "Please choose a profile sub-command (list / change / create / delete / settime / cleartime / copyto).", + "error.slash.profile.no_name": "Please specify a profile name.", + "error.slash.profile.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.profile.no_target": "Please specify a target profile to copy to.", + "error.slash.profile.unknown_subcommand": "Unknown profile sub-command.", + "error.slash.summary.no_alert_type": "Please choose an alert type (e.g. quest).", + "error.slash.summary.no_action": "Please choose an action (show / settime / cleartime / now).", + "error.slash.summary.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.summary.unknown_action": "Unknown summary action.", + "error.slash.location.no_subcommand": "Please choose a location sub-command (add / list / show / remove / remove-default).", + "error.slash.location.no_name": "Please specify a saved-location name.", + "error.slash.location.empty": "Please specify coordinates or a place name.", + "error.slash.location.unknown_subcommand": "Unknown location sub-command.", + "error.slash.location.no_geocoder": "Place-name lookup is not configured. Please provide coordinates like 51.28, 1.08.", + "error.slash.location.geocode_failed": "Could not find a location for \"{0}\".", + "msg.help.text": "**Available commands:**\n{0}track [iv:N] [cp:N] [level:N] [d:N] — Track pokemon\n{0}untrack — Remove pokemon tracking\n{0}raid [d:N] — Track raids\n{0}egg [d:N] — Track eggs\n{0}quest — Track quests\n{0}invasion [everything|] — Track invasions\n{0}lure — Track lures\n{0}gym [slot_changes] — Track gyms\n{0}nest — Track nests\n{0}maxbattle — Track max battles\n{0}fort — Track fort updates\n{0}tracked — Show all tracking\n{0}script — Export tracking as commands\n{0}area [list|add|remove] — Manage areas\n{0}location — Set location\n{0}profile [list|add|remove|switch] — Manage profiles\n{0}language — Set language\n{0}start / {0}stop — Enable/disable alerts\n{0}version — Show version", + "cmd.poracle_admin": "poracle-admin", + "cmd.pa": "pa", + "cmd.poracle_admin.not_admin": "This command is reserved for administrators.", + "cmd.poracle_admin.unknown_group": "Unknown subgroup. Try `!poracle-admin` for the list.", + "cmd.poracle_admin.unknown_sub": "Unknown subcommand for `{0}`. Try `!poracle-admin {0}` to see what's available.", + "cmd.poracle_admin.help.admin_only": "This command is reserved for server administrators. Each subgroup performs a live operations task.", + "cmd.poracle_admin.help.groups": "Available subgroups:", + "cmd.poracle_admin.help_intro": "🛠️ Poracle Admin\n\nLive operations subgroups (administrators only):", + "cmd.poracle_admin.stub": "(not yet implemented)", + "cmd.poracle_admin.group.slash.desc": "slash-command registration lifecycle", + "cmd.poracle_admin.group.reload.desc": "reload DTS, geofence, or in-memory state", + "cmd.poracle_admin.group.emoji.desc": "list, reload, or test emoji config", + "cmd.poracle_admin.group.reconcile.desc": "Discord role reconciliation (immediate or per-user)", + "cmd.poracle_admin.group.cache.desc": "cache stats and clear", + "cmd.poracle_admin.group.ratelimit.desc": "inspect and reset alert-bucket rate limits", + "cmd.poracle_admin.group.summary.desc": "summary buffer inspection and forced dispatch", + "cmd.poracle_admin.group.status.desc": "live health snapshot", + "cmd.poracle_admin.group.maintenance.desc": "pause/resume outbound delivery", + "cmd.poracle_admin.group.config.desc": "view effective merged config with secrets redacted", + "cmd.poracle_admin.group.warnings.desc": "inspect captured WARN/ERROR log entries (startup + rolling buffers)", + "cmd.poracle_admin.reload.help.intro": "Reload runtime state from disk or database.", + "cmd.poracle_admin.reload.dts.desc": "`dts` — reload DTS templates and partials from disk", + "cmd.poracle_admin.reload.geofence.desc": "`geofence` — reload geofence files and refresh state", + "cmd.poracle_admin.reload.state.desc": "`state` — reload tracking rules and humans from MySQL (bypasses debounce)", + "cmd.poracle_admin.reload.dts.success": "✅ DTS reloaded in {0}ms ({1} templates)", + "cmd.poracle_admin.reload.geofence.success": "✅ Geofence reloaded in {0}ms ({1} fences, {2} tracking rules)", + "cmd.poracle_admin.reload.state.success": "✅ State reloaded in {0}ms ({1} tracking rules, {2} active humans)", + "cmd.poracle_admin.reload.error": "❌ Reload failed: {0}", + "cmd.poracle_admin.emoji.help.intro": "😀 Emoji config — inspect and manage emoji.json + Discord guild emojis.\n\nSubcommands:", + "cmd.poracle_admin.emoji.list.desc": "`list` — list all configured emoji keys with per-platform resolutions", + "cmd.poracle_admin.emoji.reload.desc": "`reload` — reload config/emoji.json from disk", + "cmd.poracle_admin.emoji.test.desc": "`test ` — resolve one emoji key for the current platform", + "cmd.poracle_admin.emoji.upload.desc": "`upload [overwrite]` — upload uicons-based emojis to the guild and write a new emoji.json (Discord-only)", + "cmd.poracle_admin.emoji.discord_config.desc": "`discord-config` — dump emoji.json from the current guild state, no uploads (Discord-only)", + "cmd.poracle_admin.emoji.discord_only": "ℹ️ This subcommand requires a Discord bot with guild access.", + "cmd.poracle_admin.emoji.not_loaded": "ℹ️ Emoji config not loaded (DTS renderer not configured).", + "cmd.poracle_admin.emoji.list.header": "😀 Emoji configuration — {0} keys loaded", + "cmd.poracle_admin.emoji.list.row.key": " {0}:", + "cmd.poracle_admin.emoji.list.row.platform": " {0}: {1}", + "cmd.poracle_admin.emoji.reload.success": "✅ Emoji config reloaded — {0} keys (took {1}ms).", + "cmd.poracle_admin.emoji.reload.error": "❌ Emoji reload failed: {0}", + "cmd.poracle_admin.emoji.test.success": "🔎 {0} on {1}: {2}", + "cmd.poracle_admin.emoji.test.not_found": "ℹ️ Emoji key \"{0}\" not found in the loaded config.", + "cmd.poracle_admin.emoji.test.usage": "Usage: !poracle-admin emoji test ", + "cmd.poracle_admin.reconcile.help.intro": "🔄 Discord role reconciliation — trigger immediately instead of waiting for the periodic timer.", + "cmd.poracle_admin.reconcile.run.desc": "`run` — reconcile all guild members now (blocks until complete)", + "cmd.poracle_admin.reconcile.user.desc": "`user ` — reconcile a single Discord user by snowflake ID", + "cmd.poracle_admin.reconcile.not_configured": "❌ Discord reconciliation is not configured (Telegram-only deploy, or check_role=false).", + "cmd.poracle_admin.reconcile.run.success": "✅ Discord reconciliation complete (took {0}ms).", + "cmd.poracle_admin.reconcile.run.error": "❌ Reconciliation failed: {0}", + "cmd.poracle_admin.reconcile.user.success": "✅ Reconciled discord:user/{0} (took {1}ms).", + "cmd.poracle_admin.reconcile.user.error": "❌ Failed to reconcile discord:user/{0}: {1}", + "cmd.poracle_admin.reconcile.user.usage": "Usage: !poracle-admin reconcile user ", + "cmd.poracle_admin.cache.help.intro": "🗺️ Geocoder cache — inspect counters or drop the in-memory layer.", + "cmd.poracle_admin.cache.stats.desc": "`stats` — geocoder cache stats", + "cmd.poracle_admin.cache.clear.desc": "`clear geocoder` — drop the in-memory geocoder cache", + "cmd.poracle_admin.cache.not_configured": "Geocoder cache is not configured on this instance.", + "cmd.poracle_admin.cache.stats.header": "🗺️ Geocoder cache", + "cmd.poracle_admin.cache.stats.row.memory_entries": " Memory entries: {0}", + "cmd.poracle_admin.cache.stats.row.disk_entries": " Disk entries: {0}", + "cmd.poracle_admin.cache.stats.row.hits_memory": " Hits (memory): {0}", + "cmd.poracle_admin.cache.stats.row.hits_disk": " Hits (disk): {0}", + "cmd.poracle_admin.cache.stats.row.misses": " Misses: {0}", + "cmd.poracle_admin.cache.stats.row.hit_rate": " Hit rate: {0}%", + "cmd.poracle_admin.cache.clear.usage_hint": "Specify what to clear, e.g. `!poracle-admin cache clear geocoder`", + "cmd.poracle_admin.cache.clear.geocoder.success": "✅ Geocoder memory cache cleared — {0} entries dropped (disk untouched).", + "cmd.poracle_admin.ratelimit.help.intro": "🚦 Rate-limit introspection — inspect or reset per-destination alert and summary buckets.", + "cmd.poracle_admin.ratelimit.not_configured": "ℹ️ Alert rate limiter is not configured on this instance.", + "cmd.poracle_admin.ratelimit.list.desc": "`list` — show all targets currently breached or banned", + "cmd.poracle_admin.ratelimit.show.desc": "`show ` — detailed state for one target (both buckets)", + "cmd.poracle_admin.ratelimit.reset.desc": "`reset ` — clear counters and violation history", + "cmd.poracle_admin.ratelimit.userlist.desc": "`userlist` — show currently disabled users (shortcut for !userlist disabled)", + "cmd.poracle_admin.ratelimit.list.empty": "🟢 No targets currently rate-limited.", + "cmd.poracle_admin.ratelimit.list.header_title": "Currently rate-limited targets", + "cmd.poracle_admin.ratelimit.list.bucket_header": " {0} bucket ({1} breached / {2} banned):", + "cmd.poracle_admin.ratelimit.list.row": "count {0}/{1}, {2}", + "cmd.poracle_admin.ratelimit.list.status.banned": "banned for {0}", + "cmd.poracle_admin.ratelimit.list.status.breached": "window resets in {0}", + "cmd.poracle_admin.ratelimit.show.header": "🚦 Rate-limit state for {0}", + "cmd.poracle_admin.ratelimit.show.bucket_header": "{0} bucket:", + "cmd.poracle_admin.ratelimit.show.empty": "🟢 No recorded activity for {0} in either bucket.", + "cmd.poracle_admin.ratelimit.show.no_data": "(no activity in this bucket)", + "cmd.poracle_admin.ratelimit.show.no_violations": "No violations.", + "cmd.poracle_admin.ratelimit.show.violations_count": "Violations (24h): {0}", + "cmd.poracle_admin.ratelimit.show.banned_until": "Banned until: {0} (in {1})", + "cmd.poracle_admin.ratelimit.show.status.under_limit": "under limit", + "cmd.poracle_admin.ratelimit.show.status.over_limit": "over limit", + "cmd.poracle_admin.ratelimit.show.row.count": " Count: {0} / {1} ({2})\n", + "cmd.poracle_admin.ratelimit.show.row.window": " Window: opened {0} ago, resets in {1}\n", + "cmd.poracle_admin.ratelimit.reset.success": "✅ Reset rate-limit state for {0} (cleared alert + summary buckets, violations reset).", + "cmd.poracle_admin.ratelimit.reset.no_state": "ℹ️ No rate-limit state to reset for {0}.", + "cmd.poracle_admin.ratelimit.reset.note": "Note: admin_disable is NOT touched. If the user was auto-disabled by the rate-limiter, they still need to !poracle to re-register.", + "cmd.poracle_admin.ratelimit.usage.show": "Usage: !poracle-admin ratelimit show ", + "cmd.poracle_admin.ratelimit.usage.reset": "Usage: !poracle-admin ratelimit reset ", + "cmd.poracle_admin.ratelimit.userlist.lookup_failed": "❌ Could not find !userlist command in the registry.", + "cmd.poracle_admin.summary.help.intro": "📦 Summary buffer — inspect who has quests buffered and force-dispatch on demand.", + "cmd.poracle_admin.summary.not_configured": "ℹ️ Summary buffer is not configured on this instance.", + "cmd.poracle_admin.summary.list.desc": "`list` — show all users with anything buffered", + "cmd.poracle_admin.summary.show.desc": "`show ` — inspect one user's buffered entries", + "cmd.poracle_admin.summary.fire.desc": "`fire [alertType]` — force-dispatch a user's buffer immediately", + "cmd.poracle_admin.summary.list.empty": "🟢 No users have anything buffered.", + "cmd.poracle_admin.summary.list.header": "📦 Summary buffer — {0} users with {1} buffered entries", + "cmd.poracle_admin.summary.list.user_header": " {0}", + "cmd.poracle_admin.summary.list.row": " {0}: {1} entries (next fires: {2})", + "cmd.poracle_admin.summary.list.next_fire.none": "n/a", + "cmd.poracle_admin.summary.show.header": "📦 Summary buffer for {0}", + "cmd.poracle_admin.summary.show.empty": "🟢 No buffered entries for {0}.", + "cmd.poracle_admin.summary.show.alert_type": " {0}: {1} entries", + "cmd.poracle_admin.summary.show.usage": "Usage: !poracle-admin summary show ", + "cmd.poracle_admin.summary.fire.success": "✅ Dispatched summary for {0} / {1} — {2} entries delivered.", + "cmd.poracle_admin.summary.fire.usage": "Usage: !poracle-admin summary fire [alertType]", + "cmd.poracle_admin.summary.show.reward_row": " Reward type {0}, reward {1}{2} — {3} stops", + "cmd.poracle_admin.summary.show.reward_more": " ... ({0} more reward groups)", + "cmd.poracle_admin.summary.show.form_suffix": " form {0}", + "cmd.poracle_admin.maintenance.help.intro": "🛠️ **!poracle-admin maintenance** — live control over outbound delivery.\n\nSubcommands:", + "cmd.poracle_admin.maintenance.no_dispatcher": "ℹ️ Dispatcher is not available on this instance.", + "cmd.poracle_admin.maintenance.no_reason": "(no reason given)", + "cmd.poracle_admin.maintenance.pause.desc": "`pause [reason...]` (alias: `start`) — halt outbound delivery (webhooks still ingest, match, render, and queue)", + "cmd.poracle_admin.maintenance.resume.desc": "`resume` (alias: `stop`) — lift a previous pause and drain queued jobs", + "cmd.poracle_admin.maintenance.status.desc": "`status` — show current paused/running state and queue depth", + "cmd.poracle_admin.maintenance.pause.new": "🔴 Outbound delivery paused: {0}", + "cmd.poracle_admin.maintenance.pause.detail": "Webhooks still ingest, match, render, and queue — the dispatcher holds them until !poracle-admin maintenance resume.", + "cmd.poracle_admin.maintenance.pause.already": "ℹ️ Already paused since {0} ({1} ago): {2}", + "cmd.poracle_admin.maintenance.resume.success": "🟢 Outbound delivery resumed (was paused for {0}: {1})", + "cmd.poracle_admin.maintenance.resume.detail": "Queued messages are draining.", + "cmd.poracle_admin.maintenance.resume.not_paused": "ℹ️ Not currently paused.", + "cmd.poracle_admin.maintenance.status.running": "🟢 Delivery is running.", + "cmd.poracle_admin.maintenance.status.paused": "🔴 PAUSED — {0} (for {1})", + "cmd.poracle_admin.maintenance.status.queued": "{0} jobs queued waiting (across all platforms — Discord {1}, Telegram {2})", + "cmd.poracle_admin.status.help.intro": "!poracle-admin status — current health snapshot. Add -v for verbose mode (per-route Discord detail, full webhook per-type breakdown).", + "cmd.poracle_admin.status.header": "🛠️ Poracle Admin — Status", + "cmd.poracle_admin.status.paused_banner": "🔴 PAUSED — {0} (since {1} ago)\n Outbound delivery is held. Webhooks still ingest and queue.", + "cmd.poracle_admin.status.value.na": "n/a", + "cmd.poracle_admin.status.value.none": "none", + "cmd.poracle_admin.status.section.build": "**Build / Uptime**", + "cmd.poracle_admin.status.section.webhooks": "**Webhooks**", + "cmd.poracle_admin.status.section.render_queue": "**Render queue**", + "cmd.poracle_admin.status.section.delivery": "**Delivery**", + "cmd.poracle_admin.status.section.discord_rate": "**Discord rate**", + "cmd.poracle_admin.status.section.telegram_rate": "**Telegram rate**", + "cmd.poracle_admin.status.section.alert_limits": "**Alert limits**", + "cmd.poracle_admin.status.section.summary_buffer": "**Summary buffer**", + "cmd.poracle_admin.status.label.summary_buffer_totals": "Entries: {0} across {1} bucket(s)", + "cmd.poracle_admin.status.label.summary_buffer_top": "Top users:", + "cmd.poracle_admin.status.label.summary_buffer_user_row": " {0} ({1}): {2} entries", + "cmd.poracle_admin.status.section.tracking": "**Tracking**", + "cmd.poracle_admin.status.section.mysql": "**MySQL**", + "cmd.poracle_admin.status.label.version": "Version: {0} (commit {1}, built {2})", + "cmd.poracle_admin.status.label.uptime": "Uptime: {0}", + "cmd.poracle_admin.status.label.webhooks_rate": "{0} / {1} / {2} per min over last 5/15/60 min", + "cmd.poracle_admin.status.label.webhooks_by_type": "By type (last 60 min):", + "cmd.poracle_admin.status.label.delivery_discord": "Discord in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_telegram": "Telegram in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_webhook": "Webhook in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_queue_depth": "Queue depth: {0} (capacity not exposed)", + "cmd.poracle_admin.status.label.discord_routes": "Routes near limit: {0}", + "cmd.poracle_admin.status.label.discord_global": "Global tokens: {0} / {1}", + "cmd.poracle_admin.status.label.discord_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.discord_routes_detail": "Routes near limit (detail):", + "cmd.poracle_admin.status.label.telegram_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.telegram_backoff": "Current backoff: {0}", + "cmd.poracle_admin.status.label.alert_limits_counts": "Breached: alert={0}, summary={1} · Banned: {2}", + "cmd.poracle_admin.status.label.tracking_total": "Total tracking rules: {0}", + "cmd.poracle_admin.status.label.tracking_active_humans": "Active humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans": "Registered humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans_error": "Registered humans: n/a (error)", + "cmd.poracle_admin.status.label.tracking_type": "{0}: {1}", + "cmd.poracle_admin.status.label.mysql_ping_ok": "Ping: ok", + "cmd.poracle_admin.status.label.mysql_ping_fail": "Ping: failed ({0})", + "cmd.poracle_admin.status.label.mysql_pool": "Connections: {0}/{1} open ({2} in use, {3} idle, waits={4})", + "cmd.poracle_admin.status.tracking_type.pokemon": "pokemon", + "cmd.poracle_admin.status.tracking_type.raid": "raid", + "cmd.poracle_admin.status.tracking_type.egg": "egg", + "cmd.poracle_admin.status.tracking_type.quest": "quest", + "cmd.poracle_admin.status.tracking_type.invasion": "invasion", + "cmd.poracle_admin.status.tracking_type.lure": "lure", + "cmd.poracle_admin.status.tracking_type.nest": "nest", + "cmd.poracle_admin.status.tracking_type.gym": "gym", + "cmd.poracle_admin.status.tracking_type.fort": "fort", + "cmd.poracle_admin.status.tracking_type.maxbattle": "maxbattle", + "cmd.poracle_admin.slash.help.intro": "**!poracle-admin slash** — slash-command registration lifecycle.\nSubcommands:", + "cmd.poracle_admin.slash.discord_only": "❌ Slash commands are Discord-only and cannot be managed from Telegram.", + "cmd.poracle_admin.slash.not_configured": "❌ Slash commands are not configured (Discord disabled or [discord.slash_commands] enabled=false).", + "cmd.poracle_admin.slash.sync.desc": "push the current command set to Discord (fingerprint-cached, skips if unchanged)", + "cmd.poracle_admin.slash.sync.success": "✅ Slash sync complete ({0}ms)", + "cmd.poracle_admin.slash.sync.error": "❌ Slash sync failed: {0}", + "cmd.poracle_admin.slash.force_resync.desc": "clear fingerprint cache and push unconditionally", + "cmd.poracle_admin.slash.force_resync.success": "✅ Force-resync complete ({0}ms)", + "cmd.poracle_admin.slash.force_resync.error": "❌ Force-resync failed: {0}", + "cmd.poracle_admin.slash.clear_global.desc": "remove all globally-registered Discord slash commands", + "cmd.poracle_admin.slash.clear_global.success": "✅ Global slash commands cleared.", + "cmd.poracle_admin.slash.clear_global.error": "❌ Clear global failed: {0}", + "cmd.poracle_admin.slash.clear_guild.desc": "remove slash commands from one guild (requires guild_id arg)", + "cmd.poracle_admin.slash.clear_guild.needs_arg": "❌ Usage: `!poracle-admin slash clear-guild `", + "cmd.poracle_admin.slash.clear_guild.success": "✅ Slash commands cleared from guild {0}.", + "cmd.poracle_admin.slash.clear_guild.error": "❌ Clear guild failed: {0}", + "cmd.poracle_admin.slash.status.desc": "show last sync timestamp and fingerprint per scope", + "cmd.poracle_admin.slash.status.header": "**Slash command registration status:**", + "cmd.poracle_admin.slash.status.scope_row": " **{0}**: last synced {1} · fingerprint `{2}`", + "cmd.poracle_admin.slash.status.never_synced": "never", + "cmd.poracle_admin.slash.status.ago": "{0} ago", + "cmd.poracle_admin.slash.status.error": "❌ Status read failed: {0}", + "cmd.poracle_admin.config.help.intro": "⚙️ Config viewer — show effective merged config with secrets redacted.\nSubcommands:", + "cmd.poracle_admin.config.keys.desc": "list section names with key counts", + "cmd.poracle_admin.config.section.desc": "show just that section (e.g. `!poracle-admin config discord`)", + "cmd.poracle_admin.config.full.desc": "show the full config (all sections, secrets redacted)", + "cmd.poracle_admin.config.keys.header": "⚙️ Config sections:", + "cmd.poracle_admin.config.keys.row": " {0}: {1} keys", + "cmd.poracle_admin.config.unknown_section": "Unknown config section: `{0}`. Use `!poracle-admin config keys` to list valid sections, or `!poracle-admin config search ` to search across all sections.", + "cmd.poracle_admin.config.search.desc": "find keys whose path or value contains the term across every section (e.g. `!poracle-admin config search dm`)", + "cmd.poracle_admin.config.search.usage": "Usage: `!poracle-admin config search ` — e.g. `search dm`, `search shlink`, `search 3030`.", + "cmd.poracle_admin.config.search.header": "🔍 `{0}` — {1} match(es):", + "cmd.poracle_admin.config.search.no_matches": "No config keys or values match `{0}`.", + "cmd.poracle_admin.config.empty_section": "Section `{0}` has no configurable fields.", + "cmd.poracle_admin.config.not_loaded": "❌ Config not loaded.", + "cmd.poracle_admin.warnings.help.intro": "🛠️ Captured warnings — inspect in-memory WARN/ERROR log entries.\n\nSubcommands:\n (no arg) — show both startup and recent buffers\n `startup` — show only the startup buffer (first 200 entries, frozen after init)\n `recent` — show only the rolling buffer (last 50 entries)\n `clear` — empty the rolling buffer (startup is immutable)", + "cmd.poracle_admin.warnings.not_configured": "ℹ️ Log buffer is not configured on this instance.", + "cmd.poracle_admin.warnings.section.startup": "🛠️ Captured warnings — startup ({0} entries)", + "cmd.poracle_admin.warnings.section.recent": "🛠️ Captured warnings — recent ({0} entries)", + "cmd.poracle_admin.warnings.empty.startup": "🟢 No startup warnings captured.", + "cmd.poracle_admin.warnings.empty.recent": "🟢 No recent warnings.", + "cmd.poracle_admin.warnings.entry_row": " {0} {1} {2} {3}", + "cmd.poracle_admin.warnings.cleared": "✅ Cleared {0} entries from the rolling buffer (startup buffer is unaffected).", + "cmd.poracle_admin.warnings.startup.desc": "`startup` — show only the startup buffer (frozen after init)", + "cmd.poracle_admin.warnings.recent.desc": "`recent` — show only the rolling buffer (last 50 entries)", + "cmd.poracle_admin.warnings.clear.desc": "`clear` — empty the rolling buffer", + "cmd.maintenance.active_suffix": "🔧 Maintenance mode is active — alerts are not being delivered.", + "showcase_focus_pokemon": "Pokémon", + "showcase_focus_type": "Type", + "showcase_focus_alignment": "Alignment", + "showcase_focus_class": "Class", + "showcase_focus_family": "Family", + "showcase_focus_buddy": "Buddy", + "showcase_focus_generation": "Generation", + "showcase_focus_hatched": "Hatched", + "showcase_focus_mega": "Mega", + "showcase_focus_shiny": "Shiny", + "showcase_class_ultra_beast": "Ultra Beast" } diff --git a/processor/internal/i18n/locale/pl.json b/processor/internal/i18n/locale/pl.json index 709d5016f..b34b979e5 100644 --- a/processor/internal/i18n/locale/pl.json +++ b/processor/internal/i18n/locale/pl.json @@ -58,6 +58,11 @@ "tracking.pvp_little": "littlepvp", "tracking.pvp_great": "greatpvp", "tracking.pvp_ultra": "ultrapvp", + "tracking.pvp_mega_any": "mega", + "tracking.pvp_mega_x": "mega x", + "tracking.pvp_mega_y": "mega y", + "tracking.mega_x_label": "X", + "tracking.mega_y_label": "Y", "tracking.level_cap_fmt": "level cap: {0}", "tracking.everything": "Everything", "tracking.unknown_monster": "Unknown monster", @@ -81,10 +86,14 @@ "tracking.reward_fmt": "Reward: **{0}**", "tracking.reward_stardust_min_fmt": "{0} or more stardust", "tracking.reward_stardust": "stardust", + "tracking.reward_pokecoin_min_fmt": "{0} or more pokecoins", + "tracking.reward_pokecoin": "pokecoins", "tracking.reward_mega_energy": "mega energy", "tracking.reward_mega_energy_fmt": "mega energy {0}", "tracking.reward_candy": "candy", "tracking.reward_candy_fmt": "candy {0}", + "tracking.reward_any_pokemon": "any pokemon", + "tracking.reward_any_item": "any item", "tracking.reward_min_fmt": "minimum {0}", "tracking.grunt_type_fmt": "Grunt type: **{0}**", "tracking.min_avg_spawn": "Min avg. spawn {0}/hour", @@ -108,10 +117,68 @@ "tracking.template_not_found": "Template \"{0}\" does not exist.", "tracking.warn_template_not_found": "Template \"{0}\" not found for type {1}/{2}. Tracking saved but alerts may not render.", "tracking.id_hint": "To remove a specific entry, use its id — e.g. `{0}untrack id:45` or `{0}raid remove id:12`", + "tracking.id_hint_slash": "To remove a specific entry, run `/untrack ` (e.g. `/untrack raid`) and pick it from the list.", + "tracking.list_attached": "Your tracking list is long ({0} rules) — attached as a file.", "tracking.removed_prefix": "Removed: ", "tracking.uid_not_found": "id:{0} not found", + "tracking.override_location_fmt": "@ {0}", + "tracking.override_areas_fmt": "in {0}", "cmd.track": "track", "cmd.untrack": "untrack", + "cmd.mute": "mute", + "cmd.unmute": "unmute", + "msg.mute.unavailable": "Mute feature isn't enabled here.", + "msg.mute.usage": "Valid commands are `{0}mute [duration:1h]`", + "msg.mute.usage_pokemon": "Valid commands are `{0}mute pokemon [duration:1h]`", + "msg.mute.usage_gym": "Valid commands are `{0}mute gym [duration:1h]`", + "msg.mute.usage_area": "Valid commands are `{0}mute area [duration:1h]`", + "msg.mute.usage_id_scope": "Valid commands are `{0}mute {1} [duration:1h]`", + "msg.mute.bad_duration": "Invalid duration: {0}", + "msg.mute.id_not_supported": "`!mute id:N` / `!mute id:N` aren't supported yet — entity scopes (gym, pokemon, area, pokestop, station, everything) work today. Per-rule muting by UID is a follow-up.", + "msg.mute.bad_uid": "`{0}` isn't a valid tracking rule UID. Use `!tracked` to see your rule UIDs.", + "msg.mute.unknown_area": "`{0}` isn't in your available areas. Use `!area` to see what you can mute.", + "msg.mute.no_pokemon": "I don't know a pokemon called `{0}`.", + "msg.mute.everything_label": "everything", + "msg.mute.added": "🔇 Muted {0} for {1}.", + "msg.mute.removed": "✅ Unmuted {0}.", + "msg.mute.none_found": "No active mute for {0}.", + "msg.mute.cleared_all": "Cleared {0} active mutes.", + "msg.unmute.usage": "Valid commands are `{0}unmute `, `{0}unmute all`", + "msg.unmute.usage_pokemon": "Valid commands are `{0}unmute pokemon `", + "msg.unmute.usage_gym": "Valid commands are `{0}unmute gym `", + "msg.unmute.usage_area": "Valid commands are `{0}unmute area `", + "section.property_mutes": "Property mutes (apply across all tracking):", + "section.property_mutes.left": "({0} left)", + "msg.button.expired": "This alert has expired.", + "msg.button.unavailable": "This button is no longer available.", + "msg.button.wrong_target": "This button doesn't apply here.", + "msg.button.unauthorized": "This button isn't for you.", + "msg.button.unidentified": "Couldn't identify you to handle that click.", + "msg.button.unconfigured": "This button isn't configured.", + "msg.button.action_failed": "Couldn't complete that action: {0}", + "msg.button.action_failed_generic": "Couldn't complete that action.", + "msg.button.cooldown": "Slow down — try that again in a moment.", + "msg.button.actions_not_wired": "Button actions aren't wired here.", + "msg.button.not_implemented": "The {0} action isn't implemented yet.", + "msg.button.responses_not_wired": "Response rendering isn't wired here.", + "msg.button.response_failed": "Couldn't render that response: {0}", + "msg.button.done": "Done.", + "msg.button.missing_scope": "Button is missing a scope — operator config bug.", + "msg.button.missing_target": "Couldn't find a {0} to mute on this alert.", + "msg.button.no_dm_target": "Couldn't identify you to send the message.", + "msg.button.dm_failed": "Couldn't send to your DM: {0}", + "msg.button.unsubscribe_failed": "Couldn't unsubscribe — please try again.", + "msg.button.unsubscribe_already": "Those tracking rules were already removed.", + "msg.button.unsubscribed": "✅ Unsubscribed from {0} tracking rule(s).", + "msg.button.redeliver_sent": "📬 Sent to your DM.", + "msg.mute.scope_gym": "gym", + "msg.mute.scope_pokemon": "pokemon", + "msg.mute.scope_area": "area", + "msg.mute.scope_pokestop": "pokestop", + "msg.mute.scope_station": "station", + "msg.mute.scope_tracking": "tracking rule", + "cmd.mute.usage": "**{0}mute** — silence alerts for a specific gym, pokemon, area, pokestop, station, or everything for a time-bounded window.\n\n• `{0}mute everything [duration:1h]` — silence ALL alerts for the given duration\n• `{0}mute gym [duration:1h]` — silence alerts for one gym\n• `{0}mute pokemon [duration:1h]` — silence alerts for one pokemon species\n• `{0}mute area [duration:1h]` — silence alerts in one area\n• `{0}mute pokestop [duration:1h]` — silence alerts for one pokestop\n• `{0}mute station [duration:1h]` — silence alerts for one station\n\nDuration defaults to 1h if omitted. Use `{0}unmute ` to remove a mute early, or `{0}tracked` to see active mutes.", + "cmd.track.usage": "**{0}track** — set up pokemon tracking rules.\n\n• `{0}track ` — track a specific pokemon (by name or dex id) at default 100m\n• `{0}track everything` — track every pokemon (admin-permitted; see `{0}help everything`)\n• `{0}track iv:100` — filter by IV percent (`iv:90-100` for range, `miniv:90`/`maxiv:99` for one-sided)\n• `{0}track cp:1500-2500` — filter by CP\n• `{0}track level:25-35` — filter by level\n• `{0}track atk:14-15 def:14-15 sta:14-15` — filter by individual IV stats\n• `{0}track d:500` — only alert within 500m of your location\n• `{0}track location:Home d:500` — within 500m of a saved location\n• `{0}track area:london,paris` — only in named areas (replaces your default areas)\n• `{0}track great5 ultra10` — PVP filters (great/ultra/little league, rank threshold, optional cap)\n• `{0}track gen:1 type:water` — generation and type filters (alongside `everything`)\n• `{0}track rarity:rare-ultra` — rarity-tier filter\n• `{0}track clean` / `edit` — auto-delete on TTH expiry / edit-in-place\n• `{0}track remove ` or `{0}untrack ` — remove\n• `{0}untrack id:42` — remove one rule by id (see `{0}tracked` for ids)\n\nMultiple filters combine. See `{0}tracked` for what's currently active.", "cmd.raid": "raid", "cmd.egg": "egg", "cmd.quest": "quest", @@ -129,6 +196,8 @@ "cmd.fort": "fort", "cmd.help": "help", "cmd.info": "info", + "cmd.info.poracle.moved": "→ This view has moved to `!poracle-admin status` — please use that instead.", + "cmd.info.config.moved": "→ This view has moved to `!poracle-admin config` — please use that instead.", "cmd.start": "start", "cmd.stop": "stop", "cmd.tracked": "tracked", @@ -163,6 +232,8 @@ "cmd.poracle_id": "poracle-id", "arg.remove": "remove", "arg.everything": "everything", + "arg.all_pokemon": "all pokemon", + "arg.all_items": "all items", "arg.any": "any", "arg.clean": "clean", "arg.edit": "edit", @@ -170,6 +241,7 @@ "arg.list": "list", "arg.add": "add", "arg.show": "show", + "arg.default": "default", "arg.overview": "overview", "arg.dryrun": "dryrun", "arg.reset": "reset", @@ -182,6 +254,7 @@ "arg.shiny": "shiny", "arg.gmax": "gmax", "arg.stardust": "stardust", + "arg.pokecoin": "pokecoins", "arg.energy": "energy", "arg.candy": "candy", "arg.pvp": "pvp", @@ -248,7 +321,10 @@ "arg.prefix.maxsize": "maxsize", "arg.prefix.gen": "gen", "arg.prefix.cap": "cap", + "arg.mega": "mega", + "arg.prefix.mega": "mega", "arg.prefix.form": "form", + "arg.prefix.costume": "costume", "arg.prefix.template": "template", "arg.prefix.gym": "gym", "arg.prefix.move": "move", @@ -263,13 +339,17 @@ "arg.prefix.littlehigh": "littlehigh", "arg.prefix.littlecp": "littlecp", "arg.prefix.stardust": "stardust", + "arg.prefix.pokecoin": "pokecoins", "arg.prefix.energy": "energy", "arg.prefix.candy": "candy", + "arg.prefix.amount": "amount", "arg.prefix.name": "name", "arg.prefix.user": "user", "arg.prefix.channel": "channel", "arg.prefix.guild": "guild", "arg.prefix.language": "language", + "arg.prefix.area": "area", + "arg.prefix.location": "location", "arg.prefix.mon": "mon", "arg.prefix.tue": "tue", "arg.prefix.wed": "wed", @@ -323,21 +403,26 @@ "section.maxbattles.none": "You're not tracking any max battles", "msg.no_pokemon": "Nie znaleziono Pokemona", "msg.form_not_found": "Form `{0}` not recognised. Use `{1}info ` to see available forms.", + "msg.costume_not_found": "Costume `{0}` not recognised. Use `{1}info costumes` to see available costumes.", + "msg.no_costume": "no costume", "msg.nothing_to_remove": "Nothing to remove", "msg.no_levels": "No levels specified", "msg.no_egg_levels": "No egg levels specified", "msg.no_raid_target": "No raid levels or pokemon specified", "msg.no_lure_type": "No lure type specified", "msg.no_quest_type": "No quest type specified", + "msg.quest.amount_not_applicable": "`amount:N` doesn't apply to pokemon quests — pokemon rewards have no minimum amount.", + "msg.quest.bulk_not_permitted": "You do not have permission to track all pokemon or items at once. Track specific rewards instead.", "msg.removed_n": "Removed {0} tracking rules", "msg.egg.usage": "Valid commands are e.g. `{0}egg level:5`, `{0}egg legendary`, `{0}egg remove everything`", "msg.raid.usage": "Valid commands are e.g. `{0}raid level:5`, `{0}raid pikachu`, `{0}raid remove everything`", "msg.track.usage": "Valid commands are e.g. `{0}track pikachu iv:100`, `{0}track everything iv:90`, `{0}track remove pikachu`", "msg.track.everything_no_filters": "This would result in too many alerts. You need to provide additional filters to limit the number of valid candidates.", "msg.track.invalid_cap": "This level cap is not supported, valid choices are: {0}", - "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest energy:charizard`", + "msg.track.no_mega_form": "⚠️ {0} has no Mega {1} form — this PVP rule will never match.", + "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest pokecoins:10`, `{0}quest energy:charizard`", "msg.quest.edit_summary_conflict": "`edit` and `summary` are mutually exclusive — pick one.", - "msg.summary.usage": "Usage: `{0}summary quest [settime |cleartime|now]`", + "msg.summary.usage": "Valid commands are `{0}summary quest`, `{0}summary quest settime `, `{0}summary quest cleartime`, `{0}summary quest now`", "msg.summary.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.summary.no_schedule": "No schedule set for {0} summaries.", "msg.summary.scheduled": "Schedule for {0} summaries: {1}", @@ -360,11 +445,33 @@ "msg.nest.usage": "Valid commands are e.g. `{0}nest pikachu`, `{0}nest everything`, `{0}nest remove pikachu`", "msg.maxbattle.usage": "Valid commands are e.g. `{0}maxbattle pikachu`, `{0}maxbattle level:3`, `{0}maxbattle remove everything`", "msg.fort.usage": "Valid commands are e.g. `{0}fort pokestop`, `{0}fort everything`, `{0}fort remove pokestop`", - "msg.location.removed": "Location removed", - "msg.location.usage": "Valid commands are e.g. `{0}location ,`, `{0}location `", + "msg.location.removed": "✅ Removed saved location `{0}`.", + "msg.location.usage": "Valid commands are `{0}location `, `{0}location add `, `{0}location list`, `{0}location show `, `{0}location remove `, `{0}location remove default`", "msg.location.specify": "Please specify coordinates or an address", "msg.location.set": "Location set to {0},{1}", "msg.location.current": "Your current location is {0},{1}", + "msg.location.added": "✅ Saved location `{0}` at {1}, {2}.", + "msg.location.duplicate": "🙅 You already have a saved location called `{0}`. Remove it first with `{1}location remove {0}`.", + "msg.location.list_header": "Your saved locations:", + "msg.location.list_row": " `{0}`: {1}, {2}", + "msg.location.list_row_with_addr": " `{0}`: {1}, {2} — {3}", + "msg.location.list_empty": "You have no saved locations. Add one with `{0}location add `.", + "msg.location.show_not_found": "🙅 No saved location called `{0}`.", + "msg.location.show": "📍 `{0}` is at {1}, {2}.", + "msg.location.show_with_addr": "📍 `{0}` is at {1}, {2} — {3}", + "msg.location.no_default": "🙅 No default location set.", + "msg.location.default_removed": "✅ Cleared your default location.", + "msg.location.remove_referenced": "🙅 Cannot remove `{0}` — {1} tracking rule(s) reference it: {2}. Edit or remove those rules first.", + "msg.location.add_usage": "Valid commands are `{0}location add `", + "msg.location.show_usage": "Valid commands are `{0}location show `", + "msg.location.remove_usage": "Valid commands are `{0}location remove `, `{0}location remove default`", + "msg.location.geocode_failed": "🙅 Couldn't find a place matching `{0}`.", + "cmd.location.usage": "**{0}location** — manage your default location and saved named locations.\n\n• `{0}location` — show your current default location\n• `{0}location ` — set your default location\n• `{0}location add ` — save a named location (referenced later as `location:` on tracking rules)\n• `{0}location list` — list all your saved locations\n• `{0}location show ` — show one saved location's coords + address (use `default` for your default)\n• `{0}location remove ` — delete a saved location (refuses if any tracking rule references it)\n• `{0}location remove default` — clear your default location", + "msg.override.requires_distance": "🙅 `location:` needs a `d:` distance — e.g. `location:Home d:500`.", + "msg.override.area_and_distance": "🙅 `area:` and `d:` are mutually exclusive (area-mode vs distance-mode). Pick one.", + "msg.override.area_and_location": "🙅 `area:` and `location:` are mutually exclusive. Pick one.", + "msg.override.unknown_location": "🙅 No saved location called `{0}`. Add it with `{1}location add {0} `.", + "msg.override.area_not_permitted": "🙅 Area `{0}` is not in your allowed areas. Use `{1}area list` to see what you can pick.", "msg.area.usage": "Valid commands are `{0}area list`, `{0}area add `, `{0}area remove `", "msg.area.none_available": "No areas available", "msg.area.available": "**Available areas:**", @@ -382,14 +489,14 @@ "msg.profile.deleted": "Profile {0} deleted", "msg.profile.not_found": "Profile not found", "msg.profile.cannot_delete_1": "Cannot delete profile 1", - "msg.profile.hours_usage": "Usage: profile hours ", + "msg.profile.hours_usage": "Valid commands are `{0}profile hours `", "msg.profile.hours_invalid_json": "Invalid JSON for active hours", "msg.profile.hours_set": "Active hours updated for profile {0}", "msg.profile.hours_cleared": "Active hours cleared for profile {0}", - "msg.profile.settime_usage": "Usage: profile settime mon09:00 tue18:30 weekday09:00 weekend10:00", + "msg.profile.settime_usage": "Valid commands are `{0}profile settime mon09:00 tue18:30 weekday09:00 weekend10:00`", "msg.profile.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.profile.copied": "Current profile copied to: {0}", - "msg.profile.copyto_usage": "Usage: profile copyto ", + "msg.profile.copyto_usage": "Valid commands are `{0}profile copyto `", "msg.profile.copy_invalid": "These profiles were invalid: {0}", "msg.profile.usage": "Valid commands are `{0}profile `, `{0}profile list`, `{0}profile add `, `{0}profile remove `, `{0}profile settime `, `{0}profile copyto `", "msg.profile.list_header": "Currently configured profiles are:", @@ -407,6 +514,7 @@ "msg.weather.unavailable": "Weather tracking is not yet available via this command", "msg.help.unknown_topic": "No help available for '{0}'. Use `{1}help` for general help.", "msg.help.no_greeting": "No help template configured. Use `{0}help ` for command-specific help.", + "msg.help.see_detailed": "💡 More detailed help is available — `{0}help {1}`", "msg.info.sub.moves": "moves", "msg.info.sub.items": "items", "msg.info.sub.shiny": "shiny", @@ -417,9 +525,19 @@ "msg.info.sub.translate": "translate", "msg.info.sub.dts": "dts", "msg.info.sub.templates": "templates", - "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info `", + "msg.info.sub.costumes": "costumes", + "msg.info.sub.forms": "forms", + "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info costumes`, `{0}info `", "msg.info.usage_admin": "Admin: `{0}info poracle`, `{0}info dts`, `{0}info translate `, `{0}info config [search]`", "msg.info.available_forms": "Available forms:", + "msg.info.more_forms": "More than {0} forms — do {1} for the full list", + "msg.info.recent_forms": "**Recently-seen forms:**", + "msg.info.recent_raid_forms": "**Recently-seen raid forms:**", + "msg.info.available_costumes": "**Recently-seen costumes:**", + "msg.info.recent_raid_costumes": "**Recently-seen raid costumes:**", + "msg.info.costumes.header": "**Costumes** (`costume:` to track):", + "msg.info.no_costume_data": "No costume data loaded", + "msg.info.no_form_data": "No form data for that pokemon.", "msg.info.hundo_cp": "100% IV CP:", "msg.info.dts_summary": "DTS Templates loaded:", "msg.info.pokemon_not_found": "Pokemon not found: {0}", @@ -534,5 +652,661 @@ "language.sv": "Svenska", "language.zh-cn": "Chiński (uproszczony)", "language.ja": "Japoński", - "msg.help.text": "**Available commands:**\n{0}track [iv:N] [cp:N] [level:N] [d:N] — Track pokemon\n{0}untrack — Remove pokemon tracking\n{0}raid [d:N] — Track raids\n{0}egg [d:N] — Track eggs\n{0}quest — Track quests\n{0}invasion [everything|] — Track invasions\n{0}lure — Track lures\n{0}gym [slot_changes] — Track gyms\n{0}nest — Track nests\n{0}maxbattle — Track max battles\n{0}fort — Track fort updates\n{0}tracked — Show all tracking\n{0}script — Export tracking as commands\n{0}area [list|add|remove] — Manage areas\n{0}location — Set location\n{0}profile [list|add|remove|switch] — Manage profiles\n{0}language — Set language\n{0}start / {0}stop — Enable/disable alerts\n{0}version — Show version" + "slash.cmd.version": "version", + "slash.desc.version": "Show Poracle version", + "slash.cmd.tracked": "tracked", + "slash.cmd.help": "help", + "slash.cmd.info": "info", + "slash.cmd.language": "language", + "slash.cmd.track": "track", + "slash.cmd.raid": "raid", + "slash.cmd.egg": "egg", + "slash.cmd.quest": "quest", + "slash.cmd.invasion": "invasion", + "slash.cmd.incident": "incident", + "slash.cmd.lure": "lure", + "slash.cmd.nest": "nest", + "slash.cmd.maxbattle": "maxbattle", + "slash.cmd.gym": "gym", + "slash.cmd.fort": "fort", + "slash.cmd.untrack": "untrack", + "slash.cmd.area": "area", + "slash.cmd.profile": "profile", + "slash.cmd.location": "location", + "slash.cmd.summary": "summary", + "slash.cmd.start": "start", + "slash.cmd.stop": "stop", + "slash.desc.tracked": "List your tracking rules", + "slash.desc.start": "Resume alert delivery (after /stop)", + "slash.desc.stop": "Pause alert delivery (resume with /start)", + "slash.desc.help": "Show help", + "slash.desc.info": "Look up pokemon info, shiny rates, rarity tiers, or current weather", + "slash.opt.info.pokemon": "pokemon", + "slash.opt.info.pokemon.desc": "Show types, stats, evolutions, weather boost and CP table for a pokemon", + "slash.opt.info.pokemon.name": "name", + "slash.opt.info.pokemon.name.desc": "Pokemon name (any supported language) or dex id", + "slash.opt.info.rarity": "rarity", + "slash.opt.info.rarity.desc": "List pokemon by spawn rarity tier (common → ultra-rare)", + "slash.opt.info.shiny": "shiny", + "slash.opt.info.shiny.desc": "Show observed shiny rates per species", + "slash.opt.info.weather": "weather", + "slash.opt.info.weather.desc": "Show current weather and boosted types for a location", + "slash.opt.info.weather.coords": "coords", + "slash.opt.info.weather.coords.desc": "lat,lon (defaults to your saved location)", + "slash.desc.language": "Show or set your language", + "slash.desc.track": "Track a Pokemon", + "slash.desc.raid": "Track a raid boss or raid level", + "slash.desc.egg": "Track an egg / raid level", + "slash.desc.quest": "Track a quest reward", + "slash.desc.invasion": "Track a Team Rocket invasion", + "slash.desc.incident": "Track a pokestop incident (Kecleon, Gold Pokestop, Showcase…)", + "slash.desc.lure": "Track a pokestop lure", + "slash.desc.nest": "Track a nesting pokemon", + "slash.desc.maxbattle": "Track a max (Dynamax) battle", + "slash.desc.gym": "Track gym team / slot / battle changes", + "slash.desc.fort": "Track pokestop or gym updates", + "slash.desc.untrack": "Remove a tracking rule", + "slash.desc.area": "Manage your areas", + "slash.desc.profile": "Manage your profiles", + "slash.desc.location": "Manage your saved locations", + "slash.desc.summary": "Manage scheduled summary digests (e.g. quest)", + "slash.opt.help.topic": "topic", + "slash.opt.help.topic.desc": "Help topic", + "slash.opt.language.code": "code", + "slash.opt.language.code.desc": "Language code", + "slash.opt.track.pokemon": "pokemon", + "slash.opt.track.pokemon.desc": "Pokemon to track (or 'everything')", + "slash.opt.track.iv": "iv", + "slash.opt.track.iv.desc": "IV filter (e.g. 100, 95, 0-0)", + "slash.opt.track.distance": "distance", + "slash.opt.track.distance.desc": "Alert radius in metres", + "slash.opt.track.great_rank": "great_rank", + "slash.opt.track.great_rank.desc": "Top PVP rank in the Great League", + "slash.opt.track.ultra_rank": "ultra_rank", + "slash.opt.track.ultra_rank.desc": "Top PVP rank in the Ultra League", + "slash.opt.track.little_rank": "little_rank", + "slash.opt.track.little_rank.desc": "Top PVP rank in the Little League", + "slash.opt.track.clean": "clean", + "slash.opt.track.clean.desc": "Auto-delete the alert when the pokemon despawns", + "slash.opt.track.template": "template", + "slash.opt.track.template.desc": "DTS template name", + "slash.opt.track.form": "form", + "slash.opt.track.form.desc": "Pokemon form", + "slash.opt.track.size": "size", + "slash.opt.track.size.desc": "Pokemon size class", + "slash.choice.track.clean.yes": "Yes", + "slash.choice.track.size.all": "All sizes", + "slash.choice.track.size.xxs": "XXS", + "slash.choice.track.size.xs": "XS", + "slash.choice.track.size.m": "M", + "slash.choice.track.size.xl": "XL", + "slash.choice.track.size.xxl": "XXL", + "slash.opt.raid.boss": "boss", + "slash.opt.raid.boss.desc": "Raid boss pokemon", + "slash.opt.raid.level": "level", + "slash.opt.raid.level.desc": "Raid level", + "slash.opt.raid.team": "team", + "slash.opt.raid.team.desc": "Required gym-control team", + "slash.opt.raid.distance": "distance", + "slash.opt.raid.distance.desc": "Alert radius in metres", + "slash.opt.raid.clean": "clean", + "slash.opt.raid.clean.desc": "Auto-delete the alert when the raid expires", + "slash.opt.raid.template": "template", + "slash.opt.raid.template.desc": "DTS template name", + "slash.choice.raid.clean.yes": "Yes", + "slash.choice.raid.level.1": "Tier 1", + "slash.choice.raid.level.3": "Tier 3", + "slash.choice.raid.level.5": "Tier 5", + "slash.choice.raid.level.6": "Tier 6", + "slash.choice.raid.level.mega": "Mega", + "slash.choice.raid.level.legendary": "Legendary", + "slash.choice.raid.level.shadow1": "Shadow Tier 1", + "slash.choice.raid.level.shadow3": "Shadow Tier 3", + "slash.choice.raid.level.shadow5": "Shadow Tier 5", + "slash.choice.raid.level.ultra beast": "Ultra Beast", + "slash.choice.raid.level.everything": "Everything", + "slash.choice.raid.team.0": "Harmony", + "slash.choice.raid.team.1": "Mystic", + "slash.choice.raid.team.2": "Valor", + "slash.choice.raid.team.3": "Instinct", + "slash.opt.egg.level": "level", + "slash.opt.egg.level.desc": "Egg / raid level", + "slash.opt.egg.team": "team", + "slash.opt.egg.team.desc": "Required gym-control team", + "slash.opt.egg.distance": "distance", + "slash.opt.egg.distance.desc": "Alert radius in metres", + "slash.opt.egg.clean": "clean", + "slash.opt.egg.clean.desc": "Auto-delete the alert when the egg hatches", + "slash.opt.egg.template": "template", + "slash.opt.egg.template.desc": "DTS template name", + "slash.choice.egg.clean.yes": "Yes", + "slash.choice.egg.level.1": "Tier 1", + "slash.choice.egg.level.3": "Tier 3", + "slash.choice.egg.level.5": "Tier 5", + "slash.choice.egg.level.6": "Tier 6", + "slash.choice.egg.level.mega": "Mega", + "slash.choice.egg.level.legendary": "Legendary", + "slash.choice.egg.level.shadow1": "Shadow Tier 1", + "slash.choice.egg.level.shadow3": "Shadow Tier 3", + "slash.choice.egg.level.shadow5": "Shadow Tier 5", + "slash.choice.egg.level.ultra beast": "Ultra Beast", + "slash.choice.egg.level.everything": "Everything", + "slash.choice.egg.team.0": "Harmony", + "slash.choice.egg.team.1": "Mystic", + "slash.choice.egg.team.2": "Valor", + "slash.choice.egg.team.3": "Instinct", + "slash.opt.quest.pokemon": "pokemon", + "slash.opt.quest.pokemon.desc": "Pokemon reward", + "slash.opt.quest.item": "item", + "slash.opt.quest.item.desc": "Item reward (e.g. golden razz berry)", + "slash.opt.quest.stardust": "stardust", + "slash.opt.quest.stardust.desc": "Stardust reward (minimum amount)", + "slash.opt.quest.candy": "candy", + "slash.opt.quest.candy.desc": "Candy reward pokemon", + "slash.opt.quest.mega_energy": "mega_energy", + "slash.opt.quest.mega_energy.desc": "Mega energy reward pokemon", + "slash.opt.quest.min_amount": "min_amount", + "slash.opt.quest.min_amount.desc": "Minimum reward amount (item / candy / mega_energy only)", + "slash.opt.quest.distance": "distance", + "slash.opt.quest.distance.desc": "Alert radius in metres", + "slash.opt.quest.clean": "clean", + "slash.opt.quest.clean.desc": "Auto-delete the alert when the quest is completed", + "slash.opt.quest.summary": "summary", + "slash.opt.quest.summary.desc": "Buffer matches and dispatch in a scheduled batch instead of alerting immediately", + "slash.opt.quest.template": "template", + "slash.opt.quest.template.desc": "DTS template name", + "slash.choice.quest.clean.yes": "Yes", + "slash.choice.quest.summary.yes": "Yes", + "slash.opt.invasion.grunt_type": "grunt_type", + "slash.opt.invasion.grunt_type.desc": "Grunt type (Fire, Water…), boss (Giovanni…), or incident (Kecleon…)", + "slash.opt.invasion.gender": "gender", + "slash.opt.invasion.gender.desc": "Filter by grunt gender", + "slash.opt.invasion.distance": "distance", + "slash.opt.invasion.distance.desc": "Alert radius in metres", + "slash.opt.invasion.clean": "clean", + "slash.opt.invasion.clean.desc": "Auto-delete the alert when the invasion expires", + "slash.opt.invasion.template": "template", + "slash.opt.invasion.template.desc": "DTS template name", + "slash.choice.invasion.clean.yes": "Yes", + "slash.choice.invasion.gender.male": "Male", + "slash.choice.invasion.gender.female": "Female", + "slash.choice.invasion.gender.genderless": "Genderless", + "slash.opt.incident.type": "type", + "slash.opt.incident.type.desc": "Pokestop incident type (Kecleon, Gold Pokestop, Showcase…)", + "slash.opt.incident.distance": "distance", + "slash.opt.incident.distance.desc": "Alert radius in metres", + "slash.opt.incident.clean": "clean", + "slash.opt.incident.clean.desc": "Auto-delete the alert when the incident expires", + "slash.opt.incident.template": "template", + "slash.opt.incident.template.desc": "DTS template name", + "slash.choice.incident.clean.yes": "Yes", + "slash.opt.lure.lure_type": "lure_type", + "slash.opt.lure.lure_type.desc": "Lure type", + "slash.opt.lure.distance": "distance", + "slash.opt.lure.distance.desc": "Alert radius in metres", + "slash.opt.lure.clean": "clean", + "slash.opt.lure.clean.desc": "Auto-delete the alert when the lure expires", + "slash.opt.lure.template": "template", + "slash.opt.lure.template.desc": "DTS template name", + "slash.choice.lure.clean.yes": "Yes", + "slash.choice.lure.lure_type.normal": "Normal", + "slash.choice.lure.lure_type.glacial": "Glacial", + "slash.choice.lure.lure_type.mossy": "Mossy", + "slash.choice.lure.lure_type.magnetic": "Magnetic", + "slash.choice.lure.lure_type.rainy": "Rainy", + "slash.choice.lure.lure_type.sparkly": "Sparkly", + "slash.opt.nest.pokemon": "pokemon", + "slash.opt.nest.pokemon.desc": "Nesting pokemon", + "slash.opt.nest.min_spawn_avg": "min_spawn_avg", + "slash.opt.nest.min_spawn_avg.desc": "Minimum spawns per hour", + "slash.opt.nest.distance": "distance", + "slash.opt.nest.distance.desc": "Alert radius in metres", + "slash.opt.nest.clean": "clean", + "slash.opt.nest.clean.desc": "Auto-delete the alert when the nest expires", + "slash.opt.nest.template": "template", + "slash.opt.nest.template.desc": "DTS template name", + "slash.choice.nest.clean.yes": "Yes", + "slash.opt.maxbattle.pokemon": "pokemon", + "slash.opt.maxbattle.pokemon.desc": "Max battle pokemon", + "slash.opt.maxbattle.level": "level", + "slash.opt.maxbattle.level.desc": "Battle level (1..6)", + "slash.opt.maxbattle.gmax": "gmax", + "slash.opt.maxbattle.gmax.desc": "Gigantamax only", + "slash.opt.maxbattle.distance": "distance", + "slash.opt.maxbattle.distance.desc": "Alert radius in metres", + "slash.opt.maxbattle.clean": "clean", + "slash.opt.maxbattle.clean.desc": "Auto-delete the alert when the battle ends", + "slash.opt.maxbattle.template": "template", + "slash.opt.maxbattle.template.desc": "DTS template name", + "slash.choice.maxbattle.clean.yes": "Yes", + "slash.choice.maxbattle.level.1": "Level 1", + "slash.choice.maxbattle.level.2": "Level 2", + "slash.choice.maxbattle.level.3": "Level 3", + "slash.choice.maxbattle.level.4": "Level 4", + "slash.choice.maxbattle.level.5": "Level 5", + "slash.choice.maxbattle.level.6": "Level 6", + "slash.opt.gym.team": "team", + "slash.opt.gym.team.desc": "Gym-control team to alert on", + "slash.opt.gym.slot_changes": "slot_changes", + "slash.opt.gym.slot_changes.desc": "Alert on slot composition changes", + "slash.opt.gym.battle_changes": "battle_changes", + "slash.opt.gym.battle_changes.desc": "Alert on battle state changes", + "slash.opt.gym.distance": "distance", + "slash.opt.gym.distance.desc": "Alert radius in metres", + "slash.opt.gym.clean": "clean", + "slash.opt.gym.clean.desc": "Auto-delete the alert when the gym state changes", + "slash.opt.gym.template": "template", + "slash.opt.gym.template.desc": "DTS template name", + "slash.choice.gym.clean.yes": "Yes", + "slash.choice.gym.team.0": "Harmony", + "slash.choice.gym.team.1": "Mystic", + "slash.choice.gym.team.2": "Valor", + "slash.choice.gym.team.3": "Instinct", + "slash.opt.fort.fort_type": "fort_type", + "slash.opt.fort.fort_type.desc": "Fort type to track", + "slash.opt.fort.include_empty": "include_empty", + "slash.opt.fort.include_empty.desc": "Alert on empty/unowned forts", + "slash.opt.fort.distance": "distance", + "slash.opt.fort.distance.desc": "Alert radius in metres", + "slash.opt.fort.clean": "clean", + "slash.opt.fort.clean.desc": "Auto-delete the alert when the fort changes again", + "slash.opt.fort.template": "template", + "slash.opt.fort.template.desc": "DTS template name", + "slash.choice.fort.clean.yes": "Yes", + "slash.choice.fort.fort_type.0": "Pokestop", + "slash.choice.fort.fort_type.1": "Gym", + "slash.opt.tracker.location": "location", + "slash.opt.tracker.location.desc": "Use a saved location instead of your default (requires distance:)", + "slash.opt.tracker.areas": "areas", + "slash.opt.tracker.areas.desc": "Restrict to specific areas (comma-separated)", + "slash.autocomplete.untrack.remove_all": "🗑️ Remove ALL rules of this type", + "slash.opt.untrack.pokemon": "pokemon", + "slash.opt.untrack.pokemon.desc": "Remove a pokemon tracking rule", + "slash.opt.untrack.pokemon.tracking": "tracking", + "slash.opt.untrack.pokemon.tracking.desc": "Pick from your existing pokemon tracking rules", + "slash.opt.untrack.raid": "raid", + "slash.opt.untrack.raid.desc": "Remove a raid tracking rule", + "slash.opt.untrack.raid.tracking": "tracking", + "slash.opt.untrack.raid.tracking.desc": "Pick from your existing raid tracking rules", + "slash.opt.untrack.egg": "egg", + "slash.opt.untrack.egg.desc": "Remove an egg tracking rule", + "slash.opt.untrack.egg.tracking": "tracking", + "slash.opt.untrack.egg.tracking.desc": "Pick from your existing egg tracking rules", + "slash.opt.untrack.quest": "quest", + "slash.opt.untrack.quest.desc": "Remove a quest tracking rule", + "slash.opt.untrack.quest.tracking": "tracking", + "slash.opt.untrack.quest.tracking.desc": "Pick from your existing quest tracking rules", + "slash.opt.untrack.invasion": "invasion", + "slash.opt.untrack.invasion.desc": "Remove an invasion tracking rule", + "slash.opt.untrack.invasion.tracking": "tracking", + "slash.opt.untrack.invasion.tracking.desc": "Pick from your existing invasion tracking rules", + "slash.opt.untrack.lure": "lure", + "slash.opt.untrack.lure.desc": "Remove a lure tracking rule", + "slash.opt.untrack.lure.tracking": "tracking", + "slash.opt.untrack.lure.tracking.desc": "Pick from your existing lure tracking rules", + "slash.opt.untrack.nest": "nest", + "slash.opt.untrack.nest.desc": "Remove a nest tracking rule", + "slash.opt.untrack.nest.tracking": "tracking", + "slash.opt.untrack.nest.tracking.desc": "Pick from your existing nest tracking rules", + "slash.opt.untrack.gym": "gym", + "slash.opt.untrack.gym.desc": "Remove a gym tracking rule", + "slash.opt.untrack.gym.tracking": "tracking", + "slash.opt.untrack.gym.tracking.desc": "Pick from your existing gym tracking rules", + "slash.opt.untrack.fort": "fort", + "slash.opt.untrack.fort.desc": "Remove a fort tracking rule", + "slash.opt.untrack.fort.tracking": "tracking", + "slash.opt.untrack.fort.tracking.desc": "Pick from your existing fort tracking rules", + "slash.opt.untrack.maxbattle": "maxbattle", + "slash.opt.untrack.maxbattle.desc": "Remove a maxbattle tracking rule", + "slash.opt.untrack.maxbattle.tracking": "tracking", + "slash.opt.untrack.maxbattle.tracking.desc": "Pick from your existing maxbattle tracking rules", + "slash.opt.area.add": "add", + "slash.opt.area.add.desc": "Add an area to your tracking", + "slash.opt.area.add.area": "area", + "slash.opt.area.add.area.desc": "Area to add", + "slash.opt.area.remove": "remove", + "slash.opt.area.remove.desc": "Remove an area from your tracking", + "slash.opt.area.remove.area": "area", + "slash.opt.area.remove.area.desc": "Area to remove", + "slash.opt.area.show": "show", + "slash.opt.area.show.desc": "Show your selected areas", + "slash.opt.area.list": "list", + "slash.opt.area.list.desc": "List every area available to you (✓ = already added)", + "slash.opt.area.overview": "overview", + "slash.opt.area.overview.desc": "Map overview of every area available to you", + "slash.opt.profile.list": "list", + "slash.opt.profile.list.desc": "List your profiles", + "slash.opt.profile.change": "change", + "slash.opt.profile.change.desc": "Switch active profile", + "slash.opt.profile.change.name": "name", + "slash.opt.profile.change.name.desc": "Profile name", + "slash.opt.profile.create": "create", + "slash.opt.profile.create.desc": "Create a new profile", + "slash.opt.profile.create.name": "name", + "slash.opt.profile.create.name.desc": "Profile name", + "slash.opt.profile.delete": "delete", + "slash.opt.profile.delete.desc": "Delete a profile", + "slash.opt.profile.delete.name": "name", + "slash.opt.profile.delete.name.desc": "Profile name", + "slash.opt.profile.settime": "settime", + "slash.opt.profile.settime.desc": "Set active-hours for the current profile", + "slash.opt.profile.settime.times": "times", + "slash.opt.profile.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.profile.cleartime": "cleartime", + "slash.opt.profile.cleartime.desc": "Clear active-hours from the current profile", + "slash.opt.profile.copyto": "copyto", + "slash.opt.profile.copyto.desc": "Copy this profile's tracking to another profile", + "slash.opt.profile.copyto.profile": "profile", + "slash.opt.profile.copyto.profile.desc": "Target profile name or number", + "slash.opt.location.add": "add", + "slash.opt.location.add.desc": "Save a named location", + "slash.opt.location.add.name": "name", + "slash.opt.location.add.name.desc": "Short name for this location (e.g. Home)", + "slash.opt.location.add.place": "place", + "slash.opt.location.add.place.desc": "Coordinates (lat,lon) or a place name", + "slash.opt.location.list": "list", + "slash.opt.location.list.desc": "List your saved locations", + "slash.opt.location.show": "show", + "slash.opt.location.show.desc": "Show one saved location", + "slash.opt.location.show.name": "name", + "slash.opt.location.show.name.desc": "Saved-location name", + "slash.opt.location.remove": "remove", + "slash.opt.location.remove.desc": "Remove a saved location", + "slash.opt.location.remove.name": "name", + "slash.opt.location.remove.name.desc": "Saved-location name (or \"default\" to clear your default location)", + "slash.opt.location.set-default": "set-default", + "slash.opt.location.set-default.desc": "Set your default location", + "slash.opt.location.set-default.place": "place", + "slash.opt.location.set-default.place.desc": "Coordinates (lat,lon) or address to set as your default location", + "slash.opt.location.remove-default": "remove-default", + "slash.opt.location.remove-default.desc": "Clear your default location", + "slash.opt.summary.quest": "quest", + "slash.opt.summary.quest.desc": "Manage quest-summary buffering", + "slash.opt.summary.quest.show": "show", + "slash.opt.summary.quest.show.desc": "Show schedule and current buffer count", + "slash.opt.summary.quest.settime": "settime", + "slash.opt.summary.quest.settime.desc": "Set the active-hours schedule for the quest summary", + "slash.opt.summary.quest.settime.times": "times", + "slash.opt.summary.quest.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.summary.quest.cleartime": "cleartime", + "slash.opt.summary.quest.cleartime.desc": "Clear the active-hours schedule", + "slash.opt.summary.quest.now": "now", + "slash.opt.summary.quest.now.desc": "Force-dispatch the currently-buffered quests", + "error.slash.unregistered_with_channel": "🛑 You need to register first. DM me with !poracle, or run !poracle in {0}.", + "error.slash.unregistered_dm_only": "🛑 You need to register first. DM me with !poracle.", + "error.slash.track.no_pokemon": "Please specify a Pokemon to track.", + "error.slash.raid.need_boss_or_level": "Please specify either a boss or a level.", + "error.slash.raid.boss_and_level": "Please specify either a boss OR a level, not both.", + "error.slash.egg.no_level": "Please specify an egg level.", + "error.slash.quest.no_reward": "Please specify exactly one reward type (pokemon, item, stardust, candy, or mega_energy).", + "error.slash.quest.exactly_one_reward": "Please specify exactly one reward type, not multiple: {0}.", + "error.slash.quest.amount_not_applicable": "`min_amount` doesn't apply to pokemon quests. For stardust, both `stardust` and `min_amount` end up in the same field — pick whichever reads better.", + "error.slash.invasion.no_grunt": "Please specify a grunt type.", + "error.slash.incident.no_type": "Please specify an incident type.", + "error.slash.lure.no_type": "Please specify a lure type.", + "error.slash.nest.no_pokemon": "Please specify a Pokemon for the nest.", + "error.slash.maxbattle.no_pokemon": "Please specify a Pokemon for the max battle.", + "error.slash.fort.no_type": "Please specify a fort type (pokestop or gym).", + "error.slash.untrack.no_subcommand": "Please choose what kind of tracking rule to remove.", + "error.slash.untrack.no_tracking": "Please pick a tracking rule to remove.", + "error.slash.info.no_subcommand": "Please choose an info sub-command (pokemon / rarity / shiny / weather).", + "error.slash.info.no_pokemon": "Please specify a pokemon name or dex id.", + "error.slash.info.unknown_subcommand": "Unknown info sub-command.", + "error.slash.area.no_subcommand": "Please choose an area sub-command (add / remove / show).", + "error.slash.area.no_area": "Please specify an area name.", + "error.slash.area.unknown_subcommand": "Unknown area sub-command.", + "error.slash.profile.no_subcommand": "Please choose a profile sub-command (list / change / create / delete / settime / cleartime / copyto).", + "error.slash.profile.no_name": "Please specify a profile name.", + "error.slash.profile.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.profile.no_target": "Please specify a target profile to copy to.", + "error.slash.profile.unknown_subcommand": "Unknown profile sub-command.", + "error.slash.summary.no_alert_type": "Please choose an alert type (e.g. quest).", + "error.slash.summary.no_action": "Please choose an action (show / settime / cleartime / now).", + "error.slash.summary.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.summary.unknown_action": "Unknown summary action.", + "error.slash.location.no_subcommand": "Please choose a location sub-command (add / list / show / remove / remove-default).", + "error.slash.location.no_name": "Please specify a saved-location name.", + "error.slash.location.empty": "Please specify coordinates or a place name.", + "error.slash.location.unknown_subcommand": "Unknown location sub-command.", + "error.slash.location.no_geocoder": "Place-name lookup is not configured. Please provide coordinates like 51.28, 1.08.", + "error.slash.location.geocode_failed": "Could not find a location for \"{0}\".", + "msg.help.text": "**Available commands:**\n{0}track [iv:N] [cp:N] [level:N] [d:N] — Track pokemon\n{0}untrack — Remove pokemon tracking\n{0}raid [d:N] — Track raids\n{0}egg [d:N] — Track eggs\n{0}quest — Track quests\n{0}invasion [everything|] — Track invasions\n{0}lure — Track lures\n{0}gym [slot_changes] — Track gyms\n{0}nest — Track nests\n{0}maxbattle — Track max battles\n{0}fort — Track fort updates\n{0}tracked — Show all tracking\n{0}script — Export tracking as commands\n{0}area [list|add|remove] — Manage areas\n{0}location — Set location\n{0}profile [list|add|remove|switch] — Manage profiles\n{0}language — Set language\n{0}start / {0}stop — Enable/disable alerts\n{0}version — Show version", + "cmd.poracle_admin": "poracle-admin", + "cmd.pa": "pa", + "cmd.poracle_admin.not_admin": "This command is reserved for administrators.", + "cmd.poracle_admin.unknown_group": "Unknown subgroup. Try `!poracle-admin` for the list.", + "cmd.poracle_admin.unknown_sub": "Unknown subcommand for `{0}`. Try `!poracle-admin {0}` to see what's available.", + "cmd.poracle_admin.help.admin_only": "This command is reserved for server administrators. Each subgroup performs a live operations task.", + "cmd.poracle_admin.help.groups": "Available subgroups:", + "cmd.poracle_admin.help_intro": "🛠️ Poracle Admin\n\nLive operations subgroups (administrators only):", + "cmd.poracle_admin.stub": "(not yet implemented)", + "cmd.poracle_admin.group.slash.desc": "slash-command registration lifecycle", + "cmd.poracle_admin.group.reload.desc": "reload DTS, geofence, or in-memory state", + "cmd.poracle_admin.group.emoji.desc": "list, reload, or test emoji config", + "cmd.poracle_admin.group.reconcile.desc": "Discord role reconciliation (immediate or per-user)", + "cmd.poracle_admin.group.cache.desc": "cache stats and clear", + "cmd.poracle_admin.group.ratelimit.desc": "inspect and reset alert-bucket rate limits", + "cmd.poracle_admin.group.summary.desc": "summary buffer inspection and forced dispatch", + "cmd.poracle_admin.group.status.desc": "live health snapshot", + "cmd.poracle_admin.group.maintenance.desc": "pause/resume outbound delivery", + "cmd.poracle_admin.group.config.desc": "view effective merged config with secrets redacted", + "cmd.poracle_admin.group.warnings.desc": "inspect captured WARN/ERROR log entries (startup + rolling buffers)", + "cmd.poracle_admin.reload.help.intro": "Reload runtime state from disk or database.", + "cmd.poracle_admin.reload.dts.desc": "`dts` — reload DTS templates and partials from disk", + "cmd.poracle_admin.reload.geofence.desc": "`geofence` — reload geofence files and refresh state", + "cmd.poracle_admin.reload.state.desc": "`state` — reload tracking rules and humans from MySQL (bypasses debounce)", + "cmd.poracle_admin.reload.dts.success": "✅ DTS reloaded in {0}ms ({1} templates)", + "cmd.poracle_admin.reload.geofence.success": "✅ Geofence reloaded in {0}ms ({1} fences, {2} tracking rules)", + "cmd.poracle_admin.reload.state.success": "✅ State reloaded in {0}ms ({1} tracking rules, {2} active humans)", + "cmd.poracle_admin.reload.error": "❌ Reload failed: {0}", + "cmd.poracle_admin.emoji.help.intro": "😀 Emoji config — inspect and manage emoji.json + Discord guild emojis.\n\nSubcommands:", + "cmd.poracle_admin.emoji.list.desc": "`list` — list all configured emoji keys with per-platform resolutions", + "cmd.poracle_admin.emoji.reload.desc": "`reload` — reload config/emoji.json from disk", + "cmd.poracle_admin.emoji.test.desc": "`test ` — resolve one emoji key for the current platform", + "cmd.poracle_admin.emoji.upload.desc": "`upload [overwrite]` — upload uicons-based emojis to the guild and write a new emoji.json (Discord-only)", + "cmd.poracle_admin.emoji.discord_config.desc": "`discord-config` — dump emoji.json from the current guild state, no uploads (Discord-only)", + "cmd.poracle_admin.emoji.discord_only": "ℹ️ This subcommand requires a Discord bot with guild access.", + "cmd.poracle_admin.emoji.not_loaded": "ℹ️ Emoji config not loaded (DTS renderer not configured).", + "cmd.poracle_admin.emoji.list.header": "😀 Emoji configuration — {0} keys loaded", + "cmd.poracle_admin.emoji.list.row.key": " {0}:", + "cmd.poracle_admin.emoji.list.row.platform": " {0}: {1}", + "cmd.poracle_admin.emoji.reload.success": "✅ Emoji config reloaded — {0} keys (took {1}ms).", + "cmd.poracle_admin.emoji.reload.error": "❌ Emoji reload failed: {0}", + "cmd.poracle_admin.emoji.test.success": "🔎 {0} on {1}: {2}", + "cmd.poracle_admin.emoji.test.not_found": "ℹ️ Emoji key \"{0}\" not found in the loaded config.", + "cmd.poracle_admin.emoji.test.usage": "Usage: !poracle-admin emoji test ", + "cmd.poracle_admin.reconcile.help.intro": "🔄 Discord role reconciliation — trigger immediately instead of waiting for the periodic timer.", + "cmd.poracle_admin.reconcile.run.desc": "`run` — reconcile all guild members now (blocks until complete)", + "cmd.poracle_admin.reconcile.user.desc": "`user ` — reconcile a single Discord user by snowflake ID", + "cmd.poracle_admin.reconcile.not_configured": "❌ Discord reconciliation is not configured (Telegram-only deploy, or check_role=false).", + "cmd.poracle_admin.reconcile.run.success": "✅ Discord reconciliation complete (took {0}ms).", + "cmd.poracle_admin.reconcile.run.error": "❌ Reconciliation failed: {0}", + "cmd.poracle_admin.reconcile.user.success": "✅ Reconciled discord:user/{0} (took {1}ms).", + "cmd.poracle_admin.reconcile.user.error": "❌ Failed to reconcile discord:user/{0}: {1}", + "cmd.poracle_admin.reconcile.user.usage": "Usage: !poracle-admin reconcile user ", + "cmd.poracle_admin.cache.help.intro": "🗺️ Geocoder cache — inspect counters or drop the in-memory layer.", + "cmd.poracle_admin.cache.stats.desc": "`stats` — geocoder cache stats", + "cmd.poracle_admin.cache.clear.desc": "`clear geocoder` — drop the in-memory geocoder cache", + "cmd.poracle_admin.cache.not_configured": "Geocoder cache is not configured on this instance.", + "cmd.poracle_admin.cache.stats.header": "🗺️ Geocoder cache", + "cmd.poracle_admin.cache.stats.row.memory_entries": " Memory entries: {0}", + "cmd.poracle_admin.cache.stats.row.disk_entries": " Disk entries: {0}", + "cmd.poracle_admin.cache.stats.row.hits_memory": " Hits (memory): {0}", + "cmd.poracle_admin.cache.stats.row.hits_disk": " Hits (disk): {0}", + "cmd.poracle_admin.cache.stats.row.misses": " Misses: {0}", + "cmd.poracle_admin.cache.stats.row.hit_rate": " Hit rate: {0}%", + "cmd.poracle_admin.cache.clear.usage_hint": "Specify what to clear, e.g. `!poracle-admin cache clear geocoder`", + "cmd.poracle_admin.cache.clear.geocoder.success": "✅ Geocoder memory cache cleared — {0} entries dropped (disk untouched).", + "cmd.poracle_admin.ratelimit.help.intro": "🚦 Rate-limit introspection — inspect or reset per-destination alert and summary buckets.", + "cmd.poracle_admin.ratelimit.not_configured": "ℹ️ Alert rate limiter is not configured on this instance.", + "cmd.poracle_admin.ratelimit.list.desc": "`list` — show all targets currently breached or banned", + "cmd.poracle_admin.ratelimit.show.desc": "`show ` — detailed state for one target (both buckets)", + "cmd.poracle_admin.ratelimit.reset.desc": "`reset ` — clear counters and violation history", + "cmd.poracle_admin.ratelimit.userlist.desc": "`userlist` — show currently disabled users (shortcut for !userlist disabled)", + "cmd.poracle_admin.ratelimit.list.empty": "🟢 No targets currently rate-limited.", + "cmd.poracle_admin.ratelimit.list.header_title": "Currently rate-limited targets", + "cmd.poracle_admin.ratelimit.list.bucket_header": " {0} bucket ({1} breached / {2} banned):", + "cmd.poracle_admin.ratelimit.list.row": "count {0}/{1}, {2}", + "cmd.poracle_admin.ratelimit.list.status.banned": "banned for {0}", + "cmd.poracle_admin.ratelimit.list.status.breached": "window resets in {0}", + "cmd.poracle_admin.ratelimit.show.header": "🚦 Rate-limit state for {0}", + "cmd.poracle_admin.ratelimit.show.bucket_header": "{0} bucket:", + "cmd.poracle_admin.ratelimit.show.empty": "🟢 No recorded activity for {0} in either bucket.", + "cmd.poracle_admin.ratelimit.show.no_data": "(no activity in this bucket)", + "cmd.poracle_admin.ratelimit.show.no_violations": "No violations.", + "cmd.poracle_admin.ratelimit.show.violations_count": "Violations (24h): {0}", + "cmd.poracle_admin.ratelimit.show.banned_until": "Banned until: {0} (in {1})", + "cmd.poracle_admin.ratelimit.show.status.under_limit": "under limit", + "cmd.poracle_admin.ratelimit.show.status.over_limit": "over limit", + "cmd.poracle_admin.ratelimit.show.row.count": " Count: {0} / {1} ({2})\n", + "cmd.poracle_admin.ratelimit.show.row.window": " Window: opened {0} ago, resets in {1}\n", + "cmd.poracle_admin.ratelimit.reset.success": "✅ Reset rate-limit state for {0} (cleared alert + summary buckets, violations reset).", + "cmd.poracle_admin.ratelimit.reset.no_state": "ℹ️ No rate-limit state to reset for {0}.", + "cmd.poracle_admin.ratelimit.reset.note": "Note: admin_disable is NOT touched. If the user was auto-disabled by the rate-limiter, they still need to !poracle to re-register.", + "cmd.poracle_admin.ratelimit.usage.show": "Usage: !poracle-admin ratelimit show ", + "cmd.poracle_admin.ratelimit.usage.reset": "Usage: !poracle-admin ratelimit reset ", + "cmd.poracle_admin.ratelimit.userlist.lookup_failed": "❌ Could not find !userlist command in the registry.", + "cmd.poracle_admin.summary.help.intro": "📦 Summary buffer — inspect who has quests buffered and force-dispatch on demand.", + "cmd.poracle_admin.summary.not_configured": "ℹ️ Summary buffer is not configured on this instance.", + "cmd.poracle_admin.summary.list.desc": "`list` — show all users with anything buffered", + "cmd.poracle_admin.summary.show.desc": "`show ` — inspect one user's buffered entries", + "cmd.poracle_admin.summary.fire.desc": "`fire [alertType]` — force-dispatch a user's buffer immediately", + "cmd.poracle_admin.summary.list.empty": "🟢 No users have anything buffered.", + "cmd.poracle_admin.summary.list.header": "📦 Summary buffer — {0} users with {1} buffered entries", + "cmd.poracle_admin.summary.list.user_header": " {0}", + "cmd.poracle_admin.summary.list.row": " {0}: {1} entries (next fires: {2})", + "cmd.poracle_admin.summary.list.next_fire.none": "n/a", + "cmd.poracle_admin.summary.show.header": "📦 Summary buffer for {0}", + "cmd.poracle_admin.summary.show.empty": "🟢 No buffered entries for {0}.", + "cmd.poracle_admin.summary.show.alert_type": " {0}: {1} entries", + "cmd.poracle_admin.summary.show.usage": "Usage: !poracle-admin summary show ", + "cmd.poracle_admin.summary.fire.success": "✅ Dispatched summary for {0} / {1} — {2} entries delivered.", + "cmd.poracle_admin.summary.fire.usage": "Usage: !poracle-admin summary fire [alertType]", + "cmd.poracle_admin.summary.show.reward_row": " Reward type {0}, reward {1}{2} — {3} stops", + "cmd.poracle_admin.summary.show.reward_more": " ... ({0} more reward groups)", + "cmd.poracle_admin.summary.show.form_suffix": " form {0}", + "cmd.poracle_admin.maintenance.help.intro": "🛠️ **!poracle-admin maintenance** — live control over outbound delivery.\n\nSubcommands:", + "cmd.poracle_admin.maintenance.no_dispatcher": "ℹ️ Dispatcher is not available on this instance.", + "cmd.poracle_admin.maintenance.no_reason": "(no reason given)", + "cmd.poracle_admin.maintenance.pause.desc": "`pause [reason...]` (alias: `start`) — halt outbound delivery (webhooks still ingest, match, render, and queue)", + "cmd.poracle_admin.maintenance.resume.desc": "`resume` (alias: `stop`) — lift a previous pause and drain queued jobs", + "cmd.poracle_admin.maintenance.status.desc": "`status` — show current paused/running state and queue depth", + "cmd.poracle_admin.maintenance.pause.new": "🔴 Outbound delivery paused: {0}", + "cmd.poracle_admin.maintenance.pause.detail": "Webhooks still ingest, match, render, and queue — the dispatcher holds them until !poracle-admin maintenance resume.", + "cmd.poracle_admin.maintenance.pause.already": "ℹ️ Already paused since {0} ({1} ago): {2}", + "cmd.poracle_admin.maintenance.resume.success": "🟢 Outbound delivery resumed (was paused for {0}: {1})", + "cmd.poracle_admin.maintenance.resume.detail": "Queued messages are draining.", + "cmd.poracle_admin.maintenance.resume.not_paused": "ℹ️ Not currently paused.", + "cmd.poracle_admin.maintenance.status.running": "🟢 Delivery is running.", + "cmd.poracle_admin.maintenance.status.paused": "🔴 PAUSED — {0} (for {1})", + "cmd.poracle_admin.maintenance.status.queued": "{0} jobs queued waiting (across all platforms — Discord {1}, Telegram {2})", + "cmd.poracle_admin.status.help.intro": "!poracle-admin status — current health snapshot. Add -v for verbose mode (per-route Discord detail, full webhook per-type breakdown).", + "cmd.poracle_admin.status.header": "🛠️ Poracle Admin — Status", + "cmd.poracle_admin.status.paused_banner": "🔴 PAUSED — {0} (since {1} ago)\n Outbound delivery is held. Webhooks still ingest and queue.", + "cmd.poracle_admin.status.value.na": "n/a", + "cmd.poracle_admin.status.value.none": "none", + "cmd.poracle_admin.status.section.build": "**Build / Uptime**", + "cmd.poracle_admin.status.section.webhooks": "**Webhooks**", + "cmd.poracle_admin.status.section.render_queue": "**Render queue**", + "cmd.poracle_admin.status.section.delivery": "**Delivery**", + "cmd.poracle_admin.status.section.discord_rate": "**Discord rate**", + "cmd.poracle_admin.status.section.telegram_rate": "**Telegram rate**", + "cmd.poracle_admin.status.section.alert_limits": "**Alert limits**", + "cmd.poracle_admin.status.section.summary_buffer": "**Summary buffer**", + "cmd.poracle_admin.status.label.summary_buffer_totals": "Entries: {0} across {1} bucket(s)", + "cmd.poracle_admin.status.label.summary_buffer_top": "Top users:", + "cmd.poracle_admin.status.label.summary_buffer_user_row": " {0} ({1}): {2} entries", + "cmd.poracle_admin.status.section.tracking": "**Tracking**", + "cmd.poracle_admin.status.section.mysql": "**MySQL**", + "cmd.poracle_admin.status.label.version": "Version: {0} (commit {1}, built {2})", + "cmd.poracle_admin.status.label.uptime": "Uptime: {0}", + "cmd.poracle_admin.status.label.webhooks_rate": "{0} / {1} / {2} per min over last 5/15/60 min", + "cmd.poracle_admin.status.label.webhooks_by_type": "By type (last 60 min):", + "cmd.poracle_admin.status.label.delivery_discord": "Discord in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_telegram": "Telegram in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_webhook": "Webhook in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_queue_depth": "Queue depth: {0} (capacity not exposed)", + "cmd.poracle_admin.status.label.discord_routes": "Routes near limit: {0}", + "cmd.poracle_admin.status.label.discord_global": "Global tokens: {0} / {1}", + "cmd.poracle_admin.status.label.discord_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.discord_routes_detail": "Routes near limit (detail):", + "cmd.poracle_admin.status.label.telegram_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.telegram_backoff": "Current backoff: {0}", + "cmd.poracle_admin.status.label.alert_limits_counts": "Breached: alert={0}, summary={1} · Banned: {2}", + "cmd.poracle_admin.status.label.tracking_total": "Total tracking rules: {0}", + "cmd.poracle_admin.status.label.tracking_active_humans": "Active humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans": "Registered humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans_error": "Registered humans: n/a (error)", + "cmd.poracle_admin.status.label.tracking_type": "{0}: {1}", + "cmd.poracle_admin.status.label.mysql_ping_ok": "Ping: ok", + "cmd.poracle_admin.status.label.mysql_ping_fail": "Ping: failed ({0})", + "cmd.poracle_admin.status.label.mysql_pool": "Connections: {0}/{1} open ({2} in use, {3} idle, waits={4})", + "cmd.poracle_admin.status.tracking_type.pokemon": "pokemon", + "cmd.poracle_admin.status.tracking_type.raid": "raid", + "cmd.poracle_admin.status.tracking_type.egg": "egg", + "cmd.poracle_admin.status.tracking_type.quest": "quest", + "cmd.poracle_admin.status.tracking_type.invasion": "invasion", + "cmd.poracle_admin.status.tracking_type.lure": "lure", + "cmd.poracle_admin.status.tracking_type.nest": "nest", + "cmd.poracle_admin.status.tracking_type.gym": "gym", + "cmd.poracle_admin.status.tracking_type.fort": "fort", + "cmd.poracle_admin.status.tracking_type.maxbattle": "maxbattle", + "cmd.poracle_admin.slash.help.intro": "**!poracle-admin slash** — slash-command registration lifecycle.\nSubcommands:", + "cmd.poracle_admin.slash.discord_only": "❌ Slash commands are Discord-only and cannot be managed from Telegram.", + "cmd.poracle_admin.slash.not_configured": "❌ Slash commands are not configured (Discord disabled or [discord.slash_commands] enabled=false).", + "cmd.poracle_admin.slash.sync.desc": "push the current command set to Discord (fingerprint-cached, skips if unchanged)", + "cmd.poracle_admin.slash.sync.success": "✅ Slash sync complete ({0}ms)", + "cmd.poracle_admin.slash.sync.error": "❌ Slash sync failed: {0}", + "cmd.poracle_admin.slash.force_resync.desc": "clear fingerprint cache and push unconditionally", + "cmd.poracle_admin.slash.force_resync.success": "✅ Force-resync complete ({0}ms)", + "cmd.poracle_admin.slash.force_resync.error": "❌ Force-resync failed: {0}", + "cmd.poracle_admin.slash.clear_global.desc": "remove all globally-registered Discord slash commands", + "cmd.poracle_admin.slash.clear_global.success": "✅ Global slash commands cleared.", + "cmd.poracle_admin.slash.clear_global.error": "❌ Clear global failed: {0}", + "cmd.poracle_admin.slash.clear_guild.desc": "remove slash commands from one guild (requires guild_id arg)", + "cmd.poracle_admin.slash.clear_guild.needs_arg": "❌ Usage: `!poracle-admin slash clear-guild `", + "cmd.poracle_admin.slash.clear_guild.success": "✅ Slash commands cleared from guild {0}.", + "cmd.poracle_admin.slash.clear_guild.error": "❌ Clear guild failed: {0}", + "cmd.poracle_admin.slash.status.desc": "show last sync timestamp and fingerprint per scope", + "cmd.poracle_admin.slash.status.header": "**Slash command registration status:**", + "cmd.poracle_admin.slash.status.scope_row": " **{0}**: last synced {1} · fingerprint `{2}`", + "cmd.poracle_admin.slash.status.never_synced": "never", + "cmd.poracle_admin.slash.status.ago": "{0} ago", + "cmd.poracle_admin.slash.status.error": "❌ Status read failed: {0}", + "cmd.poracle_admin.config.help.intro": "⚙️ Config viewer — show effective merged config with secrets redacted.\nSubcommands:", + "cmd.poracle_admin.config.keys.desc": "list section names with key counts", + "cmd.poracle_admin.config.section.desc": "show just that section (e.g. `!poracle-admin config discord`)", + "cmd.poracle_admin.config.full.desc": "show the full config (all sections, secrets redacted)", + "cmd.poracle_admin.config.keys.header": "⚙️ Config sections:", + "cmd.poracle_admin.config.keys.row": " {0}: {1} keys", + "cmd.poracle_admin.config.unknown_section": "Unknown config section: `{0}`. Use `!poracle-admin config keys` to list valid sections, or `!poracle-admin config search ` to search across all sections.", + "cmd.poracle_admin.config.search.desc": "find keys whose path or value contains the term across every section (e.g. `!poracle-admin config search dm`)", + "cmd.poracle_admin.config.search.usage": "Usage: `!poracle-admin config search ` — e.g. `search dm`, `search shlink`, `search 3030`.", + "cmd.poracle_admin.config.search.header": "🔍 `{0}` — {1} match(es):", + "cmd.poracle_admin.config.search.no_matches": "No config keys or values match `{0}`.", + "cmd.poracle_admin.config.empty_section": "Section `{0}` has no configurable fields.", + "cmd.poracle_admin.config.not_loaded": "❌ Config not loaded.", + "cmd.poracle_admin.warnings.help.intro": "🛠️ Captured warnings — inspect in-memory WARN/ERROR log entries.\n\nSubcommands:\n (no arg) — show both startup and recent buffers\n `startup` — show only the startup buffer (first 200 entries, frozen after init)\n `recent` — show only the rolling buffer (last 50 entries)\n `clear` — empty the rolling buffer (startup is immutable)", + "cmd.poracle_admin.warnings.not_configured": "ℹ️ Log buffer is not configured on this instance.", + "cmd.poracle_admin.warnings.section.startup": "🛠️ Captured warnings — startup ({0} entries)", + "cmd.poracle_admin.warnings.section.recent": "🛠️ Captured warnings — recent ({0} entries)", + "cmd.poracle_admin.warnings.empty.startup": "🟢 No startup warnings captured.", + "cmd.poracle_admin.warnings.empty.recent": "🟢 No recent warnings.", + "cmd.poracle_admin.warnings.entry_row": " {0} {1} {2} {3}", + "cmd.poracle_admin.warnings.cleared": "✅ Cleared {0} entries from the rolling buffer (startup buffer is unaffected).", + "cmd.poracle_admin.warnings.startup.desc": "`startup` — show only the startup buffer (frozen after init)", + "cmd.poracle_admin.warnings.recent.desc": "`recent` — show only the rolling buffer (last 50 entries)", + "cmd.poracle_admin.warnings.clear.desc": "`clear` — empty the rolling buffer", + "cmd.maintenance.active_suffix": "🔧 Maintenance mode is active — alerts are not being delivered.", + "showcase_focus_pokemon": "Pokémon", + "showcase_focus_type": "Type", + "showcase_focus_alignment": "Alignment", + "showcase_focus_class": "Class", + "showcase_focus_family": "Family", + "showcase_focus_buddy": "Buddy", + "showcase_focus_generation": "Generation", + "showcase_focus_hatched": "Hatched", + "showcase_focus_mega": "Mega", + "showcase_focus_shiny": "Shiny", + "showcase_class_ultra_beast": "Ultra Beast" } diff --git a/processor/internal/i18n/locale/ru.json b/processor/internal/i18n/locale/ru.json index dfc462a13..14e541b66 100644 --- a/processor/internal/i18n/locale/ru.json +++ b/processor/internal/i18n/locale/ru.json @@ -58,6 +58,11 @@ "tracking.pvp_little": "littlepvp", "tracking.pvp_great": "*Грейт-лига*", "tracking.pvp_ultra": "*Ультра-лига*", + "tracking.pvp_mega_any": "mega", + "tracking.pvp_mega_x": "mega x", + "tracking.pvp_mega_y": "mega y", + "tracking.mega_x_label": "X", + "tracking.mega_y_label": "Y", "tracking.level_cap_fmt": "level cap: {0}", "tracking.everything": "Все", "tracking.unknown_monster": "Unknown monster", @@ -81,10 +86,14 @@ "tracking.reward_fmt": "Reward: **{0}**", "tracking.reward_stardust_min_fmt": "{0} or more stardust", "tracking.reward_stardust": "пыли", + "tracking.reward_pokecoin_min_fmt": "{0} or more pokecoins", + "tracking.reward_pokecoin": "pokecoins", "tracking.reward_mega_energy": "мега-энергия", "tracking.reward_mega_energy_fmt": "mega energy {0}", "tracking.reward_candy": "конфет", "tracking.reward_candy_fmt": "candy {0}", + "tracking.reward_any_pokemon": "any pokemon", + "tracking.reward_any_item": "any item", "tracking.reward_min_fmt": "minimum {0}", "tracking.grunt_type_fmt": "Grunt type: **{0}**", "tracking.min_avg_spawn": "Спавн {0}/час", @@ -108,10 +117,68 @@ "tracking.template_not_found": "Template \"{0}\" does not exist.", "tracking.warn_template_not_found": "Template \"{0}\" not found for type {1}/{2}. Tracking saved but alerts may not render.", "tracking.id_hint": "To remove a specific entry, use its id — e.g. `{0}untrack id:45` or `{0}raid remove id:12`", + "tracking.id_hint_slash": "To remove a specific entry, run `/untrack ` (e.g. `/untrack raid`) and pick it from the list.", + "tracking.list_attached": "Your tracking list is long ({0} rules) — attached as a file.", "tracking.removed_prefix": "Removed: ", "tracking.uid_not_found": "id:{0} not found", + "tracking.override_location_fmt": "@ {0}", + "tracking.override_areas_fmt": "in {0}", "cmd.track": "отслеживать", "cmd.untrack": "неотслеживать", + "cmd.mute": "mute", + "cmd.unmute": "unmute", + "msg.mute.unavailable": "Mute feature isn't enabled here.", + "msg.mute.usage": "Valid commands are `{0}mute [duration:1h]`", + "msg.mute.usage_pokemon": "Valid commands are `{0}mute pokemon [duration:1h]`", + "msg.mute.usage_gym": "Valid commands are `{0}mute gym [duration:1h]`", + "msg.mute.usage_area": "Valid commands are `{0}mute area [duration:1h]`", + "msg.mute.usage_id_scope": "Valid commands are `{0}mute {1} [duration:1h]`", + "msg.mute.bad_duration": "Invalid duration: {0}", + "msg.mute.id_not_supported": "`!mute id:N` / `!mute id:N` aren't supported yet — entity scopes (gym, pokemon, area, pokestop, station, everything) work today. Per-rule muting by UID is a follow-up.", + "msg.mute.bad_uid": "`{0}` isn't a valid tracking rule UID. Use `!tracked` to see your rule UIDs.", + "msg.mute.unknown_area": "`{0}` isn't in your available areas. Use `!area` to see what you can mute.", + "msg.mute.no_pokemon": "I don't know a pokemon called `{0}`.", + "msg.mute.everything_label": "everything", + "msg.mute.added": "🔇 Muted {0} for {1}.", + "msg.mute.removed": "✅ Unmuted {0}.", + "msg.mute.none_found": "No active mute for {0}.", + "msg.mute.cleared_all": "Cleared {0} active mutes.", + "msg.unmute.usage": "Valid commands are `{0}unmute `, `{0}unmute all`", + "msg.unmute.usage_pokemon": "Valid commands are `{0}unmute pokemon `", + "msg.unmute.usage_gym": "Valid commands are `{0}unmute gym `", + "msg.unmute.usage_area": "Valid commands are `{0}unmute area `", + "section.property_mutes": "Property mutes (apply across all tracking):", + "section.property_mutes.left": "({0} left)", + "msg.button.expired": "This alert has expired.", + "msg.button.unavailable": "This button is no longer available.", + "msg.button.wrong_target": "This button doesn't apply here.", + "msg.button.unauthorized": "This button isn't for you.", + "msg.button.unidentified": "Couldn't identify you to handle that click.", + "msg.button.unconfigured": "This button isn't configured.", + "msg.button.action_failed": "Couldn't complete that action: {0}", + "msg.button.action_failed_generic": "Couldn't complete that action.", + "msg.button.cooldown": "Slow down — try that again in a moment.", + "msg.button.actions_not_wired": "Button actions aren't wired here.", + "msg.button.not_implemented": "The {0} action isn't implemented yet.", + "msg.button.responses_not_wired": "Response rendering isn't wired here.", + "msg.button.response_failed": "Couldn't render that response: {0}", + "msg.button.done": "Done.", + "msg.button.missing_scope": "Button is missing a scope — operator config bug.", + "msg.button.missing_target": "Couldn't find a {0} to mute on this alert.", + "msg.button.no_dm_target": "Couldn't identify you to send the message.", + "msg.button.dm_failed": "Couldn't send to your DM: {0}", + "msg.button.unsubscribe_failed": "Couldn't unsubscribe — please try again.", + "msg.button.unsubscribe_already": "Those tracking rules were already removed.", + "msg.button.unsubscribed": "✅ Unsubscribed from {0} tracking rule(s).", + "msg.button.redeliver_sent": "📬 Sent to your DM.", + "msg.mute.scope_gym": "gym", + "msg.mute.scope_pokemon": "pokemon", + "msg.mute.scope_area": "area", + "msg.mute.scope_pokestop": "pokestop", + "msg.mute.scope_station": "station", + "msg.mute.scope_tracking": "tracking rule", + "cmd.mute.usage": "**{0}mute** — silence alerts for a specific gym, pokemon, area, pokestop, station, or everything for a time-bounded window.\n\n• `{0}mute everything [duration:1h]` — silence ALL alerts for the given duration\n• `{0}mute gym [duration:1h]` — silence alerts for one gym\n• `{0}mute pokemon [duration:1h]` — silence alerts for one pokemon species\n• `{0}mute area [duration:1h]` — silence alerts in one area\n• `{0}mute pokestop [duration:1h]` — silence alerts for one pokestop\n• `{0}mute station [duration:1h]` — silence alerts for one station\n\nDuration defaults to 1h if omitted. Use `{0}unmute ` to remove a mute early, or `{0}tracked` to see active mutes.", + "cmd.track.usage": "**{0}track** — set up pokemon tracking rules.\n\n• `{0}track ` — track a specific pokemon (by name or dex id) at default 100m\n• `{0}track everything` — track every pokemon (admin-permitted; see `{0}help everything`)\n• `{0}track iv:100` — filter by IV percent (`iv:90-100` for range, `miniv:90`/`maxiv:99` for one-sided)\n• `{0}track cp:1500-2500` — filter by CP\n• `{0}track level:25-35` — filter by level\n• `{0}track atk:14-15 def:14-15 sta:14-15` — filter by individual IV stats\n• `{0}track d:500` — only alert within 500m of your location\n• `{0}track location:Home d:500` — within 500m of a saved location\n• `{0}track area:london,paris` — only in named areas (replaces your default areas)\n• `{0}track great5 ultra10` — PVP filters (great/ultra/little league, rank threshold, optional cap)\n• `{0}track gen:1 type:water` — generation and type filters (alongside `everything`)\n• `{0}track rarity:rare-ultra` — rarity-tier filter\n• `{0}track clean` / `edit` — auto-delete on TTH expiry / edit-in-place\n• `{0}track remove ` or `{0}untrack ` — remove\n• `{0}untrack id:42` — remove one rule by id (see `{0}tracked` for ids)\n\nMultiple filters combine. See `{0}tracked` for what's currently active.", "cmd.raid": "рейд", "cmd.egg": "яйцо", "cmd.quest": "квест", @@ -129,6 +196,8 @@ "cmd.fort": "форт", "cmd.help": "помощь", "cmd.info": "инфо", + "cmd.info.poracle.moved": "→ This view has moved to `!poracle-admin status` — please use that instead.", + "cmd.info.config.moved": "→ This view has moved to `!poracle-admin config` — please use that instead.", "cmd.start": "запустить", "cmd.stop": "остановить", "cmd.tracked": "отслеживаемое", @@ -163,6 +232,8 @@ "cmd.poracle_id": "poracle-id", "arg.remove": "удалить", "arg.everything": "все", + "arg.all_pokemon": "all pokemon", + "arg.all_items": "all items", "arg.any": "любой", "arg.clean": "очистить", "arg.edit": "edit", @@ -170,6 +241,7 @@ "arg.list": "список", "arg.add": "добавить", "arg.show": "показать", + "arg.default": "default", "arg.overview": "обзор", "arg.dryrun": "dryrun", "arg.reset": "reset", @@ -182,6 +254,7 @@ "arg.shiny": "шайни", "arg.gmax": "gmax", "arg.stardust": "пыль", + "arg.pokecoin": "pokecoins", "arg.energy": "энергия", "arg.candy": "конфеты", "arg.pvp": "pvp", @@ -248,7 +321,10 @@ "arg.prefix.maxsize": "макс-размер", "arg.prefix.gen": "поколение", "arg.prefix.cap": "кап", + "arg.mega": "mega", + "arg.prefix.mega": "mega", "arg.prefix.form": "форма", + "arg.prefix.costume": "costume", "arg.prefix.template": "шаблон", "arg.prefix.gym": "gym", "arg.prefix.move": "атака", @@ -263,13 +339,17 @@ "arg.prefix.littlehigh": "литтл-макс", "arg.prefix.littlecp": "литтл-ср", "arg.prefix.stardust": "пыль", + "arg.prefix.pokecoin": "pokecoins", "arg.prefix.energy": "энергия", "arg.prefix.candy": "конфеты", + "arg.prefix.amount": "amount", "arg.prefix.name": "имя", "arg.prefix.user": "пользователь", "arg.prefix.channel": "канал", "arg.prefix.guild": "гильдия", "arg.prefix.language": "язык", + "arg.prefix.area": "area", + "arg.prefix.location": "location", "arg.prefix.mon": "пн", "arg.prefix.tue": "вт", "arg.prefix.wed": "ср", @@ -323,21 +403,26 @@ "section.maxbattles.none": "You're not tracking any max battles", "msg.no_pokemon": "покемон не найден", "msg.form_not_found": "Form `{0}` not recognised. Use `{1}info ` to see available forms.", + "msg.costume_not_found": "Costume `{0}` not recognised. Use `{1}info costumes` to see available costumes.", + "msg.no_costume": "no costume", "msg.nothing_to_remove": "Nothing to remove", "msg.no_levels": "No levels specified", "msg.no_egg_levels": "No egg levels specified", "msg.no_raid_target": "No raid levels or pokemon specified", "msg.no_lure_type": "No lure type specified", "msg.no_quest_type": "No quest type specified", + "msg.quest.amount_not_applicable": "`amount:N` doesn't apply to pokemon quests — pokemon rewards have no minimum amount.", + "msg.quest.bulk_not_permitted": "You do not have permission to track all pokemon or items at once. Track specific rewards instead.", "msg.removed_n": "Удалено ивентов: {0}", "msg.egg.usage": "Valid commands are e.g. `{0}egg level:5`, `{0}egg legendary`, `{0}egg remove everything`", "msg.raid.usage": "Valid commands are e.g. `{0}raid level:5`, `{0}raid pikachu`, `{0}raid remove everything`", "msg.track.usage": "Valid commands are e.g. `{0}track pikachu iv:100`, `{0}track everything iv:90`, `{0}track remove pikachu`", "msg.track.everything_no_filters": "Слишком много оповещений. Добавь больше фильтров.", "msg.track.invalid_cap": "This level cap is not supported, valid choices are: {0}", - "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest energy:charizard`", + "msg.track.no_mega_form": "⚠️ {0} has no Mega {1} form — this PVP rule will never match.", + "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest pokecoins:10`, `{0}quest energy:charizard`", "msg.quest.edit_summary_conflict": "`edit` and `summary` are mutually exclusive — pick one.", - "msg.summary.usage": "Usage: `{0}summary quest [settime |cleartime|now]`", + "msg.summary.usage": "Valid commands are `{0}summary quest`, `{0}summary quest settime `, `{0}summary quest cleartime`, `{0}summary quest now`", "msg.summary.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.summary.no_schedule": "No schedule set for {0} summaries.", "msg.summary.scheduled": "Schedule for {0} summaries: {1}", @@ -360,11 +445,33 @@ "msg.nest.usage": "Valid commands are e.g. `{0}nest pikachu`, `{0}nest everything`, `{0}nest remove pikachu`", "msg.maxbattle.usage": "Valid commands are e.g. `{0}maxbattle pikachu`, `{0}maxbattle level:3`, `{0}maxbattle remove everything`", "msg.fort.usage": "Valid commands are e.g. `{0}fort pokestop`, `{0}fort everything`, `{0}fort remove pokestop`", - "msg.location.removed": "Location removed", - "msg.location.usage": "Valid commands are e.g. `{0}location ,`, `{0}location `", + "msg.location.removed": "✅ Removed saved location `{0}`.", + "msg.location.usage": "Valid commands are `{0}location `, `{0}location add `, `{0}location list`, `{0}location show `, `{0}location remove `, `{0}location remove default`", "msg.location.specify": "Please specify coordinates or an address", "msg.location.set": "Location set to {0},{1}", "msg.location.current": "Your current location is {0},{1}", + "msg.location.added": "✅ Saved location `{0}` at {1}, {2}.", + "msg.location.duplicate": "🙅 You already have a saved location called `{0}`. Remove it first with `{1}location remove {0}`.", + "msg.location.list_header": "Your saved locations:", + "msg.location.list_row": " `{0}`: {1}, {2}", + "msg.location.list_row_with_addr": " `{0}`: {1}, {2} — {3}", + "msg.location.list_empty": "You have no saved locations. Add one with `{0}location add `.", + "msg.location.show_not_found": "🙅 No saved location called `{0}`.", + "msg.location.show": "📍 `{0}` is at {1}, {2}.", + "msg.location.show_with_addr": "📍 `{0}` is at {1}, {2} — {3}", + "msg.location.no_default": "🙅 No default location set.", + "msg.location.default_removed": "✅ Cleared your default location.", + "msg.location.remove_referenced": "🙅 Cannot remove `{0}` — {1} tracking rule(s) reference it: {2}. Edit or remove those rules first.", + "msg.location.add_usage": "Valid commands are `{0}location add `", + "msg.location.show_usage": "Valid commands are `{0}location show `", + "msg.location.remove_usage": "Valid commands are `{0}location remove `, `{0}location remove default`", + "msg.location.geocode_failed": "🙅 Couldn't find a place matching `{0}`.", + "cmd.location.usage": "**{0}location** — manage your default location and saved named locations.\n\n• `{0}location` — show your current default location\n• `{0}location ` — set your default location\n• `{0}location add ` — save a named location (referenced later as `location:` on tracking rules)\n• `{0}location list` — list all your saved locations\n• `{0}location show ` — show one saved location's coords + address (use `default` for your default)\n• `{0}location remove ` — delete a saved location (refuses if any tracking rule references it)\n• `{0}location remove default` — clear your default location", + "msg.override.requires_distance": "🙅 `location:` needs a `d:` distance — e.g. `location:Home d:500`.", + "msg.override.area_and_distance": "🙅 `area:` and `d:` are mutually exclusive (area-mode vs distance-mode). Pick one.", + "msg.override.area_and_location": "🙅 `area:` and `location:` are mutually exclusive. Pick one.", + "msg.override.unknown_location": "🙅 No saved location called `{0}`. Add it with `{1}location add {0} `.", + "msg.override.area_not_permitted": "🙅 Area `{0}` is not in your allowed areas. Use `{1}area list` to see what you can pick.", "msg.area.usage": "Valid commands are `{0}area list`, `{0}area add `, `{0}area remove `", "msg.area.none_available": "No areas available", "msg.area.available": "**Available areas:**", @@ -382,14 +489,14 @@ "msg.profile.deleted": "Profile {0} deleted", "msg.profile.not_found": "Профиль не найден", "msg.profile.cannot_delete_1": "Cannot delete profile 1", - "msg.profile.hours_usage": "Usage: profile hours ", + "msg.profile.hours_usage": "Valid commands are `{0}profile hours `", "msg.profile.hours_invalid_json": "Invalid JSON for active hours", "msg.profile.hours_set": "Active hours updated for profile {0}", "msg.profile.hours_cleared": "Active hours cleared for profile {0}", - "msg.profile.settime_usage": "Usage: profile settime mon09:00 tue18:30 weekday09:00 weekend10:00", + "msg.profile.settime_usage": "Valid commands are `{0}profile settime mon09:00 tue18:30 weekday09:00 weekend10:00`", "msg.profile.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.profile.copied": "Current profile copied to: {0}", - "msg.profile.copyto_usage": "Usage: profile copyto ", + "msg.profile.copyto_usage": "Valid commands are `{0}profile copyto `", "msg.profile.copy_invalid": "These profiles were invalid: {0}", "msg.profile.usage": "Valid commands are `{0}profile `, `{0}profile list`, `{0}profile add `, `{0}profile remove `, `{0}profile settime `, `{0}profile copyto `", "msg.profile.list_header": "Список профилей:", @@ -407,6 +514,7 @@ "msg.weather.unavailable": "Weather tracking is not yet available via this command", "msg.help.unknown_topic": "No help available for '{0}'. Use `{1}help` for general help.", "msg.help.no_greeting": "No help template configured. Use `{0}help ` for command-specific help.", + "msg.help.see_detailed": "💡 More detailed help is available — `{0}help {1}`", "msg.info.sub.moves": "moves", "msg.info.sub.items": "items", "msg.info.sub.shiny": "shiny", @@ -417,9 +525,19 @@ "msg.info.sub.translate": "translate", "msg.info.sub.dts": "dts", "msg.info.sub.templates": "templates", - "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info `", + "msg.info.sub.costumes": "costumes", + "msg.info.sub.forms": "forms", + "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info costumes`, `{0}info `", "msg.info.usage_admin": "Admin: `{0}info poracle`, `{0}info dts`, `{0}info translate `, `{0}info config [search]`", "msg.info.available_forms": "*Доступные формы*", + "msg.info.more_forms": "More than {0} forms — do {1} for the full list", + "msg.info.recent_forms": "**Recently-seen forms:**", + "msg.info.recent_raid_forms": "**Recently-seen raid forms:**", + "msg.info.available_costumes": "**Recently-seen costumes:**", + "msg.info.recent_raid_costumes": "**Recently-seen raid costumes:**", + "msg.info.costumes.header": "**Costumes** (`costume:` to track):", + "msg.info.no_costume_data": "No costume data loaded", + "msg.info.no_form_data": "No form data for that pokemon.", "msg.info.hundo_cp": "100% IV CP:", "msg.info.dts_summary": "DTS Templates loaded:", "msg.info.pokemon_not_found": "Pokemon not found: {0}", @@ -534,5 +652,661 @@ "language.sv": "Svenska", "language.zh-cn": "Китайский (упрощённый)", "language.ja": "Японский", - "msg.help.text": "**Available commands:**\n{0}track [iv:N] [cp:N] [level:N] [d:N] — Track pokemon\n{0}untrack — Remove pokemon tracking\n{0}raid [d:N] — Track raids\n{0}egg [d:N] — Track eggs\n{0}quest — Track quests\n{0}invasion [everything|] — Track invasions\n{0}lure — Track lures\n{0}gym [slot_changes] — Track gyms\n{0}nest — Track nests\n{0}maxbattle — Track max battles\n{0}fort — Track fort updates\n{0}tracked — Show all tracking\n{0}script — Export tracking as commands\n{0}area [list|add|remove] — Manage areas\n{0}location — Set location\n{0}profile [list|add|remove|switch] — Manage profiles\n{0}language — Set language\n{0}start / {0}stop — Enable/disable alerts\n{0}version — Show version" + "slash.cmd.version": "version", + "slash.desc.version": "Show Poracle version", + "slash.cmd.tracked": "tracked", + "slash.cmd.help": "help", + "slash.cmd.info": "info", + "slash.cmd.language": "language", + "slash.cmd.track": "track", + "slash.cmd.raid": "raid", + "slash.cmd.egg": "egg", + "slash.cmd.quest": "quest", + "slash.cmd.invasion": "invasion", + "slash.cmd.incident": "incident", + "slash.cmd.lure": "lure", + "slash.cmd.nest": "nest", + "slash.cmd.maxbattle": "maxbattle", + "slash.cmd.gym": "gym", + "slash.cmd.fort": "fort", + "slash.cmd.untrack": "untrack", + "slash.cmd.area": "area", + "slash.cmd.profile": "profile", + "slash.cmd.location": "location", + "slash.cmd.summary": "summary", + "slash.cmd.start": "start", + "slash.cmd.stop": "stop", + "slash.desc.tracked": "List your tracking rules", + "slash.desc.start": "Resume alert delivery (after /stop)", + "slash.desc.stop": "Pause alert delivery (resume with /start)", + "slash.desc.help": "Show help", + "slash.desc.info": "Look up pokemon info, shiny rates, rarity tiers, or current weather", + "slash.opt.info.pokemon": "pokemon", + "slash.opt.info.pokemon.desc": "Show types, stats, evolutions, weather boost and CP table for a pokemon", + "slash.opt.info.pokemon.name": "name", + "slash.opt.info.pokemon.name.desc": "Pokemon name (any supported language) or dex id", + "slash.opt.info.rarity": "rarity", + "slash.opt.info.rarity.desc": "List pokemon by spawn rarity tier (common → ultra-rare)", + "slash.opt.info.shiny": "shiny", + "slash.opt.info.shiny.desc": "Show observed shiny rates per species", + "slash.opt.info.weather": "weather", + "slash.opt.info.weather.desc": "Show current weather and boosted types for a location", + "slash.opt.info.weather.coords": "coords", + "slash.opt.info.weather.coords.desc": "lat,lon (defaults to your saved location)", + "slash.desc.language": "Show or set your language", + "slash.desc.track": "Track a Pokemon", + "slash.desc.raid": "Track a raid boss or raid level", + "slash.desc.egg": "Track an egg / raid level", + "slash.desc.quest": "Track a quest reward", + "slash.desc.invasion": "Track a Team Rocket invasion", + "slash.desc.incident": "Track a pokestop incident (Kecleon, Gold Pokestop, Showcase…)", + "slash.desc.lure": "Track a pokestop lure", + "slash.desc.nest": "Track a nesting pokemon", + "slash.desc.maxbattle": "Track a max (Dynamax) battle", + "slash.desc.gym": "Track gym team / slot / battle changes", + "slash.desc.fort": "Track pokestop or gym updates", + "slash.desc.untrack": "Remove a tracking rule", + "slash.desc.area": "Manage your areas", + "slash.desc.profile": "Manage your profiles", + "slash.desc.location": "Manage your saved locations", + "slash.desc.summary": "Manage scheduled summary digests (e.g. quest)", + "slash.opt.help.topic": "topic", + "slash.opt.help.topic.desc": "Help topic", + "slash.opt.language.code": "code", + "slash.opt.language.code.desc": "Language code", + "slash.opt.track.pokemon": "pokemon", + "slash.opt.track.pokemon.desc": "Pokemon to track (or 'everything')", + "slash.opt.track.iv": "iv", + "slash.opt.track.iv.desc": "IV filter (e.g. 100, 95, 0-0)", + "slash.opt.track.distance": "distance", + "slash.opt.track.distance.desc": "Alert radius in metres", + "slash.opt.track.great_rank": "great_rank", + "slash.opt.track.great_rank.desc": "Top PVP rank in the Great League", + "slash.opt.track.ultra_rank": "ultra_rank", + "slash.opt.track.ultra_rank.desc": "Top PVP rank in the Ultra League", + "slash.opt.track.little_rank": "little_rank", + "slash.opt.track.little_rank.desc": "Top PVP rank in the Little League", + "slash.opt.track.clean": "clean", + "slash.opt.track.clean.desc": "Auto-delete the alert when the pokemon despawns", + "slash.opt.track.template": "template", + "slash.opt.track.template.desc": "DTS template name", + "slash.opt.track.form": "form", + "slash.opt.track.form.desc": "Pokemon form", + "slash.opt.track.size": "size", + "slash.opt.track.size.desc": "Pokemon size class", + "slash.choice.track.clean.yes": "Yes", + "slash.choice.track.size.all": "All sizes", + "slash.choice.track.size.xxs": "XXS", + "slash.choice.track.size.xs": "XS", + "slash.choice.track.size.m": "M", + "slash.choice.track.size.xl": "XL", + "slash.choice.track.size.xxl": "XXL", + "slash.opt.raid.boss": "boss", + "slash.opt.raid.boss.desc": "Raid boss pokemon", + "slash.opt.raid.level": "level", + "slash.opt.raid.level.desc": "Raid level", + "slash.opt.raid.team": "team", + "slash.opt.raid.team.desc": "Required gym-control team", + "slash.opt.raid.distance": "distance", + "slash.opt.raid.distance.desc": "Alert radius in metres", + "slash.opt.raid.clean": "clean", + "slash.opt.raid.clean.desc": "Auto-delete the alert when the raid expires", + "slash.opt.raid.template": "template", + "slash.opt.raid.template.desc": "DTS template name", + "slash.choice.raid.clean.yes": "Yes", + "slash.choice.raid.level.1": "Tier 1", + "slash.choice.raid.level.3": "Tier 3", + "slash.choice.raid.level.5": "Tier 5", + "slash.choice.raid.level.6": "Tier 6", + "slash.choice.raid.level.mega": "Mega", + "slash.choice.raid.level.legendary": "Legendary", + "slash.choice.raid.level.shadow1": "Shadow Tier 1", + "slash.choice.raid.level.shadow3": "Shadow Tier 3", + "slash.choice.raid.level.shadow5": "Shadow Tier 5", + "slash.choice.raid.level.ultra beast": "Ultra Beast", + "slash.choice.raid.level.everything": "Everything", + "slash.choice.raid.team.0": "Harmony", + "slash.choice.raid.team.1": "Mystic", + "slash.choice.raid.team.2": "Valor", + "slash.choice.raid.team.3": "Instinct", + "slash.opt.egg.level": "level", + "slash.opt.egg.level.desc": "Egg / raid level", + "slash.opt.egg.team": "team", + "slash.opt.egg.team.desc": "Required gym-control team", + "slash.opt.egg.distance": "distance", + "slash.opt.egg.distance.desc": "Alert radius in metres", + "slash.opt.egg.clean": "clean", + "slash.opt.egg.clean.desc": "Auto-delete the alert when the egg hatches", + "slash.opt.egg.template": "template", + "slash.opt.egg.template.desc": "DTS template name", + "slash.choice.egg.clean.yes": "Yes", + "slash.choice.egg.level.1": "Tier 1", + "slash.choice.egg.level.3": "Tier 3", + "slash.choice.egg.level.5": "Tier 5", + "slash.choice.egg.level.6": "Tier 6", + "slash.choice.egg.level.mega": "Mega", + "slash.choice.egg.level.legendary": "Legendary", + "slash.choice.egg.level.shadow1": "Shadow Tier 1", + "slash.choice.egg.level.shadow3": "Shadow Tier 3", + "slash.choice.egg.level.shadow5": "Shadow Tier 5", + "slash.choice.egg.level.ultra beast": "Ultra Beast", + "slash.choice.egg.level.everything": "Everything", + "slash.choice.egg.team.0": "Harmony", + "slash.choice.egg.team.1": "Mystic", + "slash.choice.egg.team.2": "Valor", + "slash.choice.egg.team.3": "Instinct", + "slash.opt.quest.pokemon": "pokemon", + "slash.opt.quest.pokemon.desc": "Pokemon reward", + "slash.opt.quest.item": "item", + "slash.opt.quest.item.desc": "Item reward (e.g. golden razz berry)", + "slash.opt.quest.stardust": "stardust", + "slash.opt.quest.stardust.desc": "Stardust reward (minimum amount)", + "slash.opt.quest.candy": "candy", + "slash.opt.quest.candy.desc": "Candy reward pokemon", + "slash.opt.quest.mega_energy": "mega_energy", + "slash.opt.quest.mega_energy.desc": "Mega energy reward pokemon", + "slash.opt.quest.min_amount": "min_amount", + "slash.opt.quest.min_amount.desc": "Minimum reward amount (item / candy / mega_energy only)", + "slash.opt.quest.distance": "distance", + "slash.opt.quest.distance.desc": "Alert radius in metres", + "slash.opt.quest.clean": "clean", + "slash.opt.quest.clean.desc": "Auto-delete the alert when the quest is completed", + "slash.opt.quest.summary": "summary", + "slash.opt.quest.summary.desc": "Buffer matches and dispatch in a scheduled batch instead of alerting immediately", + "slash.opt.quest.template": "template", + "slash.opt.quest.template.desc": "DTS template name", + "slash.choice.quest.clean.yes": "Yes", + "slash.choice.quest.summary.yes": "Yes", + "slash.opt.invasion.grunt_type": "grunt_type", + "slash.opt.invasion.grunt_type.desc": "Grunt type (Fire, Water…), boss (Giovanni…), or incident (Kecleon…)", + "slash.opt.invasion.gender": "gender", + "slash.opt.invasion.gender.desc": "Filter by grunt gender", + "slash.opt.invasion.distance": "distance", + "slash.opt.invasion.distance.desc": "Alert radius in metres", + "slash.opt.invasion.clean": "clean", + "slash.opt.invasion.clean.desc": "Auto-delete the alert when the invasion expires", + "slash.opt.invasion.template": "template", + "slash.opt.invasion.template.desc": "DTS template name", + "slash.choice.invasion.clean.yes": "Yes", + "slash.choice.invasion.gender.male": "Male", + "slash.choice.invasion.gender.female": "Female", + "slash.choice.invasion.gender.genderless": "Genderless", + "slash.opt.incident.type": "type", + "slash.opt.incident.type.desc": "Pokestop incident type (Kecleon, Gold Pokestop, Showcase…)", + "slash.opt.incident.distance": "distance", + "slash.opt.incident.distance.desc": "Alert radius in metres", + "slash.opt.incident.clean": "clean", + "slash.opt.incident.clean.desc": "Auto-delete the alert when the incident expires", + "slash.opt.incident.template": "template", + "slash.opt.incident.template.desc": "DTS template name", + "slash.choice.incident.clean.yes": "Yes", + "slash.opt.lure.lure_type": "lure_type", + "slash.opt.lure.lure_type.desc": "Lure type", + "slash.opt.lure.distance": "distance", + "slash.opt.lure.distance.desc": "Alert radius in metres", + "slash.opt.lure.clean": "clean", + "slash.opt.lure.clean.desc": "Auto-delete the alert when the lure expires", + "slash.opt.lure.template": "template", + "slash.opt.lure.template.desc": "DTS template name", + "slash.choice.lure.clean.yes": "Yes", + "slash.choice.lure.lure_type.normal": "Normal", + "slash.choice.lure.lure_type.glacial": "Glacial", + "slash.choice.lure.lure_type.mossy": "Mossy", + "slash.choice.lure.lure_type.magnetic": "Magnetic", + "slash.choice.lure.lure_type.rainy": "Rainy", + "slash.choice.lure.lure_type.sparkly": "Sparkly", + "slash.opt.nest.pokemon": "pokemon", + "slash.opt.nest.pokemon.desc": "Nesting pokemon", + "slash.opt.nest.min_spawn_avg": "min_spawn_avg", + "slash.opt.nest.min_spawn_avg.desc": "Minimum spawns per hour", + "slash.opt.nest.distance": "distance", + "slash.opt.nest.distance.desc": "Alert radius in metres", + "slash.opt.nest.clean": "clean", + "slash.opt.nest.clean.desc": "Auto-delete the alert when the nest expires", + "slash.opt.nest.template": "template", + "slash.opt.nest.template.desc": "DTS template name", + "slash.choice.nest.clean.yes": "Yes", + "slash.opt.maxbattle.pokemon": "pokemon", + "slash.opt.maxbattle.pokemon.desc": "Max battle pokemon", + "slash.opt.maxbattle.level": "level", + "slash.opt.maxbattle.level.desc": "Battle level (1..6)", + "slash.opt.maxbattle.gmax": "gmax", + "slash.opt.maxbattle.gmax.desc": "Gigantamax only", + "slash.opt.maxbattle.distance": "distance", + "slash.opt.maxbattle.distance.desc": "Alert radius in metres", + "slash.opt.maxbattle.clean": "clean", + "slash.opt.maxbattle.clean.desc": "Auto-delete the alert when the battle ends", + "slash.opt.maxbattle.template": "template", + "slash.opt.maxbattle.template.desc": "DTS template name", + "slash.choice.maxbattle.clean.yes": "Yes", + "slash.choice.maxbattle.level.1": "Level 1", + "slash.choice.maxbattle.level.2": "Level 2", + "slash.choice.maxbattle.level.3": "Level 3", + "slash.choice.maxbattle.level.4": "Level 4", + "slash.choice.maxbattle.level.5": "Level 5", + "slash.choice.maxbattle.level.6": "Level 6", + "slash.opt.gym.team": "team", + "slash.opt.gym.team.desc": "Gym-control team to alert on", + "slash.opt.gym.slot_changes": "slot_changes", + "slash.opt.gym.slot_changes.desc": "Alert on slot composition changes", + "slash.opt.gym.battle_changes": "battle_changes", + "slash.opt.gym.battle_changes.desc": "Alert on battle state changes", + "slash.opt.gym.distance": "distance", + "slash.opt.gym.distance.desc": "Alert radius in metres", + "slash.opt.gym.clean": "clean", + "slash.opt.gym.clean.desc": "Auto-delete the alert when the gym state changes", + "slash.opt.gym.template": "template", + "slash.opt.gym.template.desc": "DTS template name", + "slash.choice.gym.clean.yes": "Yes", + "slash.choice.gym.team.0": "Harmony", + "slash.choice.gym.team.1": "Mystic", + "slash.choice.gym.team.2": "Valor", + "slash.choice.gym.team.3": "Instinct", + "slash.opt.fort.fort_type": "fort_type", + "slash.opt.fort.fort_type.desc": "Fort type to track", + "slash.opt.fort.include_empty": "include_empty", + "slash.opt.fort.include_empty.desc": "Alert on empty/unowned forts", + "slash.opt.fort.distance": "distance", + "slash.opt.fort.distance.desc": "Alert radius in metres", + "slash.opt.fort.clean": "clean", + "slash.opt.fort.clean.desc": "Auto-delete the alert when the fort changes again", + "slash.opt.fort.template": "template", + "slash.opt.fort.template.desc": "DTS template name", + "slash.choice.fort.clean.yes": "Yes", + "slash.choice.fort.fort_type.0": "Pokestop", + "slash.choice.fort.fort_type.1": "Gym", + "slash.opt.tracker.location": "location", + "slash.opt.tracker.location.desc": "Use a saved location instead of your default (requires distance:)", + "slash.opt.tracker.areas": "areas", + "slash.opt.tracker.areas.desc": "Restrict to specific areas (comma-separated)", + "slash.autocomplete.untrack.remove_all": "🗑️ Remove ALL rules of this type", + "slash.opt.untrack.pokemon": "pokemon", + "slash.opt.untrack.pokemon.desc": "Remove a pokemon tracking rule", + "slash.opt.untrack.pokemon.tracking": "tracking", + "slash.opt.untrack.pokemon.tracking.desc": "Pick from your existing pokemon tracking rules", + "slash.opt.untrack.raid": "raid", + "slash.opt.untrack.raid.desc": "Remove a raid tracking rule", + "slash.opt.untrack.raid.tracking": "tracking", + "slash.opt.untrack.raid.tracking.desc": "Pick from your existing raid tracking rules", + "slash.opt.untrack.egg": "egg", + "slash.opt.untrack.egg.desc": "Remove an egg tracking rule", + "slash.opt.untrack.egg.tracking": "tracking", + "slash.opt.untrack.egg.tracking.desc": "Pick from your existing egg tracking rules", + "slash.opt.untrack.quest": "quest", + "slash.opt.untrack.quest.desc": "Remove a quest tracking rule", + "slash.opt.untrack.quest.tracking": "tracking", + "slash.opt.untrack.quest.tracking.desc": "Pick from your existing quest tracking rules", + "slash.opt.untrack.invasion": "invasion", + "slash.opt.untrack.invasion.desc": "Remove an invasion tracking rule", + "slash.opt.untrack.invasion.tracking": "tracking", + "slash.opt.untrack.invasion.tracking.desc": "Pick from your existing invasion tracking rules", + "slash.opt.untrack.lure": "lure", + "slash.opt.untrack.lure.desc": "Remove a lure tracking rule", + "slash.opt.untrack.lure.tracking": "tracking", + "slash.opt.untrack.lure.tracking.desc": "Pick from your existing lure tracking rules", + "slash.opt.untrack.nest": "nest", + "slash.opt.untrack.nest.desc": "Remove a nest tracking rule", + "slash.opt.untrack.nest.tracking": "tracking", + "slash.opt.untrack.nest.tracking.desc": "Pick from your existing nest tracking rules", + "slash.opt.untrack.gym": "gym", + "slash.opt.untrack.gym.desc": "Remove a gym tracking rule", + "slash.opt.untrack.gym.tracking": "tracking", + "slash.opt.untrack.gym.tracking.desc": "Pick from your existing gym tracking rules", + "slash.opt.untrack.fort": "fort", + "slash.opt.untrack.fort.desc": "Remove a fort tracking rule", + "slash.opt.untrack.fort.tracking": "tracking", + "slash.opt.untrack.fort.tracking.desc": "Pick from your existing fort tracking rules", + "slash.opt.untrack.maxbattle": "maxbattle", + "slash.opt.untrack.maxbattle.desc": "Remove a maxbattle tracking rule", + "slash.opt.untrack.maxbattle.tracking": "tracking", + "slash.opt.untrack.maxbattle.tracking.desc": "Pick from your existing maxbattle tracking rules", + "slash.opt.area.add": "add", + "slash.opt.area.add.desc": "Add an area to your tracking", + "slash.opt.area.add.area": "area", + "slash.opt.area.add.area.desc": "Area to add", + "slash.opt.area.remove": "remove", + "slash.opt.area.remove.desc": "Remove an area from your tracking", + "slash.opt.area.remove.area": "area", + "slash.opt.area.remove.area.desc": "Area to remove", + "slash.opt.area.show": "show", + "slash.opt.area.show.desc": "Show your selected areas", + "slash.opt.area.list": "list", + "slash.opt.area.list.desc": "List every area available to you (✓ = already added)", + "slash.opt.area.overview": "overview", + "slash.opt.area.overview.desc": "Map overview of every area available to you", + "slash.opt.profile.list": "list", + "slash.opt.profile.list.desc": "List your profiles", + "slash.opt.profile.change": "change", + "slash.opt.profile.change.desc": "Switch active profile", + "slash.opt.profile.change.name": "name", + "slash.opt.profile.change.name.desc": "Profile name", + "slash.opt.profile.create": "create", + "slash.opt.profile.create.desc": "Create a new profile", + "slash.opt.profile.create.name": "name", + "slash.opt.profile.create.name.desc": "Profile name", + "slash.opt.profile.delete": "delete", + "slash.opt.profile.delete.desc": "Delete a profile", + "slash.opt.profile.delete.name": "name", + "slash.opt.profile.delete.name.desc": "Profile name", + "slash.opt.profile.settime": "settime", + "slash.opt.profile.settime.desc": "Set active-hours for the current profile", + "slash.opt.profile.settime.times": "times", + "slash.opt.profile.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.profile.cleartime": "cleartime", + "slash.opt.profile.cleartime.desc": "Clear active-hours from the current profile", + "slash.opt.profile.copyto": "copyto", + "slash.opt.profile.copyto.desc": "Copy this profile's tracking to another profile", + "slash.opt.profile.copyto.profile": "profile", + "slash.opt.profile.copyto.profile.desc": "Target profile name or number", + "slash.opt.location.add": "add", + "slash.opt.location.add.desc": "Save a named location", + "slash.opt.location.add.name": "name", + "slash.opt.location.add.name.desc": "Short name for this location (e.g. Home)", + "slash.opt.location.add.place": "place", + "slash.opt.location.add.place.desc": "Coordinates (lat,lon) or a place name", + "slash.opt.location.list": "list", + "slash.opt.location.list.desc": "List your saved locations", + "slash.opt.location.show": "show", + "slash.opt.location.show.desc": "Show one saved location", + "slash.opt.location.show.name": "name", + "slash.opt.location.show.name.desc": "Saved-location name", + "slash.opt.location.remove": "remove", + "slash.opt.location.remove.desc": "Remove a saved location", + "slash.opt.location.remove.name": "name", + "slash.opt.location.remove.name.desc": "Saved-location name (or \"default\" to clear your default location)", + "slash.opt.location.set-default": "set-default", + "slash.opt.location.set-default.desc": "Set your default location", + "slash.opt.location.set-default.place": "place", + "slash.opt.location.set-default.place.desc": "Coordinates (lat,lon) or address to set as your default location", + "slash.opt.location.remove-default": "remove-default", + "slash.opt.location.remove-default.desc": "Clear your default location", + "slash.opt.summary.quest": "quest", + "slash.opt.summary.quest.desc": "Manage quest-summary buffering", + "slash.opt.summary.quest.show": "show", + "slash.opt.summary.quest.show.desc": "Show schedule and current buffer count", + "slash.opt.summary.quest.settime": "settime", + "slash.opt.summary.quest.settime.desc": "Set the active-hours schedule for the quest summary", + "slash.opt.summary.quest.settime.times": "times", + "slash.opt.summary.quest.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.summary.quest.cleartime": "cleartime", + "slash.opt.summary.quest.cleartime.desc": "Clear the active-hours schedule", + "slash.opt.summary.quest.now": "now", + "slash.opt.summary.quest.now.desc": "Force-dispatch the currently-buffered quests", + "error.slash.unregistered_with_channel": "🛑 You need to register first. DM me with !poracle, or run !poracle in {0}.", + "error.slash.unregistered_dm_only": "🛑 You need to register first. DM me with !poracle.", + "error.slash.track.no_pokemon": "Please specify a Pokemon to track.", + "error.slash.raid.need_boss_or_level": "Please specify either a boss or a level.", + "error.slash.raid.boss_and_level": "Please specify either a boss OR a level, not both.", + "error.slash.egg.no_level": "Please specify an egg level.", + "error.slash.quest.no_reward": "Please specify exactly one reward type (pokemon, item, stardust, candy, or mega_energy).", + "error.slash.quest.exactly_one_reward": "Please specify exactly one reward type, not multiple: {0}.", + "error.slash.quest.amount_not_applicable": "`min_amount` doesn't apply to pokemon quests. For stardust, both `stardust` and `min_amount` end up in the same field — pick whichever reads better.", + "error.slash.invasion.no_grunt": "Please specify a grunt type.", + "error.slash.incident.no_type": "Please specify an incident type.", + "error.slash.lure.no_type": "Please specify a lure type.", + "error.slash.nest.no_pokemon": "Please specify a Pokemon for the nest.", + "error.slash.maxbattle.no_pokemon": "Please specify a Pokemon for the max battle.", + "error.slash.fort.no_type": "Please specify a fort type (pokestop or gym).", + "error.slash.untrack.no_subcommand": "Please choose what kind of tracking rule to remove.", + "error.slash.untrack.no_tracking": "Please pick a tracking rule to remove.", + "error.slash.info.no_subcommand": "Please choose an info sub-command (pokemon / rarity / shiny / weather).", + "error.slash.info.no_pokemon": "Please specify a pokemon name or dex id.", + "error.slash.info.unknown_subcommand": "Unknown info sub-command.", + "error.slash.area.no_subcommand": "Please choose an area sub-command (add / remove / show).", + "error.slash.area.no_area": "Please specify an area name.", + "error.slash.area.unknown_subcommand": "Unknown area sub-command.", + "error.slash.profile.no_subcommand": "Please choose a profile sub-command (list / change / create / delete / settime / cleartime / copyto).", + "error.slash.profile.no_name": "Please specify a profile name.", + "error.slash.profile.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.profile.no_target": "Please specify a target profile to copy to.", + "error.slash.profile.unknown_subcommand": "Unknown profile sub-command.", + "error.slash.summary.no_alert_type": "Please choose an alert type (e.g. quest).", + "error.slash.summary.no_action": "Please choose an action (show / settime / cleartime / now).", + "error.slash.summary.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.summary.unknown_action": "Unknown summary action.", + "error.slash.location.no_subcommand": "Please choose a location sub-command (add / list / show / remove / remove-default).", + "error.slash.location.no_name": "Please specify a saved-location name.", + "error.slash.location.empty": "Please specify coordinates or a place name.", + "error.slash.location.unknown_subcommand": "Unknown location sub-command.", + "error.slash.location.no_geocoder": "Place-name lookup is not configured. Please provide coordinates like 51.28, 1.08.", + "error.slash.location.geocode_failed": "Could not find a location for \"{0}\".", + "msg.help.text": "**Available commands:**\n{0}track [iv:N] [cp:N] [level:N] [d:N] — Track pokemon\n{0}untrack — Remove pokemon tracking\n{0}raid [d:N] — Track raids\n{0}egg [d:N] — Track eggs\n{0}quest — Track quests\n{0}invasion [everything|] — Track invasions\n{0}lure — Track lures\n{0}gym [slot_changes] — Track gyms\n{0}nest — Track nests\n{0}maxbattle — Track max battles\n{0}fort — Track fort updates\n{0}tracked — Show all tracking\n{0}script — Export tracking as commands\n{0}area [list|add|remove] — Manage areas\n{0}location — Set location\n{0}profile [list|add|remove|switch] — Manage profiles\n{0}language — Set language\n{0}start / {0}stop — Enable/disable alerts\n{0}version — Show version", + "cmd.poracle_admin": "poracle-admin", + "cmd.pa": "pa", + "cmd.poracle_admin.not_admin": "This command is reserved for administrators.", + "cmd.poracle_admin.unknown_group": "Unknown subgroup. Try `!poracle-admin` for the list.", + "cmd.poracle_admin.unknown_sub": "Unknown subcommand for `{0}`. Try `!poracle-admin {0}` to see what's available.", + "cmd.poracle_admin.help.admin_only": "This command is reserved for server administrators. Each subgroup performs a live operations task.", + "cmd.poracle_admin.help.groups": "Available subgroups:", + "cmd.poracle_admin.help_intro": "🛠️ Poracle Admin\n\nLive operations subgroups (administrators only):", + "cmd.poracle_admin.stub": "(not yet implemented)", + "cmd.poracle_admin.group.slash.desc": "slash-command registration lifecycle", + "cmd.poracle_admin.group.reload.desc": "reload DTS, geofence, or in-memory state", + "cmd.poracle_admin.group.emoji.desc": "list, reload, or test emoji config", + "cmd.poracle_admin.group.reconcile.desc": "Discord role reconciliation (immediate or per-user)", + "cmd.poracle_admin.group.cache.desc": "cache stats and clear", + "cmd.poracle_admin.group.ratelimit.desc": "inspect and reset alert-bucket rate limits", + "cmd.poracle_admin.group.summary.desc": "summary buffer inspection and forced dispatch", + "cmd.poracle_admin.group.status.desc": "live health snapshot", + "cmd.poracle_admin.group.maintenance.desc": "pause/resume outbound delivery", + "cmd.poracle_admin.group.config.desc": "view effective merged config with secrets redacted", + "cmd.poracle_admin.group.warnings.desc": "inspect captured WARN/ERROR log entries (startup + rolling buffers)", + "cmd.poracle_admin.reload.help.intro": "Reload runtime state from disk or database.", + "cmd.poracle_admin.reload.dts.desc": "`dts` — reload DTS templates and partials from disk", + "cmd.poracle_admin.reload.geofence.desc": "`geofence` — reload geofence files and refresh state", + "cmd.poracle_admin.reload.state.desc": "`state` — reload tracking rules and humans from MySQL (bypasses debounce)", + "cmd.poracle_admin.reload.dts.success": "✅ DTS reloaded in {0}ms ({1} templates)", + "cmd.poracle_admin.reload.geofence.success": "✅ Geofence reloaded in {0}ms ({1} fences, {2} tracking rules)", + "cmd.poracle_admin.reload.state.success": "✅ State reloaded in {0}ms ({1} tracking rules, {2} active humans)", + "cmd.poracle_admin.reload.error": "❌ Reload failed: {0}", + "cmd.poracle_admin.emoji.help.intro": "😀 Emoji config — inspect and manage emoji.json + Discord guild emojis.\n\nSubcommands:", + "cmd.poracle_admin.emoji.list.desc": "`list` — list all configured emoji keys with per-platform resolutions", + "cmd.poracle_admin.emoji.reload.desc": "`reload` — reload config/emoji.json from disk", + "cmd.poracle_admin.emoji.test.desc": "`test ` — resolve one emoji key for the current platform", + "cmd.poracle_admin.emoji.upload.desc": "`upload [overwrite]` — upload uicons-based emojis to the guild and write a new emoji.json (Discord-only)", + "cmd.poracle_admin.emoji.discord_config.desc": "`discord-config` — dump emoji.json from the current guild state, no uploads (Discord-only)", + "cmd.poracle_admin.emoji.discord_only": "ℹ️ This subcommand requires a Discord bot with guild access.", + "cmd.poracle_admin.emoji.not_loaded": "ℹ️ Emoji config not loaded (DTS renderer not configured).", + "cmd.poracle_admin.emoji.list.header": "😀 Emoji configuration — {0} keys loaded", + "cmd.poracle_admin.emoji.list.row.key": " {0}:", + "cmd.poracle_admin.emoji.list.row.platform": " {0}: {1}", + "cmd.poracle_admin.emoji.reload.success": "✅ Emoji config reloaded — {0} keys (took {1}ms).", + "cmd.poracle_admin.emoji.reload.error": "❌ Emoji reload failed: {0}", + "cmd.poracle_admin.emoji.test.success": "🔎 {0} on {1}: {2}", + "cmd.poracle_admin.emoji.test.not_found": "ℹ️ Emoji key \"{0}\" not found in the loaded config.", + "cmd.poracle_admin.emoji.test.usage": "Usage: !poracle-admin emoji test ", + "cmd.poracle_admin.reconcile.help.intro": "🔄 Discord role reconciliation — trigger immediately instead of waiting for the periodic timer.", + "cmd.poracle_admin.reconcile.run.desc": "`run` — reconcile all guild members now (blocks until complete)", + "cmd.poracle_admin.reconcile.user.desc": "`user ` — reconcile a single Discord user by snowflake ID", + "cmd.poracle_admin.reconcile.not_configured": "❌ Discord reconciliation is not configured (Telegram-only deploy, or check_role=false).", + "cmd.poracle_admin.reconcile.run.success": "✅ Discord reconciliation complete (took {0}ms).", + "cmd.poracle_admin.reconcile.run.error": "❌ Reconciliation failed: {0}", + "cmd.poracle_admin.reconcile.user.success": "✅ Reconciled discord:user/{0} (took {1}ms).", + "cmd.poracle_admin.reconcile.user.error": "❌ Failed to reconcile discord:user/{0}: {1}", + "cmd.poracle_admin.reconcile.user.usage": "Usage: !poracle-admin reconcile user ", + "cmd.poracle_admin.cache.help.intro": "🗺️ Geocoder cache — inspect counters or drop the in-memory layer.", + "cmd.poracle_admin.cache.stats.desc": "`stats` — geocoder cache stats", + "cmd.poracle_admin.cache.clear.desc": "`clear geocoder` — drop the in-memory geocoder cache", + "cmd.poracle_admin.cache.not_configured": "Geocoder cache is not configured on this instance.", + "cmd.poracle_admin.cache.stats.header": "🗺️ Geocoder cache", + "cmd.poracle_admin.cache.stats.row.memory_entries": " Memory entries: {0}", + "cmd.poracle_admin.cache.stats.row.disk_entries": " Disk entries: {0}", + "cmd.poracle_admin.cache.stats.row.hits_memory": " Hits (memory): {0}", + "cmd.poracle_admin.cache.stats.row.hits_disk": " Hits (disk): {0}", + "cmd.poracle_admin.cache.stats.row.misses": " Misses: {0}", + "cmd.poracle_admin.cache.stats.row.hit_rate": " Hit rate: {0}%", + "cmd.poracle_admin.cache.clear.usage_hint": "Specify what to clear, e.g. `!poracle-admin cache clear geocoder`", + "cmd.poracle_admin.cache.clear.geocoder.success": "✅ Geocoder memory cache cleared — {0} entries dropped (disk untouched).", + "cmd.poracle_admin.ratelimit.help.intro": "🚦 Rate-limit introspection — inspect or reset per-destination alert and summary buckets.", + "cmd.poracle_admin.ratelimit.not_configured": "ℹ️ Alert rate limiter is not configured on this instance.", + "cmd.poracle_admin.ratelimit.list.desc": "`list` — show all targets currently breached or banned", + "cmd.poracle_admin.ratelimit.show.desc": "`show ` — detailed state for one target (both buckets)", + "cmd.poracle_admin.ratelimit.reset.desc": "`reset ` — clear counters and violation history", + "cmd.poracle_admin.ratelimit.userlist.desc": "`userlist` — show currently disabled users (shortcut for !userlist disabled)", + "cmd.poracle_admin.ratelimit.list.empty": "🟢 No targets currently rate-limited.", + "cmd.poracle_admin.ratelimit.list.header_title": "Currently rate-limited targets", + "cmd.poracle_admin.ratelimit.list.bucket_header": " {0} bucket ({1} breached / {2} banned):", + "cmd.poracle_admin.ratelimit.list.row": "count {0}/{1}, {2}", + "cmd.poracle_admin.ratelimit.list.status.banned": "banned for {0}", + "cmd.poracle_admin.ratelimit.list.status.breached": "window resets in {0}", + "cmd.poracle_admin.ratelimit.show.header": "🚦 Rate-limit state for {0}", + "cmd.poracle_admin.ratelimit.show.bucket_header": "{0} bucket:", + "cmd.poracle_admin.ratelimit.show.empty": "🟢 No recorded activity for {0} in either bucket.", + "cmd.poracle_admin.ratelimit.show.no_data": "(no activity in this bucket)", + "cmd.poracle_admin.ratelimit.show.no_violations": "No violations.", + "cmd.poracle_admin.ratelimit.show.violations_count": "Violations (24h): {0}", + "cmd.poracle_admin.ratelimit.show.banned_until": "Banned until: {0} (in {1})", + "cmd.poracle_admin.ratelimit.show.status.under_limit": "under limit", + "cmd.poracle_admin.ratelimit.show.status.over_limit": "over limit", + "cmd.poracle_admin.ratelimit.show.row.count": " Count: {0} / {1} ({2})\n", + "cmd.poracle_admin.ratelimit.show.row.window": " Window: opened {0} ago, resets in {1}\n", + "cmd.poracle_admin.ratelimit.reset.success": "✅ Reset rate-limit state for {0} (cleared alert + summary buckets, violations reset).", + "cmd.poracle_admin.ratelimit.reset.no_state": "ℹ️ No rate-limit state to reset for {0}.", + "cmd.poracle_admin.ratelimit.reset.note": "Note: admin_disable is NOT touched. If the user was auto-disabled by the rate-limiter, they still need to !poracle to re-register.", + "cmd.poracle_admin.ratelimit.usage.show": "Usage: !poracle-admin ratelimit show ", + "cmd.poracle_admin.ratelimit.usage.reset": "Usage: !poracle-admin ratelimit reset ", + "cmd.poracle_admin.ratelimit.userlist.lookup_failed": "❌ Could not find !userlist command in the registry.", + "cmd.poracle_admin.summary.help.intro": "📦 Summary buffer — inspect who has quests buffered and force-dispatch on demand.", + "cmd.poracle_admin.summary.not_configured": "ℹ️ Summary buffer is not configured on this instance.", + "cmd.poracle_admin.summary.list.desc": "`list` — show all users with anything buffered", + "cmd.poracle_admin.summary.show.desc": "`show ` — inspect one user's buffered entries", + "cmd.poracle_admin.summary.fire.desc": "`fire [alertType]` — force-dispatch a user's buffer immediately", + "cmd.poracle_admin.summary.list.empty": "🟢 No users have anything buffered.", + "cmd.poracle_admin.summary.list.header": "📦 Summary buffer — {0} users with {1} buffered entries", + "cmd.poracle_admin.summary.list.user_header": " {0}", + "cmd.poracle_admin.summary.list.row": " {0}: {1} entries (next fires: {2})", + "cmd.poracle_admin.summary.list.next_fire.none": "n/a", + "cmd.poracle_admin.summary.show.header": "📦 Summary buffer for {0}", + "cmd.poracle_admin.summary.show.empty": "🟢 No buffered entries for {0}.", + "cmd.poracle_admin.summary.show.alert_type": " {0}: {1} entries", + "cmd.poracle_admin.summary.show.usage": "Usage: !poracle-admin summary show ", + "cmd.poracle_admin.summary.fire.success": "✅ Dispatched summary for {0} / {1} — {2} entries delivered.", + "cmd.poracle_admin.summary.fire.usage": "Usage: !poracle-admin summary fire [alertType]", + "cmd.poracle_admin.summary.show.reward_row": " Reward type {0}, reward {1}{2} — {3} stops", + "cmd.poracle_admin.summary.show.reward_more": " ... ({0} more reward groups)", + "cmd.poracle_admin.summary.show.form_suffix": " form {0}", + "cmd.poracle_admin.maintenance.help.intro": "🛠️ **!poracle-admin maintenance** — live control over outbound delivery.\n\nSubcommands:", + "cmd.poracle_admin.maintenance.no_dispatcher": "ℹ️ Dispatcher is not available on this instance.", + "cmd.poracle_admin.maintenance.no_reason": "(no reason given)", + "cmd.poracle_admin.maintenance.pause.desc": "`pause [reason...]` (alias: `start`) — halt outbound delivery (webhooks still ingest, match, render, and queue)", + "cmd.poracle_admin.maintenance.resume.desc": "`resume` (alias: `stop`) — lift a previous pause and drain queued jobs", + "cmd.poracle_admin.maintenance.status.desc": "`status` — show current paused/running state and queue depth", + "cmd.poracle_admin.maintenance.pause.new": "🔴 Outbound delivery paused: {0}", + "cmd.poracle_admin.maintenance.pause.detail": "Webhooks still ingest, match, render, and queue — the dispatcher holds them until !poracle-admin maintenance resume.", + "cmd.poracle_admin.maintenance.pause.already": "ℹ️ Already paused since {0} ({1} ago): {2}", + "cmd.poracle_admin.maintenance.resume.success": "🟢 Outbound delivery resumed (was paused for {0}: {1})", + "cmd.poracle_admin.maintenance.resume.detail": "Queued messages are draining.", + "cmd.poracle_admin.maintenance.resume.not_paused": "ℹ️ Not currently paused.", + "cmd.poracle_admin.maintenance.status.running": "🟢 Delivery is running.", + "cmd.poracle_admin.maintenance.status.paused": "🔴 PAUSED — {0} (for {1})", + "cmd.poracle_admin.maintenance.status.queued": "{0} jobs queued waiting (across all platforms — Discord {1}, Telegram {2})", + "cmd.poracle_admin.status.help.intro": "!poracle-admin status — current health snapshot. Add -v for verbose mode (per-route Discord detail, full webhook per-type breakdown).", + "cmd.poracle_admin.status.header": "🛠️ Poracle Admin — Status", + "cmd.poracle_admin.status.paused_banner": "🔴 PAUSED — {0} (since {1} ago)\n Outbound delivery is held. Webhooks still ingest and queue.", + "cmd.poracle_admin.status.value.na": "n/a", + "cmd.poracle_admin.status.value.none": "none", + "cmd.poracle_admin.status.section.build": "**Build / Uptime**", + "cmd.poracle_admin.status.section.webhooks": "**Webhooks**", + "cmd.poracle_admin.status.section.render_queue": "**Render queue**", + "cmd.poracle_admin.status.section.delivery": "**Delivery**", + "cmd.poracle_admin.status.section.discord_rate": "**Discord rate**", + "cmd.poracle_admin.status.section.telegram_rate": "**Telegram rate**", + "cmd.poracle_admin.status.section.alert_limits": "**Alert limits**", + "cmd.poracle_admin.status.section.summary_buffer": "**Summary buffer**", + "cmd.poracle_admin.status.label.summary_buffer_totals": "Entries: {0} across {1} bucket(s)", + "cmd.poracle_admin.status.label.summary_buffer_top": "Top users:", + "cmd.poracle_admin.status.label.summary_buffer_user_row": " {0} ({1}): {2} entries", + "cmd.poracle_admin.status.section.tracking": "**Tracking**", + "cmd.poracle_admin.status.section.mysql": "**MySQL**", + "cmd.poracle_admin.status.label.version": "Version: {0} (commit {1}, built {2})", + "cmd.poracle_admin.status.label.uptime": "Uptime: {0}", + "cmd.poracle_admin.status.label.webhooks_rate": "{0} / {1} / {2} per min over last 5/15/60 min", + "cmd.poracle_admin.status.label.webhooks_by_type": "By type (last 60 min):", + "cmd.poracle_admin.status.label.delivery_discord": "Discord in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_telegram": "Telegram in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_webhook": "Webhook in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_queue_depth": "Queue depth: {0} (capacity not exposed)", + "cmd.poracle_admin.status.label.discord_routes": "Routes near limit: {0}", + "cmd.poracle_admin.status.label.discord_global": "Global tokens: {0} / {1}", + "cmd.poracle_admin.status.label.discord_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.discord_routes_detail": "Routes near limit (detail):", + "cmd.poracle_admin.status.label.telegram_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.telegram_backoff": "Current backoff: {0}", + "cmd.poracle_admin.status.label.alert_limits_counts": "Breached: alert={0}, summary={1} · Banned: {2}", + "cmd.poracle_admin.status.label.tracking_total": "Total tracking rules: {0}", + "cmd.poracle_admin.status.label.tracking_active_humans": "Active humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans": "Registered humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans_error": "Registered humans: n/a (error)", + "cmd.poracle_admin.status.label.tracking_type": "{0}: {1}", + "cmd.poracle_admin.status.label.mysql_ping_ok": "Ping: ok", + "cmd.poracle_admin.status.label.mysql_ping_fail": "Ping: failed ({0})", + "cmd.poracle_admin.status.label.mysql_pool": "Connections: {0}/{1} open ({2} in use, {3} idle, waits={4})", + "cmd.poracle_admin.status.tracking_type.pokemon": "pokemon", + "cmd.poracle_admin.status.tracking_type.raid": "raid", + "cmd.poracle_admin.status.tracking_type.egg": "egg", + "cmd.poracle_admin.status.tracking_type.quest": "quest", + "cmd.poracle_admin.status.tracking_type.invasion": "invasion", + "cmd.poracle_admin.status.tracking_type.lure": "lure", + "cmd.poracle_admin.status.tracking_type.nest": "nest", + "cmd.poracle_admin.status.tracking_type.gym": "gym", + "cmd.poracle_admin.status.tracking_type.fort": "fort", + "cmd.poracle_admin.status.tracking_type.maxbattle": "maxbattle", + "cmd.poracle_admin.slash.help.intro": "**!poracle-admin slash** — slash-command registration lifecycle.\nSubcommands:", + "cmd.poracle_admin.slash.discord_only": "❌ Slash commands are Discord-only and cannot be managed from Telegram.", + "cmd.poracle_admin.slash.not_configured": "❌ Slash commands are not configured (Discord disabled or [discord.slash_commands] enabled=false).", + "cmd.poracle_admin.slash.sync.desc": "push the current command set to Discord (fingerprint-cached, skips if unchanged)", + "cmd.poracle_admin.slash.sync.success": "✅ Slash sync complete ({0}ms)", + "cmd.poracle_admin.slash.sync.error": "❌ Slash sync failed: {0}", + "cmd.poracle_admin.slash.force_resync.desc": "clear fingerprint cache and push unconditionally", + "cmd.poracle_admin.slash.force_resync.success": "✅ Force-resync complete ({0}ms)", + "cmd.poracle_admin.slash.force_resync.error": "❌ Force-resync failed: {0}", + "cmd.poracle_admin.slash.clear_global.desc": "remove all globally-registered Discord slash commands", + "cmd.poracle_admin.slash.clear_global.success": "✅ Global slash commands cleared.", + "cmd.poracle_admin.slash.clear_global.error": "❌ Clear global failed: {0}", + "cmd.poracle_admin.slash.clear_guild.desc": "remove slash commands from one guild (requires guild_id arg)", + "cmd.poracle_admin.slash.clear_guild.needs_arg": "❌ Usage: `!poracle-admin slash clear-guild `", + "cmd.poracle_admin.slash.clear_guild.success": "✅ Slash commands cleared from guild {0}.", + "cmd.poracle_admin.slash.clear_guild.error": "❌ Clear guild failed: {0}", + "cmd.poracle_admin.slash.status.desc": "show last sync timestamp and fingerprint per scope", + "cmd.poracle_admin.slash.status.header": "**Slash command registration status:**", + "cmd.poracle_admin.slash.status.scope_row": " **{0}**: last synced {1} · fingerprint `{2}`", + "cmd.poracle_admin.slash.status.never_synced": "never", + "cmd.poracle_admin.slash.status.ago": "{0} ago", + "cmd.poracle_admin.slash.status.error": "❌ Status read failed: {0}", + "cmd.poracle_admin.config.help.intro": "⚙️ Config viewer — show effective merged config with secrets redacted.\nSubcommands:", + "cmd.poracle_admin.config.keys.desc": "list section names with key counts", + "cmd.poracle_admin.config.section.desc": "show just that section (e.g. `!poracle-admin config discord`)", + "cmd.poracle_admin.config.full.desc": "show the full config (all sections, secrets redacted)", + "cmd.poracle_admin.config.keys.header": "⚙️ Config sections:", + "cmd.poracle_admin.config.keys.row": " {0}: {1} keys", + "cmd.poracle_admin.config.unknown_section": "Unknown config section: `{0}`. Use `!poracle-admin config keys` to list valid sections, or `!poracle-admin config search ` to search across all sections.", + "cmd.poracle_admin.config.search.desc": "find keys whose path or value contains the term across every section (e.g. `!poracle-admin config search dm`)", + "cmd.poracle_admin.config.search.usage": "Usage: `!poracle-admin config search ` — e.g. `search dm`, `search shlink`, `search 3030`.", + "cmd.poracle_admin.config.search.header": "🔍 `{0}` — {1} match(es):", + "cmd.poracle_admin.config.search.no_matches": "No config keys or values match `{0}`.", + "cmd.poracle_admin.config.empty_section": "Section `{0}` has no configurable fields.", + "cmd.poracle_admin.config.not_loaded": "❌ Config not loaded.", + "cmd.poracle_admin.warnings.help.intro": "🛠️ Captured warnings — inspect in-memory WARN/ERROR log entries.\n\nSubcommands:\n (no arg) — show both startup and recent buffers\n `startup` — show only the startup buffer (first 200 entries, frozen after init)\n `recent` — show only the rolling buffer (last 50 entries)\n `clear` — empty the rolling buffer (startup is immutable)", + "cmd.poracle_admin.warnings.not_configured": "ℹ️ Log buffer is not configured on this instance.", + "cmd.poracle_admin.warnings.section.startup": "🛠️ Captured warnings — startup ({0} entries)", + "cmd.poracle_admin.warnings.section.recent": "🛠️ Captured warnings — recent ({0} entries)", + "cmd.poracle_admin.warnings.empty.startup": "🟢 No startup warnings captured.", + "cmd.poracle_admin.warnings.empty.recent": "🟢 No recent warnings.", + "cmd.poracle_admin.warnings.entry_row": " {0} {1} {2} {3}", + "cmd.poracle_admin.warnings.cleared": "✅ Cleared {0} entries from the rolling buffer (startup buffer is unaffected).", + "cmd.poracle_admin.warnings.startup.desc": "`startup` — show only the startup buffer (frozen after init)", + "cmd.poracle_admin.warnings.recent.desc": "`recent` — show only the rolling buffer (last 50 entries)", + "cmd.poracle_admin.warnings.clear.desc": "`clear` — empty the rolling buffer", + "cmd.maintenance.active_suffix": "🔧 Maintenance mode is active — alerts are not being delivered.", + "showcase_focus_pokemon": "Pokémon", + "showcase_focus_type": "Type", + "showcase_focus_alignment": "Alignment", + "showcase_focus_class": "Class", + "showcase_focus_family": "Family", + "showcase_focus_buddy": "Buddy", + "showcase_focus_generation": "Generation", + "showcase_focus_hatched": "Hatched", + "showcase_focus_mega": "Mega", + "showcase_focus_shiny": "Shiny", + "showcase_class_ultra_beast": "Ultra Beast" } diff --git a/processor/internal/i18n/locale/sv.json b/processor/internal/i18n/locale/sv.json index 0a441268e..8797d4aad 100644 --- a/processor/internal/i18n/locale/sv.json +++ b/processor/internal/i18n/locale/sv.json @@ -58,6 +58,11 @@ "tracking.pvp_little": "littlepvp", "tracking.pvp_great": "greatpvp", "tracking.pvp_ultra": "ultrapvp", + "tracking.pvp_mega_any": "mega", + "tracking.pvp_mega_x": "mega x", + "tracking.pvp_mega_y": "mega y", + "tracking.mega_x_label": "X", + "tracking.mega_y_label": "Y", "tracking.level_cap_fmt": "level tak: {0}", "tracking.everything": "Allting", "tracking.unknown_monster": "Okänd pokémon", @@ -81,10 +86,14 @@ "tracking.reward_fmt": "Belöning: **{0}**", "tracking.reward_stardust_min_fmt": "{0} eller mer stardust", "tracking.reward_stardust": "stardust", + "tracking.reward_pokecoin_min_fmt": "{0} or more pokecoins", + "tracking.reward_pokecoin": "pokecoins", "tracking.reward_mega_energy": "mega energy", "tracking.reward_mega_energy_fmt": "mega energy {0}", "tracking.reward_candy": "candy", "tracking.reward_candy_fmt": "candy {0}", + "tracking.reward_any_pokemon": "any pokemon", + "tracking.reward_any_item": "any item", "tracking.reward_min_fmt": "minimum {0}", "tracking.grunt_type_fmt": "Grunt-typ: **{0}**", "tracking.min_avg_spawn": "Min medel spawn {0}/h", @@ -108,10 +117,68 @@ "tracking.template_not_found": "Mallen \"{0}\" finns inte.", "tracking.warn_template_not_found": "Mall \"{0}\" hittades inte för typ {1}/{2}. Spårning sparad men aviseringar kanske inte skapas.", "tracking.id_hint": "För att ta bort en specifik post, använd dess id — t.ex. `{0}untrack id:45` eller `{0}raid remove id:12`", + "tracking.id_hint_slash": "To remove a specific entry, run `/untrack ` (e.g. `/untrack raid`) and pick it from the list.", + "tracking.list_attached": "Your tracking list is long ({0} rules) — attached as a file.", "tracking.removed_prefix": "Borttagen: ", "tracking.uid_not_found": "id:{0} hittades inte", + "tracking.override_location_fmt": "@ {0}", + "tracking.override_areas_fmt": "in {0}", "cmd.track": "track", "cmd.untrack": "untrack", + "cmd.mute": "mute", + "cmd.unmute": "unmute", + "msg.mute.unavailable": "Mute feature isn't enabled here.", + "msg.mute.usage": "Valid commands are `{0}mute [duration:1h]`", + "msg.mute.usage_pokemon": "Valid commands are `{0}mute pokemon [duration:1h]`", + "msg.mute.usage_gym": "Valid commands are `{0}mute gym [duration:1h]`", + "msg.mute.usage_area": "Valid commands are `{0}mute area [duration:1h]`", + "msg.mute.usage_id_scope": "Valid commands are `{0}mute {1} [duration:1h]`", + "msg.mute.bad_duration": "Invalid duration: {0}", + "msg.mute.id_not_supported": "`!mute id:N` / `!mute id:N` aren't supported yet — entity scopes (gym, pokemon, area, pokestop, station, everything) work today. Per-rule muting by UID is a follow-up.", + "msg.mute.bad_uid": "`{0}` isn't a valid tracking rule UID. Use `!tracked` to see your rule UIDs.", + "msg.mute.unknown_area": "`{0}` isn't in your available areas. Use `!area` to see what you can mute.", + "msg.mute.no_pokemon": "I don't know a pokemon called `{0}`.", + "msg.mute.everything_label": "everything", + "msg.mute.added": "🔇 Muted {0} for {1}.", + "msg.mute.removed": "✅ Unmuted {0}.", + "msg.mute.none_found": "No active mute for {0}.", + "msg.mute.cleared_all": "Cleared {0} active mutes.", + "msg.unmute.usage": "Valid commands are `{0}unmute `, `{0}unmute all`", + "msg.unmute.usage_pokemon": "Valid commands are `{0}unmute pokemon `", + "msg.unmute.usage_gym": "Valid commands are `{0}unmute gym `", + "msg.unmute.usage_area": "Valid commands are `{0}unmute area `", + "section.property_mutes": "Property mutes (apply across all tracking):", + "section.property_mutes.left": "({0} left)", + "msg.button.expired": "This alert has expired.", + "msg.button.unavailable": "This button is no longer available.", + "msg.button.wrong_target": "This button doesn't apply here.", + "msg.button.unauthorized": "This button isn't for you.", + "msg.button.unidentified": "Couldn't identify you to handle that click.", + "msg.button.unconfigured": "This button isn't configured.", + "msg.button.action_failed": "Couldn't complete that action: {0}", + "msg.button.action_failed_generic": "Couldn't complete that action.", + "msg.button.cooldown": "Slow down — try that again in a moment.", + "msg.button.actions_not_wired": "Button actions aren't wired here.", + "msg.button.not_implemented": "The {0} action isn't implemented yet.", + "msg.button.responses_not_wired": "Response rendering isn't wired here.", + "msg.button.response_failed": "Couldn't render that response: {0}", + "msg.button.done": "Done.", + "msg.button.missing_scope": "Button is missing a scope — operator config bug.", + "msg.button.missing_target": "Couldn't find a {0} to mute on this alert.", + "msg.button.no_dm_target": "Couldn't identify you to send the message.", + "msg.button.dm_failed": "Couldn't send to your DM: {0}", + "msg.button.unsubscribe_failed": "Couldn't unsubscribe — please try again.", + "msg.button.unsubscribe_already": "Those tracking rules were already removed.", + "msg.button.unsubscribed": "✅ Unsubscribed from {0} tracking rule(s).", + "msg.button.redeliver_sent": "📬 Sent to your DM.", + "msg.mute.scope_gym": "gym", + "msg.mute.scope_pokemon": "pokemon", + "msg.mute.scope_area": "area", + "msg.mute.scope_pokestop": "pokestop", + "msg.mute.scope_station": "station", + "msg.mute.scope_tracking": "tracking rule", + "cmd.mute.usage": "**{0}mute** — silence alerts for a specific gym, pokemon, area, pokestop, station, or everything for a time-bounded window.\n\n• `{0}mute everything [duration:1h]` — silence ALL alerts for the given duration\n• `{0}mute gym [duration:1h]` — silence alerts for one gym\n• `{0}mute pokemon [duration:1h]` — silence alerts for one pokemon species\n• `{0}mute area [duration:1h]` — silence alerts in one area\n• `{0}mute pokestop [duration:1h]` — silence alerts for one pokestop\n• `{0}mute station [duration:1h]` — silence alerts for one station\n\nDuration defaults to 1h if omitted. Use `{0}unmute ` to remove a mute early, or `{0}tracked` to see active mutes.", + "cmd.track.usage": "**{0}track** — set up pokemon tracking rules.\n\n• `{0}track ` — track a specific pokemon (by name or dex id) at default 100m\n• `{0}track everything` — track every pokemon (admin-permitted; see `{0}help everything`)\n• `{0}track iv:100` — filter by IV percent (`iv:90-100` for range, `miniv:90`/`maxiv:99` for one-sided)\n• `{0}track cp:1500-2500` — filter by CP\n• `{0}track level:25-35` — filter by level\n• `{0}track atk:14-15 def:14-15 sta:14-15` — filter by individual IV stats\n• `{0}track d:500` — only alert within 500m of your location\n• `{0}track location:Home d:500` — within 500m of a saved location\n• `{0}track area:london,paris` — only in named areas (replaces your default areas)\n• `{0}track great5 ultra10` — PVP filters (great/ultra/little league, rank threshold, optional cap)\n• `{0}track gen:1 type:water` — generation and type filters (alongside `everything`)\n• `{0}track rarity:rare-ultra` — rarity-tier filter\n• `{0}track clean` / `edit` — auto-delete on TTH expiry / edit-in-place\n• `{0}track remove ` or `{0}untrack ` — remove\n• `{0}untrack id:42` — remove one rule by id (see `{0}tracked` for ids)\n\nMultiple filters combine. See `{0}tracked` for what's currently active.", "cmd.raid": "raid", "cmd.egg": "egg", "cmd.quest": "quest", @@ -129,6 +196,8 @@ "cmd.fort": "fort", "cmd.help": "help", "cmd.info": "info", + "cmd.info.poracle.moved": "→ This view has moved to `!poracle-admin status` — please use that instead.", + "cmd.info.config.moved": "→ This view has moved to `!poracle-admin config` — please use that instead.", "cmd.start": "start", "cmd.stop": "stop", "cmd.tracked": "tracked", @@ -163,6 +232,8 @@ "cmd.poracle_id": "poracle-id", "arg.remove": "ta bort", "arg.everything": "allting", + "arg.all_pokemon": "all pokemon", + "arg.all_items": "all items", "arg.any": "någon", "arg.clean": "städa", "arg.edit": "ändra", @@ -170,6 +241,7 @@ "arg.list": "lista", "arg.add": "lägg till", "arg.show": "visa", + "arg.default": "default", "arg.overview": "översikt", "arg.dryrun": "dryrun", "arg.reset": "reset", @@ -182,6 +254,7 @@ "arg.shiny": "shiny", "arg.gmax": "gmax", "arg.stardust": "stardust", + "arg.pokecoin": "pokecoins", "arg.energy": "energy", "arg.candy": "candy", "arg.pvp": "pvp", @@ -248,7 +321,10 @@ "arg.prefix.maxsize": "maxsize", "arg.prefix.gen": "gen", "arg.prefix.cap": "cap", + "arg.mega": "mega", + "arg.prefix.mega": "mega", "arg.prefix.form": "form", + "arg.prefix.costume": "costume", "arg.prefix.template": "template", "arg.prefix.gym": "gym", "arg.prefix.move": "move", @@ -263,13 +339,17 @@ "arg.prefix.littlehigh": "littlehigh", "arg.prefix.littlecp": "littlecp", "arg.prefix.stardust": "stardust", + "arg.prefix.pokecoin": "pokecoins", "arg.prefix.energy": "energy", "arg.prefix.candy": "candy", + "arg.prefix.amount": "amount", "arg.prefix.name": "namn", "arg.prefix.user": "användare", "arg.prefix.channel": "kanal", "arg.prefix.guild": "gille", "arg.prefix.language": "språk", + "arg.prefix.area": "area", + "arg.prefix.location": "location", "arg.prefix.mon": "mån", "arg.prefix.tue": "tis", "arg.prefix.wed": "ons", @@ -323,21 +403,26 @@ "section.maxbattles.none": "You're not tracking any max battles", "msg.no_pokemon": "No pokemon specified", "msg.form_not_found": "Form `{0}` not recognised. Use `{1}info ` to see available forms.", + "msg.costume_not_found": "Costume `{0}` not recognised. Use `{1}info costumes` to see available costumes.", + "msg.no_costume": "no costume", "msg.nothing_to_remove": "Nothing to remove", "msg.no_levels": "No levels specified", "msg.no_egg_levels": "No egg levels specified", "msg.no_raid_target": "No raid levels or pokemon specified", "msg.no_lure_type": "No lure type specified", "msg.no_quest_type": "No quest type specified", + "msg.quest.amount_not_applicable": "`amount:N` doesn't apply to pokemon quests — pokemon rewards have no minimum amount.", + "msg.quest.bulk_not_permitted": "You do not have permission to track all pokemon or items at once. Track specific rewards instead.", "msg.removed_n": "Removed {0} tracking rules", "msg.egg.usage": "Valid commands are e.g. `{0}egg level:5`, `{0}egg legendary`, `{0}egg remove everything`", "msg.raid.usage": "Valid commands are e.g. `{0}raid level:5`, `{0}raid pikachu`, `{0}raid remove everything`", "msg.track.usage": "Valid commands are e.g. `{0}track pikachu iv:100`, `{0}track everything iv:90`, `{0}track remove pikachu`", "msg.track.everything_no_filters": "This would result in too many alerts. You need to provide additional filters to limit the number of valid candidates.", "msg.track.invalid_cap": "This level cap is not supported, valid choices are: {0}", - "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest energy:charizard`", + "msg.track.no_mega_form": "⚠️ {0} has no Mega {1} form — this PVP rule will never match.", + "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest pokecoins:10`, `{0}quest energy:charizard`", "msg.quest.edit_summary_conflict": "`edit` and `summary` are mutually exclusive — pick one.", - "msg.summary.usage": "Usage: `{0}summary quest [settime |cleartime|now]`", + "msg.summary.usage": "Valid commands are `{0}summary quest`, `{0}summary quest settime `, `{0}summary quest cleartime`, `{0}summary quest now`", "msg.summary.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.summary.no_schedule": "No schedule set for {0} summaries.", "msg.summary.scheduled": "Schedule for {0} summaries: {1}", @@ -360,11 +445,33 @@ "msg.nest.usage": "Valid commands are e.g. `{0}nest pikachu`, `{0}nest everything`, `{0}nest remove pikachu`", "msg.maxbattle.usage": "Valid commands are e.g. `{0}maxbattle pikachu`, `{0}maxbattle level:3`, `{0}maxbattle remove everything`", "msg.fort.usage": "Valid commands are e.g. `{0}fort pokestop`, `{0}fort everything`, `{0}fort remove pokestop`", - "msg.location.removed": "Location removed", - "msg.location.usage": "Valid commands are e.g. `{0}location ,`, `{0}location `", + "msg.location.removed": "✅ Removed saved location `{0}`.", + "msg.location.usage": "Valid commands are `{0}location `, `{0}location add `, `{0}location list`, `{0}location show `, `{0}location remove `, `{0}location remove default`", "msg.location.specify": "Please specify coordinates or an address", "msg.location.set": "Location set to {0},{1}", "msg.location.current": "Your current location is {0},{1}", + "msg.location.added": "✅ Saved location `{0}` at {1}, {2}.", + "msg.location.duplicate": "🙅 You already have a saved location called `{0}`. Remove it first with `{1}location remove {0}`.", + "msg.location.list_header": "Your saved locations:", + "msg.location.list_row": " `{0}`: {1}, {2}", + "msg.location.list_row_with_addr": " `{0}`: {1}, {2} — {3}", + "msg.location.list_empty": "You have no saved locations. Add one with `{0}location add `.", + "msg.location.show_not_found": "🙅 No saved location called `{0}`.", + "msg.location.show": "📍 `{0}` is at {1}, {2}.", + "msg.location.show_with_addr": "📍 `{0}` is at {1}, {2} — {3}", + "msg.location.no_default": "🙅 No default location set.", + "msg.location.default_removed": "✅ Cleared your default location.", + "msg.location.remove_referenced": "🙅 Cannot remove `{0}` — {1} tracking rule(s) reference it: {2}. Edit or remove those rules first.", + "msg.location.add_usage": "Valid commands are `{0}location add `", + "msg.location.show_usage": "Valid commands are `{0}location show `", + "msg.location.remove_usage": "Valid commands are `{0}location remove `, `{0}location remove default`", + "msg.location.geocode_failed": "🙅 Couldn't find a place matching `{0}`.", + "cmd.location.usage": "**{0}location** — manage your default location and saved named locations.\n\n• `{0}location` — show your current default location\n• `{0}location ` — set your default location\n• `{0}location add ` — save a named location (referenced later as `location:` on tracking rules)\n• `{0}location list` — list all your saved locations\n• `{0}location show ` — show one saved location's coords + address (use `default` for your default)\n• `{0}location remove ` — delete a saved location (refuses if any tracking rule references it)\n• `{0}location remove default` — clear your default location", + "msg.override.requires_distance": "🙅 `location:` needs a `d:` distance — e.g. `location:Home d:500`.", + "msg.override.area_and_distance": "🙅 `area:` and `d:` are mutually exclusive (area-mode vs distance-mode). Pick one.", + "msg.override.area_and_location": "🙅 `area:` and `location:` are mutually exclusive. Pick one.", + "msg.override.unknown_location": "🙅 No saved location called `{0}`. Add it with `{1}location add {0} `.", + "msg.override.area_not_permitted": "🙅 Area `{0}` is not in your allowed areas. Use `{1}area list` to see what you can pick.", "msg.area.usage": "Valid commands are `{0}area list`, `{0}area add `, `{0}area remove `", "msg.area.none_available": "No areas available", "msg.area.available": "**Available areas:**", @@ -382,14 +489,14 @@ "msg.profile.deleted": "Profile {0} deleted", "msg.profile.not_found": "Profile not found", "msg.profile.cannot_delete_1": "Cannot delete profile 1", - "msg.profile.hours_usage": "Usage: profile hours ", + "msg.profile.hours_usage": "Valid commands are `{0}profile hours `", "msg.profile.hours_invalid_json": "Ogiltig JSON för aktiva timmar", "msg.profile.hours_set": "Aktiva timmar uppdaterade för profil {0}", "msg.profile.hours_cleared": "Active hours cleared for profile {0}", - "msg.profile.settime_usage": "Usage: profile settime mon09:00 tue18:30 weekday09:00 weekend10:00", + "msg.profile.settime_usage": "Valid commands are `{0}profile settime mon09:00 tue18:30 weekday09:00 weekend10:00`", "msg.profile.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.profile.copied": "Aktuell profil har kopierats till: {0}", - "msg.profile.copyto_usage": "Usage: profile copyto ", + "msg.profile.copyto_usage": "Valid commands are `{0}profile copyto `", "msg.profile.copy_invalid": "Dessa profiler var ogiltiga: {0}", "msg.profile.usage": "Valid commands are `{0}profile `, `{0}profile list`, `{0}profile add `, `{0}profile remove `, `{0}profile settime `, `{0}profile copyto `", "msg.profile.list_header": "Nuvarande konfigurerade profiler är:", @@ -407,6 +514,7 @@ "msg.weather.unavailable": "Väderspårning är ännu inte tillgänglig via detta kommando", "msg.help.unknown_topic": "Ingen hjälp tillgänglig för '{0}'. Använd `{1}help` för allmän hjälp.", "msg.help.no_greeting": "Ingen hjälpmall konfigurerad. Använd `{0}hjälp ` för kommandospecifik hjälp.", + "msg.help.see_detailed": "💡 More detailed help is available — `{0}help {1}`", "msg.info.sub.moves": "moves", "msg.info.sub.items": "items", "msg.info.sub.shiny": "shiny", @@ -417,9 +525,19 @@ "msg.info.sub.translate": "översätt", "msg.info.sub.dts": "dts", "msg.info.sub.templates": "mallar", - "msg.info.usage": "Giltiga kommandon är `{0}info-mallar`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info `", + "msg.info.sub.costumes": "costumes", + "msg.info.sub.forms": "forms", + "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info costumes`, `{0}info `", "msg.info.usage_admin": "Admin: `{0}info poracle`, `{0}info dts`, `{0}info translate `, `{0}info config [search]`", "msg.info.available_forms": "Tillgängliga former:", + "msg.info.more_forms": "More than {0} forms — do {1} for the full list", + "msg.info.recent_forms": "**Recently-seen forms:**", + "msg.info.recent_raid_forms": "**Recently-seen raid forms:**", + "msg.info.available_costumes": "**Recently-seen costumes:**", + "msg.info.recent_raid_costumes": "**Recently-seen raid costumes:**", + "msg.info.costumes.header": "**Costumes** (`costume:` to track):", + "msg.info.no_costume_data": "No costume data loaded", + "msg.info.no_form_data": "No form data for that pokemon.", "msg.info.hundo_cp": "100% IV CP:", "msg.info.dts_summary": "Laddade DTS-mallar:", "msg.info.pokemon_not_found": "Pokémon hittades inte: {0}", @@ -534,5 +652,661 @@ "language.sv": "Svenska", "language.zh-cn": "Kinesiska (förenklad)", "language.ja": "Japanska", - "msg.help.text": "**Available commands:**\n{0}track [iv:N] [cp:N] [level:N] [d:N] — Track pokemon\n{0}untrack — Remove pokemon tracking\n{0}raid [d:N] — Track raids\n{0}egg [d:N] — Track eggs\n{0}quest — Track quests\n{0}invasion [everything|] — Track invasions\n{0}lure — Track lures\n{0}gym [slot_changes] — Track gyms\n{0}nest — Track nests\n{0}maxbattle — Track max battles\n{0}fort — Track fort updates\n{0}tracked — Show all tracking\n{0}script — Export tracking as commands\n{0}area [list|add|remove] — Manage areas\n{0}location — Set location\n{0}profile [list|add|remove|switch] — Manage profiles\n{0}language — Set language\n{0}start / {0}stop — Enable/disable alerts\n{0}version — Show version" + "slash.cmd.version": "version", + "slash.desc.version": "Show Poracle version", + "slash.cmd.tracked": "tracked", + "slash.cmd.help": "help", + "slash.cmd.info": "info", + "slash.cmd.language": "language", + "slash.cmd.track": "track", + "slash.cmd.raid": "raid", + "slash.cmd.egg": "egg", + "slash.cmd.quest": "quest", + "slash.cmd.invasion": "invasion", + "slash.cmd.incident": "incident", + "slash.cmd.lure": "lure", + "slash.cmd.nest": "nest", + "slash.cmd.maxbattle": "maxbattle", + "slash.cmd.gym": "gym", + "slash.cmd.fort": "fort", + "slash.cmd.untrack": "untrack", + "slash.cmd.area": "area", + "slash.cmd.profile": "profile", + "slash.cmd.location": "location", + "slash.cmd.summary": "summary", + "slash.cmd.start": "start", + "slash.cmd.stop": "stop", + "slash.desc.tracked": "List your tracking rules", + "slash.desc.start": "Resume alert delivery (after /stop)", + "slash.desc.stop": "Pause alert delivery (resume with /start)", + "slash.desc.help": "Show help", + "slash.desc.info": "Look up pokemon info, shiny rates, rarity tiers, or current weather", + "slash.opt.info.pokemon": "pokemon", + "slash.opt.info.pokemon.desc": "Show types, stats, evolutions, weather boost and CP table for a pokemon", + "slash.opt.info.pokemon.name": "name", + "slash.opt.info.pokemon.name.desc": "Pokemon name (any supported language) or dex id", + "slash.opt.info.rarity": "rarity", + "slash.opt.info.rarity.desc": "List pokemon by spawn rarity tier (common → ultra-rare)", + "slash.opt.info.shiny": "shiny", + "slash.opt.info.shiny.desc": "Show observed shiny rates per species", + "slash.opt.info.weather": "weather", + "slash.opt.info.weather.desc": "Show current weather and boosted types for a location", + "slash.opt.info.weather.coords": "coords", + "slash.opt.info.weather.coords.desc": "lat,lon (defaults to your saved location)", + "slash.desc.language": "Show or set your language", + "slash.desc.track": "Track a Pokemon", + "slash.desc.raid": "Track a raid boss or raid level", + "slash.desc.egg": "Track an egg / raid level", + "slash.desc.quest": "Track a quest reward", + "slash.desc.invasion": "Track a Team Rocket invasion", + "slash.desc.incident": "Track a pokestop incident (Kecleon, Gold Pokestop, Showcase…)", + "slash.desc.lure": "Track a pokestop lure", + "slash.desc.nest": "Track a nesting pokemon", + "slash.desc.maxbattle": "Track a max (Dynamax) battle", + "slash.desc.gym": "Track gym team / slot / battle changes", + "slash.desc.fort": "Track pokestop or gym updates", + "slash.desc.untrack": "Remove a tracking rule", + "slash.desc.area": "Manage your areas", + "slash.desc.profile": "Manage your profiles", + "slash.desc.location": "Manage your saved locations", + "slash.desc.summary": "Manage scheduled summary digests (e.g. quest)", + "slash.opt.help.topic": "topic", + "slash.opt.help.topic.desc": "Help topic", + "slash.opt.language.code": "code", + "slash.opt.language.code.desc": "Language code", + "slash.opt.track.pokemon": "pokemon", + "slash.opt.track.pokemon.desc": "Pokemon to track (or 'everything')", + "slash.opt.track.iv": "iv", + "slash.opt.track.iv.desc": "IV filter (e.g. 100, 95, 0-0)", + "slash.opt.track.distance": "distance", + "slash.opt.track.distance.desc": "Alert radius in metres", + "slash.opt.track.great_rank": "great_rank", + "slash.opt.track.great_rank.desc": "Top PVP rank in the Great League", + "slash.opt.track.ultra_rank": "ultra_rank", + "slash.opt.track.ultra_rank.desc": "Top PVP rank in the Ultra League", + "slash.opt.track.little_rank": "little_rank", + "slash.opt.track.little_rank.desc": "Top PVP rank in the Little League", + "slash.opt.track.clean": "clean", + "slash.opt.track.clean.desc": "Auto-delete the alert when the pokemon despawns", + "slash.opt.track.template": "template", + "slash.opt.track.template.desc": "DTS template name", + "slash.opt.track.form": "form", + "slash.opt.track.form.desc": "Pokemon form", + "slash.opt.track.size": "size", + "slash.opt.track.size.desc": "Pokemon size class", + "slash.choice.track.clean.yes": "Yes", + "slash.choice.track.size.all": "All sizes", + "slash.choice.track.size.xxs": "XXS", + "slash.choice.track.size.xs": "XS", + "slash.choice.track.size.m": "M", + "slash.choice.track.size.xl": "XL", + "slash.choice.track.size.xxl": "XXL", + "slash.opt.raid.boss": "boss", + "slash.opt.raid.boss.desc": "Raid boss pokemon", + "slash.opt.raid.level": "level", + "slash.opt.raid.level.desc": "Raid level", + "slash.opt.raid.team": "team", + "slash.opt.raid.team.desc": "Required gym-control team", + "slash.opt.raid.distance": "distance", + "slash.opt.raid.distance.desc": "Alert radius in metres", + "slash.opt.raid.clean": "clean", + "slash.opt.raid.clean.desc": "Auto-delete the alert when the raid expires", + "slash.opt.raid.template": "template", + "slash.opt.raid.template.desc": "DTS template name", + "slash.choice.raid.clean.yes": "Yes", + "slash.choice.raid.level.1": "Tier 1", + "slash.choice.raid.level.3": "Tier 3", + "slash.choice.raid.level.5": "Tier 5", + "slash.choice.raid.level.6": "Tier 6", + "slash.choice.raid.level.mega": "Mega", + "slash.choice.raid.level.legendary": "Legendary", + "slash.choice.raid.level.shadow1": "Shadow Tier 1", + "slash.choice.raid.level.shadow3": "Shadow Tier 3", + "slash.choice.raid.level.shadow5": "Shadow Tier 5", + "slash.choice.raid.level.ultra beast": "Ultra Beast", + "slash.choice.raid.level.everything": "Everything", + "slash.choice.raid.team.0": "Harmony", + "slash.choice.raid.team.1": "Mystic", + "slash.choice.raid.team.2": "Valor", + "slash.choice.raid.team.3": "Instinct", + "slash.opt.egg.level": "level", + "slash.opt.egg.level.desc": "Egg / raid level", + "slash.opt.egg.team": "team", + "slash.opt.egg.team.desc": "Required gym-control team", + "slash.opt.egg.distance": "distance", + "slash.opt.egg.distance.desc": "Alert radius in metres", + "slash.opt.egg.clean": "clean", + "slash.opt.egg.clean.desc": "Auto-delete the alert when the egg hatches", + "slash.opt.egg.template": "template", + "slash.opt.egg.template.desc": "DTS template name", + "slash.choice.egg.clean.yes": "Yes", + "slash.choice.egg.level.1": "Tier 1", + "slash.choice.egg.level.3": "Tier 3", + "slash.choice.egg.level.5": "Tier 5", + "slash.choice.egg.level.6": "Tier 6", + "slash.choice.egg.level.mega": "Mega", + "slash.choice.egg.level.legendary": "Legendary", + "slash.choice.egg.level.shadow1": "Shadow Tier 1", + "slash.choice.egg.level.shadow3": "Shadow Tier 3", + "slash.choice.egg.level.shadow5": "Shadow Tier 5", + "slash.choice.egg.level.ultra beast": "Ultra Beast", + "slash.choice.egg.level.everything": "Everything", + "slash.choice.egg.team.0": "Harmony", + "slash.choice.egg.team.1": "Mystic", + "slash.choice.egg.team.2": "Valor", + "slash.choice.egg.team.3": "Instinct", + "slash.opt.quest.pokemon": "pokemon", + "slash.opt.quest.pokemon.desc": "Pokemon reward", + "slash.opt.quest.item": "item", + "slash.opt.quest.item.desc": "Item reward (e.g. golden razz berry)", + "slash.opt.quest.stardust": "stardust", + "slash.opt.quest.stardust.desc": "Stardust reward (minimum amount)", + "slash.opt.quest.candy": "candy", + "slash.opt.quest.candy.desc": "Candy reward pokemon", + "slash.opt.quest.mega_energy": "mega_energy", + "slash.opt.quest.mega_energy.desc": "Mega energy reward pokemon", + "slash.opt.quest.min_amount": "min_amount", + "slash.opt.quest.min_amount.desc": "Minimum reward amount (item / candy / mega_energy only)", + "slash.opt.quest.distance": "distance", + "slash.opt.quest.distance.desc": "Alert radius in metres", + "slash.opt.quest.clean": "clean", + "slash.opt.quest.clean.desc": "Auto-delete the alert when the quest is completed", + "slash.opt.quest.summary": "summary", + "slash.opt.quest.summary.desc": "Buffer matches and dispatch in a scheduled batch instead of alerting immediately", + "slash.opt.quest.template": "template", + "slash.opt.quest.template.desc": "DTS template name", + "slash.choice.quest.clean.yes": "Yes", + "slash.choice.quest.summary.yes": "Yes", + "slash.opt.invasion.grunt_type": "grunt_type", + "slash.opt.invasion.grunt_type.desc": "Grunt type (Fire, Water…), boss (Giovanni…), or incident (Kecleon…)", + "slash.opt.invasion.gender": "gender", + "slash.opt.invasion.gender.desc": "Filter by grunt gender", + "slash.opt.invasion.distance": "distance", + "slash.opt.invasion.distance.desc": "Alert radius in metres", + "slash.opt.invasion.clean": "clean", + "slash.opt.invasion.clean.desc": "Auto-delete the alert when the invasion expires", + "slash.opt.invasion.template": "template", + "slash.opt.invasion.template.desc": "DTS template name", + "slash.choice.invasion.clean.yes": "Yes", + "slash.choice.invasion.gender.male": "Male", + "slash.choice.invasion.gender.female": "Female", + "slash.choice.invasion.gender.genderless": "Genderless", + "slash.opt.incident.type": "type", + "slash.opt.incident.type.desc": "Pokestop incident type (Kecleon, Gold Pokestop, Showcase…)", + "slash.opt.incident.distance": "distance", + "slash.opt.incident.distance.desc": "Alert radius in metres", + "slash.opt.incident.clean": "clean", + "slash.opt.incident.clean.desc": "Auto-delete the alert when the incident expires", + "slash.opt.incident.template": "template", + "slash.opt.incident.template.desc": "DTS template name", + "slash.choice.incident.clean.yes": "Yes", + "slash.opt.lure.lure_type": "lure_type", + "slash.opt.lure.lure_type.desc": "Lure type", + "slash.opt.lure.distance": "distance", + "slash.opt.lure.distance.desc": "Alert radius in metres", + "slash.opt.lure.clean": "clean", + "slash.opt.lure.clean.desc": "Auto-delete the alert when the lure expires", + "slash.opt.lure.template": "template", + "slash.opt.lure.template.desc": "DTS template name", + "slash.choice.lure.clean.yes": "Yes", + "slash.choice.lure.lure_type.normal": "Normal", + "slash.choice.lure.lure_type.glacial": "Glacial", + "slash.choice.lure.lure_type.mossy": "Mossy", + "slash.choice.lure.lure_type.magnetic": "Magnetic", + "slash.choice.lure.lure_type.rainy": "Rainy", + "slash.choice.lure.lure_type.sparkly": "Sparkly", + "slash.opt.nest.pokemon": "pokemon", + "slash.opt.nest.pokemon.desc": "Nesting pokemon", + "slash.opt.nest.min_spawn_avg": "min_spawn_avg", + "slash.opt.nest.min_spawn_avg.desc": "Minimum spawns per hour", + "slash.opt.nest.distance": "distance", + "slash.opt.nest.distance.desc": "Alert radius in metres", + "slash.opt.nest.clean": "clean", + "slash.opt.nest.clean.desc": "Auto-delete the alert when the nest expires", + "slash.opt.nest.template": "template", + "slash.opt.nest.template.desc": "DTS template name", + "slash.choice.nest.clean.yes": "Yes", + "slash.opt.maxbattle.pokemon": "pokemon", + "slash.opt.maxbattle.pokemon.desc": "Max battle pokemon", + "slash.opt.maxbattle.level": "level", + "slash.opt.maxbattle.level.desc": "Battle level (1..6)", + "slash.opt.maxbattle.gmax": "gmax", + "slash.opt.maxbattle.gmax.desc": "Gigantamax only", + "slash.opt.maxbattle.distance": "distance", + "slash.opt.maxbattle.distance.desc": "Alert radius in metres", + "slash.opt.maxbattle.clean": "clean", + "slash.opt.maxbattle.clean.desc": "Auto-delete the alert when the battle ends", + "slash.opt.maxbattle.template": "template", + "slash.opt.maxbattle.template.desc": "DTS template name", + "slash.choice.maxbattle.clean.yes": "Yes", + "slash.choice.maxbattle.level.1": "Level 1", + "slash.choice.maxbattle.level.2": "Level 2", + "slash.choice.maxbattle.level.3": "Level 3", + "slash.choice.maxbattle.level.4": "Level 4", + "slash.choice.maxbattle.level.5": "Level 5", + "slash.choice.maxbattle.level.6": "Level 6", + "slash.opt.gym.team": "team", + "slash.opt.gym.team.desc": "Gym-control team to alert on", + "slash.opt.gym.slot_changes": "slot_changes", + "slash.opt.gym.slot_changes.desc": "Alert on slot composition changes", + "slash.opt.gym.battle_changes": "battle_changes", + "slash.opt.gym.battle_changes.desc": "Alert on battle state changes", + "slash.opt.gym.distance": "distance", + "slash.opt.gym.distance.desc": "Alert radius in metres", + "slash.opt.gym.clean": "clean", + "slash.opt.gym.clean.desc": "Auto-delete the alert when the gym state changes", + "slash.opt.gym.template": "template", + "slash.opt.gym.template.desc": "DTS template name", + "slash.choice.gym.clean.yes": "Yes", + "slash.choice.gym.team.0": "Harmony", + "slash.choice.gym.team.1": "Mystic", + "slash.choice.gym.team.2": "Valor", + "slash.choice.gym.team.3": "Instinct", + "slash.opt.fort.fort_type": "fort_type", + "slash.opt.fort.fort_type.desc": "Fort type to track", + "slash.opt.fort.include_empty": "include_empty", + "slash.opt.fort.include_empty.desc": "Alert on empty/unowned forts", + "slash.opt.fort.distance": "distance", + "slash.opt.fort.distance.desc": "Alert radius in metres", + "slash.opt.fort.clean": "clean", + "slash.opt.fort.clean.desc": "Auto-delete the alert when the fort changes again", + "slash.opt.fort.template": "template", + "slash.opt.fort.template.desc": "DTS template name", + "slash.choice.fort.clean.yes": "Yes", + "slash.choice.fort.fort_type.0": "Pokestop", + "slash.choice.fort.fort_type.1": "Gym", + "slash.opt.tracker.location": "location", + "slash.opt.tracker.location.desc": "Use a saved location instead of your default (requires distance:)", + "slash.opt.tracker.areas": "areas", + "slash.opt.tracker.areas.desc": "Restrict to specific areas (comma-separated)", + "slash.autocomplete.untrack.remove_all": "🗑️ Remove ALL rules of this type", + "slash.opt.untrack.pokemon": "pokemon", + "slash.opt.untrack.pokemon.desc": "Remove a pokemon tracking rule", + "slash.opt.untrack.pokemon.tracking": "tracking", + "slash.opt.untrack.pokemon.tracking.desc": "Pick from your existing pokemon tracking rules", + "slash.opt.untrack.raid": "raid", + "slash.opt.untrack.raid.desc": "Remove a raid tracking rule", + "slash.opt.untrack.raid.tracking": "tracking", + "slash.opt.untrack.raid.tracking.desc": "Pick from your existing raid tracking rules", + "slash.opt.untrack.egg": "egg", + "slash.opt.untrack.egg.desc": "Remove an egg tracking rule", + "slash.opt.untrack.egg.tracking": "tracking", + "slash.opt.untrack.egg.tracking.desc": "Pick from your existing egg tracking rules", + "slash.opt.untrack.quest": "quest", + "slash.opt.untrack.quest.desc": "Remove a quest tracking rule", + "slash.opt.untrack.quest.tracking": "tracking", + "slash.opt.untrack.quest.tracking.desc": "Pick from your existing quest tracking rules", + "slash.opt.untrack.invasion": "invasion", + "slash.opt.untrack.invasion.desc": "Remove an invasion tracking rule", + "slash.opt.untrack.invasion.tracking": "tracking", + "slash.opt.untrack.invasion.tracking.desc": "Pick from your existing invasion tracking rules", + "slash.opt.untrack.lure": "lure", + "slash.opt.untrack.lure.desc": "Remove a lure tracking rule", + "slash.opt.untrack.lure.tracking": "tracking", + "slash.opt.untrack.lure.tracking.desc": "Pick from your existing lure tracking rules", + "slash.opt.untrack.nest": "nest", + "slash.opt.untrack.nest.desc": "Remove a nest tracking rule", + "slash.opt.untrack.nest.tracking": "tracking", + "slash.opt.untrack.nest.tracking.desc": "Pick from your existing nest tracking rules", + "slash.opt.untrack.gym": "gym", + "slash.opt.untrack.gym.desc": "Remove a gym tracking rule", + "slash.opt.untrack.gym.tracking": "tracking", + "slash.opt.untrack.gym.tracking.desc": "Pick from your existing gym tracking rules", + "slash.opt.untrack.fort": "fort", + "slash.opt.untrack.fort.desc": "Remove a fort tracking rule", + "slash.opt.untrack.fort.tracking": "tracking", + "slash.opt.untrack.fort.tracking.desc": "Pick from your existing fort tracking rules", + "slash.opt.untrack.maxbattle": "maxbattle", + "slash.opt.untrack.maxbattle.desc": "Remove a maxbattle tracking rule", + "slash.opt.untrack.maxbattle.tracking": "tracking", + "slash.opt.untrack.maxbattle.tracking.desc": "Pick from your existing maxbattle tracking rules", + "slash.opt.area.add": "add", + "slash.opt.area.add.desc": "Add an area to your tracking", + "slash.opt.area.add.area": "area", + "slash.opt.area.add.area.desc": "Area to add", + "slash.opt.area.remove": "remove", + "slash.opt.area.remove.desc": "Remove an area from your tracking", + "slash.opt.area.remove.area": "area", + "slash.opt.area.remove.area.desc": "Area to remove", + "slash.opt.area.show": "show", + "slash.opt.area.show.desc": "Show your selected areas", + "slash.opt.area.list": "list", + "slash.opt.area.list.desc": "List every area available to you (✓ = already added)", + "slash.opt.area.overview": "overview", + "slash.opt.area.overview.desc": "Map overview of every area available to you", + "slash.opt.profile.list": "list", + "slash.opt.profile.list.desc": "List your profiles", + "slash.opt.profile.change": "change", + "slash.opt.profile.change.desc": "Switch active profile", + "slash.opt.profile.change.name": "name", + "slash.opt.profile.change.name.desc": "Profile name", + "slash.opt.profile.create": "create", + "slash.opt.profile.create.desc": "Create a new profile", + "slash.opt.profile.create.name": "name", + "slash.opt.profile.create.name.desc": "Profile name", + "slash.opt.profile.delete": "delete", + "slash.opt.profile.delete.desc": "Delete a profile", + "slash.opt.profile.delete.name": "name", + "slash.opt.profile.delete.name.desc": "Profile name", + "slash.opt.profile.settime": "settime", + "slash.opt.profile.settime.desc": "Set active-hours for the current profile", + "slash.opt.profile.settime.times": "times", + "slash.opt.profile.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.profile.cleartime": "cleartime", + "slash.opt.profile.cleartime.desc": "Clear active-hours from the current profile", + "slash.opt.profile.copyto": "copyto", + "slash.opt.profile.copyto.desc": "Copy this profile's tracking to another profile", + "slash.opt.profile.copyto.profile": "profile", + "slash.opt.profile.copyto.profile.desc": "Target profile name or number", + "slash.opt.location.add": "add", + "slash.opt.location.add.desc": "Save a named location", + "slash.opt.location.add.name": "name", + "slash.opt.location.add.name.desc": "Short name for this location (e.g. Home)", + "slash.opt.location.add.place": "place", + "slash.opt.location.add.place.desc": "Coordinates (lat,lon) or a place name", + "slash.opt.location.list": "list", + "slash.opt.location.list.desc": "List your saved locations", + "slash.opt.location.show": "show", + "slash.opt.location.show.desc": "Show one saved location", + "slash.opt.location.show.name": "name", + "slash.opt.location.show.name.desc": "Saved-location name", + "slash.opt.location.remove": "remove", + "slash.opt.location.remove.desc": "Remove a saved location", + "slash.opt.location.remove.name": "name", + "slash.opt.location.remove.name.desc": "Saved-location name (or \"default\" to clear your default location)", + "slash.opt.location.set-default": "set-default", + "slash.opt.location.set-default.desc": "Set your default location", + "slash.opt.location.set-default.place": "place", + "slash.opt.location.set-default.place.desc": "Coordinates (lat,lon) or address to set as your default location", + "slash.opt.location.remove-default": "remove-default", + "slash.opt.location.remove-default.desc": "Clear your default location", + "slash.opt.summary.quest": "quest", + "slash.opt.summary.quest.desc": "Manage quest-summary buffering", + "slash.opt.summary.quest.show": "show", + "slash.opt.summary.quest.show.desc": "Show schedule and current buffer count", + "slash.opt.summary.quest.settime": "settime", + "slash.opt.summary.quest.settime.desc": "Set the active-hours schedule for the quest summary", + "slash.opt.summary.quest.settime.times": "times", + "slash.opt.summary.quest.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.summary.quest.cleartime": "cleartime", + "slash.opt.summary.quest.cleartime.desc": "Clear the active-hours schedule", + "slash.opt.summary.quest.now": "now", + "slash.opt.summary.quest.now.desc": "Force-dispatch the currently-buffered quests", + "error.slash.unregistered_with_channel": "🛑 You need to register first. DM me with !poracle, or run !poracle in {0}.", + "error.slash.unregistered_dm_only": "🛑 You need to register first. DM me with !poracle.", + "error.slash.track.no_pokemon": "Please specify a Pokemon to track.", + "error.slash.raid.need_boss_or_level": "Please specify either a boss or a level.", + "error.slash.raid.boss_and_level": "Please specify either a boss OR a level, not both.", + "error.slash.egg.no_level": "Please specify an egg level.", + "error.slash.quest.no_reward": "Please specify exactly one reward type (pokemon, item, stardust, candy, or mega_energy).", + "error.slash.quest.exactly_one_reward": "Please specify exactly one reward type, not multiple: {0}.", + "error.slash.quest.amount_not_applicable": "`min_amount` doesn't apply to pokemon quests. For stardust, both `stardust` and `min_amount` end up in the same field — pick whichever reads better.", + "error.slash.invasion.no_grunt": "Please specify a grunt type.", + "error.slash.incident.no_type": "Please specify an incident type.", + "error.slash.lure.no_type": "Please specify a lure type.", + "error.slash.nest.no_pokemon": "Please specify a Pokemon for the nest.", + "error.slash.maxbattle.no_pokemon": "Please specify a Pokemon for the max battle.", + "error.slash.fort.no_type": "Please specify a fort type (pokestop or gym).", + "error.slash.untrack.no_subcommand": "Please choose what kind of tracking rule to remove.", + "error.slash.untrack.no_tracking": "Please pick a tracking rule to remove.", + "error.slash.info.no_subcommand": "Please choose an info sub-command (pokemon / rarity / shiny / weather).", + "error.slash.info.no_pokemon": "Please specify a pokemon name or dex id.", + "error.slash.info.unknown_subcommand": "Unknown info sub-command.", + "error.slash.area.no_subcommand": "Please choose an area sub-command (add / remove / show).", + "error.slash.area.no_area": "Please specify an area name.", + "error.slash.area.unknown_subcommand": "Unknown area sub-command.", + "error.slash.profile.no_subcommand": "Please choose a profile sub-command (list / change / create / delete / settime / cleartime / copyto).", + "error.slash.profile.no_name": "Please specify a profile name.", + "error.slash.profile.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.profile.no_target": "Please specify a target profile to copy to.", + "error.slash.profile.unknown_subcommand": "Unknown profile sub-command.", + "error.slash.summary.no_alert_type": "Please choose an alert type (e.g. quest).", + "error.slash.summary.no_action": "Please choose an action (show / settime / cleartime / now).", + "error.slash.summary.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.summary.unknown_action": "Unknown summary action.", + "error.slash.location.no_subcommand": "Please choose a location sub-command (add / list / show / remove / remove-default).", + "error.slash.location.no_name": "Please specify a saved-location name.", + "error.slash.location.empty": "Please specify coordinates or a place name.", + "error.slash.location.unknown_subcommand": "Unknown location sub-command.", + "error.slash.location.no_geocoder": "Place-name lookup is not configured. Please provide coordinates like 51.28, 1.08.", + "error.slash.location.geocode_failed": "Could not find a location for \"{0}\".", + "msg.help.text": "**Available commands:**\n{0}track [iv:N] [cp:N] [level:N] [d:N] — Track pokemon\n{0}untrack — Remove pokemon tracking\n{0}raid [d:N] — Track raids\n{0}egg [d:N] — Track eggs\n{0}quest — Track quests\n{0}invasion [everything|] — Track invasions\n{0}lure — Track lures\n{0}gym [slot_changes] — Track gyms\n{0}nest — Track nests\n{0}maxbattle — Track max battles\n{0}fort — Track fort updates\n{0}tracked — Show all tracking\n{0}script — Export tracking as commands\n{0}area [list|add|remove] — Manage areas\n{0}location — Set location\n{0}profile [list|add|remove|switch] — Manage profiles\n{0}language — Set language\n{0}start / {0}stop — Enable/disable alerts\n{0}version — Show version", + "cmd.poracle_admin": "poracle-admin", + "cmd.pa": "pa", + "cmd.poracle_admin.not_admin": "This command is reserved for administrators.", + "cmd.poracle_admin.unknown_group": "Unknown subgroup. Try `!poracle-admin` for the list.", + "cmd.poracle_admin.unknown_sub": "Unknown subcommand for `{0}`. Try `!poracle-admin {0}` to see what's available.", + "cmd.poracle_admin.help.admin_only": "This command is reserved for server administrators. Each subgroup performs a live operations task.", + "cmd.poracle_admin.help.groups": "Available subgroups:", + "cmd.poracle_admin.help_intro": "🛠️ Poracle Admin\n\nLive operations subgroups (administrators only):", + "cmd.poracle_admin.stub": "(not yet implemented)", + "cmd.poracle_admin.group.slash.desc": "slash-command registration lifecycle", + "cmd.poracle_admin.group.reload.desc": "reload DTS, geofence, or in-memory state", + "cmd.poracle_admin.group.emoji.desc": "list, reload, or test emoji config", + "cmd.poracle_admin.group.reconcile.desc": "Discord role reconciliation (immediate or per-user)", + "cmd.poracle_admin.group.cache.desc": "cache stats and clear", + "cmd.poracle_admin.group.ratelimit.desc": "inspect and reset alert-bucket rate limits", + "cmd.poracle_admin.group.summary.desc": "summary buffer inspection and forced dispatch", + "cmd.poracle_admin.group.status.desc": "live health snapshot", + "cmd.poracle_admin.group.maintenance.desc": "pause/resume outbound delivery", + "cmd.poracle_admin.group.config.desc": "view effective merged config with secrets redacted", + "cmd.poracle_admin.group.warnings.desc": "inspect captured WARN/ERROR log entries (startup + rolling buffers)", + "cmd.poracle_admin.reload.help.intro": "Reload runtime state from disk or database.", + "cmd.poracle_admin.reload.dts.desc": "`dts` — reload DTS templates and partials from disk", + "cmd.poracle_admin.reload.geofence.desc": "`geofence` — reload geofence files and refresh state", + "cmd.poracle_admin.reload.state.desc": "`state` — reload tracking rules and humans from MySQL (bypasses debounce)", + "cmd.poracle_admin.reload.dts.success": "✅ DTS reloaded in {0}ms ({1} templates)", + "cmd.poracle_admin.reload.geofence.success": "✅ Geofence reloaded in {0}ms ({1} fences, {2} tracking rules)", + "cmd.poracle_admin.reload.state.success": "✅ State reloaded in {0}ms ({1} tracking rules, {2} active humans)", + "cmd.poracle_admin.reload.error": "❌ Reload failed: {0}", + "cmd.poracle_admin.emoji.help.intro": "😀 Emoji config — inspect and manage emoji.json + Discord guild emojis.\n\nSubcommands:", + "cmd.poracle_admin.emoji.list.desc": "`list` — list all configured emoji keys with per-platform resolutions", + "cmd.poracle_admin.emoji.reload.desc": "`reload` — reload config/emoji.json from disk", + "cmd.poracle_admin.emoji.test.desc": "`test ` — resolve one emoji key for the current platform", + "cmd.poracle_admin.emoji.upload.desc": "`upload [overwrite]` — upload uicons-based emojis to the guild and write a new emoji.json (Discord-only)", + "cmd.poracle_admin.emoji.discord_config.desc": "`discord-config` — dump emoji.json from the current guild state, no uploads (Discord-only)", + "cmd.poracle_admin.emoji.discord_only": "ℹ️ This subcommand requires a Discord bot with guild access.", + "cmd.poracle_admin.emoji.not_loaded": "ℹ️ Emoji config not loaded (DTS renderer not configured).", + "cmd.poracle_admin.emoji.list.header": "😀 Emoji configuration — {0} keys loaded", + "cmd.poracle_admin.emoji.list.row.key": " {0}:", + "cmd.poracle_admin.emoji.list.row.platform": " {0}: {1}", + "cmd.poracle_admin.emoji.reload.success": "✅ Emoji config reloaded — {0} keys (took {1}ms).", + "cmd.poracle_admin.emoji.reload.error": "❌ Emoji reload failed: {0}", + "cmd.poracle_admin.emoji.test.success": "🔎 {0} on {1}: {2}", + "cmd.poracle_admin.emoji.test.not_found": "ℹ️ Emoji key \"{0}\" not found in the loaded config.", + "cmd.poracle_admin.emoji.test.usage": "Usage: !poracle-admin emoji test ", + "cmd.poracle_admin.reconcile.help.intro": "🔄 Discord role reconciliation — trigger immediately instead of waiting for the periodic timer.", + "cmd.poracle_admin.reconcile.run.desc": "`run` — reconcile all guild members now (blocks until complete)", + "cmd.poracle_admin.reconcile.user.desc": "`user ` — reconcile a single Discord user by snowflake ID", + "cmd.poracle_admin.reconcile.not_configured": "❌ Discord reconciliation is not configured (Telegram-only deploy, or check_role=false).", + "cmd.poracle_admin.reconcile.run.success": "✅ Discord reconciliation complete (took {0}ms).", + "cmd.poracle_admin.reconcile.run.error": "❌ Reconciliation failed: {0}", + "cmd.poracle_admin.reconcile.user.success": "✅ Reconciled discord:user/{0} (took {1}ms).", + "cmd.poracle_admin.reconcile.user.error": "❌ Failed to reconcile discord:user/{0}: {1}", + "cmd.poracle_admin.reconcile.user.usage": "Usage: !poracle-admin reconcile user ", + "cmd.poracle_admin.cache.help.intro": "🗺️ Geocoder cache — inspect counters or drop the in-memory layer.", + "cmd.poracle_admin.cache.stats.desc": "`stats` — geocoder cache stats", + "cmd.poracle_admin.cache.clear.desc": "`clear geocoder` — drop the in-memory geocoder cache", + "cmd.poracle_admin.cache.not_configured": "Geocoder cache is not configured on this instance.", + "cmd.poracle_admin.cache.stats.header": "🗺️ Geocoder cache", + "cmd.poracle_admin.cache.stats.row.memory_entries": " Memory entries: {0}", + "cmd.poracle_admin.cache.stats.row.disk_entries": " Disk entries: {0}", + "cmd.poracle_admin.cache.stats.row.hits_memory": " Hits (memory): {0}", + "cmd.poracle_admin.cache.stats.row.hits_disk": " Hits (disk): {0}", + "cmd.poracle_admin.cache.stats.row.misses": " Misses: {0}", + "cmd.poracle_admin.cache.stats.row.hit_rate": " Hit rate: {0}%", + "cmd.poracle_admin.cache.clear.usage_hint": "Specify what to clear, e.g. `!poracle-admin cache clear geocoder`", + "cmd.poracle_admin.cache.clear.geocoder.success": "✅ Geocoder memory cache cleared — {0} entries dropped (disk untouched).", + "cmd.poracle_admin.ratelimit.help.intro": "🚦 Rate-limit introspection — inspect or reset per-destination alert and summary buckets.", + "cmd.poracle_admin.ratelimit.not_configured": "ℹ️ Alert rate limiter is not configured on this instance.", + "cmd.poracle_admin.ratelimit.list.desc": "`list` — show all targets currently breached or banned", + "cmd.poracle_admin.ratelimit.show.desc": "`show ` — detailed state for one target (both buckets)", + "cmd.poracle_admin.ratelimit.reset.desc": "`reset ` — clear counters and violation history", + "cmd.poracle_admin.ratelimit.userlist.desc": "`userlist` — show currently disabled users (shortcut for !userlist disabled)", + "cmd.poracle_admin.ratelimit.list.empty": "🟢 No targets currently rate-limited.", + "cmd.poracle_admin.ratelimit.list.header_title": "Currently rate-limited targets", + "cmd.poracle_admin.ratelimit.list.bucket_header": " {0} bucket ({1} breached / {2} banned):", + "cmd.poracle_admin.ratelimit.list.row": "count {0}/{1}, {2}", + "cmd.poracle_admin.ratelimit.list.status.banned": "banned for {0}", + "cmd.poracle_admin.ratelimit.list.status.breached": "window resets in {0}", + "cmd.poracle_admin.ratelimit.show.header": "🚦 Rate-limit state for {0}", + "cmd.poracle_admin.ratelimit.show.bucket_header": "{0} bucket:", + "cmd.poracle_admin.ratelimit.show.empty": "🟢 No recorded activity for {0} in either bucket.", + "cmd.poracle_admin.ratelimit.show.no_data": "(no activity in this bucket)", + "cmd.poracle_admin.ratelimit.show.no_violations": "No violations.", + "cmd.poracle_admin.ratelimit.show.violations_count": "Violations (24h): {0}", + "cmd.poracle_admin.ratelimit.show.banned_until": "Banned until: {0} (in {1})", + "cmd.poracle_admin.ratelimit.show.status.under_limit": "under limit", + "cmd.poracle_admin.ratelimit.show.status.over_limit": "over limit", + "cmd.poracle_admin.ratelimit.show.row.count": " Count: {0} / {1} ({2})\n", + "cmd.poracle_admin.ratelimit.show.row.window": " Window: opened {0} ago, resets in {1}\n", + "cmd.poracle_admin.ratelimit.reset.success": "✅ Reset rate-limit state for {0} (cleared alert + summary buckets, violations reset).", + "cmd.poracle_admin.ratelimit.reset.no_state": "ℹ️ No rate-limit state to reset for {0}.", + "cmd.poracle_admin.ratelimit.reset.note": "Note: admin_disable is NOT touched. If the user was auto-disabled by the rate-limiter, they still need to !poracle to re-register.", + "cmd.poracle_admin.ratelimit.usage.show": "Usage: !poracle-admin ratelimit show ", + "cmd.poracle_admin.ratelimit.usage.reset": "Usage: !poracle-admin ratelimit reset ", + "cmd.poracle_admin.ratelimit.userlist.lookup_failed": "❌ Could not find !userlist command in the registry.", + "cmd.poracle_admin.summary.help.intro": "📦 Summary buffer — inspect who has quests buffered and force-dispatch on demand.", + "cmd.poracle_admin.summary.not_configured": "ℹ️ Summary buffer is not configured on this instance.", + "cmd.poracle_admin.summary.list.desc": "`list` — show all users with anything buffered", + "cmd.poracle_admin.summary.show.desc": "`show ` — inspect one user's buffered entries", + "cmd.poracle_admin.summary.fire.desc": "`fire [alertType]` — force-dispatch a user's buffer immediately", + "cmd.poracle_admin.summary.list.empty": "🟢 No users have anything buffered.", + "cmd.poracle_admin.summary.list.header": "📦 Summary buffer — {0} users with {1} buffered entries", + "cmd.poracle_admin.summary.list.user_header": " {0}", + "cmd.poracle_admin.summary.list.row": " {0}: {1} entries (next fires: {2})", + "cmd.poracle_admin.summary.list.next_fire.none": "n/a", + "cmd.poracle_admin.summary.show.header": "📦 Summary buffer for {0}", + "cmd.poracle_admin.summary.show.empty": "🟢 No buffered entries for {0}.", + "cmd.poracle_admin.summary.show.alert_type": " {0}: {1} entries", + "cmd.poracle_admin.summary.show.usage": "Usage: !poracle-admin summary show ", + "cmd.poracle_admin.summary.fire.success": "✅ Dispatched summary for {0} / {1} — {2} entries delivered.", + "cmd.poracle_admin.summary.fire.usage": "Usage: !poracle-admin summary fire [alertType]", + "cmd.poracle_admin.summary.show.reward_row": " Reward type {0}, reward {1}{2} — {3} stops", + "cmd.poracle_admin.summary.show.reward_more": " ... ({0} more reward groups)", + "cmd.poracle_admin.summary.show.form_suffix": " form {0}", + "cmd.poracle_admin.maintenance.help.intro": "🛠️ **!poracle-admin maintenance** — live control over outbound delivery.\n\nSubcommands:", + "cmd.poracle_admin.maintenance.no_dispatcher": "ℹ️ Dispatcher is not available on this instance.", + "cmd.poracle_admin.maintenance.no_reason": "(no reason given)", + "cmd.poracle_admin.maintenance.pause.desc": "`pause [reason...]` (alias: `start`) — halt outbound delivery (webhooks still ingest, match, render, and queue)", + "cmd.poracle_admin.maintenance.resume.desc": "`resume` (alias: `stop`) — lift a previous pause and drain queued jobs", + "cmd.poracle_admin.maintenance.status.desc": "`status` — show current paused/running state and queue depth", + "cmd.poracle_admin.maintenance.pause.new": "🔴 Outbound delivery paused: {0}", + "cmd.poracle_admin.maintenance.pause.detail": "Webhooks still ingest, match, render, and queue — the dispatcher holds them until !poracle-admin maintenance resume.", + "cmd.poracle_admin.maintenance.pause.already": "ℹ️ Already paused since {0} ({1} ago): {2}", + "cmd.poracle_admin.maintenance.resume.success": "🟢 Outbound delivery resumed (was paused for {0}: {1})", + "cmd.poracle_admin.maintenance.resume.detail": "Queued messages are draining.", + "cmd.poracle_admin.maintenance.resume.not_paused": "ℹ️ Not currently paused.", + "cmd.poracle_admin.maintenance.status.running": "🟢 Delivery is running.", + "cmd.poracle_admin.maintenance.status.paused": "🔴 PAUSED — {0} (for {1})", + "cmd.poracle_admin.maintenance.status.queued": "{0} jobs queued waiting (across all platforms — Discord {1}, Telegram {2})", + "cmd.poracle_admin.status.help.intro": "!poracle-admin status — current health snapshot. Add -v for verbose mode (per-route Discord detail, full webhook per-type breakdown).", + "cmd.poracle_admin.status.header": "🛠️ Poracle Admin — Status", + "cmd.poracle_admin.status.paused_banner": "🔴 PAUSED — {0} (since {1} ago)\n Outbound delivery is held. Webhooks still ingest and queue.", + "cmd.poracle_admin.status.value.na": "n/a", + "cmd.poracle_admin.status.value.none": "none", + "cmd.poracle_admin.status.section.build": "**Build / Uptime**", + "cmd.poracle_admin.status.section.webhooks": "**Webhooks**", + "cmd.poracle_admin.status.section.render_queue": "**Render queue**", + "cmd.poracle_admin.status.section.delivery": "**Delivery**", + "cmd.poracle_admin.status.section.discord_rate": "**Discord rate**", + "cmd.poracle_admin.status.section.telegram_rate": "**Telegram rate**", + "cmd.poracle_admin.status.section.alert_limits": "**Alert limits**", + "cmd.poracle_admin.status.section.summary_buffer": "**Summary buffer**", + "cmd.poracle_admin.status.label.summary_buffer_totals": "Entries: {0} across {1} bucket(s)", + "cmd.poracle_admin.status.label.summary_buffer_top": "Top users:", + "cmd.poracle_admin.status.label.summary_buffer_user_row": " {0} ({1}): {2} entries", + "cmd.poracle_admin.status.section.tracking": "**Tracking**", + "cmd.poracle_admin.status.section.mysql": "**MySQL**", + "cmd.poracle_admin.status.label.version": "Version: {0} (commit {1}, built {2})", + "cmd.poracle_admin.status.label.uptime": "Uptime: {0}", + "cmd.poracle_admin.status.label.webhooks_rate": "{0} / {1} / {2} per min over last 5/15/60 min", + "cmd.poracle_admin.status.label.webhooks_by_type": "By type (last 60 min):", + "cmd.poracle_admin.status.label.delivery_discord": "Discord in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_telegram": "Telegram in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_webhook": "Webhook in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_queue_depth": "Queue depth: {0} (capacity not exposed)", + "cmd.poracle_admin.status.label.discord_routes": "Routes near limit: {0}", + "cmd.poracle_admin.status.label.discord_global": "Global tokens: {0} / {1}", + "cmd.poracle_admin.status.label.discord_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.discord_routes_detail": "Routes near limit (detail):", + "cmd.poracle_admin.status.label.telegram_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.telegram_backoff": "Current backoff: {0}", + "cmd.poracle_admin.status.label.alert_limits_counts": "Breached: alert={0}, summary={1} · Banned: {2}", + "cmd.poracle_admin.status.label.tracking_total": "Total tracking rules: {0}", + "cmd.poracle_admin.status.label.tracking_active_humans": "Active humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans": "Registered humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans_error": "Registered humans: n/a (error)", + "cmd.poracle_admin.status.label.tracking_type": "{0}: {1}", + "cmd.poracle_admin.status.label.mysql_ping_ok": "Ping: ok", + "cmd.poracle_admin.status.label.mysql_ping_fail": "Ping: failed ({0})", + "cmd.poracle_admin.status.label.mysql_pool": "Connections: {0}/{1} open ({2} in use, {3} idle, waits={4})", + "cmd.poracle_admin.status.tracking_type.pokemon": "pokemon", + "cmd.poracle_admin.status.tracking_type.raid": "raid", + "cmd.poracle_admin.status.tracking_type.egg": "egg", + "cmd.poracle_admin.status.tracking_type.quest": "quest", + "cmd.poracle_admin.status.tracking_type.invasion": "invasion", + "cmd.poracle_admin.status.tracking_type.lure": "lure", + "cmd.poracle_admin.status.tracking_type.nest": "nest", + "cmd.poracle_admin.status.tracking_type.gym": "gym", + "cmd.poracle_admin.status.tracking_type.fort": "fort", + "cmd.poracle_admin.status.tracking_type.maxbattle": "maxbattle", + "cmd.poracle_admin.slash.help.intro": "**!poracle-admin slash** — slash-command registration lifecycle.\nSubcommands:", + "cmd.poracle_admin.slash.discord_only": "❌ Slash commands are Discord-only and cannot be managed from Telegram.", + "cmd.poracle_admin.slash.not_configured": "❌ Slash commands are not configured (Discord disabled or [discord.slash_commands] enabled=false).", + "cmd.poracle_admin.slash.sync.desc": "push the current command set to Discord (fingerprint-cached, skips if unchanged)", + "cmd.poracle_admin.slash.sync.success": "✅ Slash sync complete ({0}ms)", + "cmd.poracle_admin.slash.sync.error": "❌ Slash sync failed: {0}", + "cmd.poracle_admin.slash.force_resync.desc": "clear fingerprint cache and push unconditionally", + "cmd.poracle_admin.slash.force_resync.success": "✅ Force-resync complete ({0}ms)", + "cmd.poracle_admin.slash.force_resync.error": "❌ Force-resync failed: {0}", + "cmd.poracle_admin.slash.clear_global.desc": "remove all globally-registered Discord slash commands", + "cmd.poracle_admin.slash.clear_global.success": "✅ Global slash commands cleared.", + "cmd.poracle_admin.slash.clear_global.error": "❌ Clear global failed: {0}", + "cmd.poracle_admin.slash.clear_guild.desc": "remove slash commands from one guild (requires guild_id arg)", + "cmd.poracle_admin.slash.clear_guild.needs_arg": "❌ Usage: `!poracle-admin slash clear-guild `", + "cmd.poracle_admin.slash.clear_guild.success": "✅ Slash commands cleared from guild {0}.", + "cmd.poracle_admin.slash.clear_guild.error": "❌ Clear guild failed: {0}", + "cmd.poracle_admin.slash.status.desc": "show last sync timestamp and fingerprint per scope", + "cmd.poracle_admin.slash.status.header": "**Slash command registration status:**", + "cmd.poracle_admin.slash.status.scope_row": " **{0}**: last synced {1} · fingerprint `{2}`", + "cmd.poracle_admin.slash.status.never_synced": "never", + "cmd.poracle_admin.slash.status.ago": "{0} ago", + "cmd.poracle_admin.slash.status.error": "❌ Status read failed: {0}", + "cmd.poracle_admin.config.help.intro": "⚙️ Config viewer — show effective merged config with secrets redacted.\nSubcommands:", + "cmd.poracle_admin.config.keys.desc": "list section names with key counts", + "cmd.poracle_admin.config.section.desc": "show just that section (e.g. `!poracle-admin config discord`)", + "cmd.poracle_admin.config.full.desc": "show the full config (all sections, secrets redacted)", + "cmd.poracle_admin.config.keys.header": "⚙️ Config sections:", + "cmd.poracle_admin.config.keys.row": " {0}: {1} keys", + "cmd.poracle_admin.config.unknown_section": "Unknown config section: `{0}`. Use `!poracle-admin config keys` to list valid sections, or `!poracle-admin config search ` to search across all sections.", + "cmd.poracle_admin.config.search.desc": "find keys whose path or value contains the term across every section (e.g. `!poracle-admin config search dm`)", + "cmd.poracle_admin.config.search.usage": "Usage: `!poracle-admin config search ` — e.g. `search dm`, `search shlink`, `search 3030`.", + "cmd.poracle_admin.config.search.header": "🔍 `{0}` — {1} match(es):", + "cmd.poracle_admin.config.search.no_matches": "No config keys or values match `{0}`.", + "cmd.poracle_admin.config.empty_section": "Section `{0}` has no configurable fields.", + "cmd.poracle_admin.config.not_loaded": "❌ Config not loaded.", + "cmd.poracle_admin.warnings.help.intro": "🛠️ Captured warnings — inspect in-memory WARN/ERROR log entries.\n\nSubcommands:\n (no arg) — show both startup and recent buffers\n `startup` — show only the startup buffer (first 200 entries, frozen after init)\n `recent` — show only the rolling buffer (last 50 entries)\n `clear` — empty the rolling buffer (startup is immutable)", + "cmd.poracle_admin.warnings.not_configured": "ℹ️ Log buffer is not configured on this instance.", + "cmd.poracle_admin.warnings.section.startup": "🛠️ Captured warnings — startup ({0} entries)", + "cmd.poracle_admin.warnings.section.recent": "🛠️ Captured warnings — recent ({0} entries)", + "cmd.poracle_admin.warnings.empty.startup": "🟢 No startup warnings captured.", + "cmd.poracle_admin.warnings.empty.recent": "🟢 No recent warnings.", + "cmd.poracle_admin.warnings.entry_row": " {0} {1} {2} {3}", + "cmd.poracle_admin.warnings.cleared": "✅ Cleared {0} entries from the rolling buffer (startup buffer is unaffected).", + "cmd.poracle_admin.warnings.startup.desc": "`startup` — show only the startup buffer (frozen after init)", + "cmd.poracle_admin.warnings.recent.desc": "`recent` — show only the rolling buffer (last 50 entries)", + "cmd.poracle_admin.warnings.clear.desc": "`clear` — empty the rolling buffer", + "cmd.maintenance.active_suffix": "🔧 Maintenance mode is active — alerts are not being delivered.", + "showcase_focus_pokemon": "Pokémon", + "showcase_focus_type": "Type", + "showcase_focus_alignment": "Alignment", + "showcase_focus_class": "Class", + "showcase_focus_family": "Family", + "showcase_focus_buddy": "Buddy", + "showcase_focus_generation": "Generation", + "showcase_focus_hatched": "Hatched", + "showcase_focus_mega": "Mega", + "showcase_focus_shiny": "Shiny", + "showcase_class_ultra_beast": "Ultra Beast" } diff --git a/processor/internal/i18n/locale/zh-cn.json b/processor/internal/i18n/locale/zh-cn.json index fd3224b7a..6c76e26ae 100644 --- a/processor/internal/i18n/locale/zh-cn.json +++ b/processor/internal/i18n/locale/zh-cn.json @@ -58,6 +58,11 @@ "tracking.pvp_little": "小型杯PVP", "tracking.pvp_great": "超级杯PVP", "tracking.pvp_ultra": "高级杯PVP", + "tracking.pvp_mega_any": "mega", + "tracking.pvp_mega_x": "mega x", + "tracking.pvp_mega_y": "mega y", + "tracking.mega_x_label": "X", + "tracking.mega_y_label": "Y", "tracking.level_cap_fmt": "等级上限:{0}", "tracking.everything": "全部", "tracking.unknown_monster": "未知宝可梦", @@ -81,10 +86,14 @@ "tracking.reward_fmt": "奖励:**{0}**", "tracking.reward_stardust_min_fmt": "{0} 或更多星尘", "tracking.reward_stardust": "星尘", + "tracking.reward_pokecoin_min_fmt": "{0} or more pokecoins", + "tracking.reward_pokecoin": "pokecoins", "tracking.reward_mega_energy": "超级能量", "tracking.reward_mega_energy_fmt": "超级能量 {0}", "tracking.reward_candy": "糖果", "tracking.reward_candy_fmt": "糖果 {0}", + "tracking.reward_any_pokemon": "any pokemon", + "tracking.reward_any_item": "any item", "tracking.reward_min_fmt": "至少 {0}", "tracking.grunt_type_fmt": "喽啰类型:**{0}**", "tracking.min_avg_spawn": "最小平均刷新:{0}/小时", @@ -108,10 +117,68 @@ "tracking.template_not_found": "模板 \"{0}\" 不存在。", "tracking.warn_template_not_found": "类型 {1}/{2} 找不到模板 \"{0}\"。追踪已保存但提醒可能无法渲染。", "tracking.id_hint": "要移除特定条目,请使用其 id — 例如 `{0}untrack id:45` 或 `{0}raid remove id:12`", + "tracking.id_hint_slash": "To remove a specific entry, run `/untrack ` (e.g. `/untrack raid`) and pick it from the list.", + "tracking.list_attached": "Your tracking list is long ({0} rules) — attached as a file.", "tracking.removed_prefix": "已移除:", "tracking.uid_not_found": "未找到 id:{0}", + "tracking.override_location_fmt": "@ {0}", + "tracking.override_areas_fmt": "in {0}", "cmd.track": "track", "cmd.untrack": "untrack", + "cmd.mute": "mute", + "cmd.unmute": "unmute", + "msg.mute.unavailable": "Mute feature isn't enabled here.", + "msg.mute.usage": "Valid commands are `{0}mute [duration:1h]`", + "msg.mute.usage_pokemon": "Valid commands are `{0}mute pokemon [duration:1h]`", + "msg.mute.usage_gym": "Valid commands are `{0}mute gym [duration:1h]`", + "msg.mute.usage_area": "Valid commands are `{0}mute area [duration:1h]`", + "msg.mute.usage_id_scope": "Valid commands are `{0}mute {1} [duration:1h]`", + "msg.mute.bad_duration": "Invalid duration: {0}", + "msg.mute.id_not_supported": "`!mute id:N` / `!mute id:N` aren't supported yet — entity scopes (gym, pokemon, area, pokestop, station, everything) work today. Per-rule muting by UID is a follow-up.", + "msg.mute.bad_uid": "`{0}` isn't a valid tracking rule UID. Use `!tracked` to see your rule UIDs.", + "msg.mute.unknown_area": "`{0}` isn't in your available areas. Use `!area` to see what you can mute.", + "msg.mute.no_pokemon": "I don't know a pokemon called `{0}`.", + "msg.mute.everything_label": "everything", + "msg.mute.added": "🔇 Muted {0} for {1}.", + "msg.mute.removed": "✅ Unmuted {0}.", + "msg.mute.none_found": "No active mute for {0}.", + "msg.mute.cleared_all": "Cleared {0} active mutes.", + "msg.unmute.usage": "Valid commands are `{0}unmute `, `{0}unmute all`", + "msg.unmute.usage_pokemon": "Valid commands are `{0}unmute pokemon `", + "msg.unmute.usage_gym": "Valid commands are `{0}unmute gym `", + "msg.unmute.usage_area": "Valid commands are `{0}unmute area `", + "section.property_mutes": "Property mutes (apply across all tracking):", + "section.property_mutes.left": "({0} left)", + "msg.button.expired": "This alert has expired.", + "msg.button.unavailable": "This button is no longer available.", + "msg.button.wrong_target": "This button doesn't apply here.", + "msg.button.unauthorized": "This button isn't for you.", + "msg.button.unidentified": "Couldn't identify you to handle that click.", + "msg.button.unconfigured": "This button isn't configured.", + "msg.button.action_failed": "Couldn't complete that action: {0}", + "msg.button.action_failed_generic": "Couldn't complete that action.", + "msg.button.cooldown": "Slow down — try that again in a moment.", + "msg.button.actions_not_wired": "Button actions aren't wired here.", + "msg.button.not_implemented": "The {0} action isn't implemented yet.", + "msg.button.responses_not_wired": "Response rendering isn't wired here.", + "msg.button.response_failed": "Couldn't render that response: {0}", + "msg.button.done": "Done.", + "msg.button.missing_scope": "Button is missing a scope — operator config bug.", + "msg.button.missing_target": "Couldn't find a {0} to mute on this alert.", + "msg.button.no_dm_target": "Couldn't identify you to send the message.", + "msg.button.dm_failed": "Couldn't send to your DM: {0}", + "msg.button.unsubscribe_failed": "Couldn't unsubscribe — please try again.", + "msg.button.unsubscribe_already": "Those tracking rules were already removed.", + "msg.button.unsubscribed": "✅ Unsubscribed from {0} tracking rule(s).", + "msg.button.redeliver_sent": "📬 Sent to your DM.", + "msg.mute.scope_gym": "gym", + "msg.mute.scope_pokemon": "pokemon", + "msg.mute.scope_area": "area", + "msg.mute.scope_pokestop": "pokestop", + "msg.mute.scope_station": "station", + "msg.mute.scope_tracking": "tracking rule", + "cmd.mute.usage": "**{0}mute** — silence alerts for a specific gym, pokemon, area, pokestop, station, or everything for a time-bounded window.\n\n• `{0}mute everything [duration:1h]` — silence ALL alerts for the given duration\n• `{0}mute gym [duration:1h]` — silence alerts for one gym\n• `{0}mute pokemon [duration:1h]` — silence alerts for one pokemon species\n• `{0}mute area [duration:1h]` — silence alerts in one area\n• `{0}mute pokestop [duration:1h]` — silence alerts for one pokestop\n• `{0}mute station [duration:1h]` — silence alerts for one station\n\nDuration defaults to 1h if omitted. Use `{0}unmute ` to remove a mute early, or `{0}tracked` to see active mutes.", + "cmd.track.usage": "**{0}track** — set up pokemon tracking rules.\n\n• `{0}track ` — track a specific pokemon (by name or dex id) at default 100m\n• `{0}track everything` — track every pokemon (admin-permitted; see `{0}help everything`)\n• `{0}track iv:100` — filter by IV percent (`iv:90-100` for range, `miniv:90`/`maxiv:99` for one-sided)\n• `{0}track cp:1500-2500` — filter by CP\n• `{0}track level:25-35` — filter by level\n• `{0}track atk:14-15 def:14-15 sta:14-15` — filter by individual IV stats\n• `{0}track d:500` — only alert within 500m of your location\n• `{0}track location:Home d:500` — within 500m of a saved location\n• `{0}track area:london,paris` — only in named areas (replaces your default areas)\n• `{0}track great5 ultra10` — PVP filters (great/ultra/little league, rank threshold, optional cap)\n• `{0}track gen:1 type:water` — generation and type filters (alongside `everything`)\n• `{0}track rarity:rare-ultra` — rarity-tier filter\n• `{0}track clean` / `edit` — auto-delete on TTH expiry / edit-in-place\n• `{0}track remove ` or `{0}untrack ` — remove\n• `{0}untrack id:42` — remove one rule by id (see `{0}tracked` for ids)\n\nMultiple filters combine. See `{0}tracked` for what's currently active.", "cmd.raid": "raid", "cmd.egg": "egg", "cmd.quest": "quest", @@ -129,6 +196,8 @@ "cmd.fort": "fort", "cmd.help": "help", "cmd.info": "info", + "cmd.info.poracle.moved": "→ This view has moved to `!poracle-admin status` — please use that instead.", + "cmd.info.config.moved": "→ This view has moved to `!poracle-admin config` — please use that instead.", "cmd.start": "start", "cmd.stop": "stop", "cmd.tracked": "tracked", @@ -163,6 +232,8 @@ "cmd.poracle_id": "poracle-id", "arg.remove": "remove", "arg.everything": "everything", + "arg.all_pokemon": "all pokemon", + "arg.all_items": "all items", "arg.any": "any", "arg.clean": "clean", "arg.edit": "edit", @@ -170,6 +241,7 @@ "arg.list": "list", "arg.add": "add", "arg.show": "show", + "arg.default": "default", "arg.overview": "overview", "arg.dryrun": "dryrun", "arg.reset": "reset", @@ -182,6 +254,7 @@ "arg.shiny": "shiny", "arg.gmax": "gmax", "arg.stardust": "stardust", + "arg.pokecoin": "pokecoins", "arg.energy": "energy", "arg.candy": "candy", "arg.pvp": "pvp", @@ -248,7 +321,10 @@ "arg.prefix.maxsize": "maxsize", "arg.prefix.gen": "gen", "arg.prefix.cap": "cap", + "arg.mega": "mega", + "arg.prefix.mega": "mega", "arg.prefix.form": "form", + "arg.prefix.costume": "costume", "arg.prefix.template": "template", "arg.prefix.gym": "gym", "arg.prefix.move": "move", @@ -263,13 +339,17 @@ "arg.prefix.littlehigh": "littlehigh", "arg.prefix.littlecp": "littlecp", "arg.prefix.stardust": "stardust", + "arg.prefix.pokecoin": "pokecoins", "arg.prefix.energy": "energy", "arg.prefix.candy": "candy", + "arg.prefix.amount": "amount", "arg.prefix.name": "name", "arg.prefix.user": "user", "arg.prefix.channel": "channel", "arg.prefix.guild": "guild", "arg.prefix.language": "language", + "arg.prefix.area": "area", + "arg.prefix.location": "location", "arg.prefix.mon": "mon", "arg.prefix.tue": "tue", "arg.prefix.wed": "wed", @@ -323,21 +403,26 @@ "section.maxbattles.none": "您未追踪任何极巨战", "msg.no_pokemon": "未指定宝可梦", "msg.form_not_found": "Form `{0}` not recognised. Use `{1}info ` to see available forms.", + "msg.costume_not_found": "Costume `{0}` not recognised. Use `{1}info costumes` to see available costumes.", + "msg.no_costume": "no costume", "msg.nothing_to_remove": "没有可移除的内容", "msg.no_levels": "未指定等级", "msg.no_egg_levels": "未指定蛋等级", "msg.no_raid_target": "未指定团战等级或宝可梦", "msg.no_lure_type": "未指定诱饵类型", "msg.no_quest_type": "未指定任务类型", + "msg.quest.amount_not_applicable": "`amount:N` doesn't apply to pokemon quests — pokemon rewards have no minimum amount.", + "msg.quest.bulk_not_permitted": "You do not have permission to track all pokemon or items at once. Track specific rewards instead.", "msg.removed_n": "已移除 {0} 条追踪规则", "msg.egg.usage": "有效命令如:`{0}egg level:5`、`{0}egg legendary`、`{0}egg remove everything`", "msg.raid.usage": "有效命令如:`{0}raid level:5`、`{0}raid pikachu`、`{0}raid remove everything`", "msg.track.usage": "有效命令如:`{0}track pikachu iv:100`、`{0}track everything iv:90`、`{0}track remove pikachu`", "msg.track.everything_no_filters": "这会产生过多提醒。您需要提供额外筛选条件以限制候选数量。", "msg.track.invalid_cap": "不支持此等级上限,可选值为:{0}", - "msg.quest.usage": "有效命令如:`{0}quest pikachu`、`{0}quest stardust:1000`、`{0}quest energy:charizard`", + "msg.track.no_mega_form": "⚠️ {0} has no Mega {1} form — this PVP rule will never match.", + "msg.quest.usage": "Valid commands are e.g. `{0}quest pikachu`, `{0}quest stardust:1000`, `{0}quest pokecoins:10`, `{0}quest energy:charizard`", "msg.quest.edit_summary_conflict": "`edit` and `summary` are mutually exclusive — pick one.", - "msg.summary.usage": "Usage: `{0}summary quest [settime |cleartime|now]`", + "msg.summary.usage": "Valid commands are `{0}summary quest`, `{0}summary quest settime `, `{0}summary quest cleartime`, `{0}summary quest now`", "msg.summary.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.summary.no_schedule": "No schedule set for {0} summaries.", "msg.summary.scheduled": "Schedule for {0} summaries: {1}", @@ -360,11 +445,33 @@ "msg.nest.usage": "有效命令如:`{0}nest pikachu`、`{0}nest everything`、`{0}nest remove pikachu`", "msg.maxbattle.usage": "有效命令如:`{0}maxbattle pikachu`、`{0}maxbattle level:3`、`{0}maxbattle remove everything`", "msg.fort.usage": "有效命令如:`{0}fort pokestop`、`{0}fort everything`、`{0}fort remove pokestop`", - "msg.location.removed": "位置已移除", - "msg.location.usage": "有效命令如:`{0}location <纬度>,<经度>`、`{0}location <您的地址>`", + "msg.location.removed": "✅ Removed saved location `{0}`.", + "msg.location.usage": "Valid commands are `{0}location `, `{0}location add `, `{0}location list`, `{0}location show `, `{0}location remove `, `{0}location remove default`", "msg.location.specify": "请指定坐标或地址", "msg.location.set": "位置已设为 {0},{1}", "msg.location.current": "Your current location is {0},{1}", + "msg.location.added": "✅ Saved location `{0}` at {1}, {2}.", + "msg.location.duplicate": "🙅 You already have a saved location called `{0}`. Remove it first with `{1}location remove {0}`.", + "msg.location.list_header": "Your saved locations:", + "msg.location.list_row": " `{0}`: {1}, {2}", + "msg.location.list_row_with_addr": " `{0}`: {1}, {2} — {3}", + "msg.location.list_empty": "You have no saved locations. Add one with `{0}location add `.", + "msg.location.show_not_found": "🙅 No saved location called `{0}`.", + "msg.location.show": "📍 `{0}` is at {1}, {2}.", + "msg.location.show_with_addr": "📍 `{0}` is at {1}, {2} — {3}", + "msg.location.no_default": "🙅 No default location set.", + "msg.location.default_removed": "✅ Cleared your default location.", + "msg.location.remove_referenced": "🙅 Cannot remove `{0}` — {1} tracking rule(s) reference it: {2}. Edit or remove those rules first.", + "msg.location.add_usage": "Valid commands are `{0}location add `", + "msg.location.show_usage": "Valid commands are `{0}location show `", + "msg.location.remove_usage": "Valid commands are `{0}location remove `, `{0}location remove default`", + "msg.location.geocode_failed": "🙅 Couldn't find a place matching `{0}`.", + "cmd.location.usage": "**{0}location** — manage your default location and saved named locations.\n\n• `{0}location` — show your current default location\n• `{0}location ` — set your default location\n• `{0}location add ` — save a named location (referenced later as `location:` on tracking rules)\n• `{0}location list` — list all your saved locations\n• `{0}location show ` — show one saved location's coords + address (use `default` for your default)\n• `{0}location remove ` — delete a saved location (refuses if any tracking rule references it)\n• `{0}location remove default` — clear your default location", + "msg.override.requires_distance": "🙅 `location:` needs a `d:` distance — e.g. `location:Home d:500`.", + "msg.override.area_and_distance": "🙅 `area:` and `d:` are mutually exclusive (area-mode vs distance-mode). Pick one.", + "msg.override.area_and_location": "🙅 `area:` and `location:` are mutually exclusive. Pick one.", + "msg.override.unknown_location": "🙅 No saved location called `{0}`. Add it with `{1}location add {0} `.", + "msg.override.area_not_permitted": "🙅 Area `{0}` is not in your allowed areas. Use `{1}area list` to see what you can pick.", "msg.area.usage": "Valid commands are `{0}area list`, `{0}area add `, `{0}area remove `", "msg.area.none_available": "没有可用的区域", "msg.area.available": "**可用区域:**", @@ -382,14 +489,14 @@ "msg.profile.deleted": "配置 {0} 已删除", "msg.profile.not_found": "未找到配置", "msg.profile.cannot_delete_1": "无法删除配置 1", - "msg.profile.hours_usage": "用法:profile hours <配置编号> ", + "msg.profile.hours_usage": "Valid commands are `{0}profile hours `", "msg.profile.hours_invalid_json": "激活时间的 JSON 无效", "msg.profile.hours_set": "配置 {0} 的激活时间已更新", "msg.profile.hours_cleared": "Active hours cleared for profile {0}", - "msg.profile.settime_usage": "用法:profile settime mon09:00 tue18:30 weekday09:00 weekend10:00", + "msg.profile.settime_usage": "Valid commands are `{0}profile settime mon09:00 tue18:30 weekday09:00 weekend10:00`", "msg.profile.settime_invalid": "Cannot parse schedule entry `{0}`: {1}", "msg.profile.copied": "当前配置已复制到:{0}", - "msg.profile.copyto_usage": "用法:profile copyto <名称|all>", + "msg.profile.copyto_usage": "Valid commands are `{0}profile copyto `", "msg.profile.copy_invalid": "以下配置无效:{0}", "msg.profile.usage": "有效命令为 `{0}profile <名称>`、`{0}profile list`、`{0}profile add <名称>`、`{0}profile remove <名称>`、`{0}profile settime <时间字符串>`、`{0}profile copyto <名称>`", "msg.profile.list_header": "当前已配置的配置文件:", @@ -407,6 +514,7 @@ "msg.weather.unavailable": "此命令暂不支持天气追踪", "msg.help.unknown_topic": "没有 '{0}' 的帮助。使用 `{1}help` 获取通用帮助。", "msg.help.no_greeting": "未配置帮助模板。使用 `{0}help <命令>` 查看具体命令帮助。", + "msg.help.see_detailed": "💡 More detailed help is available — `{0}help {1}`", "msg.info.sub.moves": "招式", "msg.info.sub.items": "道具", "msg.info.sub.shiny": "闪光", @@ -417,9 +525,19 @@ "msg.info.sub.translate": "翻译", "msg.info.sub.dts": "dts", "msg.info.sub.templates": "模板", - "msg.info.usage": "有效命令为 `{0}info templates`、`{0}info rarity`、`{0}info shiny`、`{0}info weather`、`{0}info moves`、`{0}info items`、`{0}info <宝可梦>`", + "msg.info.sub.costumes": "costumes", + "msg.info.sub.forms": "forms", + "msg.info.usage": "Valid commands are `{0}info templates`, `{0}info rarity`, `{0}info shiny`, `{0}info weather`, `{0}info moves`, `{0}info items`, `{0}info costumes`, `{0}info `", "msg.info.usage_admin": "Admin: `{0}info poracle`, `{0}info dts`, `{0}info translate `, `{0}info config [search]`", "msg.info.available_forms": "可用形态:", + "msg.info.more_forms": "More than {0} forms — do {1} for the full list", + "msg.info.recent_forms": "**Recently-seen forms:**", + "msg.info.recent_raid_forms": "**Recently-seen raid forms:**", + "msg.info.available_costumes": "**Recently-seen costumes:**", + "msg.info.recent_raid_costumes": "**Recently-seen raid costumes:**", + "msg.info.costumes.header": "**Costumes** (`costume:` to track):", + "msg.info.no_costume_data": "No costume data loaded", + "msg.info.no_form_data": "No form data for that pokemon.", "msg.info.hundo_cp": "100% IV CP:", "msg.info.dts_summary": "已加载 DTS 模板:", "msg.info.pokemon_not_found": "未找到宝可梦:{0}", @@ -534,5 +652,661 @@ "language.sv": "瑞典语", "language.zh-cn": "简体中文", "language.ja": "日语", - "msg.help.text": "**可用命令:**\n{0}track <宝可梦> [iv:N] [cp:N] [level:N] [d:N] — 追踪宝可梦\n{0}untrack <宝可梦> — 移除宝可梦追踪\n{0}raid <宝可梦|level:N|legendary> [d:N] — 追踪团战\n{0}egg [d:N] — 追踪蛋\n{0}quest <宝可梦|stardust|energy:宝可梦|candy:宝可梦> — 追踪任务\n{0}invasion [everything|<类型>] — 追踪入侵\n{0}lure <类型|everything> — 追踪诱饵\n{0}gym <队伍|everything> [slot_changes] — 追踪道馆\n{0}nest <宝可梦|everything> — 追踪巢穴\n{0}maxbattle <宝可梦|level:N> — 追踪极巨战\n{0}fort — 追踪据点更新\n{0}tracked — 显示所有追踪\n{0}script — 将追踪导出为命令\n{0}area [list|add|remove] — 管理区域\n{0}location <纬度,经度> — 设置位置\n{0}profile [list|add|remove|switch] — 管理配置\n{0}language <代码> — 设置语言\n{0}start / {0}stop — 启用/停用提醒\n{0}version — 显示版本" + "slash.cmd.version": "version", + "slash.desc.version": "Show Poracle version", + "slash.cmd.tracked": "tracked", + "slash.cmd.help": "help", + "slash.cmd.info": "info", + "slash.cmd.language": "language", + "slash.cmd.track": "track", + "slash.cmd.raid": "raid", + "slash.cmd.egg": "egg", + "slash.cmd.quest": "quest", + "slash.cmd.invasion": "invasion", + "slash.cmd.incident": "incident", + "slash.cmd.lure": "lure", + "slash.cmd.nest": "nest", + "slash.cmd.maxbattle": "maxbattle", + "slash.cmd.gym": "gym", + "slash.cmd.fort": "fort", + "slash.cmd.untrack": "untrack", + "slash.cmd.area": "area", + "slash.cmd.profile": "profile", + "slash.cmd.location": "location", + "slash.cmd.summary": "summary", + "slash.cmd.start": "start", + "slash.cmd.stop": "stop", + "slash.desc.tracked": "List your tracking rules", + "slash.desc.start": "Resume alert delivery (after /stop)", + "slash.desc.stop": "Pause alert delivery (resume with /start)", + "slash.desc.help": "Show help", + "slash.desc.info": "Look up pokemon info, shiny rates, rarity tiers, or current weather", + "slash.opt.info.pokemon": "pokemon", + "slash.opt.info.pokemon.desc": "Show types, stats, evolutions, weather boost and CP table for a pokemon", + "slash.opt.info.pokemon.name": "name", + "slash.opt.info.pokemon.name.desc": "Pokemon name (any supported language) or dex id", + "slash.opt.info.rarity": "rarity", + "slash.opt.info.rarity.desc": "List pokemon by spawn rarity tier (common → ultra-rare)", + "slash.opt.info.shiny": "shiny", + "slash.opt.info.shiny.desc": "Show observed shiny rates per species", + "slash.opt.info.weather": "weather", + "slash.opt.info.weather.desc": "Show current weather and boosted types for a location", + "slash.opt.info.weather.coords": "coords", + "slash.opt.info.weather.coords.desc": "lat,lon (defaults to your saved location)", + "slash.desc.language": "Show or set your language", + "slash.desc.track": "Track a Pokemon", + "slash.desc.raid": "Track a raid boss or raid level", + "slash.desc.egg": "Track an egg / raid level", + "slash.desc.quest": "Track a quest reward", + "slash.desc.invasion": "Track a Team Rocket invasion", + "slash.desc.incident": "Track a pokestop incident (Kecleon, Gold Pokestop, Showcase…)", + "slash.desc.lure": "Track a pokestop lure", + "slash.desc.nest": "Track a nesting pokemon", + "slash.desc.maxbattle": "Track a max (Dynamax) battle", + "slash.desc.gym": "Track gym team / slot / battle changes", + "slash.desc.fort": "Track pokestop or gym updates", + "slash.desc.untrack": "Remove a tracking rule", + "slash.desc.area": "Manage your areas", + "slash.desc.profile": "Manage your profiles", + "slash.desc.location": "Manage your saved locations", + "slash.desc.summary": "Manage scheduled summary digests (e.g. quest)", + "slash.opt.help.topic": "topic", + "slash.opt.help.topic.desc": "Help topic", + "slash.opt.language.code": "code", + "slash.opt.language.code.desc": "Language code", + "slash.opt.track.pokemon": "pokemon", + "slash.opt.track.pokemon.desc": "Pokemon to track (or 'everything')", + "slash.opt.track.iv": "iv", + "slash.opt.track.iv.desc": "IV filter (e.g. 100, 95, 0-0)", + "slash.opt.track.distance": "distance", + "slash.opt.track.distance.desc": "Alert radius in metres", + "slash.opt.track.great_rank": "great_rank", + "slash.opt.track.great_rank.desc": "Top PVP rank in the Great League", + "slash.opt.track.ultra_rank": "ultra_rank", + "slash.opt.track.ultra_rank.desc": "Top PVP rank in the Ultra League", + "slash.opt.track.little_rank": "little_rank", + "slash.opt.track.little_rank.desc": "Top PVP rank in the Little League", + "slash.opt.track.clean": "clean", + "slash.opt.track.clean.desc": "Auto-delete the alert when the pokemon despawns", + "slash.opt.track.template": "template", + "slash.opt.track.template.desc": "DTS template name", + "slash.opt.track.form": "form", + "slash.opt.track.form.desc": "Pokemon form", + "slash.opt.track.size": "size", + "slash.opt.track.size.desc": "Pokemon size class", + "slash.choice.track.clean.yes": "Yes", + "slash.choice.track.size.all": "All sizes", + "slash.choice.track.size.xxs": "XXS", + "slash.choice.track.size.xs": "XS", + "slash.choice.track.size.m": "M", + "slash.choice.track.size.xl": "XL", + "slash.choice.track.size.xxl": "XXL", + "slash.opt.raid.boss": "boss", + "slash.opt.raid.boss.desc": "Raid boss pokemon", + "slash.opt.raid.level": "level", + "slash.opt.raid.level.desc": "Raid level", + "slash.opt.raid.team": "team", + "slash.opt.raid.team.desc": "Required gym-control team", + "slash.opt.raid.distance": "distance", + "slash.opt.raid.distance.desc": "Alert radius in metres", + "slash.opt.raid.clean": "clean", + "slash.opt.raid.clean.desc": "Auto-delete the alert when the raid expires", + "slash.opt.raid.template": "template", + "slash.opt.raid.template.desc": "DTS template name", + "slash.choice.raid.clean.yes": "Yes", + "slash.choice.raid.level.1": "Tier 1", + "slash.choice.raid.level.3": "Tier 3", + "slash.choice.raid.level.5": "Tier 5", + "slash.choice.raid.level.6": "Tier 6", + "slash.choice.raid.level.mega": "Mega", + "slash.choice.raid.level.legendary": "Legendary", + "slash.choice.raid.level.shadow1": "Shadow Tier 1", + "slash.choice.raid.level.shadow3": "Shadow Tier 3", + "slash.choice.raid.level.shadow5": "Shadow Tier 5", + "slash.choice.raid.level.ultra beast": "Ultra Beast", + "slash.choice.raid.level.everything": "Everything", + "slash.choice.raid.team.0": "Harmony", + "slash.choice.raid.team.1": "Mystic", + "slash.choice.raid.team.2": "Valor", + "slash.choice.raid.team.3": "Instinct", + "slash.opt.egg.level": "level", + "slash.opt.egg.level.desc": "Egg / raid level", + "slash.opt.egg.team": "team", + "slash.opt.egg.team.desc": "Required gym-control team", + "slash.opt.egg.distance": "distance", + "slash.opt.egg.distance.desc": "Alert radius in metres", + "slash.opt.egg.clean": "clean", + "slash.opt.egg.clean.desc": "Auto-delete the alert when the egg hatches", + "slash.opt.egg.template": "template", + "slash.opt.egg.template.desc": "DTS template name", + "slash.choice.egg.clean.yes": "Yes", + "slash.choice.egg.level.1": "Tier 1", + "slash.choice.egg.level.3": "Tier 3", + "slash.choice.egg.level.5": "Tier 5", + "slash.choice.egg.level.6": "Tier 6", + "slash.choice.egg.level.mega": "Mega", + "slash.choice.egg.level.legendary": "Legendary", + "slash.choice.egg.level.shadow1": "Shadow Tier 1", + "slash.choice.egg.level.shadow3": "Shadow Tier 3", + "slash.choice.egg.level.shadow5": "Shadow Tier 5", + "slash.choice.egg.level.ultra beast": "Ultra Beast", + "slash.choice.egg.level.everything": "Everything", + "slash.choice.egg.team.0": "Harmony", + "slash.choice.egg.team.1": "Mystic", + "slash.choice.egg.team.2": "Valor", + "slash.choice.egg.team.3": "Instinct", + "slash.opt.quest.pokemon": "pokemon", + "slash.opt.quest.pokemon.desc": "Pokemon reward", + "slash.opt.quest.item": "item", + "slash.opt.quest.item.desc": "Item reward (e.g. golden razz berry)", + "slash.opt.quest.stardust": "stardust", + "slash.opt.quest.stardust.desc": "Stardust reward (minimum amount)", + "slash.opt.quest.candy": "candy", + "slash.opt.quest.candy.desc": "Candy reward pokemon", + "slash.opt.quest.mega_energy": "mega_energy", + "slash.opt.quest.mega_energy.desc": "Mega energy reward pokemon", + "slash.opt.quest.min_amount": "min_amount", + "slash.opt.quest.min_amount.desc": "Minimum reward amount (item / candy / mega_energy only)", + "slash.opt.quest.distance": "distance", + "slash.opt.quest.distance.desc": "Alert radius in metres", + "slash.opt.quest.clean": "clean", + "slash.opt.quest.clean.desc": "Auto-delete the alert when the quest is completed", + "slash.opt.quest.summary": "summary", + "slash.opt.quest.summary.desc": "Buffer matches and dispatch in a scheduled batch instead of alerting immediately", + "slash.opt.quest.template": "template", + "slash.opt.quest.template.desc": "DTS template name", + "slash.choice.quest.clean.yes": "Yes", + "slash.choice.quest.summary.yes": "Yes", + "slash.opt.invasion.grunt_type": "grunt_type", + "slash.opt.invasion.grunt_type.desc": "Grunt type (Fire, Water…), boss (Giovanni…), or incident (Kecleon…)", + "slash.opt.invasion.gender": "gender", + "slash.opt.invasion.gender.desc": "Filter by grunt gender", + "slash.opt.invasion.distance": "distance", + "slash.opt.invasion.distance.desc": "Alert radius in metres", + "slash.opt.invasion.clean": "clean", + "slash.opt.invasion.clean.desc": "Auto-delete the alert when the invasion expires", + "slash.opt.invasion.template": "template", + "slash.opt.invasion.template.desc": "DTS template name", + "slash.choice.invasion.clean.yes": "Yes", + "slash.choice.invasion.gender.male": "Male", + "slash.choice.invasion.gender.female": "Female", + "slash.choice.invasion.gender.genderless": "Genderless", + "slash.opt.incident.type": "type", + "slash.opt.incident.type.desc": "Pokestop incident type (Kecleon, Gold Pokestop, Showcase…)", + "slash.opt.incident.distance": "distance", + "slash.opt.incident.distance.desc": "Alert radius in metres", + "slash.opt.incident.clean": "clean", + "slash.opt.incident.clean.desc": "Auto-delete the alert when the incident expires", + "slash.opt.incident.template": "template", + "slash.opt.incident.template.desc": "DTS template name", + "slash.choice.incident.clean.yes": "Yes", + "slash.opt.lure.lure_type": "lure_type", + "slash.opt.lure.lure_type.desc": "Lure type", + "slash.opt.lure.distance": "distance", + "slash.opt.lure.distance.desc": "Alert radius in metres", + "slash.opt.lure.clean": "clean", + "slash.opt.lure.clean.desc": "Auto-delete the alert when the lure expires", + "slash.opt.lure.template": "template", + "slash.opt.lure.template.desc": "DTS template name", + "slash.choice.lure.clean.yes": "Yes", + "slash.choice.lure.lure_type.normal": "Normal", + "slash.choice.lure.lure_type.glacial": "Glacial", + "slash.choice.lure.lure_type.mossy": "Mossy", + "slash.choice.lure.lure_type.magnetic": "Magnetic", + "slash.choice.lure.lure_type.rainy": "Rainy", + "slash.choice.lure.lure_type.sparkly": "Sparkly", + "slash.opt.nest.pokemon": "pokemon", + "slash.opt.nest.pokemon.desc": "Nesting pokemon", + "slash.opt.nest.min_spawn_avg": "min_spawn_avg", + "slash.opt.nest.min_spawn_avg.desc": "Minimum spawns per hour", + "slash.opt.nest.distance": "distance", + "slash.opt.nest.distance.desc": "Alert radius in metres", + "slash.opt.nest.clean": "clean", + "slash.opt.nest.clean.desc": "Auto-delete the alert when the nest expires", + "slash.opt.nest.template": "template", + "slash.opt.nest.template.desc": "DTS template name", + "slash.choice.nest.clean.yes": "Yes", + "slash.opt.maxbattle.pokemon": "pokemon", + "slash.opt.maxbattle.pokemon.desc": "Max battle pokemon", + "slash.opt.maxbattle.level": "level", + "slash.opt.maxbattle.level.desc": "Battle level (1..6)", + "slash.opt.maxbattle.gmax": "gmax", + "slash.opt.maxbattle.gmax.desc": "Gigantamax only", + "slash.opt.maxbattle.distance": "distance", + "slash.opt.maxbattle.distance.desc": "Alert radius in metres", + "slash.opt.maxbattle.clean": "clean", + "slash.opt.maxbattle.clean.desc": "Auto-delete the alert when the battle ends", + "slash.opt.maxbattle.template": "template", + "slash.opt.maxbattle.template.desc": "DTS template name", + "slash.choice.maxbattle.clean.yes": "Yes", + "slash.choice.maxbattle.level.1": "Level 1", + "slash.choice.maxbattle.level.2": "Level 2", + "slash.choice.maxbattle.level.3": "Level 3", + "slash.choice.maxbattle.level.4": "Level 4", + "slash.choice.maxbattle.level.5": "Level 5", + "slash.choice.maxbattle.level.6": "Level 6", + "slash.opt.gym.team": "team", + "slash.opt.gym.team.desc": "Gym-control team to alert on", + "slash.opt.gym.slot_changes": "slot_changes", + "slash.opt.gym.slot_changes.desc": "Alert on slot composition changes", + "slash.opt.gym.battle_changes": "battle_changes", + "slash.opt.gym.battle_changes.desc": "Alert on battle state changes", + "slash.opt.gym.distance": "distance", + "slash.opt.gym.distance.desc": "Alert radius in metres", + "slash.opt.gym.clean": "clean", + "slash.opt.gym.clean.desc": "Auto-delete the alert when the gym state changes", + "slash.opt.gym.template": "template", + "slash.opt.gym.template.desc": "DTS template name", + "slash.choice.gym.clean.yes": "Yes", + "slash.choice.gym.team.0": "Harmony", + "slash.choice.gym.team.1": "Mystic", + "slash.choice.gym.team.2": "Valor", + "slash.choice.gym.team.3": "Instinct", + "slash.opt.fort.fort_type": "fort_type", + "slash.opt.fort.fort_type.desc": "Fort type to track", + "slash.opt.fort.include_empty": "include_empty", + "slash.opt.fort.include_empty.desc": "Alert on empty/unowned forts", + "slash.opt.fort.distance": "distance", + "slash.opt.fort.distance.desc": "Alert radius in metres", + "slash.opt.fort.clean": "clean", + "slash.opt.fort.clean.desc": "Auto-delete the alert when the fort changes again", + "slash.opt.fort.template": "template", + "slash.opt.fort.template.desc": "DTS template name", + "slash.choice.fort.clean.yes": "Yes", + "slash.choice.fort.fort_type.0": "Pokestop", + "slash.choice.fort.fort_type.1": "Gym", + "slash.opt.tracker.location": "location", + "slash.opt.tracker.location.desc": "Use a saved location instead of your default (requires distance:)", + "slash.opt.tracker.areas": "areas", + "slash.opt.tracker.areas.desc": "Restrict to specific areas (comma-separated)", + "slash.autocomplete.untrack.remove_all": "🗑️ Remove ALL rules of this type", + "slash.opt.untrack.pokemon": "pokemon", + "slash.opt.untrack.pokemon.desc": "Remove a pokemon tracking rule", + "slash.opt.untrack.pokemon.tracking": "tracking", + "slash.opt.untrack.pokemon.tracking.desc": "Pick from your existing pokemon tracking rules", + "slash.opt.untrack.raid": "raid", + "slash.opt.untrack.raid.desc": "Remove a raid tracking rule", + "slash.opt.untrack.raid.tracking": "tracking", + "slash.opt.untrack.raid.tracking.desc": "Pick from your existing raid tracking rules", + "slash.opt.untrack.egg": "egg", + "slash.opt.untrack.egg.desc": "Remove an egg tracking rule", + "slash.opt.untrack.egg.tracking": "tracking", + "slash.opt.untrack.egg.tracking.desc": "Pick from your existing egg tracking rules", + "slash.opt.untrack.quest": "quest", + "slash.opt.untrack.quest.desc": "Remove a quest tracking rule", + "slash.opt.untrack.quest.tracking": "tracking", + "slash.opt.untrack.quest.tracking.desc": "Pick from your existing quest tracking rules", + "slash.opt.untrack.invasion": "invasion", + "slash.opt.untrack.invasion.desc": "Remove an invasion tracking rule", + "slash.opt.untrack.invasion.tracking": "tracking", + "slash.opt.untrack.invasion.tracking.desc": "Pick from your existing invasion tracking rules", + "slash.opt.untrack.lure": "lure", + "slash.opt.untrack.lure.desc": "Remove a lure tracking rule", + "slash.opt.untrack.lure.tracking": "tracking", + "slash.opt.untrack.lure.tracking.desc": "Pick from your existing lure tracking rules", + "slash.opt.untrack.nest": "nest", + "slash.opt.untrack.nest.desc": "Remove a nest tracking rule", + "slash.opt.untrack.nest.tracking": "tracking", + "slash.opt.untrack.nest.tracking.desc": "Pick from your existing nest tracking rules", + "slash.opt.untrack.gym": "gym", + "slash.opt.untrack.gym.desc": "Remove a gym tracking rule", + "slash.opt.untrack.gym.tracking": "tracking", + "slash.opt.untrack.gym.tracking.desc": "Pick from your existing gym tracking rules", + "slash.opt.untrack.fort": "fort", + "slash.opt.untrack.fort.desc": "Remove a fort tracking rule", + "slash.opt.untrack.fort.tracking": "tracking", + "slash.opt.untrack.fort.tracking.desc": "Pick from your existing fort tracking rules", + "slash.opt.untrack.maxbattle": "maxbattle", + "slash.opt.untrack.maxbattle.desc": "Remove a maxbattle tracking rule", + "slash.opt.untrack.maxbattle.tracking": "tracking", + "slash.opt.untrack.maxbattle.tracking.desc": "Pick from your existing maxbattle tracking rules", + "slash.opt.area.add": "add", + "slash.opt.area.add.desc": "Add an area to your tracking", + "slash.opt.area.add.area": "area", + "slash.opt.area.add.area.desc": "Area to add", + "slash.opt.area.remove": "remove", + "slash.opt.area.remove.desc": "Remove an area from your tracking", + "slash.opt.area.remove.area": "area", + "slash.opt.area.remove.area.desc": "Area to remove", + "slash.opt.area.show": "show", + "slash.opt.area.show.desc": "Show your selected areas", + "slash.opt.area.list": "list", + "slash.opt.area.list.desc": "List every area available to you (✓ = already added)", + "slash.opt.area.overview": "overview", + "slash.opt.area.overview.desc": "Map overview of every area available to you", + "slash.opt.profile.list": "list", + "slash.opt.profile.list.desc": "List your profiles", + "slash.opt.profile.change": "change", + "slash.opt.profile.change.desc": "Switch active profile", + "slash.opt.profile.change.name": "name", + "slash.opt.profile.change.name.desc": "Profile name", + "slash.opt.profile.create": "create", + "slash.opt.profile.create.desc": "Create a new profile", + "slash.opt.profile.create.name": "name", + "slash.opt.profile.create.name.desc": "Profile name", + "slash.opt.profile.delete": "delete", + "slash.opt.profile.delete.desc": "Delete a profile", + "slash.opt.profile.delete.name": "name", + "slash.opt.profile.delete.name.desc": "Profile name", + "slash.opt.profile.settime": "settime", + "slash.opt.profile.settime.desc": "Set active-hours for the current profile", + "slash.opt.profile.settime.times": "times", + "slash.opt.profile.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.profile.cleartime": "cleartime", + "slash.opt.profile.cleartime.desc": "Clear active-hours from the current profile", + "slash.opt.profile.copyto": "copyto", + "slash.opt.profile.copyto.desc": "Copy this profile's tracking to another profile", + "slash.opt.profile.copyto.profile": "profile", + "slash.opt.profile.copyto.profile.desc": "Target profile name or number", + "slash.opt.location.add": "add", + "slash.opt.location.add.desc": "Save a named location", + "slash.opt.location.add.name": "name", + "slash.opt.location.add.name.desc": "Short name for this location (e.g. Home)", + "slash.opt.location.add.place": "place", + "slash.opt.location.add.place.desc": "Coordinates (lat,lon) or a place name", + "slash.opt.location.list": "list", + "slash.opt.location.list.desc": "List your saved locations", + "slash.opt.location.show": "show", + "slash.opt.location.show.desc": "Show one saved location", + "slash.opt.location.show.name": "name", + "slash.opt.location.show.name.desc": "Saved-location name", + "slash.opt.location.remove": "remove", + "slash.opt.location.remove.desc": "Remove a saved location", + "slash.opt.location.remove.name": "name", + "slash.opt.location.remove.name.desc": "Saved-location name (or \"default\" to clear your default location)", + "slash.opt.location.set-default": "set-default", + "slash.opt.location.set-default.desc": "Set your default location", + "slash.opt.location.set-default.place": "place", + "slash.opt.location.set-default.place.desc": "Coordinates (lat,lon) or address to set as your default location", + "slash.opt.location.remove-default": "remove-default", + "slash.opt.location.remove-default.desc": "Clear your default location", + "slash.opt.summary.quest": "quest", + "slash.opt.summary.quest.desc": "Manage quest-summary buffering", + "slash.opt.summary.quest.show": "show", + "slash.opt.summary.quest.show.desc": "Show schedule and current buffer count", + "slash.opt.summary.quest.settime": "settime", + "slash.opt.summary.quest.settime.desc": "Set the active-hours schedule for the quest summary", + "slash.opt.summary.quest.settime.times": "times", + "slash.opt.summary.quest.settime.times.desc": "Time-range string (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2)", + "slash.opt.summary.quest.cleartime": "cleartime", + "slash.opt.summary.quest.cleartime.desc": "Clear the active-hours schedule", + "slash.opt.summary.quest.now": "now", + "slash.opt.summary.quest.now.desc": "Force-dispatch the currently-buffered quests", + "error.slash.unregistered_with_channel": "🛑 You need to register first. DM me with !poracle, or run !poracle in {0}.", + "error.slash.unregistered_dm_only": "🛑 You need to register first. DM me with !poracle.", + "error.slash.track.no_pokemon": "Please specify a Pokemon to track.", + "error.slash.raid.need_boss_or_level": "Please specify either a boss or a level.", + "error.slash.raid.boss_and_level": "Please specify either a boss OR a level, not both.", + "error.slash.egg.no_level": "Please specify an egg level.", + "error.slash.quest.no_reward": "Please specify exactly one reward type (pokemon, item, stardust, candy, or mega_energy).", + "error.slash.quest.exactly_one_reward": "Please specify exactly one reward type, not multiple: {0}.", + "error.slash.quest.amount_not_applicable": "`min_amount` doesn't apply to pokemon quests. For stardust, both `stardust` and `min_amount` end up in the same field — pick whichever reads better.", + "error.slash.invasion.no_grunt": "Please specify a grunt type.", + "error.slash.incident.no_type": "Please specify an incident type.", + "error.slash.lure.no_type": "Please specify a lure type.", + "error.slash.nest.no_pokemon": "Please specify a Pokemon for the nest.", + "error.slash.maxbattle.no_pokemon": "Please specify a Pokemon for the max battle.", + "error.slash.fort.no_type": "Please specify a fort type (pokestop or gym).", + "error.slash.untrack.no_subcommand": "Please choose what kind of tracking rule to remove.", + "error.slash.untrack.no_tracking": "Please pick a tracking rule to remove.", + "error.slash.info.no_subcommand": "Please choose an info sub-command (pokemon / rarity / shiny / weather).", + "error.slash.info.no_pokemon": "Please specify a pokemon name or dex id.", + "error.slash.info.unknown_subcommand": "Unknown info sub-command.", + "error.slash.area.no_subcommand": "Please choose an area sub-command (add / remove / show).", + "error.slash.area.no_area": "Please specify an area name.", + "error.slash.area.unknown_subcommand": "Unknown area sub-command.", + "error.slash.profile.no_subcommand": "Please choose a profile sub-command (list / change / create / delete / settime / cleartime / copyto).", + "error.slash.profile.no_name": "Please specify a profile name.", + "error.slash.profile.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.profile.no_target": "Please specify a target profile to copy to.", + "error.slash.profile.unknown_subcommand": "Unknown profile sub-command.", + "error.slash.summary.no_alert_type": "Please choose an alert type (e.g. quest).", + "error.slash.summary.no_action": "Please choose an action (show / settime / cleartime / now).", + "error.slash.summary.no_times": "Please specify a time-range (e.g. mon07:30, weekday07:30-18:00, weekday:9-17/2).", + "error.slash.summary.unknown_action": "Unknown summary action.", + "error.slash.location.no_subcommand": "Please choose a location sub-command (add / list / show / remove / remove-default).", + "error.slash.location.no_name": "Please specify a saved-location name.", + "error.slash.location.empty": "Please specify coordinates or a place name.", + "error.slash.location.unknown_subcommand": "Unknown location sub-command.", + "error.slash.location.no_geocoder": "Place-name lookup is not configured. Please provide coordinates like 51.28, 1.08.", + "error.slash.location.geocode_failed": "Could not find a location for \"{0}\".", + "msg.help.text": "**可用命令:**\n{0}track <宝可梦> [iv:N] [cp:N] [level:N] [d:N] — 追踪宝可梦\n{0}untrack <宝可梦> — 移除宝可梦追踪\n{0}raid <宝可梦|level:N|legendary> [d:N] — 追踪团战\n{0}egg [d:N] — 追踪蛋\n{0}quest <宝可梦|stardust|energy:宝可梦|candy:宝可梦> — 追踪任务\n{0}invasion [everything|<类型>] — 追踪入侵\n{0}lure <类型|everything> — 追踪诱饵\n{0}gym <队伍|everything> [slot_changes] — 追踪道馆\n{0}nest <宝可梦|everything> — 追踪巢穴\n{0}maxbattle <宝可梦|level:N> — 追踪极巨战\n{0}fort — 追踪据点更新\n{0}tracked — 显示所有追踪\n{0}script — 将追踪导出为命令\n{0}area [list|add|remove] — 管理区域\n{0}location <纬度,经度> — 设置位置\n{0}profile [list|add|remove|switch] — 管理配置\n{0}language <代码> — 设置语言\n{0}start / {0}stop — 启用/停用提醒\n{0}version — 显示版本", + "cmd.poracle_admin": "poracle-admin", + "cmd.pa": "pa", + "cmd.poracle_admin.not_admin": "This command is reserved for administrators.", + "cmd.poracle_admin.unknown_group": "Unknown subgroup. Try `!poracle-admin` for the list.", + "cmd.poracle_admin.unknown_sub": "Unknown subcommand for `{0}`. Try `!poracle-admin {0}` to see what's available.", + "cmd.poracle_admin.help.admin_only": "This command is reserved for server administrators. Each subgroup performs a live operations task.", + "cmd.poracle_admin.help.groups": "Available subgroups:", + "cmd.poracle_admin.help_intro": "🛠️ Poracle Admin\n\nLive operations subgroups (administrators only):", + "cmd.poracle_admin.stub": "(not yet implemented)", + "cmd.poracle_admin.group.slash.desc": "slash-command registration lifecycle", + "cmd.poracle_admin.group.reload.desc": "reload DTS, geofence, or in-memory state", + "cmd.poracle_admin.group.emoji.desc": "list, reload, or test emoji config", + "cmd.poracle_admin.group.reconcile.desc": "Discord role reconciliation (immediate or per-user)", + "cmd.poracle_admin.group.cache.desc": "cache stats and clear", + "cmd.poracle_admin.group.ratelimit.desc": "inspect and reset alert-bucket rate limits", + "cmd.poracle_admin.group.summary.desc": "summary buffer inspection and forced dispatch", + "cmd.poracle_admin.group.status.desc": "live health snapshot", + "cmd.poracle_admin.group.maintenance.desc": "pause/resume outbound delivery", + "cmd.poracle_admin.group.config.desc": "view effective merged config with secrets redacted", + "cmd.poracle_admin.group.warnings.desc": "inspect captured WARN/ERROR log entries (startup + rolling buffers)", + "cmd.poracle_admin.reload.help.intro": "Reload runtime state from disk or database.", + "cmd.poracle_admin.reload.dts.desc": "`dts` — reload DTS templates and partials from disk", + "cmd.poracle_admin.reload.geofence.desc": "`geofence` — reload geofence files and refresh state", + "cmd.poracle_admin.reload.state.desc": "`state` — reload tracking rules and humans from MySQL (bypasses debounce)", + "cmd.poracle_admin.reload.dts.success": "✅ DTS reloaded in {0}ms ({1} templates)", + "cmd.poracle_admin.reload.geofence.success": "✅ Geofence reloaded in {0}ms ({1} fences, {2} tracking rules)", + "cmd.poracle_admin.reload.state.success": "✅ State reloaded in {0}ms ({1} tracking rules, {2} active humans)", + "cmd.poracle_admin.reload.error": "❌ Reload failed: {0}", + "cmd.poracle_admin.emoji.help.intro": "😀 Emoji config — inspect and manage emoji.json + Discord guild emojis.\n\nSubcommands:", + "cmd.poracle_admin.emoji.list.desc": "`list` — list all configured emoji keys with per-platform resolutions", + "cmd.poracle_admin.emoji.reload.desc": "`reload` — reload config/emoji.json from disk", + "cmd.poracle_admin.emoji.test.desc": "`test ` — resolve one emoji key for the current platform", + "cmd.poracle_admin.emoji.upload.desc": "`upload [overwrite]` — upload uicons-based emojis to the guild and write a new emoji.json (Discord-only)", + "cmd.poracle_admin.emoji.discord_config.desc": "`discord-config` — dump emoji.json from the current guild state, no uploads (Discord-only)", + "cmd.poracle_admin.emoji.discord_only": "ℹ️ This subcommand requires a Discord bot with guild access.", + "cmd.poracle_admin.emoji.not_loaded": "ℹ️ Emoji config not loaded (DTS renderer not configured).", + "cmd.poracle_admin.emoji.list.header": "😀 Emoji configuration — {0} keys loaded", + "cmd.poracle_admin.emoji.list.row.key": " {0}:", + "cmd.poracle_admin.emoji.list.row.platform": " {0}: {1}", + "cmd.poracle_admin.emoji.reload.success": "✅ Emoji config reloaded — {0} keys (took {1}ms).", + "cmd.poracle_admin.emoji.reload.error": "❌ Emoji reload failed: {0}", + "cmd.poracle_admin.emoji.test.success": "🔎 {0} on {1}: {2}", + "cmd.poracle_admin.emoji.test.not_found": "ℹ️ Emoji key \"{0}\" not found in the loaded config.", + "cmd.poracle_admin.emoji.test.usage": "Usage: !poracle-admin emoji test ", + "cmd.poracle_admin.reconcile.help.intro": "🔄 Discord role reconciliation — trigger immediately instead of waiting for the periodic timer.", + "cmd.poracle_admin.reconcile.run.desc": "`run` — reconcile all guild members now (blocks until complete)", + "cmd.poracle_admin.reconcile.user.desc": "`user ` — reconcile a single Discord user by snowflake ID", + "cmd.poracle_admin.reconcile.not_configured": "❌ Discord reconciliation is not configured (Telegram-only deploy, or check_role=false).", + "cmd.poracle_admin.reconcile.run.success": "✅ Discord reconciliation complete (took {0}ms).", + "cmd.poracle_admin.reconcile.run.error": "❌ Reconciliation failed: {0}", + "cmd.poracle_admin.reconcile.user.success": "✅ Reconciled discord:user/{0} (took {1}ms).", + "cmd.poracle_admin.reconcile.user.error": "❌ Failed to reconcile discord:user/{0}: {1}", + "cmd.poracle_admin.reconcile.user.usage": "Usage: !poracle-admin reconcile user ", + "cmd.poracle_admin.cache.help.intro": "🗺️ Geocoder cache — inspect counters or drop the in-memory layer.", + "cmd.poracle_admin.cache.stats.desc": "`stats` — geocoder cache stats", + "cmd.poracle_admin.cache.clear.desc": "`clear geocoder` — drop the in-memory geocoder cache", + "cmd.poracle_admin.cache.not_configured": "Geocoder cache is not configured on this instance.", + "cmd.poracle_admin.cache.stats.header": "🗺️ Geocoder cache", + "cmd.poracle_admin.cache.stats.row.memory_entries": " Memory entries: {0}", + "cmd.poracle_admin.cache.stats.row.disk_entries": " Disk entries: {0}", + "cmd.poracle_admin.cache.stats.row.hits_memory": " Hits (memory): {0}", + "cmd.poracle_admin.cache.stats.row.hits_disk": " Hits (disk): {0}", + "cmd.poracle_admin.cache.stats.row.misses": " Misses: {0}", + "cmd.poracle_admin.cache.stats.row.hit_rate": " Hit rate: {0}%", + "cmd.poracle_admin.cache.clear.usage_hint": "Specify what to clear, e.g. `!poracle-admin cache clear geocoder`", + "cmd.poracle_admin.cache.clear.geocoder.success": "✅ Geocoder memory cache cleared — {0} entries dropped (disk untouched).", + "cmd.poracle_admin.ratelimit.help.intro": "🚦 Rate-limit introspection — inspect or reset per-destination alert and summary buckets.", + "cmd.poracle_admin.ratelimit.not_configured": "ℹ️ Alert rate limiter is not configured on this instance.", + "cmd.poracle_admin.ratelimit.list.desc": "`list` — show all targets currently breached or banned", + "cmd.poracle_admin.ratelimit.show.desc": "`show ` — detailed state for one target (both buckets)", + "cmd.poracle_admin.ratelimit.reset.desc": "`reset ` — clear counters and violation history", + "cmd.poracle_admin.ratelimit.userlist.desc": "`userlist` — show currently disabled users (shortcut for !userlist disabled)", + "cmd.poracle_admin.ratelimit.list.empty": "🟢 No targets currently rate-limited.", + "cmd.poracle_admin.ratelimit.list.header_title": "Currently rate-limited targets", + "cmd.poracle_admin.ratelimit.list.bucket_header": " {0} bucket ({1} breached / {2} banned):", + "cmd.poracle_admin.ratelimit.list.row": "count {0}/{1}, {2}", + "cmd.poracle_admin.ratelimit.list.status.banned": "banned for {0}", + "cmd.poracle_admin.ratelimit.list.status.breached": "window resets in {0}", + "cmd.poracle_admin.ratelimit.show.header": "🚦 Rate-limit state for {0}", + "cmd.poracle_admin.ratelimit.show.bucket_header": "{0} bucket:", + "cmd.poracle_admin.ratelimit.show.empty": "🟢 No recorded activity for {0} in either bucket.", + "cmd.poracle_admin.ratelimit.show.no_data": "(no activity in this bucket)", + "cmd.poracle_admin.ratelimit.show.no_violations": "No violations.", + "cmd.poracle_admin.ratelimit.show.violations_count": "Violations (24h): {0}", + "cmd.poracle_admin.ratelimit.show.banned_until": "Banned until: {0} (in {1})", + "cmd.poracle_admin.ratelimit.show.status.under_limit": "under limit", + "cmd.poracle_admin.ratelimit.show.status.over_limit": "over limit", + "cmd.poracle_admin.ratelimit.show.row.count": " Count: {0} / {1} ({2})\n", + "cmd.poracle_admin.ratelimit.show.row.window": " Window: opened {0} ago, resets in {1}\n", + "cmd.poracle_admin.ratelimit.reset.success": "✅ Reset rate-limit state for {0} (cleared alert + summary buckets, violations reset).", + "cmd.poracle_admin.ratelimit.reset.no_state": "ℹ️ No rate-limit state to reset for {0}.", + "cmd.poracle_admin.ratelimit.reset.note": "Note: admin_disable is NOT touched. If the user was auto-disabled by the rate-limiter, they still need to !poracle to re-register.", + "cmd.poracle_admin.ratelimit.usage.show": "Usage: !poracle-admin ratelimit show ", + "cmd.poracle_admin.ratelimit.usage.reset": "Usage: !poracle-admin ratelimit reset ", + "cmd.poracle_admin.ratelimit.userlist.lookup_failed": "❌ Could not find !userlist command in the registry.", + "cmd.poracle_admin.summary.help.intro": "📦 Summary buffer — inspect who has quests buffered and force-dispatch on demand.", + "cmd.poracle_admin.summary.not_configured": "ℹ️ Summary buffer is not configured on this instance.", + "cmd.poracle_admin.summary.list.desc": "`list` — show all users with anything buffered", + "cmd.poracle_admin.summary.show.desc": "`show ` — inspect one user's buffered entries", + "cmd.poracle_admin.summary.fire.desc": "`fire [alertType]` — force-dispatch a user's buffer immediately", + "cmd.poracle_admin.summary.list.empty": "🟢 No users have anything buffered.", + "cmd.poracle_admin.summary.list.header": "📦 Summary buffer — {0} users with {1} buffered entries", + "cmd.poracle_admin.summary.list.user_header": " {0}", + "cmd.poracle_admin.summary.list.row": " {0}: {1} entries (next fires: {2})", + "cmd.poracle_admin.summary.list.next_fire.none": "n/a", + "cmd.poracle_admin.summary.show.header": "📦 Summary buffer for {0}", + "cmd.poracle_admin.summary.show.empty": "🟢 No buffered entries for {0}.", + "cmd.poracle_admin.summary.show.alert_type": " {0}: {1} entries", + "cmd.poracle_admin.summary.show.usage": "Usage: !poracle-admin summary show ", + "cmd.poracle_admin.summary.fire.success": "✅ Dispatched summary for {0} / {1} — {2} entries delivered.", + "cmd.poracle_admin.summary.fire.usage": "Usage: !poracle-admin summary fire [alertType]", + "cmd.poracle_admin.summary.show.reward_row": " Reward type {0}, reward {1}{2} — {3} stops", + "cmd.poracle_admin.summary.show.reward_more": " ... ({0} more reward groups)", + "cmd.poracle_admin.summary.show.form_suffix": " form {0}", + "cmd.poracle_admin.maintenance.help.intro": "🛠️ **!poracle-admin maintenance** — live control over outbound delivery.\n\nSubcommands:", + "cmd.poracle_admin.maintenance.no_dispatcher": "ℹ️ Dispatcher is not available on this instance.", + "cmd.poracle_admin.maintenance.no_reason": "(no reason given)", + "cmd.poracle_admin.maintenance.pause.desc": "`pause [reason...]` (alias: `start`) — halt outbound delivery (webhooks still ingest, match, render, and queue)", + "cmd.poracle_admin.maintenance.resume.desc": "`resume` (alias: `stop`) — lift a previous pause and drain queued jobs", + "cmd.poracle_admin.maintenance.status.desc": "`status` — show current paused/running state and queue depth", + "cmd.poracle_admin.maintenance.pause.new": "🔴 Outbound delivery paused: {0}", + "cmd.poracle_admin.maintenance.pause.detail": "Webhooks still ingest, match, render, and queue — the dispatcher holds them until !poracle-admin maintenance resume.", + "cmd.poracle_admin.maintenance.pause.already": "ℹ️ Already paused since {0} ({1} ago): {2}", + "cmd.poracle_admin.maintenance.resume.success": "🟢 Outbound delivery resumed (was paused for {0}: {1})", + "cmd.poracle_admin.maintenance.resume.detail": "Queued messages are draining.", + "cmd.poracle_admin.maintenance.resume.not_paused": "ℹ️ Not currently paused.", + "cmd.poracle_admin.maintenance.status.running": "🟢 Delivery is running.", + "cmd.poracle_admin.maintenance.status.paused": "🔴 PAUSED — {0} (for {1})", + "cmd.poracle_admin.maintenance.status.queued": "{0} jobs queued waiting (across all platforms — Discord {1}, Telegram {2})", + "cmd.poracle_admin.status.help.intro": "!poracle-admin status — current health snapshot. Add -v for verbose mode (per-route Discord detail, full webhook per-type breakdown).", + "cmd.poracle_admin.status.header": "🛠️ Poracle Admin — Status", + "cmd.poracle_admin.status.paused_banner": "🔴 PAUSED — {0} (since {1} ago)\n Outbound delivery is held. Webhooks still ingest and queue.", + "cmd.poracle_admin.status.value.na": "n/a", + "cmd.poracle_admin.status.value.none": "none", + "cmd.poracle_admin.status.section.build": "**Build / Uptime**", + "cmd.poracle_admin.status.section.webhooks": "**Webhooks**", + "cmd.poracle_admin.status.section.render_queue": "**Render queue**", + "cmd.poracle_admin.status.section.delivery": "**Delivery**", + "cmd.poracle_admin.status.section.discord_rate": "**Discord rate**", + "cmd.poracle_admin.status.section.telegram_rate": "**Telegram rate**", + "cmd.poracle_admin.status.section.alert_limits": "**Alert limits**", + "cmd.poracle_admin.status.section.summary_buffer": "**Summary buffer**", + "cmd.poracle_admin.status.label.summary_buffer_totals": "Entries: {0} across {1} bucket(s)", + "cmd.poracle_admin.status.label.summary_buffer_top": "Top users:", + "cmd.poracle_admin.status.label.summary_buffer_user_row": " {0} ({1}): {2} entries", + "cmd.poracle_admin.status.section.tracking": "**Tracking**", + "cmd.poracle_admin.status.section.mysql": "**MySQL**", + "cmd.poracle_admin.status.label.version": "Version: {0} (commit {1}, built {2})", + "cmd.poracle_admin.status.label.uptime": "Uptime: {0}", + "cmd.poracle_admin.status.label.webhooks_rate": "{0} / {1} / {2} per min over last 5/15/60 min", + "cmd.poracle_admin.status.label.webhooks_by_type": "By type (last 60 min):", + "cmd.poracle_admin.status.label.delivery_discord": "Discord in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_telegram": "Telegram in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_webhook": "Webhook in-flight: {0}", + "cmd.poracle_admin.status.label.delivery_queue_depth": "Queue depth: {0} (capacity not exposed)", + "cmd.poracle_admin.status.label.discord_routes": "Routes near limit: {0}", + "cmd.poracle_admin.status.label.discord_global": "Global tokens: {0} / {1}", + "cmd.poracle_admin.status.label.discord_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.discord_routes_detail": "Routes near limit (detail):", + "cmd.poracle_admin.status.label.telegram_429s": "429s in last 5 min: {0}", + "cmd.poracle_admin.status.label.telegram_backoff": "Current backoff: {0}", + "cmd.poracle_admin.status.label.alert_limits_counts": "Breached: alert={0}, summary={1} · Banned: {2}", + "cmd.poracle_admin.status.label.tracking_total": "Total tracking rules: {0}", + "cmd.poracle_admin.status.label.tracking_active_humans": "Active humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans": "Registered humans: {0}", + "cmd.poracle_admin.status.label.tracking_registered_humans_error": "Registered humans: n/a (error)", + "cmd.poracle_admin.status.label.tracking_type": "{0}: {1}", + "cmd.poracle_admin.status.label.mysql_ping_ok": "Ping: ok", + "cmd.poracle_admin.status.label.mysql_ping_fail": "Ping: failed ({0})", + "cmd.poracle_admin.status.label.mysql_pool": "Connections: {0}/{1} open ({2} in use, {3} idle, waits={4})", + "cmd.poracle_admin.status.tracking_type.pokemon": "pokemon", + "cmd.poracle_admin.status.tracking_type.raid": "raid", + "cmd.poracle_admin.status.tracking_type.egg": "egg", + "cmd.poracle_admin.status.tracking_type.quest": "quest", + "cmd.poracle_admin.status.tracking_type.invasion": "invasion", + "cmd.poracle_admin.status.tracking_type.lure": "lure", + "cmd.poracle_admin.status.tracking_type.nest": "nest", + "cmd.poracle_admin.status.tracking_type.gym": "gym", + "cmd.poracle_admin.status.tracking_type.fort": "fort", + "cmd.poracle_admin.status.tracking_type.maxbattle": "maxbattle", + "cmd.poracle_admin.slash.help.intro": "**!poracle-admin slash** — slash-command registration lifecycle.\nSubcommands:", + "cmd.poracle_admin.slash.discord_only": "❌ Slash commands are Discord-only and cannot be managed from Telegram.", + "cmd.poracle_admin.slash.not_configured": "❌ Slash commands are not configured (Discord disabled or [discord.slash_commands] enabled=false).", + "cmd.poracle_admin.slash.sync.desc": "push the current command set to Discord (fingerprint-cached, skips if unchanged)", + "cmd.poracle_admin.slash.sync.success": "✅ Slash sync complete ({0}ms)", + "cmd.poracle_admin.slash.sync.error": "❌ Slash sync failed: {0}", + "cmd.poracle_admin.slash.force_resync.desc": "clear fingerprint cache and push unconditionally", + "cmd.poracle_admin.slash.force_resync.success": "✅ Force-resync complete ({0}ms)", + "cmd.poracle_admin.slash.force_resync.error": "❌ Force-resync failed: {0}", + "cmd.poracle_admin.slash.clear_global.desc": "remove all globally-registered Discord slash commands", + "cmd.poracle_admin.slash.clear_global.success": "✅ Global slash commands cleared.", + "cmd.poracle_admin.slash.clear_global.error": "❌ Clear global failed: {0}", + "cmd.poracle_admin.slash.clear_guild.desc": "remove slash commands from one guild (requires guild_id arg)", + "cmd.poracle_admin.slash.clear_guild.needs_arg": "❌ Usage: `!poracle-admin slash clear-guild `", + "cmd.poracle_admin.slash.clear_guild.success": "✅ Slash commands cleared from guild {0}.", + "cmd.poracle_admin.slash.clear_guild.error": "❌ Clear guild failed: {0}", + "cmd.poracle_admin.slash.status.desc": "show last sync timestamp and fingerprint per scope", + "cmd.poracle_admin.slash.status.header": "**Slash command registration status:**", + "cmd.poracle_admin.slash.status.scope_row": " **{0}**: last synced {1} · fingerprint `{2}`", + "cmd.poracle_admin.slash.status.never_synced": "never", + "cmd.poracle_admin.slash.status.ago": "{0} ago", + "cmd.poracle_admin.slash.status.error": "❌ Status read failed: {0}", + "cmd.poracle_admin.config.help.intro": "⚙️ Config viewer — show effective merged config with secrets redacted.\nSubcommands:", + "cmd.poracle_admin.config.keys.desc": "list section names with key counts", + "cmd.poracle_admin.config.section.desc": "show just that section (e.g. `!poracle-admin config discord`)", + "cmd.poracle_admin.config.full.desc": "show the full config (all sections, secrets redacted)", + "cmd.poracle_admin.config.keys.header": "⚙️ Config sections:", + "cmd.poracle_admin.config.keys.row": " {0}: {1} keys", + "cmd.poracle_admin.config.unknown_section": "Unknown config section: `{0}`. Use `!poracle-admin config keys` to list valid sections, or `!poracle-admin config search ` to search across all sections.", + "cmd.poracle_admin.config.search.desc": "find keys whose path or value contains the term across every section (e.g. `!poracle-admin config search dm`)", + "cmd.poracle_admin.config.search.usage": "Usage: `!poracle-admin config search ` — e.g. `search dm`, `search shlink`, `search 3030`.", + "cmd.poracle_admin.config.search.header": "🔍 `{0}` — {1} match(es):", + "cmd.poracle_admin.config.search.no_matches": "No config keys or values match `{0}`.", + "cmd.poracle_admin.config.empty_section": "Section `{0}` has no configurable fields.", + "cmd.poracle_admin.config.not_loaded": "❌ Config not loaded.", + "cmd.poracle_admin.warnings.help.intro": "🛠️ Captured warnings — inspect in-memory WARN/ERROR log entries.\n\nSubcommands:\n (no arg) — show both startup and recent buffers\n `startup` — show only the startup buffer (first 200 entries, frozen after init)\n `recent` — show only the rolling buffer (last 50 entries)\n `clear` — empty the rolling buffer (startup is immutable)", + "cmd.poracle_admin.warnings.not_configured": "ℹ️ Log buffer is not configured on this instance.", + "cmd.poracle_admin.warnings.section.startup": "🛠️ Captured warnings — startup ({0} entries)", + "cmd.poracle_admin.warnings.section.recent": "🛠️ Captured warnings — recent ({0} entries)", + "cmd.poracle_admin.warnings.empty.startup": "🟢 No startup warnings captured.", + "cmd.poracle_admin.warnings.empty.recent": "🟢 No recent warnings.", + "cmd.poracle_admin.warnings.entry_row": " {0} {1} {2} {3}", + "cmd.poracle_admin.warnings.cleared": "✅ Cleared {0} entries from the rolling buffer (startup buffer is unaffected).", + "cmd.poracle_admin.warnings.startup.desc": "`startup` — show only the startup buffer (frozen after init)", + "cmd.poracle_admin.warnings.recent.desc": "`recent` — show only the rolling buffer (last 50 entries)", + "cmd.poracle_admin.warnings.clear.desc": "`clear` — empty the rolling buffer", + "cmd.maintenance.active_suffix": "🔧 Maintenance mode is active — alerts are not being delivered.", + "showcase_focus_pokemon": "Pokémon", + "showcase_focus_type": "Type", + "showcase_focus_alignment": "Alignment", + "showcase_focus_class": "Class", + "showcase_focus_family": "Family", + "showcase_focus_buddy": "Buddy", + "showcase_focus_generation": "Generation", + "showcase_focus_hatched": "Hatched", + "showcase_focus_mega": "Mega", + "showcase_focus_shiny": "Shiny", + "showcase_class_ultra_beast": "Ultra Beast" }