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 * from './timezone.js';

export const LocaleSchema = z.enum(['de', 'en']);
export type Locale = z.infer<typeof LocaleSchema>;

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<typeof ModerationActionSchema>;

type Dictionary = Record<string, string>;
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:<name>`.',
  'core.help.moduleLine': '**{module}**: {commands}',
  'core.help.unknownModule': 'Unbekanntes Modul. Verfügbar: {modules}',
  'core.help.footer': 'Mehr Infos: /info · /about · 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.about.defaultTitle': 'Über Nexumi',
  'core.about.defaultBody':
    'Nexumi ist ein öffentlicher Discord-Bot mit Dashboard. Konfiguriere diese Nachricht im Owner-Panel unter About.',
  'core.about.disabled': 'Die About-Nachricht ist derzeit deaktiviert.',
  '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.success.caseWithReason':
    'Aktion erfolgreich ausgeführt (Fall #{caseNumber}).\nGrund: {reason}',
  '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.defaultTitle': 'Support-Tickets',
  '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.control.title': 'Ticket-Steuerung',
  'ticket.control.description':
    'Übernehmen, schließen, Priorität setzen oder Nutzer über die Menüs hinzufügen/entfernen. Zusätzlich: `/ticket rename`.',
  'ticket.control.claim': 'Übernehmen',
  'ticket.control.close': 'Schließen',
  'ticket.control.addPlaceholder': 'Nutzer zum Ticket hinzufügen…',
  'ticket.control.removePlaceholder': 'Nutzer aus dem Ticket entfernen…',
  'ticket.control.priorityPlaceholder': 'Priorität wählen…',
  'ticket.control.priorityLowHint': 'Geringe Dringlichkeit',
  'ticket.control.priorityNormalHint': 'Standard-Priorität',
  'ticket.control.priorityHighHint': 'Erhöhte Dringlichkeit',
  'ticket.control.priorityUrgentHint': 'Sofortige Bearbeitung',
  '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.missing_permission':
    'Mir fehlen Berechtigungen, um das Ticket-Panel in diesem Kanal zu posten (Kanal sehen, Nachrichten senden, Embeds).',
  '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.member_not_found': 'Mitglied nicht auf dem Server 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.cooldown': 'Cooldown: {seconds}s',
  'tag.info.noCooldown': 'Cooldown: aus',
  '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.cooldown': 'Cooldown aktiv. Versuche es in {seconds} Sekunden erneut.',
  '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:<name>`.',
  'core.help.moduleLine': '**{module}**: {commands}',
  'core.help.unknownModule': 'Unknown module. Available: {modules}',
  'core.help.footer': 'More: /info · /about · 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.about.defaultTitle': 'About Nexumi',
  'core.about.defaultBody':
    'Nexumi is a public Discord bot with a dashboard. Configure this message in the Owner panel under About.',
  'core.about.disabled': 'The about message is currently disabled.',
  '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.success.caseWithReason':
    'Action executed successfully (case #{caseNumber}).\nReason: {reason}',
  '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.defaultTitle': 'Support Tickets',
  '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.control.title': 'Ticket controls',
  'ticket.control.description':
    'Claim, close, set priority, or add/remove users with the menus below. Also: `/ticket rename`.',
  'ticket.control.claim': 'Claim',
  'ticket.control.close': 'Close',
  'ticket.control.addPlaceholder': 'Add a user to this ticket…',
  'ticket.control.removePlaceholder': 'Remove a user from this ticket…',
  'ticket.control.priorityPlaceholder': 'Choose priority…',
  'ticket.control.priorityLowHint': 'Low urgency',
  'ticket.control.priorityNormalHint': 'Default priority',
  'ticket.control.priorityHighHint': 'Elevated urgency',
  'ticket.control.priorityUrgentHint': 'Needs immediate attention',
  '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.missing_permission':
    'I am missing permissions to post the ticket panel in this channel (View Channel, Send Messages, Embed Links).',
  '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.member_not_found': 'Member is not on this server.',
  '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.cooldown': 'Cooldown: {seconds}s',
  'tag.info.noCooldown': 'Cooldown: off',
  '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.cooldown': 'Cooldown active. Try again in {seconds} seconds.',
  '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<Locale, Dictionary> = { 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, string | number>): string {
  const base = t(locale, key);
  return Object.entries(vars).reduce(
    (acc, [name, value]) => acc.replaceAll(`{${name}}`, String(value)),
    base
  );
}
