Implement leveling and economy features with associated models and commands
- Added new models for leveling and economy functionalities in the Prisma schema, including LevelingConfig, MemberLevel, LevelReward, EconomyConfig, MemberEconomy, ShopItem, and InventoryItem. - Introduced commands for managing XP, economy transactions, and shop interactions, enhancing user engagement. - Updated job handling to include reminders and poll closing functionalities. - Enhanced localization support for new commands and features in both German and English. - Improved the bot's job processing capabilities with a dedicated reminder worker for scheduled tasks.
This commit is contained in:
@@ -4,6 +4,7 @@ export * from './audit.js';
|
||||
export * from './command-locales.js';
|
||||
export * from './discord-localization.js';
|
||||
export * from './phase2.js';
|
||||
export * from './phase3.js';
|
||||
|
||||
export const LocaleSchema = z.enum(['de', 'en']);
|
||||
export type Locale = z.infer<typeof LocaleSchema>;
|
||||
@@ -92,7 +93,152 @@ const de: Dictionary = {
|
||||
'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'
|
||||
'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.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'
|
||||
};
|
||||
const en: Dictionary = {
|
||||
'generic.noPermission': 'You do not have permission for this action.',
|
||||
@@ -148,7 +294,152 @@ const en: Dictionary = {
|
||||
'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'
|
||||
'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.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'
|
||||
};
|
||||
|
||||
const locales: Record<Locale, Dictionary> = { de, en };
|
||||
|
||||
Reference in New Issue
Block a user