/** * util/i18n.js * Übersetzungen für DE und EN. * Nutzung: t(lang, "key") oder t(lang, "key", { var: "wert" }) */ const strings = { de: { // Allgemein "error.noArgs": "Du hast nicht genug Argumente angegeben!", "error.noPermission": "Du hast keine Berechtigung diesen Befehl auszuführen!", "error.onlyOwner": "Dieser Befehl kann nur vom Bot-Besitzer genutzt werden!", "error.cooldown": "Bitte warte {seconds} Sekunde(n) bevor du diesen Befehl erneut verwendest!", "error.nsfw": "Dieser Befehl ist als NSFW markiert. Bitte verwende ihn in einem NSFW-Kanal!", "error.notFound": "Ich konnte `{name}` nicht in der Befehlsliste finden!", "error.invalidID": "Ups! `{id}` ist keine gültige Ressourcen-ID!", "error.noAuthor": "Ups! Der Autor für Ressource `{id}` konnte nicht gefunden werden.", "error.apiDown": "Die API konnte nicht erreicht werden. Bitte versuche es später erneut.", "error.saveFailed": "Beim Speichern der Daten ist ein Fehler aufgetreten.", "error.timeout": "⏱️ Zeit abgelaufen – Befehl wurde abgebrochen.", "general.confirm": "✅ Bestätigen", "general.cancel": "❌ Abbrechen", "general.cancelled": "❌ Abgebrochen.", "general.author": "Autor: {name}", // add "add.alreadyWatched": "Diese Ressource wird bereits in <#{channelID}> beobachtet.", "add.invalidChannel": "Dieser Kanal ist ungültig. Bitte erwähne einen Kanal auf diesem Server.", "add.notInGuild": "Dieser Kanal befindet sich nicht auf diesem Server!", "add.versionFail": "Die neueste Version konnte nicht von SpigotMC abgerufen werden. Bitte versuche es erneut.", "add.confirmTitle": "Plugin beobachten: {name}", "add.confirmDesc": "{tag}\n\nSoll dieses Plugin in <#{channelID}> beobachtet werden?", "add.successTitle": "✅ Wird jetzt beobachtet: {name}", "add.buttonConfirm": "✅ Bestätigen", "add.channel": "Kanal", "add.version": "Version", "add.download": "Download", // remove "remove.noResources": "Dieser Server hat keine beobachteten Ressourcen!", "remove.notFound": "Fehler: Ressource `{id}` wurde auf diesem Server nicht beobachtet.", "remove.success": "✅ **{name}** (`{id}`) wird nicht mehr beobachtet.", "remove.saveFail": "Beim Aktualisieren der Beobachtungsdaten ist ein Fehler aufgetreten.", // list "list.noResources": "Dieser Server hat keine beobachteten Ressourcen. Nutze `{prefix}add` um eine hinzuzufügen.", "list.title": "📋 Beobachtete Plugins ({count})", "list.interval": "⏱️ Update-Intervall: {min} Minute(n)", "list.intervalDefault": "⏱️ Update-Intervall: 5 Minuten (Standard)", "list.channel": "Kanal", // setinterval "setinterval.invalid": "Ungültiger Wert. Bitte gib eine Zahl zwischen {min} und {max} Minuten an.", "setinterval.success": "Das Update-Intervall für diesen Server wurde auf **{min} Minute(n)** gesetzt.", "setinterval.title": "⏱️ Update-Intervall aktualisiert", "setinterval.footer": "Der nächste Check erfolgt nach Ablauf des neuen Intervalls.", // setchannel "setchannel.notWatched": "Ressource `{id}` wird auf diesem Server nicht beobachtet.", "setchannel.success": "✅ Update-Kanal für **{name}** wurde auf <#{channelID}> geändert.", // setmention "setmention.set": "✅ Bei Updates für **{name}** wird jetzt <@&{roleID}> gepingt.", "setmention.removed": "✅ Mention für **{name}** wurde entfernt.", "setmention.notWatched": "Ressource `{id}` wird auf diesem Server nicht beobachtet.", // setlang "setlang.success": "✅ Sprache wurde auf **Deutsch** gesetzt.", "setlang.title": "🌐 Sprache geändert", // status "status.title": "📡 {botName} – Status", "status.spiget": "🌐 Spiget API", "status.spigot": "🌐 SpigotMC API", "status.discord": "💬 Discord Ping", "status.queue": "⚙️ Queue", "status.nextCheck": "⏱️ Nächster Check", "status.checksTotal": "🔄 Checks gesamt", "status.updatesFound": "🔔 Updates gefunden", "status.updatesPosted": "📤 Updates gepostet", "status.apiErrors": "⚠️ API-Fehler", "status.onlineSince": "🕐 Online seit", "status.jobsDone": "🏓 Jobs verarbeitet", "status.ownerDMs": "📩 Owner-DMs", "status.ok": "✅ Erreichbar", "status.unreachable": "❌ Nicht erreichbar", "status.queueActive": "🔄 Aktiv ({count} ausstehend)", "status.queueWaiting": "⏳ Wartend ({count} Jobs)", "status.queueIdle": "✅ Leerlauf", // top "top.title": "🏆 Top Plugins – {sort}", "top.downloads": "Downloads", "top.rating": "Bewertung", "top.noData": "Keine beobachteten Ressourcen gefunden.", // check "check.title": "🔍 Kompatibilität: {name}", "check.compatible": "✅ Kompatibel", "check.incompatible": "❌ Nicht kompatibel", "check.unknown": "❓ Unbekannt", "check.testedVersions": "Getestete Versionen", "check.supportedVersions": "Unterstützte Versionen", // compare "compare.title": "⚖️ Vergleich", "compare.downloads": "⬇️ Downloads", "compare.rating": "⭐ Bewertung", "compare.version": "📦 Version", "compare.updated": "🕐 Letztes Update", "compare.winner": "🏆 Besser", // ping "ping.measuring": "Ping?", "ping.result": ":ping_pong: Pong! Die Latenz beträgt **{ms}ms**.", }, en: { // General "error.noArgs": "You didn't provide enough arguments!", "error.noPermission": "You don't have permission to run that command!", "error.onlyOwner": "This command can only be used by the bot owner!", "error.cooldown": "Please wait {seconds} second(s) before using that command again!", "error.nsfw": "This command is marked NSFW. Please run it in an NSFW channel!", "error.notFound": "I couldn't find `{name}` in the command list!", "error.invalidID": "Oops! `{id}` is not a valid resource ID!", "error.noAuthor": "Oops! I couldn't find the author for resource `{id}`.", "error.apiDown": "Could not reach the API. Please try again later.", "error.saveFailed": "An error occurred while saving the data.", "error.timeout": "⏱️ Timed out – command was cancelled.", "general.confirm": "✅ Confirm", "general.cancel": "❌ Cancel", "general.cancelled": "❌ Cancelled.", "general.author": "Author: {name}", // add "add.alreadyWatched": "That resource is already being watched in <#{channelID}>.", "add.invalidChannel": "That channel is invalid. Please mention a channel in this server.", "add.notInGuild": "That channel is not in this server!", "add.versionFail": "Could not fetch the latest version from SpigotMC. Please try again.", "add.confirmTitle": "Watch plugin: {name}", "add.confirmDesc": "{tag}\n\nShould this plugin be watched in <#{channelID}>?", "add.successTitle": "✅ Now watching: {name}", "add.buttonConfirm": "✅ Confirm", "add.channel": "Channel", "add.version": "Version", "add.download": "Download", // remove "remove.noResources": "This server has no watched resources!", "remove.notFound": "Error: Resource `{id}` was not being watched in this server.", "remove.success": "✅ **{name}** (`{id}`) is no longer being watched.", "remove.saveFail": "An error occurred while updating the watch data.", // list "list.noResources": "This server has no watched resources. Use `{prefix}add` to add one.", "list.title": "📋 Watched Plugins ({count})", "list.interval": "⏱️ Update interval: {min} minute(s)", "list.intervalDefault": "⏱️ Update interval: 5 minutes (default)", "list.channel": "Channel", // setinterval "setinterval.invalid": "Invalid value. Please provide a number between {min} and {max} minutes.", "setinterval.success": "The update interval for this server has been set to **{min} minute(s)**.", "setinterval.title": "⏱️ Update interval updated", "setinterval.footer": "The next check will run after the new interval has elapsed.", // setchannel "setchannel.notWatched": "Resource `{id}` is not being watched in this server.", "setchannel.success": "✅ Update channel for **{name}** changed to <#{channelID}>.", // setmention "setmention.set": "✅ <@&{roleID}> will now be pinged for updates to **{name}**.", "setmention.removed": "✅ Mention for **{name}** has been removed.", "setmention.notWatched": "Resource `{id}` is not being watched in this server.", // setlang "setlang.success": "✅ Language has been set to **English**.", "setlang.title": "🌐 Language changed", // status "status.title": "📡 {botName} – Status", "status.spiget": "🌐 Spiget API", "status.spigot": "🌐 SpigotMC API", "status.discord": "💬 Discord Ping", "status.queue": "⚙️ Queue", "status.nextCheck": "⏱️ Next Check", "status.checksTotal": "🔄 Total Checks", "status.updatesFound": "🔔 Updates Found", "status.updatesPosted": "📤 Updates Posted", "status.apiErrors": "⚠️ API Errors", "status.onlineSince": "🕐 Online Since", "status.jobsDone": "🏓 Jobs Processed", "status.ownerDMs": "📩 Owner DMs", "status.ok": "✅ Reachable", "status.unreachable": "❌ Unreachable", "status.queueActive": "🔄 Active ({count} pending)", "status.queueWaiting": "⏳ Waiting ({count} jobs)", "status.queueIdle": "✅ Idle", // top "top.title": "🏆 Top Plugins – {sort}", "top.downloads": "Downloads", "top.rating": "Rating", "top.noData": "No watched resources found.", // check "check.title": "🔍 Compatibility: {name}", "check.compatible": "✅ Compatible", "check.incompatible": "❌ Not compatible", "check.unknown": "❓ Unknown", "check.testedVersions": "Tested Versions", "check.supportedVersions": "Supported Versions", // compare "compare.title": "⚖️ Comparison", "compare.downloads": "⬇️ Downloads", "compare.rating": "⭐ Rating", "compare.version": "📦 Version", "compare.updated": "🕐 Last Updated", "compare.winner": "🏆 Better", // ping "ping.measuring": "Ping?", "ping.result": ":ping_pong: Pong! Latency is **{ms}ms**.", }, }; /** * Gibt den übersetzten String zurück. * Variablen werden mit {key} ersetzt. * @param {string} lang "de" | "en" * @param {string} key * @param {Object} [vars] */ export function t(lang, key, vars = {}) { const dict = strings[lang] ?? strings.de; let str = dict[key] ?? strings.de[key] ?? key; for (const [k, v] of Object.entries(vars)) { str = str.replaceAll(`{${k}}`, v); } return str; } /** * Gibt die gespeicherte Serversprache zurück (Standard: "de"). * @param {Object} jsonData Serverdaten aus serverdata/ */ export function getLang(jsonData) { return jsonData?.lang ?? "de"; }