import { z } from 'zod'; export * from './audit.js'; export * from './command-locales.js'; export * from './discord-localization.js'; export * from './phase2.js'; export * from './phase3.js'; export * from './phase4.js'; export * from './phase5.js'; export * from './phase6.js'; export * from './dashboard.js'; export * from './owner.js'; export * from './public.js'; export * from './premium.js'; export * from './components-v2.js'; export const LocaleSchema = z.enum(['de', 'en']); export type Locale = z.infer; export const GuildSettingsSchema = z.object({ guildId: z.string(), locale: LocaleSchema.default('de'), timezone: z.string().default('Europe/Berlin'), moderationEnabled: z.boolean().default(true) }); export const ModerationActionSchema = z.enum([ 'BAN', 'UNBAN', 'KICK', 'TIMEOUT', 'UN_TIMEOUT', 'WARN_ADD', 'WARN_REMOVE', 'WARN_CLEAR', 'PURGE', 'LOCK', 'UNLOCK', 'SLOWMODE', 'NICK_SET', 'NICK_RESET', 'CASE_EDIT', 'CASE_DELETE', 'MODNOTE_ADD' ]); export type ModerationAction = z.infer; type Dictionary = Record; const de: Dictionary = { 'generic.noPermission': 'Du hast keine Berechtigung für diese Aktion.', 'generic.guildOnly': 'Dieser Command kann nur auf einem Server verwendet werden.', 'generic.botMissingPermission': 'Dem Bot fehlt die erforderliche Berechtigung ({permission}).', 'generic.invalidRegex': 'Ungültiges Regex-Muster.', 'generic.error': 'Es ist ein Fehler aufgetreten.', 'generic.maintenance': 'Nexumi ist derzeit im Wartungsmodus. Bitte versuche es später erneut.', 'generic.unknownCommand': 'Unbekannter Befehl.', 'generic.commandDisabled': 'Dieser Befehl ist auf diesem Server deaktiviert.', 'generic.commandChannelBlocked': 'Dieser Befehl ist in diesem Kanal nicht erlaubt.', 'generic.commandRoleBlocked': 'Du darfst diesen Befehl mit deinen Rollen nicht nutzen.', 'generic.commandCooldown': 'Bitte warte noch {seconds} Sekunden, bevor du diesen Befehl erneut nutzt.', 'generic.moduleDisabled': 'Dieses Modul ist auf diesem Server deaktiviert.', 'generic.userBlacklisted': 'Du darfst Nexumi derzeit nicht nutzen.', 'generic.guildBlacklisted': 'Dieser Server darf Nexumi derzeit nicht nutzen.', 'core.help.title': 'Nexumi Hilfe', 'core.help.subtitle': 'Commands nach Modul. Optional: `/help module:`.', 'core.help.moduleLine': '**{module}**: {commands}', 'core.help.unknownModule': 'Unbekanntes Modul. Verfügbar: {modules}', 'core.help.footer': 'Mehr Infos: /info · Dashboard: {webui}', 'core.info.title': 'Nexumi', 'core.info.version': 'Version', 'core.info.uptime': 'Uptime', 'core.info.shard': 'Shard', 'core.info.guilds': 'Server (dieser Shard)', 'core.info.latency': 'API-Latenz', 'core.info.links': 'Links', 'core.info.link.dashboard': 'Dashboard', 'core.info.link.invite': 'Einladen', 'core.info.link.support': 'Support', 'core.info.link.status': 'Status', 'core.invite.title': 'Nexumi einladen', 'core.invite.body': 'Lade Nexumi mit diesem Link auf deinen Server ein:', 'core.support.title': 'Support', 'core.support.body': 'Tritt unserem Support-Server bei:', 'core.support.missing': 'Kein Support-Server konfiguriert. Bitte SUPPORT_SERVER_URL setzen.', 'core.module.core': 'Basis', 'core.module.moderation': 'Moderation', 'core.module.automod': 'Auto-Moderation', 'core.module.welcome': 'Willkommen', 'core.module.verification': 'Verifizierung', 'core.module.leveling': 'Leveling', 'core.module.economy': 'Economy', 'core.module.utility': 'Utility', 'core.module.fun': 'Fun', 'core.module.giveaways': 'Giveaways', 'core.module.tickets': 'Tickets', 'core.module.selfroles': 'Self-Roles', 'core.module.tags': 'Tags', 'core.module.starboard': 'Starboard', 'core.module.suggestions': 'Vorschläge', 'core.module.birthdays': 'Geburtstage', 'core.module.tempvoice': 'Temp-Voice', 'core.module.stats': 'Statistiken', 'core.module.feeds': 'Feeds', 'core.module.scheduler': 'Scheduler', 'core.module.guildbackup': 'Backup', 'gdpr.privacy.title': 'Datenschutz', 'gdpr.privacy.body': 'Nexumi speichert Discord-IDs und modulbezogene Daten (z. B. Verwarnungen, XP, Economy), soweit für den Betrieb nötig.', 'gdpr.privacy.link': 'Vollständige Datenschutzerklärung: {url}', 'gdpr.privacy.deleteHint': 'Persönliche Daten löschen: `/gdpr delete confirm:true`', 'gdpr.delete.needConfirm': 'Setze `confirm` auf `true`, um die Löschung zu bestätigen.', 'gdpr.delete.doneTitle': 'Daten gelöscht', 'gdpr.delete.doneBody': 'Gelöscht/anonymisiert: {warnings} Verwarnungen, {levels} Level-Einträge, {economy} Economy-Einträge, {cases} Cases anonymisiert.', 'moderation.success': 'Aktion erfolgreich ausgeführt.', 'moderation.success.case': 'Aktion erfolgreich ausgeführt (Fall #{caseNumber}).', 'moderation.duration.invalid': 'Ungültige Dauer. Nutze z. B. 30m, 12h oder 7d.', 'moderation.duration.invalidTimeout': 'Ungültige Timeout-Dauer. Nutze z. B. 30m oder 1d (max. 28 Tage).', 'moderation.hierarchy.self': 'Du kannst diese Aktion nicht auf dich selbst anwenden.', 'moderation.hierarchy.owner': 'Der Server-Owner kann nicht moderiert werden.', 'moderation.hierarchy.moderator': 'Du kannst keine Mitglieder moderieren, die gleich oder höher in der Rollenhierarchie stehen.', 'moderation.hierarchy.bot': 'Der Bot kann dieses Mitglied wegen der Rollenhierarchie oder fehlender Rechte nicht moderieren.', 'moderation.hierarchy.notMember': 'Dieses Mitglied ist nicht auf dem Server.', 'moderation.reason.none': 'Kein Grund angegeben', 'moderation.warning.created': 'Verwarnung erstellt: {warningId}', 'moderation.warning.none': 'Keine Verwarnungen vorhanden.', 'moderation.warning.defaultReason': 'Kein Grund', 'moderation.warning.notFound': 'Verwarnung nicht gefunden.', 'moderation.purge.done': '{deletedCount} Nachrichten gelöscht (Fall #{caseNumber}).', 'moderation.note.none': 'Keine Notizen vorhanden.', 'moderation.case.notFound': 'Fall nicht gefunden.', 'moderation.escalation.durationRequired': 'Für TIMEOUT-Eskalation ist eine Dauer erforderlich.', 'moderation.escalation.noneConfigured': 'Keine Eskalationsregeln konfiguriert.', 'moderation.escalation.saved': 'Eskalationsregel gespeichert: {warnCount} Verwarnungen => {action}{duration}.', 'moderation.escalation.removed': 'Eskalationsregel für {warnCount} Verwarnungen entfernt.', 'moderation.escalation.defaultReason': 'Auto-Eskalation bei {warnCount} Verwarnungen', 'moderation.escalation.skippedDuration': 'Eskalationsregel für {warnCount} Verwarnungen übersprungen (fehlende Dauer).', 'moderation.escalation.skippedPermission': 'Eskalationsregel für {warnCount} Verwarnungen übersprungen (fehlende Bot-Rechte).', 'moderation.escalation.appliedTimeout': 'Auto-Eskalation angewendet: Timeout ({durationMs} ms).', 'moderation.escalation.appliedKick': 'Auto-Eskalation angewendet: Kick.', 'moderation.escalation.appliedBan': 'Auto-Eskalation angewendet: Ban.', 'moderation.confirm.button.confirm': 'Bestätigen', 'moderation.confirm.button.cancel': 'Abbrechen', 'moderation.confirm.permanent': 'dauerhaft', 'moderation.confirm.ban': 'Ban bestätigen für <@{userId}>?\nGrund: {reason}\nDauer: {duration}', 'moderation.confirm.purge': '{amount} Nachrichten löschen? Diese Aktion kann nicht rückgängig gemacht werden.', 'moderation.confirm.caseDelete': 'Fall #{caseNumber} wirklich löschen?', 'moderation.confirm.expired': 'Bestätigung abgelaufen. Bitte den Befehl erneut ausführen.', 'moderation.confirm.cancelled': 'Aktion abgebrochen.', 'moderation.confirm.unauthorized': 'Nur der ausführende Moderator kann diese Bestätigung nutzen.', 'automod.status.header': '**AutoMod enabled:** {enabled}\n**Anti-raid:** {antiRaid}\n**Anti-nuke:** {antiNuke}\n**Lockdown:** {lockdown}', 'automod.status.ruleLine': '- {type} → {action}', 'automod.status.noRules': 'Keine aktiven Regeln.', 'automod.status.yes': 'ja', 'automod.status.no': 'nein', 'welcome.notConfigured': 'Willkommensnachricht ist noch nicht konfiguriert.', 'welcome.invalidChannel': 'Der konfigurierte Willkommenskanal ist ungültig.', 'welcome.testSent': 'Test-Willkommensnachricht gesendet.', 'verification.disabled': 'Verifizierung ist deaktiviert.', 'verification.success': 'Du wurdest erfolgreich verifiziert.', 'verification.setupDone': 'Verifizierung konfiguriert.', 'verification.notConfigured': 'Verifizierung ist noch nicht eingerichtet. Nutze `/verify setup`.', 'verification.invalidChannel': 'Der Verifizierungskanal ist ungültig.', 'verification.panelPosted': 'Verifizierungs-Panel gepostet.', 'verification.panelMissingPermission': 'Dem Bot fehlen Rechte in diesem Kanal (Kanal sehen, Nachrichten senden, Embeds).', 'verification.panel.title': 'Verifizierung', 'verification.panel.description': 'Klicke auf den Button unten, um dich zu verifizieren und Zugang zum Server zu erhalten.', 'verification.panel.button': 'Verifizieren', 'verification.panel.buttonCaptcha': 'Verifizieren (Captcha)', 'verification.captchaLink': 'Öffne diesen Link zur Captcha-Verifizierung: {url}', 'verification.error.not_configured': 'Verifizierung ist nicht konfiguriert.', 'verification.error.member_not_found': 'Mitglied nicht gefunden.', 'verification.error.account_too_young': 'Dein Account ist zu jung für die Verifizierung.', 'verification.error.missing_permissions': 'Dem Bot fehlen Berechtigungen.', 'verification.error.invalid_role': 'Die Verifizierungsrolle ist ungültig.', 'verification.error.alt_detected': 'Verifizierung abgelehnt: möglicher Zweitaccount erkannt.', 'verification.error.generic': 'Verifizierung fehlgeschlagen.', 'verification.captcha.success': 'Captcha bestanden. Du wurdest verifiziert.', 'verification.captcha.invalid': 'Captcha ungültig oder abgelaufen.', 'verification.captcha.title': 'Nexumi Verifizierung', 'leveling.disabled': 'Leveling ist auf diesem Server deaktiviert.', 'leveling.rank.title': 'Rangkarte', 'leveling.leaderboard.title': 'Leaderboard', 'leveling.leaderboard.empty': 'Noch keine XP-Daten vorhanden.', 'leveling.leaderboard.entry': '{rank}. {user} — Level {level} ({xp} XP)', 'leveling.leaderboard.footer': 'Top {count} Mitglieder', 'leveling.levelUp.default': 'Glückwunsch {user}, du hast Level {level} erreicht!', 'leveling.xp.give.success': '{amount} XP an {user} vergeben. Neues Level: {level}.', 'leveling.xp.remove.success': '{amount} XP von {user} entfernt. Neues Level: {level}.', 'leveling.xp.reset.success': 'XP von {user} zurückgesetzt.', 'leveling.xp.invalidAmount': 'Der Betrag muss größer als 0 sein.', 'leveling.user.notFound': 'Nutzer nicht auf diesem Server gefunden.', 'economy.error.disabled': 'Das Economy-Modul ist auf diesem Server deaktiviert.', 'economy.error.insufficient': 'Du hast nicht genug Geld.', 'economy.error.cooldown': 'Cooldown aktiv. Versuche es in {seconds} Sekunden erneut.', 'economy.error.invalid_amount': 'Ungültiger Betrag.', 'economy.error.self_transfer': 'Du kannst dir nicht selbst Geld senden.', 'economy.error.not_found': 'Eintrag nicht gefunden.', 'economy.error.out_of_stock': 'Dieser Artikel ist ausverkauft.', 'economy.error.role_assign_failed': 'Kauf erfolgreich, aber die Rolle konnte nicht vergeben werden.', 'economy.error.game_in_progress': 'Du hast bereits ein laufendes Blackjack-Spiel.', 'economy.balance.result': 'Kontostand von {user}: {amount}', 'economy.daily.success': 'Tägliche Belohnung: {amount}. Neuer Kontostand: {balance}', 'economy.weekly.success': 'Wöchentliche Belohnung: {amount}. Neuer Kontostand: {balance}', 'economy.work.success': 'Du hast {amount} verdient. Neuer Kontostand: {balance}', 'economy.pay.success': 'Du hast {amount} an {user} gesendet. Dein Kontostand: {balance}', 'economy.gamble.win': 'Gewonnen! +{amount}. Kontostand: {balance}', 'economy.gamble.lose': 'Verloren! -{amount}. Kontostand: {balance}', 'economy.slots.win': '{reels}\nGewinn: {payout}. Kontostand: {balance}', 'economy.slots.lose': '{reels}\nKein Gewinn. Kontostand: {balance}', 'economy.coinflip.win': '{result} – du hattest {choice} gewählt. Gewonnen! +{amount}. Kontostand: {balance}', 'economy.coinflip.lose': '{result} – du hattest {choice} gewählt. Verloren! -{amount}. Kontostand: {balance}', 'economy.choice.heads': 'Kopf', 'economy.choice.tails': 'Zahl', 'economy.shop.empty': 'Der Shop ist leer.', 'economy.shop.noDescription': 'Keine Beschreibung', 'economy.shop.itemLine': '**{name}** (`{id}`) – {price} | Bestand: {stock}\n{description}', 'economy.shop.purchased': 'Du hast **{name}** gekauft. Kontostand: {balance}', 'economy.inventory.empty': 'Dein Inventar ist leer.', 'economy.inventory.itemLine': '- {name} × {quantity}', 'economy.leaderboard.empty': 'Noch keine Einträge auf der Bestenliste.', 'economy.leaderboard.line': '{rank}. {user} – {amount}', 'economy.admin.give': '{amount} an {user} vergeben. Neuer Kontostand: {balance}', 'economy.admin.remove': '{amount} von {user} entfernt. Neuer Kontostand: {balance}', 'economy.admin.reset': 'Economy-Daten von {user} zurückgesetzt.', 'economy.blackjack.title': 'Blackjack', 'economy.blackjack.hand': 'Einsatz: {bet}\n\n**Du:** {playerHand} ({playerTotal})\n**Dealer:** {dealerHand} ({dealerTotal})', 'economy.blackjack.button.hit': 'Hit', 'economy.blackjack.button.stand': 'Stand', 'economy.blackjack.outcome.win': 'Du gewinnst {bet}!', 'economy.blackjack.outcome.lose': 'Du verlierst deinen Einsatz.', 'economy.blackjack.outcome.push': 'Unentschieden – Einsatz zurück.', 'economy.blackjack.outcome.blackjack': 'Blackjack! Du gewinnst {bet}!', 'economy.blackjack.expired': 'Dieses Blackjack-Spiel ist abgelaufen oder existiert nicht mehr.', 'economy.blackjack.notOwner': 'Nur der Spieler kann diese Buttons nutzen.', 'utility.error.invalid_when': 'Ungültiger Zeitpunkt. Nutze z. B. 30m oder ein ISO-Datum in der Zukunft.', 'utility.error.invalid_datetime': 'Ungültiges Datum/Uhrzeit.', 'utility.error.invalid_poll_options': 'Es werden 2–5 Optionen benötigt (kommagetrennt).', 'utility.error.channel_not_found': 'Kanal nicht gefunden.', 'utility.error.role_not_found': 'Rolle nicht gefunden.', 'utility.error.poll_not_found': 'Umfrage nicht gefunden.', 'utility.error.reminder_channel_unavailable': 'Erinnerungskanal nicht erreichbar.', 'utility.poll.created': 'Umfrage erstellt.', 'utility.poll.closed': 'Diese Umfrage ist geschlossen.', 'utility.poll.notFound': 'Umfrage nicht gefunden.', 'utility.poll.invalidOption': 'Ungültige Option.', 'utility.poll.alreadyVoted': 'Du hast bereits abgestimmt.', 'utility.poll.voted': 'Stimme für **{option}** gezählt.', 'utility.poll.votes': 'Stimmen', 'utility.poll.endsAt': 'Endet {time}', 'utility.poll.multiSelect': 'Mehrfachauswahl', 'utility.poll.multiSelectHint': 'Du kannst mehrere Optionen wählen.', 'utility.remindme.created': 'Erinnerung erstellt (ID: `{id}`).', 'utility.reminders.none': 'Keine Erinnerungen.', 'utility.reminders.line': '`{id}` — {time}: {content}', 'utility.reminders.deleted': 'Erinnerung gelöscht.', 'utility.reminders.notFound': 'Erinnerung nicht gefunden.', 'utility.afk.set': 'AFK gesetzt. Grund: {reason}', 'utility.afk.welcomeBack': 'Willkommen zurück! Du warst AFK: {reason}', 'utility.afk.mention': '{user} ist AFK: {reason}', 'utility.avatar.title': 'Avatar von {user}', 'utility.banner.title': 'Banner von {user}', 'utility.banner.none': 'Kein Banner gesetzt.', 'utility.emoji.noSource': 'Anhang oder URL erforderlich.', 'utility.emoji.added': 'Emoji {emoji} hinzugefügt.', 'utility.emoji.removed': 'Emoji entfernt.', 'utility.emoji.notFound': 'Emoji nicht gefunden.', 'utility.emoji.messageNotFound': 'Nachricht nicht gefunden.', 'utility.emoji.noEmojiInMessage': 'Kein Custom-Emoji in der Nachricht.', 'utility.emoji.stolen': 'Emoji {emoji} gestohlen.', 'utility.sticker.noSource': 'Anhang oder URL erforderlich.', 'utility.sticker.added': 'Sticker **{name}** hinzugefügt.', 'utility.embed.sent': 'Embed gesendet.', 'utility.embed.invalidColor': 'Ungültige Farbe. Nutze z. B. 6366F1.', 'utility.snipe.none': 'Nichts zum Anzeigen.', 'utility.snipe.disabled': 'Snipe ist auf diesem Server deaktiviert (Datenschutz).', 'utility.snipe.privacy': 'Datenschutz: Snipe speichert gelöschte/bearbeitete Nachrichten kurzzeitig (1 h) in Redis.', 'utility.snipe.deletedAt': 'Gelöschte Nachricht von {user}', 'utility.snipe.editedAt': 'Bearbeitete Nachricht von {user}', 'utility.translate.noContent': 'Kein übersetzbare Textinhalt.', 'utility.translate.failed': 'Übersetzung fehlgeschlagen.', 'utility.translate.result': '**Übersetzung:** {text}', 'fun.8ball.result': '**Frage:** {question}\n**Antwort:** {answer}', 'fun.dice.result': 'Würfel ({sides} Seiten): {rolls}', 'fun.flip.result': 'Die Münze zeigt: **{result}**', 'fun.rps.win': 'Du wähltest **{player}**, ich **{bot}**. Du gewinnst!', 'fun.rps.lose': 'Du wähltest **{player}**, ich **{bot}**. Du verlierst!', 'fun.rps.draw': 'Beide wählten **{player}**. Unentschieden!', 'fun.rps.choice.rock': 'Stein', 'fun.rps.choice.paper': 'Papier', 'fun.rps.choice.scissors': 'Schere', 'fun.choose.result': 'Ich wähle: **{choice}**', 'fun.choose.tooFew': 'Gib mindestens zwei Optionen an (kommagetrennt).', 'fun.trivia.title': 'Trivia', 'fun.trivia.question': '**{question}**\n\n{options}', 'fun.trivia.footer': 'Nur {user} kann antworten.', 'fun.trivia.correct': '✅ Richtig!', 'fun.trivia.incorrect': '❌ Falsch!', 'fun.trivia.notOwner': 'Nur der Initiator kann diese Frage beantworten.', 'fun.tictactoe.title': 'Tic-Tac-Toe', 'fun.tictactoe.board': '❌: {x} | ⭕: {o}\n\n{board}', 'fun.tictactoe.challenge': '{challenger} fordert {opponent} zu Tic-Tac-Toe heraus!', 'fun.tictactoe.turn': 'Am Zug: {user}', 'fun.tictactoe.won': '{user} gewinnt!', 'fun.tictactoe.draw': 'Unentschieden!', 'fun.tictactoe.invalidMove': 'Ungültiger Zug.', 'fun.connect4.title': 'Connect 4', 'fun.connect4.board': '🔴: {red} | 🟡: {yellow}\n\n{board}', 'fun.connect4.challenge': '{challenger} fordert {opponent} zu Connect 4 heraus!', 'fun.connect4.turn': 'Am Zug: {user}', 'fun.connect4.won': '{user} gewinnt!', 'fun.connect4.draw': 'Unentschieden!', 'fun.connect4.invalidMove': 'Diese Spalte ist voll.', 'fun.hangman.title': 'Hangman', 'fun.hangman.progress': 'Wort: {word}\nFehler: {wrong}/{max}\nGeraten: {guessed}', 'fun.hangman.won': 'Gewonnen! Das Wort war **{word}**.', 'fun.hangman.lost': 'Verloren! Das Wort war **{word}**.', 'fun.common.notParticipant': 'Du bist nicht an diesem Spiel beteiligt.', 'fun.common.expired': 'Dieses Spiel ist abgelaufen oder existiert nicht mehr.', 'fun.common.selfChallenge': 'Du kannst dich nicht selbst herausfordern.', 'fun.common.botChallenge': 'Du kannst keinen Bot herausfordern.', 'fun.media.disabled': 'Medien-Commands sind auf diesem Server deaktiviert.', 'fun.media.fetchFailed': 'Bild konnte nicht geladen werden. Versuche es später erneut.', 'fun.cat.title': 'Random Cat', 'fun.dog.title': 'Random Dog', 'starboard.notConfigured': 'Starboard ist noch nicht konfiguriert. Nutze `/starboard setup`.', 'starboard.invalidChannel': 'Der Starboard-Kanal ist ungültig oder dem Bot fehlen Rechte (Ansehen, Senden, Embeds).', 'starboard.setupDone': 'Starboard konfiguriert und aktiviert.', 'starboard.noContent': '*Kein Textinhalt*', 'starboard.field.stars': 'Sterne', 'starboard.field.source': 'Quelle', 'starboard.jumpLink': 'Zur Nachricht', 'starboard.statusLine': 'Starboard aktiv → Kanal {channel}, Emoji {emoji}, Schwelle {threshold}, Self-Star: {selfStar}', 'starboard.selfStarOn': 'erlaubt', 'starboard.selfStarOff': 'verboten', 'suggestion.created': 'Vorschlag eingereicht (ID: `{id}`).', 'suggestion.setupDone': 'Vorschlagssystem konfiguriert.', 'suggestion.staffUpdated': 'Vorschlag aktualisiert ({status}).', 'suggestion.votedUp': 'Upvote gezählt.', 'suggestion.votedDown': 'Downvote gezählt.', 'suggestion.threadName': 'Diskussion #{id}', 'suggestion.error.not_configured': 'Vorschläge sind nicht konfiguriert. Nutze `/suggestion setup`.', 'suggestion.error.invalid_channel': 'Der konfigurierte Kanal ist ungültig.', 'suggestion.error.not_found': 'Vorschlag nicht gefunden.', 'suggestion.error.not_open': 'Dieser Vorschlag ist nicht mehr offen.', 'suggestion.error.already_voted': 'Du hast bereits so abgestimmt.', 'suggestion.embed.title': 'Vorschlag #{id}', 'suggestion.embed.status': 'Status', 'suggestion.embed.votes': 'Stimmen', 'suggestion.embed.author': 'Von {author}', 'suggestion.embed.staffReason': 'Team-Begründung', 'suggestion.status.open': 'Offen', 'suggestion.status.approved': 'Angenommen', 'suggestion.status.denied': 'Abgelehnt', 'suggestion.status.considered': 'In Prüfung', 'suggestion.status.implemented': 'Umgesetzt', 'suggestion.dm.statusUpdate': 'Dein Vorschlag wurde aktualisiert: **{status}**\nBegründung: {reason}', 'giveaway.embed.title': 'Giveaway', 'giveaway.embed.prize': 'Preis', 'giveaway.embed.winners': 'Gewinner', 'giveaway.embed.entrants': 'Teilnehmer', 'giveaway.embed.host': 'Host', 'giveaway.embed.requirements': 'Anforderungen', 'giveaway.embed.active': 'Klicke auf **Join**, um teilzunehmen!', 'giveaway.embed.paused': '⏸️ Dieses Giveaway ist pausiert.', 'giveaway.embed.ended': 'Beendet', 'giveaway.embed.endedWinners': 'Gewinner: {winners}', 'giveaway.embed.endedNoWinners': 'Keine gültigen Teilnehmer.', 'giveaway.embed.endsAt': 'Endet {time}', 'giveaway.button.join': 'Teilnehmen', 'giveaway.requirement.role': 'Rolle: {role}', 'giveaway.requirement.level': 'Mindest-Level: {level}', 'giveaway.requirement.memberDays': 'Server-Mitglied seit mindestens {days} Tagen', 'giveaway.started': 'Giveaway gestartet (ID: `{id}`).', 'giveaway.ended': 'Giveaway beendet.', 'giveaway.rerolled': 'Neue Gewinner: {winners}', 'giveaway.deleted': 'Giveaway gelöscht.', 'giveaway.paused': 'Giveaway pausiert.', 'giveaway.resumed': 'Giveaway fortgesetzt.', 'giveaway.joined': 'Du nimmst am Giveaway teil!', 'giveaway.list.header': '**Aktive Giveaways**', 'giveaway.list.empty': 'Keine aktiven Giveaways.', 'giveaway.list.entrants': 'Teilnehmer', 'giveaway.dm.won': 'Glückwunsch! Du hast **{prize}** auf **{guild}** gewonnen!', 'giveaway.error.not_found': 'Giveaway nicht gefunden oder bereits beendet.', 'giveaway.error.already_ended': 'Dieses Giveaway ist bereits beendet.', 'giveaway.error.not_ended': 'Giveaway ist noch nicht beendet.', 'giveaway.error.paused': 'Dieses Giveaway ist pausiert.', 'giveaway.error.already_joined': 'Du nimmst bereits teil.', 'giveaway.error.member_not_found': 'Mitglied nicht gefunden.', 'giveaway.error.missing_role': 'Dir fehlt die erforderliche Rolle.', 'giveaway.error.insufficient_level': 'Dein Level ist zu niedrig.', 'giveaway.error.insufficient_member_days': 'Du bist noch nicht lange genug auf dem Server.', 'giveaway.error.invalid_duration': 'Ungültige Dauer. Nutze z. B. 1h, 2d.', 'giveaway.error.duration_too_short': 'Die Dauer muss mindestens 1 Minute betragen.', 'giveaway.error.invalid_channel': 'Ungültiger Kanal.', 'ticket.panel.defaultDescription': 'Wähle eine Kategorie, um ein Ticket zu öffnen.', 'ticket.panel.created': 'Ticket-Panel erstellt.', 'ticket.category.created': 'Kategorie **{name}** erstellt.', 'ticket.created': 'Dein Ticket wurde erstellt: {channel}', 'ticket.opened': '{user} hat ein Ticket geöffnet.', 'ticket.subjectLine': 'Betreff: {subject}', 'ticket.claimed': '{user} hat dieses Ticket übernommen.', 'ticket.userAdded': '{user} wurde zum Ticket hinzugefügt.', 'ticket.userRemoved': '{user} wurde aus dem Ticket entfernt.', 'ticket.renamed': 'Ticket umbenannt in **{name}**.', 'ticket.prioritySet': 'Priorität gesetzt: **{priority}**', 'ticket.closed': 'Ticket geschlossen von {user}.', 'ticket.closedWithReason': 'Ticket geschlossen von {user}.\nGrund: {reason}', 'ticket.close.success': 'Ticket geschlossen.', 'ticket.claim.success': 'Ticket übernommen.', 'ticket.add.success': '{user} hinzugefügt.', 'ticket.remove.success': '{user} entfernt.', 'ticket.rename.success': 'Ticket umbenannt in **{name}**.', 'ticket.priority.success': 'Priorität: **{priority}**', 'ticket.transcriptDm': 'Hier ist dein Ticket-Transkript.', 'ticket.ratePrompt': 'Wie zufrieden warst du mit dem Support? (1–5)', 'ticket.rated': 'Danke für deine Bewertung: {rating}/5', 'ticket.autoCloseReason': 'Automatisch wegen Inaktivität geschlossen', 'ticket.modal.subject': 'Betreff', 'ticket.log.closed': 'Ticket geschlossen', 'ticket.log.opener': 'Ersteller', 'ticket.log.closedBy': 'Geschlossen von', 'ticket.priority.LOW': 'Niedrig', 'ticket.priority.NORMAL': 'Normal', 'ticket.priority.HIGH': 'Hoch', 'ticket.priority.URGENT': 'Dringend', 'ticket.error.disabled': 'Das Ticket-System ist deaktiviert.', 'ticket.error.category_not_found': 'Kategorie nicht gefunden.', 'ticket.error.no_categories': 'Keine Ticket-Kategorien vorhanden.', 'ticket.error.not_in_ticket': 'Dieser Befehl kann nur in einem Ticket-Kanal genutzt werden.', 'ticket.error.not_staff': 'Du hast keine Berechtigung für diese Ticket-Aktion.', 'ticket.error.already_open': 'Du hast bereits ein offenes Ticket.', 'ticket.error.closed': 'Dieses Ticket ist bereits geschlossen.', 'ticket.error.already_claimed': 'Du hast dieses Ticket bereits übernommen.', 'ticket.error.cannot_remove_opener': 'Der Ticket-Ersteller kann nicht entfernt werden.', 'ticket.error.no_channel': 'Ticket-Kanal nicht gefunden.', 'ticket.error.invalid_name': 'Ungültiger Name.', 'ticket.error.invalid_channel': 'Ungültiger Kanal.', 'ticket.error.no_parent_channel': 'Kein Elternkanal für Thread-Tickets konfiguriert.', 'ticket.error.invalid_parent_channel': 'Der konfigurierte Elternkanal ist ungültig.', 'ticket.error.not_found': 'Ticket nicht gefunden.', 'ticket.error.already_rated': 'Du hast dieses Ticket bereits bewertet.', 'birthdays.error.invalidDate': 'Ungültiges Datum. Prüfe Tag, Monat und optionales Jahr.', 'birthdays.error.invalidTimezone': 'Ungültige Zeitzone. Nutze z. B. Europe/Berlin.', 'birthdays.setup.done': 'Geburtstags-Modul konfiguriert.', 'birthdays.set.success': 'Geburtstag gespeichert: {day}.{month}.{year}', 'birthdays.remove.none': 'Du hast keinen Geburtstag eingetragen.', 'birthdays.remove.success': 'Dein Geburtstag wurde entfernt.', 'birthdays.list.empty': 'Noch keine Geburtstage eingetragen.', 'birthdays.list.header': '**Geburtstage (sortiert nach nächstem Datum):**', 'birthdays.next.header': '**Nächste Geburtstage:**', 'birthdays.list.line': '{rank}. {user} — {date} (in {days} T.)', 'stats.notConfigured': 'Server-Statistiken sind noch nicht eingerichtet. Nutze `/stats setup`.', 'stats.setup.done': 'Statistik-Kanäle konfiguriert und aktualisiert.', 'stats.refresh.done': 'Statistik-Kanäle wurden aktualisiert.', 'stats.error.invalidSetup': 'Ungültige Eingabe für die Statistik-Konfiguration.', 'invites.view.empty': '{user} hat noch keine Invite-Statistiken.', 'invites.view.result': '**Invite-Statistik für {user}**\nJoins: {joins} | Leaves: {leaves} | Fakes: {fakes} | Netto: {net}', 'invites.leaderboard.empty': 'Noch keine Invite-Daten vorhanden.', 'invites.leaderboard.header': '**Top Einlader:**', 'invites.leaderboard.line': '{rank}. {user} — Joins: {joins}, Leaves: {leaves}, Fakes: {fakes}, Netto: {net}', 'tempvoice.error.disabled': 'Temp-Voice ist auf diesem Server deaktiviert.', 'tempvoice.error.invalidCategory': 'Ungültige Kategorie.', 'tempvoice.error.notOwner': 'Du bist nicht der Besitzer dieses Temp-Voice-Kanals.', 'tempvoice.error.notInChannel': 'Du musst in einem Temp-Voice-Kanal sein.', 'tempvoice.error.notFound': 'Temp-Voice-Kanal nicht gefunden.', 'tempvoice.error.invalidName': 'Ungültiger Kanalname.', 'tempvoice.error.invalidLimit': 'Limit muss zwischen 0 und 99 liegen.', 'tempvoice.setup.done': 'Temp-Voice konfiguriert.', 'tempvoice.rename.success': 'Kanal umbenannt in **{name}**.', 'tempvoice.limit.success': 'Nutzerlimit auf **{limit}** gesetzt (0 = unbegrenzt).', 'tempvoice.lock.success': 'Kanal gesperrt (Connect für @everyone entfernt).', 'tempvoice.hide.success': 'Kanal versteckt (ViewChannel für @everyone entfernt).', 'tempvoice.kick.self': 'Du kannst dich nicht selbst kicken.', 'tempvoice.kick.notInChannel': 'Dieser Nutzer ist nicht in deinem Kanal.', 'tempvoice.kick.success': '{user} wurde aus dem Kanal entfernt.', 'tempvoice.transfer.self': 'Du kannst den Kanal nicht an dich selbst übertragen.', 'tempvoice.transfer.notInChannel': 'Der neue Besitzer muss in deinem Kanal sein.', 'tempvoice.transfer.success': 'Kanal an {user} übertragen.', 'tempvoice.claim.ownerPresent': 'Der Besitzer ist noch im Kanal.', 'tempvoice.claim.success': 'Du bist jetzt Besitzer dieses Kanals.', 'tempvoice.panel.title': 'Temp-Voice Steuerung', 'tempvoice.panel.description': 'Verwalte **{channel}** mit den Buttons oder `/voice`-Commands.', 'tempvoice.panel.sent': 'Control-Panel wurde in den Voice-Kanal-Chat gesendet.', 'tempvoice.button.rename': 'Umbenennen', 'tempvoice.button.limit': 'Limit', 'tempvoice.button.lock': 'Sperren', 'tempvoice.button.hide': 'Verstecken', 'tempvoice.button.kick': 'Kicken', 'tempvoice.button.transfer': 'Übertragen', 'tempvoice.button.claim': 'Übernehmen', 'selfroles.panel.defaultDescription': 'Wähle unten deine Rollen aus.', 'selfroles.panel.rolesField': 'Rollen', 'selfroles.panel.temporaryFooter': 'Rollen sind temporär und laufen automatisch ab.', 'selfroles.panel.created': 'Self-Role-Panel erstellt (ID: `{id}`).', 'selfroles.panel.updated': 'Self-Role-Panel aktualisiert (ID: `{id}`).', 'selfroles.panel.deleted': 'Self-Role-Panel gelöscht.', 'selfroles.role.added': 'Rolle hinzugefügt.', 'selfroles.role.removed': 'Rolle entfernt.', 'selfroles.role.verified': 'Rolle vergeben.', 'selfroles.role.unchanged': 'Du hast diese Rolle bereits.', 'selfroles.error.not_found': 'Self-Role-Panel nicht gefunden.', 'selfroles.error.invalid_roles': 'Ungültiges Rollen-Format. Nutze roleId:label:emoji.', 'selfroles.error.too_many_roles': 'Maximal 25 Rollen pro Panel.', 'selfroles.error.invalid_channel': 'Ungültiger Kanal.', 'selfroles.error.invalid_duration': 'Ungültige Dauer. Nutze z. B. 1h, 2d.', 'selfroles.error.duration_too_short': 'Die Dauer muss mindestens 1 Minute betragen.', 'selfroles.error.duration_required': 'Für temporäre Panels ist eine Dauer erforderlich.', 'selfroles.error.reaction_emoji_required': 'Reaktions-Modus erfordert Emojis für alle Rollen.', 'selfroles.error.member_not_found': 'Mitglied nicht gefunden.', 'selfroles.error.role_not_in_panel': 'Diese Rolle gehört nicht zu diesem Panel.', 'selfroles.error.role_not_found': 'Rolle nicht gefunden.', 'selfroles.error.role_hierarchy': 'Die Rolle liegt über der höchsten Bot-Rolle.', 'selfroles.error.role_managed': 'Integrierte Rollen können nicht vergeben werden.', 'selfroles.error.bot_missing_permissions': 'Dem Bot fehlt die Berechtigung Rollen zu verwalten.', 'tag.created': 'Tag `{name}` erstellt.', 'tag.updated': 'Tag `{name}` aktualisiert.', 'tag.deleted': 'Tag gelöscht.', 'tag.list.header': '**Tags**', 'tag.list.empty': 'Keine Tags vorhanden.', 'tag.list.uses': 'Aufrufe', 'tag.info.name': 'Name: `{name}`', 'tag.info.type': 'Typ: {type}', 'tag.info.uses': 'Aufrufe: {count}', 'tag.info.trigger': 'Trigger: `{word}`', 'tag.info.noTrigger': 'Kein Auto-Responder.', 'tag.info.roles': 'Rollen: {roles}', 'tag.info.allRoles': 'Rollen: alle', 'tag.info.channels': 'Kanäle: {channels}', 'tag.info.allChannels': 'Kanäle: alle', 'tag.error.not_found': 'Tag nicht gefunden.', 'tag.error.not_allowed': 'Du darfst diesen Tag hier nicht nutzen.', 'tag.error.invalid_name': 'Ungültiger Tag-Name (1–32 Zeichen, a-z, 0-9, _, -).', 'tag.error.content_required': 'Text-Tags benötigen Inhalt.', 'tag.error.embed_required': 'Embed-Tags benötigen Titel oder Beschreibung.', 'tag.error.premium_limit': 'Tag-Limit für diese Premium-Stufe erreicht.', 'tag.error.premium_feature': 'Tags sind für diese Premium-Stufe deaktiviert.', 'guildbackup.description': 'Server-Backups erstellen und wiederherstellen', 'guildbackup.created': 'Backup **{name}** erstellt (ID: `{id}`).', 'guildbackup.deleted': 'Backup `{id}` gelöscht.', 'guildbackup.list.header': '**Server-Backups**', 'guildbackup.list.empty': 'Keine Backups vorhanden.', 'guildbackup.list.line': '• `{id}` — **{name}** ({date})', 'guildbackup.info.id': 'ID: `{id}`', 'guildbackup.info.name': 'Name: **{name}**', 'guildbackup.info.created': 'Erstellt: {date}', 'guildbackup.info.createdBy': 'Erstellt von: <@{userId}>', 'guildbackup.info.roles': 'Rollen: {count}', 'guildbackup.info.channels': 'Kanäle: {count}', 'guildbackup.info.limitations': 'Hinweis: Backups enthalten keine Nachrichten. Beim Restore werden IDs nicht übernommen; fehlende Rollen/Kanäle werden nach Name ergänzt, bestehende nicht gelöscht.', 'guildbackup.confirm.delete': 'Backup `{id}` wirklich löschen?', 'guildbackup.confirm.restore.step1': 'Backup `{id}` wiederherstellen? Es werden fehlende Rollen/Kanäle ergänzt und Overwrites best-effort angewendet. Bestehende Kanäle werden **nicht** gelöscht.', 'guildbackup.confirm.restore.step2': '**Letzte Bestätigung:** Backup `{id}` jetzt wiederherstellen? Diese Aktion kann nicht rückgängig gemacht werden.', 'guildbackup.confirm.button.confirm': 'Bestätigen', 'guildbackup.confirm.button.cancel': 'Abbrechen', 'guildbackup.confirm.expired': 'Diese Bestätigung ist abgelaufen.', 'guildbackup.confirm.unauthorized': 'Nur der auslösende Nutzer kann das bestätigen.', 'guildbackup.confirm.cancelled': 'Abgebrochen.', 'guildbackup.restore.done': 'Backup `{id}` wiederhergestellt. Rollen: {rolesCreated} neu, {rolesSkipped} übersprungen. Kanäle: {channelsCreated} neu, {channelsUpdated} aktualisiert. Overwrites: {overwritesApplied}.', 'guildbackup.restore.queued': 'Großes Backup `{id}` — Restore wurde in die Warteschlange gestellt und läuft im Hintergrund.', 'guildbackup.error.not_found': 'Backup nicht gefunden.', 'guildbackup.error.invalid_payload': 'Backup-Daten sind ungültig oder veraltet.', 'guildbackup.error.invalid_name': 'Ungültiger Backup-Name (1–100 Zeichen).', 'guildbackup.error.owner_only': 'Nur der Server-Owner kann Backups wiederherstellen.', 'guildbackup.error.bot_missing_permissions': 'Dem Bot fehlen Manage Roles oder Manage Channels für einen Restore.', 'guildbackup.error.premium_limit': 'Backup-Limit für diese Premium-Stufe erreicht.', 'guildbackup.error.premium_feature': 'Backups sind für diese Premium-Stufe deaktiviert.', 'feeds.added': 'Feed `{id}` ({type}) hinzugefügt.', 'feeds.removed': 'Feed `{id}` entfernt.', 'feeds.list.header': '**Social Feeds**', 'feeds.list.empty': 'Keine Feeds konfiguriert.', 'feeds.list.line': '`{id}` — {type}: {source} → {channel}', 'feeds.test.posted': 'Test erfolgreich: {count} Nachricht(en) gesendet.', 'feeds.test.noItems': 'Keine neuen Einträge gefunden.', 'feeds.test.failed': 'Abruf fehlgeschlagen: {reason}', 'feeds.test.skipped': 'Feed-Test übersprungen.', 'feeds.test.twitchSkipped': 'Twitch-Feed übersprungen: TWITCH_CLIENT_ID und TWITCH_CLIENT_SECRET fehlen in der Bot-Konfiguration.', 'feeds.error.not_found': 'Feed nicht gefunden.', 'feeds.error.premium_limit': 'Feed-Limit für diese Premium-Stufe erreicht.', 'feeds.error.premium_feature': 'Feeds sind für diese Premium-Stufe deaktiviert.', 'scheduler.created': 'Geplante Nachricht erstellt (ID: `{id}`). {timing}', 'scheduler.created.at': 'Sendung: {time}', 'scheduler.created.cron': 'Wiederholung: `{cron}`', 'scheduler.deleted': 'Geplante Nachricht gelöscht.', 'scheduler.announce.sent': 'Ankündigung gesendet.', 'scheduler.list.header': '**Geplante Nachrichten**', 'scheduler.list.empty': 'Keine geplanten Nachrichten.', 'scheduler.list.line': '`{id}` — {channel} — {timing} — {preview}', 'scheduler.list.cron': 'Cron `{cron}`', 'scheduler.list.embedPreview': '[Embed]', 'scheduler.list.componentsPreview': '[Components V2]', 'scheduler.error.missing_schedule_time': 'Gib `when` oder `cron` an.', 'scheduler.error.invalid_when': 'Ungültige Zeit. Nutze z. B. 1h, 2d oder ein ISO-Datum.', 'scheduler.error.invalid_cron': 'Ungültiger Cron-Ausdruck (5–6 Felder).', 'scheduler.error.invalid_channel': 'Ungültiger Kanal.', 'scheduler.error.channel_unavailable': 'Der Bot kann in diesem Kanal nicht senden.', 'scheduler.error.not_found': 'Geplante Nachricht nicht gefunden.', 'scheduler.error.content_required': 'Inhalt oder Embed-Titel/Beschreibung erforderlich.', 'componentsV2.error.notFound': 'Diese Komponenten-Nachricht ist nicht mehr verfügbar.', 'componentsV2.error.actionMissing': 'Für diese Interaktion ist keine Aktion konfiguriert.', 'componentsV2.error.botMissingManageRoles': 'Dem Bot fehlt die Berechtigung Rollen zu verwalten.', 'componentsV2.error.roleNotFound': 'Rolle nicht gefunden.', 'componentsV2.error.roleManaged': 'Integrierte Rollen können nicht vergeben werden.', 'componentsV2.error.roleHierarchy': 'Die Rolle liegt über der höchsten Bot-Rolle.', 'componentsV2.error.noRolesSelected': 'Keine Rollen ausgewählt.', 'componentsV2.role.assigned': 'Rolle vergeben.', 'componentsV2.role.removed': 'Rolle entfernt.', 'componentsV2.role.assignedSelected': 'Ausgewählte Rollen vergeben.', 'utility.embed.components.sent': 'Components-V2-Nachricht gesendet.', 'utility.embed.components.dashboardHint': 'Für den vollen Builder inkl. Interaktionen: {url}', 'utility.embed.components.missingText': 'Text ist erforderlich.', 'tag.error.components_required': 'Components-V2-Tags benötigen Komponenten.' }; const en: Dictionary = { 'generic.noPermission': 'You do not have permission for this action.', 'generic.guildOnly': 'This command can only be used in a server.', 'generic.botMissingPermission': 'Bot lacks required permission ({permission}).', 'generic.invalidRegex': 'Invalid regex pattern.', 'generic.error': 'An error occurred.', 'generic.maintenance': 'Nexumi is currently in maintenance mode. Please try again later.', 'generic.unknownCommand': 'Unknown command.', 'generic.commandDisabled': 'This command is disabled on this server.', 'generic.commandChannelBlocked': 'This command is not allowed in this channel.', 'generic.commandRoleBlocked': 'You are not allowed to use this command with your roles.', 'generic.commandCooldown': 'Please wait {seconds} more seconds before using this command again.', 'generic.moduleDisabled': 'This module is disabled on this server.', 'generic.userBlacklisted': 'You are not allowed to use Nexumi right now.', 'generic.guildBlacklisted': 'This server is not allowed to use Nexumi right now.', 'core.help.title': 'Nexumi Help', 'core.help.subtitle': 'Commands by module. Optional: `/help module:`.', 'core.help.moduleLine': '**{module}**: {commands}', 'core.help.unknownModule': 'Unknown module. Available: {modules}', 'core.help.footer': 'More: /info · Dashboard: {webui}', 'core.info.title': 'Nexumi', 'core.info.version': 'Version', 'core.info.uptime': 'Uptime', 'core.info.shard': 'Shard', 'core.info.guilds': 'Servers (this shard)', 'core.info.latency': 'API latency', 'core.info.links': 'Links', 'core.info.link.dashboard': 'Dashboard', 'core.info.link.invite': 'Invite', 'core.info.link.support': 'Support', 'core.info.link.status': 'Status', 'core.invite.title': 'Invite Nexumi', 'core.invite.body': 'Invite Nexumi to your server with this link:', 'core.support.title': 'Support', 'core.support.body': 'Join our support server:', 'core.support.missing': 'No support server configured. Set SUPPORT_SERVER_URL.', 'core.module.core': 'Core', 'core.module.moderation': 'Moderation', 'core.module.automod': 'Auto-Moderation', 'core.module.welcome': 'Welcome', 'core.module.verification': 'Verification', 'core.module.leveling': 'Leveling', 'core.module.economy': 'Economy', 'core.module.utility': 'Utility', 'core.module.fun': 'Fun', 'core.module.giveaways': 'Giveaways', 'core.module.tickets': 'Tickets', 'core.module.selfroles': 'Self-Roles', 'core.module.tags': 'Tags', 'core.module.starboard': 'Starboard', 'core.module.suggestions': 'Suggestions', 'core.module.birthdays': 'Birthdays', 'core.module.tempvoice': 'Temp Voice', 'core.module.stats': 'Stats', 'core.module.feeds': 'Feeds', 'core.module.scheduler': 'Scheduler', 'core.module.guildbackup': 'Backup', 'gdpr.privacy.title': 'Privacy', 'gdpr.privacy.body': 'Nexumi stores Discord IDs and module-related data (e.g. warnings, XP, economy) as needed to operate.', 'gdpr.privacy.link': 'Full privacy policy: {url}', 'gdpr.privacy.deleteHint': 'Delete personal data: `/gdpr delete confirm:true`', 'gdpr.delete.needConfirm': 'Set `confirm` to `true` to confirm deletion.', 'gdpr.delete.doneTitle': 'Data deleted', 'gdpr.delete.doneBody': 'Deleted/anonymized: {warnings} warnings, {levels} level rows, {economy} economy rows, {cases} cases anonymized.', 'moderation.success': 'Action executed successfully.', 'moderation.success.case': 'Action executed successfully (case #{caseNumber}).', 'moderation.duration.invalid': 'Invalid duration. Use e.g. 30m, 12h, or 7d.', 'moderation.duration.invalidTimeout': 'Invalid timeout duration. Use e.g. 30m or 1d (max 28 days).', 'moderation.hierarchy.self': 'You cannot apply this action to yourself.', 'moderation.hierarchy.owner': 'The server owner cannot be moderated.', 'moderation.hierarchy.moderator': 'You cannot moderate members with equal or higher roles.', 'moderation.hierarchy.bot': 'The bot cannot moderate this member due to role hierarchy or missing permissions.', 'moderation.hierarchy.notMember': 'That member is not on this server.', 'moderation.reason.none': 'No reason provided', 'moderation.warning.created': 'Warning created: {warningId}', 'moderation.warning.none': 'No warnings.', 'moderation.warning.defaultReason': 'No reason', 'moderation.warning.notFound': 'Warning not found.', 'moderation.purge.done': 'Deleted {deletedCount} messages (case #{caseNumber}).', 'moderation.note.none': 'No notes.', 'moderation.case.notFound': 'Case not found.', 'moderation.escalation.durationRequired': 'Duration is required for TIMEOUT escalation.', 'moderation.escalation.noneConfigured': 'No escalation rules configured.', 'moderation.escalation.saved': 'Escalation rule saved: {warnCount} warnings => {action}{duration}.', 'moderation.escalation.removed': 'Escalation rule removed for {warnCount} warnings.', 'moderation.escalation.defaultReason': 'Auto escalation at {warnCount} warnings', 'moderation.escalation.skippedDuration': 'Escalation rule for {warnCount} warns skipped (missing duration).', 'moderation.escalation.skippedPermission': 'Escalation rule for {warnCount} warns skipped (missing bot permissions).', 'moderation.escalation.appliedTimeout': 'Auto escalation applied: timeout ({durationMs} ms).', 'moderation.escalation.appliedKick': 'Auto escalation applied: kick.', 'moderation.escalation.appliedBan': 'Auto escalation applied: ban.', 'moderation.confirm.button.confirm': 'Confirm', 'moderation.confirm.button.cancel': 'Cancel', 'moderation.confirm.permanent': 'permanent', 'moderation.confirm.ban': 'Confirm ban for <@{userId}>?\nReason: {reason}\nDuration: {duration}', 'moderation.confirm.purge': 'Delete {amount} messages? This action cannot be undone.', 'moderation.confirm.caseDelete': 'Really delete case #{caseNumber}?', 'moderation.confirm.expired': 'Confirmation expired. Please run the command again.', 'moderation.confirm.cancelled': 'Action cancelled.', 'moderation.confirm.unauthorized': 'Only the moderator who started this action can confirm it.', 'automod.status.header': '**AutoMod enabled:** {enabled}\n**Anti-raid:** {antiRaid}\n**Anti-nuke:** {antiNuke}\n**Lockdown:** {lockdown}', 'automod.status.ruleLine': '- {type} → {action}', 'automod.status.noRules': 'No active rules.', 'automod.status.yes': 'yes', 'automod.status.no': 'no', 'welcome.notConfigured': 'Welcome message is not configured yet.', 'welcome.invalidChannel': 'The configured welcome channel is invalid.', 'welcome.testSent': 'Test welcome message sent.', 'verification.disabled': 'Verification is disabled.', 'verification.success': 'You have been verified successfully.', 'verification.setupDone': 'Verification configured.', 'verification.notConfigured': 'Verification is not set up yet. Use `/verify setup`.', 'verification.invalidChannel': 'The verification channel is invalid.', 'verification.panelPosted': 'Verification panel posted.', 'verification.panelMissingPermission': 'The bot lacks permissions in that channel (View Channel, Send Messages, Embed Links).', 'verification.panel.title': 'Verification', 'verification.panel.description': 'Click the button below to verify and gain access to the server.', 'verification.panel.button': 'Verify', 'verification.panel.buttonCaptcha': 'Verify (Captcha)', 'verification.captchaLink': 'Open this link to complete captcha verification: {url}', 'verification.error.not_configured': 'Verification is not configured.', 'verification.error.member_not_found': 'Member not found.', 'verification.error.account_too_young': 'Your account is too young to verify.', 'verification.error.missing_permissions': 'Bot lacks permissions.', 'verification.error.invalid_role': 'Verification role is invalid.', 'verification.error.alt_detected': 'Verification denied: possible alternate account detected.', 'verification.error.generic': 'Verification failed.', 'verification.captcha.success': 'Captcha passed. You have been verified.', 'verification.captcha.invalid': 'Captcha invalid or expired.', 'verification.captcha.title': 'Nexumi Verification', 'leveling.disabled': 'Leveling is disabled on this server.', 'leveling.rank.title': 'Rank card', 'leveling.leaderboard.title': 'Leaderboard', 'leveling.leaderboard.empty': 'No XP data yet.', 'leveling.leaderboard.entry': '{rank}. {user} — Level {level} ({xp} XP)', 'leveling.leaderboard.footer': 'Top {count} members', 'leveling.levelUp.default': 'Congratulations {user}, you reached level {level}!', 'leveling.xp.give.success': 'Gave {amount} XP to {user}. New level: {level}.', 'leveling.xp.remove.success': 'Removed {amount} XP from {user}. New level: {level}.', 'leveling.xp.reset.success': 'Reset XP for {user}.', 'leveling.xp.invalidAmount': 'Amount must be greater than 0.', 'leveling.user.notFound': 'User not found on this server.', 'economy.error.disabled': 'The economy module is disabled on this server.', 'economy.error.insufficient': 'You do not have enough money.', 'economy.error.cooldown': 'Cooldown active. Try again in {seconds} seconds.', 'economy.error.invalid_amount': 'Invalid amount.', 'economy.error.self_transfer': 'You cannot send money to yourself.', 'economy.error.not_found': 'Entry not found.', 'economy.error.out_of_stock': 'This item is out of stock.', 'economy.error.role_assign_failed': 'Purchase succeeded, but the role could not be assigned.', 'economy.error.game_in_progress': 'You already have an active blackjack game.', 'economy.balance.result': 'Balance of {user}: {amount}', 'economy.daily.success': 'Daily reward: {amount}. New balance: {balance}', 'economy.weekly.success': 'Weekly reward: {amount}. New balance: {balance}', 'economy.work.success': 'You earned {amount}. New balance: {balance}', 'economy.pay.success': 'You sent {amount} to {user}. Your balance: {balance}', 'economy.gamble.win': 'You won! +{amount}. Balance: {balance}', 'economy.gamble.lose': 'You lost! -{amount}. Balance: {balance}', 'economy.slots.win': '{reels}\nWinnings: {payout}. Balance: {balance}', 'economy.slots.lose': '{reels}\nNo win. Balance: {balance}', 'economy.coinflip.win': '{result} – you picked {choice}. You won! +{amount}. Balance: {balance}', 'economy.coinflip.lose': '{result} – you picked {choice}. You lost! -{amount}. Balance: {balance}', 'economy.choice.heads': 'Heads', 'economy.choice.tails': 'Tails', 'economy.shop.empty': 'The shop is empty.', 'economy.shop.noDescription': 'No description', 'economy.shop.itemLine': '**{name}** (`{id}`) – {price} | Stock: {stock}\n{description}', 'economy.shop.purchased': 'You purchased **{name}**. Balance: {balance}', 'economy.inventory.empty': 'Your inventory is empty.', 'economy.inventory.itemLine': '- {name} × {quantity}', 'economy.leaderboard.empty': 'No leaderboard entries yet.', 'economy.leaderboard.line': '{rank}. {user} – {amount}', 'economy.admin.give': 'Gave {amount} to {user}. New balance: {balance}', 'economy.admin.remove': 'Removed {amount} from {user}. New balance: {balance}', 'economy.admin.reset': 'Reset economy data for {user}.', 'economy.blackjack.title': 'Blackjack', 'economy.blackjack.hand': 'Bet: {bet}\n\n**You:** {playerHand} ({playerTotal})\n**Dealer:** {dealerHand} ({dealerTotal})', 'economy.blackjack.button.hit': 'Hit', 'economy.blackjack.button.stand': 'Stand', 'economy.blackjack.outcome.win': 'You win {bet}!', 'economy.blackjack.outcome.lose': 'You lose your bet.', 'economy.blackjack.outcome.push': 'Push – bet returned.', 'economy.blackjack.outcome.blackjack': 'Blackjack! You win {bet}!', 'economy.blackjack.expired': 'This blackjack game expired or no longer exists.', 'economy.blackjack.notOwner': 'Only the player can use these buttons.', 'utility.error.invalid_when': 'Invalid time. Use e.g. 30m or a future ISO datetime.', 'utility.error.invalid_datetime': 'Invalid date/time.', 'utility.error.invalid_poll_options': 'Provide 2–5 comma-separated options.', 'utility.error.channel_not_found': 'Channel not found.', 'utility.error.role_not_found': 'Role not found.', 'utility.error.poll_not_found': 'Poll not found.', 'utility.error.reminder_channel_unavailable': 'Reminder channel unavailable.', 'utility.poll.created': 'Poll created.', 'utility.poll.closed': 'This poll is closed.', 'utility.poll.notFound': 'Poll not found.', 'utility.poll.invalidOption': 'Invalid option.', 'utility.poll.alreadyVoted': 'You already voted.', 'utility.poll.voted': 'Vote counted for **{option}**.', 'utility.poll.votes': 'votes', 'utility.poll.endsAt': 'Ends {time}', 'utility.poll.multiSelect': 'Multi-select', 'utility.poll.multiSelectHint': 'You may select multiple options.', 'utility.remindme.created': 'Reminder created (ID: `{id}`).', 'utility.reminders.none': 'No reminders.', 'utility.reminders.line': '`{id}` — {time}: {content}', 'utility.reminders.deleted': 'Reminder deleted.', 'utility.reminders.notFound': 'Reminder not found.', 'utility.afk.set': 'AFK set. Reason: {reason}', 'utility.afk.welcomeBack': 'Welcome back! You were AFK: {reason}', 'utility.afk.mention': '{user} is AFK: {reason}', 'utility.avatar.title': 'Avatar of {user}', 'utility.banner.title': 'Banner of {user}', 'utility.banner.none': 'No banner set.', 'utility.emoji.noSource': 'Attachment or URL required.', 'utility.emoji.added': 'Added emoji {emoji}.', 'utility.emoji.removed': 'Emoji removed.', 'utility.emoji.notFound': 'Emoji not found.', 'utility.emoji.messageNotFound': 'Message not found.', 'utility.emoji.noEmojiInMessage': 'No custom emoji in message.', 'utility.emoji.stolen': 'Stole emoji {emoji}.', 'utility.sticker.noSource': 'Attachment or URL required.', 'utility.sticker.added': 'Added sticker **{name}**.', 'utility.embed.sent': 'Embed sent.', 'utility.embed.invalidColor': 'Invalid color. Use e.g. 6366F1.', 'utility.snipe.none': 'Nothing to show.', 'utility.snipe.disabled': 'Snipe is disabled on this server (privacy).', 'utility.snipe.privacy': 'Privacy: Snipe stores deleted/edited messages briefly (1 h) in Redis.', 'utility.snipe.deletedAt': 'Deleted message by {user}', 'utility.snipe.editedAt': 'Edited message by {user}', 'utility.translate.noContent': 'No translatable text content.', 'utility.translate.failed': 'Translation failed.', 'utility.translate.result': '**Translation:** {text}', 'fun.8ball.result': '**Question:** {question}\n**Answer:** {answer}', 'fun.dice.result': 'Dice ({sides} sides): {rolls}', 'fun.flip.result': 'The coin shows: **{result}**', 'fun.rps.win': 'You picked **{player}**, I picked **{bot}**. You win!', 'fun.rps.lose': 'You picked **{player}**, I picked **{bot}**. You lose!', 'fun.rps.draw': 'Both picked **{player}**. Draw!', 'fun.rps.choice.rock': 'Rock', 'fun.rps.choice.paper': 'Paper', 'fun.rps.choice.scissors': 'Scissors', 'fun.choose.result': 'I choose: **{choice}**', 'fun.choose.tooFew': 'Provide at least two comma-separated options.', 'fun.trivia.title': 'Trivia', 'fun.trivia.question': '**{question}**\n\n{options}', 'fun.trivia.footer': 'Only {user} can answer.', 'fun.trivia.correct': '✅ Correct!', 'fun.trivia.incorrect': '❌ Wrong!', 'fun.trivia.notOwner': 'Only the initiator can answer this question.', 'fun.tictactoe.title': 'Tic-Tac-Toe', 'fun.tictactoe.board': '❌: {x} | ⭕: {o}\n\n{board}', 'fun.tictactoe.challenge': '{challenger} challenges {opponent} to Tic-Tac-Toe!', 'fun.tictactoe.turn': 'Turn: {user}', 'fun.tictactoe.won': '{user} wins!', 'fun.tictactoe.draw': 'Draw!', 'fun.tictactoe.invalidMove': 'Invalid move.', 'fun.connect4.title': 'Connect 4', 'fun.connect4.board': '🔴: {red} | 🟡: {yellow}\n\n{board}', 'fun.connect4.challenge': '{challenger} challenges {opponent} to Connect 4!', 'fun.connect4.turn': 'Turn: {user}', 'fun.connect4.won': '{user} wins!', 'fun.connect4.draw': 'Draw!', 'fun.connect4.invalidMove': 'This column is full.', 'fun.hangman.title': 'Hangman', 'fun.hangman.progress': 'Word: {word}\nWrong: {wrong}/{max}\nGuessed: {guessed}', 'fun.hangman.won': 'You won! The word was **{word}**.', 'fun.hangman.lost': 'You lost! The word was **{word}**.', 'fun.common.notParticipant': 'You are not a participant in this game.', 'fun.common.expired': 'This game expired or no longer exists.', 'fun.common.selfChallenge': 'You cannot challenge yourself.', 'fun.common.botChallenge': 'You cannot challenge a bot.', 'fun.media.disabled': 'Media commands are disabled on this server.', 'fun.media.fetchFailed': 'Could not load image. Try again later.', 'fun.cat.title': 'Random Cat', 'fun.dog.title': 'Random Dog', 'starboard.notConfigured': 'Starboard is not configured yet. Use `/starboard setup`.', 'starboard.invalidChannel': 'The starboard channel is invalid or the bot lacks permissions (View, Send, Embed Links).', 'starboard.setupDone': 'Starboard configured and enabled.', 'starboard.noContent': '*No text content*', 'starboard.field.stars': 'Stars', 'starboard.field.source': 'Source', 'starboard.jumpLink': 'Jump to message', 'starboard.statusLine': 'Starboard active → channel {channel}, emoji {emoji}, threshold {threshold}, self-star: {selfStar}', 'starboard.selfStarOn': 'allowed', 'starboard.selfStarOff': 'denied', 'suggestion.created': 'Suggestion submitted (ID: `{id}`).', 'suggestion.setupDone': 'Suggestion system configured.', 'suggestion.staffUpdated': 'Suggestion updated ({status}).', 'suggestion.votedUp': 'Upvote recorded.', 'suggestion.votedDown': 'Downvote recorded.', 'suggestion.threadName': 'Discussion #{id}', 'suggestion.error.not_configured': 'Suggestions are not configured. Use `/suggestion setup`.', 'suggestion.error.invalid_channel': 'The configured channel is invalid.', 'suggestion.error.not_found': 'Suggestion not found.', 'suggestion.error.not_open': 'This suggestion is no longer open.', 'suggestion.error.already_voted': 'You already voted this way.', 'suggestion.embed.title': 'Suggestion #{id}', 'suggestion.embed.status': 'Status', 'suggestion.embed.votes': 'Votes', 'suggestion.embed.author': 'By {author}', 'suggestion.embed.staffReason': 'Staff reason', 'suggestion.status.open': 'Open', 'suggestion.status.approved': 'Approved', 'suggestion.status.denied': 'Denied', 'suggestion.status.considered': 'Under consideration', 'suggestion.status.implemented': 'Implemented', 'suggestion.dm.statusUpdate': 'Your suggestion was updated: **{status}**\nReason: {reason}', 'giveaway.embed.title': 'Giveaway', 'giveaway.embed.prize': 'Prize', 'giveaway.embed.winners': 'Winners', 'giveaway.embed.entrants': 'Entrants', 'giveaway.embed.host': 'Host', 'giveaway.embed.requirements': 'Requirements', 'giveaway.embed.active': 'Click **Join** to enter!', 'giveaway.embed.paused': '⏸️ This giveaway is paused.', 'giveaway.embed.ended': 'Ended', 'giveaway.embed.endedWinners': 'Winners: {winners}', 'giveaway.embed.endedNoWinners': 'No valid entrants.', 'giveaway.embed.endsAt': 'Ends {time}', 'giveaway.button.join': 'Join', 'giveaway.requirement.role': 'Role: {role}', 'giveaway.requirement.level': 'Minimum level: {level}', 'giveaway.requirement.memberDays': 'Member for at least {days} days', 'giveaway.started': 'Giveaway started (ID: `{id}`).', 'giveaway.ended': 'Giveaway ended.', 'giveaway.rerolled': 'New winners: {winners}', 'giveaway.deleted': 'Giveaway deleted.', 'giveaway.paused': 'Giveaway paused.', 'giveaway.resumed': 'Giveaway resumed.', 'giveaway.joined': 'You entered the giveaway!', 'giveaway.list.header': '**Active giveaways**', 'giveaway.list.empty': 'No active giveaways.', 'giveaway.list.entrants': 'entrants', 'giveaway.dm.won': 'Congratulations! You won **{prize}** on **{guild}**!', 'giveaway.error.not_found': 'Giveaway not found or already ended.', 'giveaway.error.already_ended': 'This giveaway has already ended.', 'giveaway.error.not_ended': 'Giveaway has not ended yet.', 'giveaway.error.paused': 'This giveaway is paused.', 'giveaway.error.already_joined': 'You already entered.', 'giveaway.error.member_not_found': 'Member not found.', 'giveaway.error.missing_role': 'You are missing the required role.', 'giveaway.error.insufficient_level': 'Your level is too low.', 'giveaway.error.insufficient_member_days': 'You have not been on the server long enough.', 'giveaway.error.invalid_duration': 'Invalid duration. Use e.g. 1h, 2d.', 'giveaway.error.duration_too_short': 'Duration must be at least 1 minute.', 'giveaway.error.invalid_channel': 'Invalid channel.', 'ticket.panel.defaultDescription': 'Select a category to open a ticket.', 'ticket.panel.created': 'Ticket panel created.', 'ticket.category.created': 'Category **{name}** created.', 'ticket.created': 'Your ticket was created: {channel}', 'ticket.opened': '{user} opened a ticket.', 'ticket.subjectLine': 'Subject: {subject}', 'ticket.claimed': '{user} claimed this ticket.', 'ticket.userAdded': '{user} was added to the ticket.', 'ticket.userRemoved': '{user} was removed from the ticket.', 'ticket.renamed': 'Ticket renamed to **{name}**.', 'ticket.prioritySet': 'Priority set to **{priority}**', 'ticket.closed': 'Ticket closed by {user}.', 'ticket.closedWithReason': 'Ticket closed by {user}.\nReason: {reason}', 'ticket.close.success': 'Ticket closed.', 'ticket.claim.success': 'Ticket claimed.', 'ticket.add.success': 'Added {user}.', 'ticket.remove.success': 'Removed {user}.', 'ticket.rename.success': 'Ticket renamed to **{name}**.', 'ticket.priority.success': 'Priority: **{priority}**', 'ticket.transcriptDm': 'Here is your ticket transcript.', 'ticket.ratePrompt': 'How satisfied were you with support? (1–5)', 'ticket.rated': 'Thanks for your rating: {rating}/5', 'ticket.autoCloseReason': 'Auto-closed due to inactivity', 'ticket.modal.subject': 'Subject', 'ticket.log.closed': 'Ticket closed', 'ticket.log.opener': 'Opener', 'ticket.log.closedBy': 'Closed by', 'ticket.priority.LOW': 'Low', 'ticket.priority.NORMAL': 'Normal', 'ticket.priority.HIGH': 'High', 'ticket.priority.URGENT': 'Urgent', 'ticket.error.disabled': 'The ticket system is disabled.', 'ticket.error.category_not_found': 'Category not found.', 'ticket.error.no_categories': 'No ticket categories configured.', 'ticket.error.not_in_ticket': 'This command can only be used inside a ticket channel.', 'ticket.error.not_staff': 'You do not have permission for this ticket action.', 'ticket.error.already_open': 'You already have an open ticket.', 'ticket.error.closed': 'This ticket is already closed.', 'ticket.error.already_claimed': 'You already claimed this ticket.', 'ticket.error.cannot_remove_opener': 'The ticket opener cannot be removed.', 'ticket.error.no_channel': 'Ticket channel not found.', 'ticket.error.invalid_name': 'Invalid name.', 'ticket.error.invalid_channel': 'Invalid channel.', 'ticket.error.no_parent_channel': 'No parent channel configured for thread tickets.', 'ticket.error.invalid_parent_channel': 'The configured parent channel is invalid.', 'ticket.error.not_found': 'Ticket not found.', 'ticket.error.already_rated': 'You already rated this ticket.', 'birthdays.error.invalidDate': 'Invalid date. Check day, month, and optional year.', 'birthdays.error.invalidTimezone': 'Invalid timezone. Use e.g. Europe/Berlin.', 'birthdays.setup.done': 'Birthday module configured.', 'birthdays.set.success': 'Birthday saved: {day}/{month}/{year}', 'birthdays.remove.none': 'You have not set a birthday.', 'birthdays.remove.success': 'Your birthday was removed.', 'birthdays.list.empty': 'No birthdays registered yet.', 'birthdays.list.header': '**Birthdays (sorted by next date):**', 'birthdays.next.header': '**Upcoming birthdays:**', 'birthdays.list.line': '{rank}. {user} — {date} (in {days} d)', 'stats.notConfigured': 'Server statistics are not configured yet. Use `/stats setup`.', 'stats.setup.done': 'Stats channels configured and updated.', 'stats.refresh.done': 'Stats channels have been refreshed.', 'stats.error.invalidSetup': 'Invalid input for stats configuration.', 'invites.view.empty': '{user} has no invite statistics yet.', 'invites.view.result': '**Invite stats for {user}**\nJoins: {joins} | Leaves: {leaves} | Fakes: {fakes} | Net: {net}', 'invites.leaderboard.empty': 'No invite data available yet.', 'invites.leaderboard.header': '**Top inviters:**', 'invites.leaderboard.line': '{rank}. {user} — Joins: {joins}, Leaves: {leaves}, Fakes: {fakes}, Net: {net}', 'tempvoice.error.disabled': 'Temp voice is disabled on this server.', 'tempvoice.error.invalidCategory': 'Invalid category.', 'tempvoice.error.notOwner': 'You are not the owner of this temp voice channel.', 'tempvoice.error.notInChannel': 'You must be in a temp voice channel.', 'tempvoice.error.notFound': 'Temp voice channel not found.', 'tempvoice.error.invalidName': 'Invalid channel name.', 'tempvoice.error.invalidLimit': 'Limit must be between 0 and 99.', 'tempvoice.setup.done': 'Temp voice configured.', 'tempvoice.rename.success': 'Channel renamed to **{name}**.', 'tempvoice.limit.success': 'User limit set to **{limit}** (0 = unlimited).', 'tempvoice.lock.success': 'Channel locked (Connect denied for @everyone).', 'tempvoice.hide.success': 'Channel hidden (ViewChannel denied for @everyone).', 'tempvoice.kick.self': 'You cannot kick yourself.', 'tempvoice.kick.notInChannel': 'That user is not in your channel.', 'tempvoice.kick.success': 'Removed {user} from the channel.', 'tempvoice.transfer.self': 'You cannot transfer the channel to yourself.', 'tempvoice.transfer.notInChannel': 'The new owner must be in your channel.', 'tempvoice.transfer.success': 'Channel transferred to {user}.', 'tempvoice.claim.ownerPresent': 'The owner is still in the channel.', 'tempvoice.claim.success': 'You are now the owner of this channel.', 'tempvoice.panel.title': 'Temp Voice Control', 'tempvoice.panel.description': 'Manage **{channel}** with the buttons below or `/voice` commands.', 'tempvoice.panel.sent': 'Control panel posted in the voice channel chat.', 'tempvoice.button.rename': 'Rename', 'tempvoice.button.limit': 'Limit', 'tempvoice.button.lock': 'Lock', 'tempvoice.button.hide': 'Hide', 'tempvoice.button.kick': 'Kick', 'tempvoice.button.transfer': 'Transfer', 'tempvoice.button.claim': 'Claim', 'selfroles.panel.defaultDescription': 'Choose your roles below.', 'selfroles.panel.rolesField': 'Roles', 'selfroles.panel.temporaryFooter': 'Roles are temporary and expire automatically.', 'selfroles.panel.created': 'Self-role panel created (ID: `{id}`).', 'selfroles.panel.updated': 'Self-role panel updated (ID: `{id}`).', 'selfroles.panel.deleted': 'Self-role panel deleted.', 'selfroles.role.added': 'Role added.', 'selfroles.role.removed': 'Role removed.', 'selfroles.role.verified': 'Role granted.', 'selfroles.role.unchanged': 'You already have this role.', 'selfroles.error.not_found': 'Self-role panel not found.', 'selfroles.error.invalid_roles': 'Invalid roles format. Use roleId:label:emoji.', 'selfroles.error.too_many_roles': 'Maximum 25 roles per panel.', 'selfroles.error.invalid_channel': 'Invalid channel.', 'selfroles.error.invalid_duration': 'Invalid duration. Use e.g. 1h, 2d.', 'selfroles.error.duration_too_short': 'Duration must be at least 1 minute.', 'selfroles.error.duration_required': 'Temporary panels require a duration.', 'selfroles.error.reaction_emoji_required': 'Reaction mode requires emojis for all roles.', 'selfroles.error.member_not_found': 'Member not found.', 'selfroles.error.role_not_in_panel': 'This role is not part of this panel.', 'selfroles.error.role_not_found': 'Role not found.', 'selfroles.error.role_hierarchy': 'The role is above the bot\'s highest role.', 'selfroles.error.role_managed': 'Managed roles cannot be assigned.', 'selfroles.error.bot_missing_permissions': 'The bot lacks Manage Roles permission.', 'tag.created': 'Tag `{name}` created.', 'tag.updated': 'Tag `{name}` updated.', 'tag.deleted': 'Tag deleted.', 'tag.list.header': '**Tags**', 'tag.list.empty': 'No tags configured.', 'tag.list.uses': 'uses', 'tag.info.name': 'Name: `{name}`', 'tag.info.type': 'Type: {type}', 'tag.info.uses': 'Uses: {count}', 'tag.info.trigger': 'Trigger: `{word}`', 'tag.info.noTrigger': 'No auto-responder.', 'tag.info.roles': 'Roles: {roles}', 'tag.info.allRoles': 'Roles: all', 'tag.info.channels': 'Channels: {channels}', 'tag.info.allChannels': 'Channels: all', 'tag.error.not_found': 'Tag not found.', 'tag.error.not_allowed': 'You are not allowed to use this tag here.', 'tag.error.invalid_name': 'Invalid tag name (1–32 chars, a-z, 0-9, _, -).', 'tag.error.content_required': 'Text tags require content.', 'tag.error.embed_required': 'Embed tags require a title or description.', 'tag.error.premium_limit': 'Tag limit reached for this premium tier.', 'tag.error.premium_feature': 'Tags are disabled for this premium tier.', 'guildbackup.description': 'Create and restore server backups', 'guildbackup.created': 'Created backup **{name}** (ID: `{id}`).', 'guildbackup.deleted': 'Deleted backup `{id}`.', 'guildbackup.list.header': '**Server backups**', 'guildbackup.list.empty': 'No backups found.', 'guildbackup.list.line': '• `{id}` — **{name}** ({date})', 'guildbackup.info.id': 'ID: `{id}`', 'guildbackup.info.name': 'Name: **{name}**', 'guildbackup.info.created': 'Created: {date}', 'guildbackup.info.createdBy': 'Created by: <@{userId}>', 'guildbackup.info.roles': 'Roles: {count}', 'guildbackup.info.channels': 'Channels: {count}', 'guildbackup.info.limitations': 'Note: Backups do not include messages. Restore cannot preserve IDs; missing roles/channels are added by name, existing channels are not deleted.', 'guildbackup.confirm.delete': 'Really delete backup `{id}`?', 'guildbackup.confirm.restore.step1': 'Restore backup `{id}`? Missing roles/channels will be added and overwrites applied best-effort. Existing channels will **not** be deleted.', 'guildbackup.confirm.restore.step2': '**Final confirmation:** Restore backup `{id}` now? This cannot be undone.', 'guildbackup.confirm.button.confirm': 'Confirm', 'guildbackup.confirm.button.cancel': 'Cancel', 'guildbackup.confirm.expired': 'This confirmation has expired.', 'guildbackup.confirm.unauthorized': 'Only the user who started this action can confirm.', 'guildbackup.confirm.cancelled': 'Cancelled.', 'guildbackup.restore.done': 'Restored backup `{id}`. Roles: {rolesCreated} created, {rolesSkipped} skipped. Channels: {channelsCreated} created, {channelsUpdated} updated. Overwrites: {overwritesApplied}.', 'guildbackup.restore.queued': 'Large backup `{id}` — restore queued and will run in the background.', 'guildbackup.error.not_found': 'Backup not found.', 'guildbackup.error.invalid_payload': 'Backup data is invalid or outdated.', 'guildbackup.error.invalid_name': 'Invalid backup name (1–100 characters).', 'guildbackup.error.owner_only': 'Only the server owner can restore backups.', 'guildbackup.error.bot_missing_permissions': 'The bot is missing Manage Roles or Manage Channels for a restore.', 'guildbackup.error.premium_limit': 'Backup limit reached for this premium tier.', 'guildbackup.error.premium_feature': 'Backups are disabled for this premium tier.', 'feeds.added': 'Added feed `{id}` ({type}).', 'feeds.removed': 'Removed feed `{id}`.', 'feeds.list.header': '**Social Feeds**', 'feeds.list.empty': 'No feeds configured.', 'feeds.list.line': '`{id}` — {type}: {source} → {channel}', 'feeds.test.posted': 'Test successful: sent {count} message(s).', 'feeds.test.noItems': 'No new items found.', 'feeds.test.failed': 'Fetch failed: {reason}', 'feeds.test.skipped': 'Feed test skipped.', 'feeds.test.twitchSkipped': 'Twitch feed skipped: TWITCH_CLIENT_ID and TWITCH_CLIENT_SECRET are missing in the bot configuration.', 'feeds.error.not_found': 'Feed not found.', 'feeds.error.premium_limit': 'Feed limit reached for this premium tier.', 'feeds.error.premium_feature': 'Feeds are disabled for this premium tier.', 'scheduler.created': 'Scheduled message created (ID: `{id}`). {timing}', 'scheduler.created.at': 'Sends at: {time}', 'scheduler.created.cron': 'Repeats: `{cron}`', 'scheduler.deleted': 'Scheduled message deleted.', 'scheduler.announce.sent': 'Announcement sent.', 'scheduler.list.header': '**Scheduled messages**', 'scheduler.list.empty': 'No scheduled messages.', 'scheduler.list.line': '`{id}` — {channel} — {timing} — {preview}', 'scheduler.list.cron': 'Cron `{cron}`', 'scheduler.list.embedPreview': '[Embed]', 'scheduler.list.componentsPreview': '[Components V2]', 'scheduler.error.missing_schedule_time': 'Provide `when` or `cron`.', 'scheduler.error.invalid_when': 'Invalid time. Use e.g. 1h, 2d, or an ISO date.', 'scheduler.error.invalid_cron': 'Invalid cron expression (5–6 fields).', 'scheduler.error.invalid_channel': 'Invalid channel.', 'scheduler.error.channel_unavailable': 'The bot cannot send messages in that channel.', 'scheduler.error.not_found': 'Scheduled message not found.', 'scheduler.error.content_required': 'Content or embed title/description is required.', 'componentsV2.error.notFound': 'This component message is no longer available.', 'componentsV2.error.actionMissing': 'No action is configured for this interaction.', 'componentsV2.error.botMissingManageRoles': 'The bot lacks Manage Roles permission.', 'componentsV2.error.roleNotFound': 'Role not found.', 'componentsV2.error.roleManaged': 'Managed roles cannot be assigned.', 'componentsV2.error.roleHierarchy': 'The role is above the bot\'s highest role.', 'componentsV2.error.noRolesSelected': 'No roles selected.', 'componentsV2.role.assigned': 'Role assigned.', 'componentsV2.role.removed': 'Role removed.', 'componentsV2.role.assignedSelected': 'Selected roles assigned.', 'utility.embed.components.sent': 'Components V2 message sent.', 'utility.embed.components.dashboardHint': 'For the full builder including interactions: {url}', 'utility.embed.components.missingText': 'Text is required.', 'tag.error.components_required': 'Components V2 tags require components.' }; const locales: Record = { de, en }; export function t(locale: Locale, key: string): string { return locales[locale][key] ?? key; } export function tf(locale: Locale, key: string, vars: Record): string { const base = t(locale, key); return Object.entries(vars).reduce( (acc, [name, value]) => acc.replaceAll(`{${name}}`, String(value)), base ); }