translate command

This commit is contained in:
Cynthia Foxwell 2025-07-30 20:13:37 -06:00
parent 9630f02275
commit 663b97ae39
Signed by: Cynosphere
SSH key fingerprint: SHA256:H3SM8ufP/uxqLwKSH7xY89TDnbR9uOHzjLoBr0tlajk
2 changed files with 206 additions and 3 deletions

View file

@ -0,0 +1,204 @@
const Command = require("#lib/command.js");
const InteractionCommand = require("#lib/interactionCommand.js");
const {ApplicationCommandOptionTypes} = require("#util/dconstants.js");
const {Icons} = require("#util/constants.js");
const languageCodeToName = {
en: "English",
sq: "Albanian",
ar: "Arabic",
az: "Azerbaijani",
eu: "Basque",
bn: "Bengali",
bg: "Bulgarian",
ca: "Catalan",
"zh-Hans": "Chinese",
"zh-Hant": "Chinese (traditional)",
cs: "Czech",
da: "Danish",
nl: "Dutch",
eo: "Esperanto",
et: "Estonian",
fi: "Finnish",
fr: "French",
gl: "Galician",
de: "German",
el: "Greek",
he: "Hebrew",
hi: "Hindi",
hu: "Hungarian",
id: "Indonesian",
ga: "Irish",
it: "Italian",
ja: "Japanese",
ko: "Korean",
ky: "Kyrgyz",
lv: "Latvian",
lt: "Lithuanian",
ms: "Malay",
nb: "Norwegian",
fa: "Persian",
pl: "Polish",
pt: "Portuguese",
"pt-BR": "Portuguese (Brazil)",
ro: "Romanian",
ru: "Russian",
sk: "Slovak",
sl: "Slovenian",
es: "Spanish",
sv: "Swedish",
tl: "Tagalog",
th: "Thai",
tr: "Turkish",
uk: "Ukrainian",
ur: "Urdu",
auto: "Auto Detect",
};
const languageCodeToFlag = {
en: "\ud83c\uddfa\ud83c\uddf8",
sq: "\ud83c\udde6\ud83c\uddf1",
ar: "\ud83c\uddea\ud83c\uddec",
az: "\ud83c\udde6\ud83c\uddff",
eu: "\ud83d\udfe5",
bn: "\ud83c\udde7\ud83c\udde9",
bg: "\ud83c\udde7\ud83c\uddec",
ca: "\ud83c\udde6\ud83c\udde9",
"zh-Hans": "\ud83c\udde8\ud83c\uddf3",
"zh-Hant": "\ud83c\udde8\ud83c\uddf3",
cs: "\ud83c\udde8\ud83c\uddff",
da: "\ud83c\udde9\ud83c\uddf0",
nl: "\ud83c\uddf3\ud83c\uddf1",
eo: "\ud83d\udfe9",
et: "\ud83c\uddea\ud83c\uddea",
fi: "\ud83c\uddeb\ud83c\uddee",
fr: "\ud83c\uddeb\ud83c\uddf7",
gl: "\ud83d\udfe6",
de: "\ud83c\udde9\ud83c\uddea",
el: "\ud83c\uddec\ud83c\uddf7",
he: "\ud83c\uddee\ud83c\uddf1",
hi: "\ud83c\uddee\ud83c\uddf3",
hu: "\ud83c\udded\ud83c\uddfa",
id: "\ud83c\uddee\ud83c\udde9",
ga: "\ud83c\uddee\ud83c\uddea",
it: "\ud83c\uddee\ud83c\uddf9",
ja: "\ud83c\uddef\ud83c\uddf5",
ko: "\ud83c\uddf0\ud83c\uddf7",
ky: "\ud83c\uddf0\ud83c\uddec",
lv: "\ud83c\uddf1\ud83c\uddfb",
lt: "\ud83c\uddf1\ud83c\uddf9",
ms: "\ud83c\uddf2\ud83c\uddfe",
nb: "\ud83c\uddf3\ud83c\uddf4",
fa: "\ud83c\uddee\ud83c\uddf7",
pl: "\ud83c\uddf5\ud83c\uddf1",
pt: "\ud83c\uddf5\ud83c\uddf9",
"pt-BR": "\ud83c\udde7\ud83c\uddf7",
ro: "\ud83c\uddf7\ud83c\uddf4",
ru: "\ud83c\uddf7\ud83c\uddfa",
sk: "\ud83c\uddf8\ud83c\uddf0",
sl: "\ud83c\uddf8\ud83c\uddee",
es: "\ud83c\uddea\ud83c\uddf8",
sv: "\ud83c\uddf8\ud83c\uddfb",
tl: "\ud83c\uddf5\ud83c\udded",
th: "\ud83c\uddf9\ud83c\udded",
tr: "\ud83c\uddf9\ud83c\uddf7",
uk: "\ud83c\uddfa\ud83c\udde6",
ur: "\ud83c\uddf5\ud83c\uddf0",
};
const translate = new Command("translate");
translate.category = "misc";
translate.helpText = "Translate";
translate.usage = "<--from=lang> <--to=lang> [string]";
translate.addAlias("tr");
translate.callback = async function (msg, line, args, {from, to, languages}) {
if (!hf.config.libretranslate) return "No translation provider is set on this instance.";
if (languages) {
return Object.keys(languageCodeToName)
.map((code) => `${languageCodeToFlag} ${languageCodeToName[code]} - \`${code}\``)
.join("\n");
}
let text = args?.join(" ") ?? "";
if (text == null || text == "") {
if (msg.messageReference?.messageID) {
const reply = await msg.channel.getMessage(msg.messageReference.messageID);
text = reply.content;
} else {
return "Arguments or reply required.";
}
}
if (text == null || text == "") return "No text provided.";
if (from == null) from = "auto";
if (to == null) to = "en";
if (languageCodeToName[from] == null) {
from = "auto";
}
if (languageCodeToName[to] == null) {
to = "en";
}
const res = await fetch(`${hf.config.libretranslate}/translate`, {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
q: text,
source: from,
target: to,
alternatives: 0,
api_key: "",
}),
}).then((res) => res.json());
const fromLanguage = res.detectedLanguage?.language ?? from;
const confidence = res.detectedLanguage ? ` (${res.detectedLanguage.confidence}%)` : "";
return `-# Translated from ${languageCodeToFlag[fromLanguage] ?? Icons.blank} **${
languageCodeToName[fromLanguage] ?? `<unknown: \`${fromLanguage}\`>`
}**${confidence} to ${languageCodeToFlag[to] ?? Icons.blank} **${
languageCodeToName[to] ?? `<unknown: \`${to}\`>`
}**\n${res.translatedText
.replaceAll("`", "\\`")
.replaceAll("*", "\\*")
.replaceAll("_", "\\_")
.replaceAll("||", "|\u200b|")
.replaceAll("~~", "~\u200b~")}`;
};
hf.registerCommand(translate);
const translateInteraction = new InteractionCommand("translate");
translateInteraction.helpText = "Translate";
translateInteraction.options.content = {
name: "text",
type: ApplicationCommandOptionTypes.STRING,
description: "Text to translate",
required: true,
default: "",
};
translateInteraction.options.from = {
name: "from",
type: ApplicationCommandOptionTypes.STRING,
description: "Language to translate from (default: Auto Detect)",
default: "auto",
choices: Object.entries(languageCodeToName).map(([code, name]) => ({name, value: code})),
};
translateInteraction.options.to = {
name: "to",
type: ApplicationCommandOptionTypes.STRING,
description: "Language to translate to (default: English)",
default: "en",
choices: Object.entries(languageCodeToName)
.filter(([code]) => code !== "auto")
.map(([code, name]) => ({name, value: code})),
};
translateInteraction.callback = async function (interaction) {
const text = this.getOption(interaction, "text");
const from = this.getOption(interaction, "from");
const to = this.getOption(interaction, "to");
return translate.callback(interaction, text, text.split(" "), {from, to});
};
hf.registerCommand(translateInteraction);

View file

@ -71,4 +71,3 @@ charinfoInteraction.callback = async function (interaction) {
return charinfo.callback(interaction, content); return charinfo.callback(interaction, content);
}; };
hf.registerCommand(charinfoInteraction); hf.registerCommand(charinfoInteraction);