//META{"name":"GoogleTranslateOption"}*// class GoogleTranslateOption { initConstructor () { this.labels = {}; this.patchModules = { "ChannelTextArea":"componentDidMount", "Message":"componentDidMount", "MessageOptionPopout":"componentDidMount" }; this.languages = {}; this.doTranslate = false; this.translating = false; this.defaults = { settings: { sendOriginalMessage: {value:false, description:"Send the original message together with the translation."} }, translators: { useGoogle: {value:true, choice1:"DeepL", choice2:"Google", popout:true} }, choices: { inputContext: {value:"auto", place:"Context", direction:"Input", popout:false, description:"Input Language in selected Messages:"}, outputContext: {value:"$discord", place:"Context", direction:"Output", popout:false, description:"Output Language in selected Messages:"}, inputMessage: {value:"auto", place:"Message", direction:"Input", popout:true, description:"Input Language in your Message:"}, outputMessage: {value:"$discord", place:"Message", direction:"Output", popout:true, description:"Output Language in your Message:"} } }; this.messageTranslateContextEntryMarkup = `
REPLACE_context_messagetranslateoption_text
`; this.messageUntranslateContextEntryMarkup = `
REPLACE_context_messageuntranslateoption_text
`; this.messageSearchContextEntryMarkup = `
REPLACE_context_googletranslateoption_text
`; this.popoutTranslateEntryMarkup = ``; this.popoutUntranslateEntryMarkup = ``; this.translateButtonMarkup = `
`; this.reverseButtonMarkup = ` `; this.translatePopoutMarkup = `

Words starting with "!" will be ignored

${Object.keys(this.defaults.choices).map((key, i) => `

${this.defaults.choices[key].description}

${this.defaults.choices[key].direction == "Output" ? this.reverseButtonMarkup.replace("REPLACETYPE",key) : ""}
`).join("")}

Translate:

${Object.keys(this.defaults.translators).map((key, i) => `

Translator:

${this.defaults.translators[key].choice1}

${this.defaults.translators[key].choice2}

`).join("")}
`; this.DeepLTranslateAPI = function () { var INPUT, OUTPUT, clearInput, current, domReady, enabled, executeScript, getLanguage, getOutput, langI, langO, setInput, setLanguage, timer, wc, webview; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i];for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } }return target; } class DeepLTranslateAPI { start() { enabled = true; webview = document.createElement("webview"); webview.style.visibility = "hidden"; webview.id = "wvDeepLTranslateAPI"; webview.partition = "persist:DeepLTranslateAPI"; webview.addEventListener("dom-ready", async function () { wc = webview.getWebContents(); webview.setAudioMuted(true); domReady = await executeScript(function () { var tas = document.querySelectorAll("textarea"); window["INPUT"] = tas[0]; window["OUTPUT"] = tas[1]; return Promise.resolve(true); }); }); webview.src = "https://www.deepl.com/translator"; document.body.appendChild(webview); } stop() { enabled = domReady = false; // webview.terminate() webview.remove(); if (timer) { cancelAnimationFrame(timer); } if (current != null) { current.reject(new Error("DeepLTranslateAPI was stopped.")); } webview = wc = langI = langO = current = timer = null; } isReady() { return domReady; } translate(text) { return new Promise(function (resolve, reject) { if (langI === langO) { return resolve(text); } if (!enabled) { return reject(new Error("DeepLTranslateAPI is disabled!")); } if (!domReady) { return reject(new Error("DeepL didn't load (yet?)!")); } if (current != null) { current.reject(new Error("Can only translate so much.")); } current = { resolve, reject }; (async function () { var __unchanged__, valueNew, valueOld; valueOld = await getOutput(); ({ __unchanged__ } = await setInput(text)); if (true === __unchanged__) { valueOld = void 0; } if (timer) { return; } // todo: figgure out event based change on output while (enabled && valueOld === (valueNew = await getOutput())) { await new Promise(function (c) { return timer = requestAnimationFrame(c); }); } current.resolve(valueNew); timer = current = null; })(); }); } setInputLanguage(lang) { return setLanguage(true, lang); } setOutputLanguage(lang) { return setLanguage(false, lang); } getInputLanguage(lang) { return getLanguage(true); } getOutputLanguage(lang) { return getLanguage(false); } clearInput() { return clearInput(); } }; webview = wc = current = timer = null; enabled = domReady = false; langI = langO = "auto"; INPUT = "#_ta0#input#DeepLTranslateAPI#"; OUTPUT = "#_ta1#output#DeepLTranslateAPI#"; executeScript = function (replace, func) { var code, k, v; if (!func) { func = replace; replace = { INPUT, OUTPUT }; } else { replace = _extends({ INPUT, OUTPUT }, replace); } code = "(" + func.toString() + ")()"; for (k in replace) { v = replace[k]; if ("string" === typeof v) { v = v.split("\n").join("\\n"); v = v.replace(/[^\w\d\s]/g, "\\$&"); } code = code.split(k).join(v); } return wc.executeJavaScript(code); }; setInput = function (text) { return executeScript({ text }, function () { return Promise.resolve(window["INPUT"].value === "text" ? { __unchanged__: true } : (window["INPUT"].value = "text", window["INPUT"].dispatchEvent(new Event("change")), window["INPUT"].value)); }); }; getOutput = function () { return executeScript(function () { return Promise.resolve(window["OUTPUT"].value); }); }; setLanguage = async function (inputOrOutput, lang) { if (!domReady) { throw new Error("DeepL didn't load (yet?)!"); } lang = !lang || lang === "auto" ? lang : lang.toUpperCase(); if (!(lang === "DE" || lang === "EN" || lang === "FR" || lang === "ES" || lang === "IT" || lang === "NL" || lang === "PL" || inputOrOutput && "auto" === lang)) { throw new Error(`${lang} is not a supported language!`); } if (inputOrOutput) { langI = lang; } else { if (langI === (langO = lang)) { return; } } await executeScript({ inputOrOutput, __lang____: lang }, function () { document.querySelector(`.lmt__language_select--${inputOrOutput ? "source" : "target"} li[dl-value=__lang____]`).click(); }); }; getLanguage = async function (inputOrOutput) { if (!domReady) { throw new Error("DeepL didn't load (yet?)!"); } return await executeScript({ inputOrOutput }, function () { return Promise.resolve(document.querySelector(`.lmt__language_select--${inputOrOutput ? "source" : "target"}`).getAttribute("dl-value")); }); }; clearInput = async function () { if (!domReady) { throw new Error("DeepL didn't load (yet?)!"); } await executeScript(function () { document.querySelector(".lmt__clear_text_button").click(); }); }; return DeepLTranslateAPI; }.call(this); this.css = ` ${BDFDB.dotCN.textareainner} { border: none !important; } ${BDFDB.dotCN.textareainner} ${BDFDB.dotCN.textareapickerbuttons} { height: auto; } ${BDFDB.dotCN.textareainner} .send-button { top: calc(50% - 15px); right: 9px; } ${BDFDB.dotCN.textareainner} .send-button, ${BDFDB.dotCN.textareainner} ${BDFDB.dotCN.button} { max-height: unset; } ${BDFDB.dotCN.textareabuttonwrapper}.popout-open ${BDFDB.dotCN.textareabutton}.translate-button { opacity: 1; } ${BDFDB.dotCN.textareabuttonwrapper + BDFDB.dotCNS.textareabuttonactive + BDFDB.dotCN.textareabutton}.translate-button { color: #F04747 !important; } ${BDFDB.dotCNS.textareabuttonwrapper + BDFDB.dotCN.textareabutton}.translate-button ${BDFDB.dotCN.textareaicon} { height: 24px; width: 24px; } ${BDFDB.dotCN.textareabuttonwrapper}.popout-open ${BDFDB.dotCN.textareabutton}.translate-button ${BDFDB.dotCN.textareaicon} { transform: none; } .reverse-button { margin-top: -5px; opacity: 0.2; transition: all 200ms ease; } ${BDFDB.dotCN.themedark} .reverse-button { fill: #fff; } ${BDFDB.dotCN.themelight} .reverse-button { fill: #4f545c; } .reverse-button:hover { cursor: pointer; opacity: 1; } ${BDFDB.dotCN.popout}.popout-googletranslate ${BDFDB.dotCN.popoutthemedpopout} { padding: 0 10px; width: 400px; } ${BDFDB.dotCN.selectmenuouter} .inChat { top: 0%; transform: translateY(-100%); border-radius: 4px 4px 0 0; margin-top: 1px; }`; } getName () {return "GoogleTranslateOption";} getDescription () {return "Adds a Google Translate option to your context menu, which shows a preview of the translated text and on click will open the selected text in Google Translate. Also adds a translation button to your textareas, which will automatically translate the text for you before it is being send. DeepLApi written by square. Thanks ;)";} getVersion () {return "1.5.7";} getAuthor () {return "DevilBro, square";} getSettingsPanel () { if (!this.started || typeof BDFDB !== "object") return; var choices = BDFDB.getAllData(this, "choices"); var settings = BDFDB.getAllData(this, "settings"); var translators = BDFDB.getAllData(this, "translators"); var settingshtml = `
${this.getName()}
`; for (let key in choices) { let choice = this.getLanguageChoice(key); settingshtml += `

${this.defaults.choices[key].description}

${this.languages[choice].name}
` } for (let key in settings) { settingshtml += `

${this.defaults.settings[key].description}

`; } for (let key in translators) { settingshtml += `

Translator:

${this.defaults.translators[key].choice1}

${this.defaults.translators[key].choice2}

`; } settingshtml += `
`; var settingspanel = $(settingshtml)[0]; BDFDB.initElements(settingspanel); $(settingspanel) .on("click", BDFDB.dotCN.selectcontrol, (e) => {this.openDropdownMenu("inSettings", e);}) .on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);}); return settingspanel; } //legacy load () {} start () { var libraryScript = null; if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) { libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]'); if (libraryScript) libraryScript.remove(); libraryScript = document.createElement("script"); libraryScript.setAttribute("type", "text/javascript"); libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"); document.head.appendChild(libraryScript); } this.startTimeout = setTimeout(() => {this.initialize();}, 30000); if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize(); else libraryScript.addEventListener("load", () => {this.initialize();}); } initialize () { if (typeof BDFDB === "object") { BDFDB.loadMessage(this); this.GuildUtils = BDFDB.WebModules.findByProperties("getGuilds","getGuild"); this.ChannelUtils = BDFDB.WebModules.findByProperties("getChannels","getChannel"); this.LastGuildStore = BDFDB.WebModules.findByProperties("getLastSelectedGuildId"); this.LastChannelStore = BDFDB.WebModules.findByProperties("getLastSelectedChannelId"); this.setLanguage(); BDFDB.WebModules.forceAllUpdates(this); } else { console.error(this.getName() + ": Fatal Error: Could not load BD functions!"); } } stop () { if (typeof BDFDB === "object") { this.stopDeepL(); document.querySelectorAll(BDFDB.dotCN.message + ".translated").forEach(message => { this.resetMessage(message); }); BDFDB.removeEles(".translate-button-wrapper"); BDFDB.unloadMessage(this); } } // begin of own functions startDeepL () { this.stopDeepL(); this.DeepLTranslate = new this.DeepLTranslateAPI(); this.DeepLTranslate.start(); } stopDeepL () { if (this.DeepLTranslate && typeof this.DeepLTranslate.stop === "function") this.DeepLTranslate.stop(); this.DeepLTranslate = undefined; } changeLanguageStrings () { this.messageTranslateContextEntryMarkup = this.messageTranslateContextEntryMarkup.replace("REPLACE_context_messagetranslateoption_text", this.labels.context_messagetranslateoption_text); this.messageUntranslateContextEntryMarkup = this.messageUntranslateContextEntryMarkup.replace("REPLACE_context_messageuntranslateoption_text", this.labels.context_messageuntranslateoption_text); this.messageSearchContextEntryMarkup = this.messageSearchContextEntryMarkup.replace("REPLACE_context_googletranslateoption_text", this.labels.context_googletranslateoption_text); this.popoutTranslateEntryMarkup = this.popoutTranslateEntryMarkup.replace("REPLACE_popout_translateoption_text", this.labels.popout_translateoption_text); this.popoutUntranslateEntryMarkup = this.popoutUntranslateEntryMarkup.replace("REPLACE_popout_untranslateoption_text", this.labels.popout_untranslateoption_text); } updateSettings (settingspanel) { var data = {}; for (let input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) { let option = input.getAttribute("option"); let value = input.value; if (option && value) { if (!data[option]) data[option] = {}; data[option][input.value] = input.checked; } } for (let option in data) { BDFDB.saveAllData(data[option], this, option); } this.setLanguage(); } onMessageContextMenu (instance, menu) { if (instance.props && instance.props.message && instance.props.channel && instance.props.target && !menu.querySelector(".googletranslateoption-item")) { let {messagediv, pos} = this.getMessageAndPos(instance.props.target); if (!messagediv || pos == -1) return; let pininstance = BDFDB.getOwnerInstance({node:menu,name:"MessagePinItem"}); if (pininstance && pininstance._reactInternalFiber && pininstance._reactInternalFiber.return && pininstance._reactInternalFiber.return.stateNode) { $(messagediv.classList.contains("translated") ? this.messageUntranslateContextEntryMarkup : this.messageTranslateContextEntryMarkup) .on("click", ".googletranslateoption-translate-item, .googletranslateoption-untranslate-item", () => { instance._reactInternalFiber.return.memoizedProps.closeContextMenu(); this.translateMessage(instance.props.message, instance.props.target, instance.props.channel); }) .insertAfter(pininstance._reactInternalFiber.return.stateNode); if (BDFDB.isPluginEnabled("MessageUtilities")) { BDFDB.setContextHint(menu.querySelector(".googletranslateoption-item"), bdplugins.MessageUtilities.plugin.getActiveShortcutString("__Translate_Message")); } } let text = document.getSelection().toString(); let searchinstance = BDFDB.getOwnerInstance({node:menu,props:["handleSearchWithGoogle"]}); if (text && searchinstance && searchinstance._reactInternalFiber && searchinstance._reactInternalFiber.return && searchinstance._reactInternalFiber.return.stateNode) { $(this.messageSearchContextEntryMarkup).insertAfter(searchinstance._reactInternalFiber.return.stateNode) .on("mouseenter", ".googletranslateoption-search-item", (e) => { this.translateText(text, "context", (translation, input, output) => { if (translation) { let rects = e.currentTarget.getBoundingClientRect(); BDFDB.createTooltip(`From ${input.name}:\n${text}\n\nTo ${output.name}:\n${translation}`, e.currentTarget, {type: "right",selector:"googletranslate-tooltip",style:`max-width: ${window.outerWidth - rects.left - rects.width}px !important;`}); $(e.currentTarget.parentElement) .off("click") .on("click", ".googletranslateoption-item", () => { instance._reactInternalFiber.return.memoizedProps.closeContextMenu(); window.open(this.getGoogleTranslatePageURL(input.id, output.id, text), "_blank"); }); } }); }); } } } setLanguage () { this.languages = Object.assign({}, {"auto": {name:"Auto", id:"auto", integrated:false, dic:false, deepl:true}}, BDFDB.languages, {"binary": {name:"Binary", id:"binary", integrated:false, dic:false, deepl:true}} ); if (!BDFDB.getData("useGoogle", this, "translators")) { this.languages = BDFDB.filterObject(this.languages, (lang) => {return lang.deepl == true ? lang : null}); this.startDeepL(); } else { this.stopDeepL(); } } getLanguageChoice (direction, place) { var type = typeof place === "undefined" ? direction : direction.toLowerCase() + place.charAt(0).toUpperCase() + place.slice(1).toLowerCase(); var choice = BDFDB.getData(type, this, "choices"); choice = this.languages[choice] ? choice : Object.keys(this.languages)[0]; choice = type.indexOf("output") > -1 && choice == "auto" ? "en" : choice; return choice; } processChannelTextArea (instance, wrapper) { if (instance.props && instance.props.type && instance.props.type == "normal" && !instance.props.disabled && !wrapper.querySelector(".translate-button-wrapper")) { let textarea = wrapper.querySelector("textarea"); if (textarea) { var buttoncontainer = wrapper.querySelector(BDFDB.dotCN.textareapickerbuttons); if (!buttoncontainer) return; var button = $(this.translateButtonMarkup)[0]; $(button) .on("click." + this.getName(), () => { this.openTranslatePopout(button); }) .on("contextmenu." + this.getName(), () => { this.translating = !this.translating; document.querySelectorAll(BDFDB.dotCNS.textareawrapchat + ".translate-button-wrapper").forEach(btn => { btn.classList.toggle(BDFDB.disCN.textareabuttonactive, this.translating); }); }); buttoncontainer.insertBefore(button, buttoncontainer.firstElementChild); button.classList.add(instance.props.type); button.classList.toggle(BDFDB.disCN.textareabuttonactive, this.translating); $(textarea) .off("input." + this.getName()) .on("input." + this.getName(), () => { if (this.doTranslate) { this.doTranslate = false; if (document.activeElement == textarea) { var text = textarea.value; textarea.focus(); textarea.selectionStart = 0; textarea.selectionEnd = text.length; document.execCommand("insertText", false, ""); this.translateText(text, "message", (translation, input, output) => { translation = !translation ? text : (BDFDB.getData("sendOriginalMessage", this, "settings") ? text + "\n\n" + translation : translation); textarea.focus(); document.execCommand("insertText", false, translation + " "); BDFDB.triggerSend(textarea); }); } } }) .off("keydown." + this.getName()) .on("keydown." + this.getName(), e => { if (textarea.value && this.translating && !e.shiftKey && e.which == 13 && !wrapper.querySelector(BDFDB.dotCN.autocomplete)) { this.doTranslate = true; $(textarea).trigger("input"); } }); } } } processMessage (instance, wrapper) { if (instance.props && typeof instance.props.renderButtons == "function" && !wrapper.querySelector(BDFDB.dotCN.optionpopoutbutton)) { let buttonwrap = wrapper.querySelector(BDFDB.dotCN.messagebuttoncontainer); if (buttonwrap) { let button = $(`
`)[0]; $(button).on("click", () => {BDFDB.createMessageOptionPopout(button);}).appendTo(buttonwrap); } } } processMessageOptionPopout (instance, wrapper) { if (instance.props.message && instance.props.channel && instance._reactInternalFiber.memoizedProps.target && !wrapper.querySelector(".personalpin-itembtn")) { let {messagediv, pos} = this.getMessageAndPos(instance._reactInternalFiber.memoizedProps.target); if (!messagediv || pos == -1) return; $(messagediv.classList.contains("translated") ? this.popoutUntranslateEntryMarkup : this.popoutTranslateEntryMarkup) .on("click." + this.getName(), () => { this.translateMessage(instance.props.message, instance._reactInternalFiber.memoizedProps.target, instance.props.channel); instance.props.onClose(); }) .appendTo(wrapper); } } getMessageAndPos (target) { let messagediv = BDFDB.getParentEle(BDFDB.dotCN.message, target); let pos = Array.from(messagediv.parentElement.querySelectorAll(BDFDB.dotCN.message)).indexOf(messagediv); return {messagediv, pos}; } translateMessage (message, target, channel) { if (!message || !target) return; let {messagediv, pos} = this.getMessageAndPos(target); if (!messagediv || pos == -1) return; channel = channel ? channel : this.ChannelUtils.getChannel(message.channel_id); if (!messagediv.querySelector(BDFDB.dotCN.messageedited + ".translated")) { var markup = messagediv.querySelector(BDFDB.dotCN.messagemarkup); var fakemarkup = markup.cloneNode(true); var oldhtml = markup.innerHTML; let compactheader = fakemarkup.querySelector(BDFDB.dotCN.messageheadercompact); if (compactheader) compactheader.remove(); this.translateText(fakemarkup.innerHTML, "context", (translation, input, output) => { if (translation) { $(markup).data("orightmlGoogleTranslate", oldhtml); markup.innerHTML = (compactheader ? "" : "") + translation.replace(/\n/g, "DevilBroBDFDBPlacerHolderN").replace(/\s/g, " ").replace(/DevilBroBDFDBPlacerHolderN/g, "\n").replace(/ *([<>]) */g, "$1"); $(``) .on("mouseenter." + this.getName(), (e) => { BDFDB.createTooltip(`
From: ${input.name}
To: ${output.name}
`, e.currentTarget, {html:true, type:"top", selector:"translation-tooltip"}); }) .appendTo(markup); messagediv.classList.add("translated"); if (compactheader) markup.insertBefore(compactheader, markup.firstElementChild); } }); } else this.resetMessage(messagediv); } resetMessage (messagediv) { $(messagediv) .removeClass("translated") .find(BDFDB.dotCN.messageedited + ".translated").remove(); let markup = messagediv.querySelector(BDFDB.dotCN.messagemarkup); markup.innerHTML = $(markup).data("orightmlGoogleTranslate"); } translateText (text, type, callback) { var finishTranslation = (translation, exceptions, input, output, toast) => { if (translation) translation = this.addExceptions(translation, exceptions); clearInterval(toast.interval); toast.close(); callback(translation, input, output); }; var [newtext, exceptions, translate] = this.removeExceptions(text.trim(), type); var input = Object.assign({}, this.languages[this.getLanguageChoice("input", type)]); var output = Object.assign({}, this.languages[this.getLanguageChoice("output", type)]); var translation = ""; if (translate) { var toast = BDFDB.showToast("Translating. Please wait", {timeout:0}); toast.interval = setInterval(() => { toast.textContent = toast.textContent.indexOf(".....") > -1 ? "Translating. Please wait" : toast.textContent + "."; },500); if (input.id == "binary" || output.id == "binary") { if (input.id == "binary" && output.id != "binary") translation = this.binary2string(newtext); else if (input.id != "binary" && output.id == "binary") translation = this.string2binary(newtext); else if (input.id == "binary" && output.id == "binary") translation = newtext; finishTranslation(translation, exceptions, input, output, toast); } else { if (BDFDB.getData("useGoogle", this, "translators")) { require("request")(this.getGoogleTranslateApiURL(input.id, output.id, newtext), (error, response, result) => { if (!error && result) { result = JSON.parse(result); result[0].forEach((array) => {translation += array[0];}); if (this.languages[result[2]]) input.name = this.languages[result[2]].name; finishTranslation(translation, exceptions, input, output, toast); } }); } else { this.DeepLTranslate.setInputLanguage(input.id); this.DeepLTranslate.setOutputLanguage(output.id); this.DeepLTranslate.translate(newtext).then((translation) => { if (newtext.lastIndexOf(".") != newtext.length-1 && translation.lastIndexOf(".") == translation.length-1) translation = translation.slice(0,-1); finishTranslation(translation, exceptions, input, output, toast); }); } } } else { translation = text; finishTranslation(translation, exceptions, input, output, toast); } } addExceptions (string, exceptions) { for (let i in exceptions) string = string.replace("a" + i + "_______", exceptions[i].indexOf("!") == 0 ? exceptions[i].slice(1) : exceptions[i]); return string; } removeExceptions (string, type) { var exceptions = {}, newString = [], count = 0; if (type == "context") { let text = [], i = 0; string.split("").forEach(chara => { if (chara == "<" && text[i]) i++; text[i] = text[i] ? text[i] + chara : chara; if (chara == ">") i++; }); for (let j in text) { if (text[j].indexOf("<") == 0) { newString.push("a" + count + "_______"); exceptions[count] = text[j]; count++; } else newString.push(text[j]); } } else { string.split(" ").forEach(word => { if (word.indexOf("<@!") == 0 || word.indexOf(":") == 0 || word.indexOf("@") == 0 || word.indexOf("#") == 0 || (word.indexOf("!") == 0 && word.length > 1)) { newString.push("a" + count + "_______"); exceptions[count] = word; count++; } else newString.push(word); }); } return [newString.join(" "), exceptions, newString.length-count != 0]; } openTranslatePopout (button) { if (button.classList.contains(BDFDB.disCN.optionpopoutopen)) return; button.classList.add(BDFDB.disCN.optionpopoutopen); var popout = $(this.translatePopoutMarkup); popout .appendTo(BDFDB.dotCN.popouts) .css("left", $(button).offset().left + $(button).outerWidth() + "px") .css("top", $(button).offset().top - $(button).outerHeight()/2 + "px") .on("click", BDFDB.dotCN.selectcontrol, (e) => {this.openDropdownMenu("inChat", e);}) .on("click", ".reverse-button", (e) => { var place = e.currentTarget.getAttribute("type").replace("output",""); var input = this.getLanguageChoice("output", place); var output = this.getLanguageChoice("input", place); output = output == "auto" ? "en" : output; popout.find(BDFDB.dotCN.select + "[type='input" + place + "']").attr("value", input).find(BDFDB.dotCN.title).text(this.languages[input].name); popout.find(BDFDB.dotCN.select + "[type='output" + place + "']").attr("value", output).find(BDFDB.dotCN.title).text(this.languages[output].name); BDFDB.saveData("input" + place, input, this, "choices"); BDFDB.saveData("output" + place, output, this, "choices"); }); popout.find(BDFDB.dotCN.select).each((_,selectWrap) => { let language = this.getLanguageChoice(selectWrap.getAttribute("type")); selectWrap.setAttribute("value", language); selectWrap.querySelector(BDFDB.dotCN.title).innerText = this.languages[language].name; }); var checkbox = popout[0].querySelector("#translating-checkbox"); checkbox.checked = this.translating; $(checkbox).on("click." + this.getName(), () => { button.classList.toggle(BDFDB.disCN.textareabuttonactive, checkbox.checked); this.translating = checkbox.checked; }); var translators = BDFDB.getAllData(this, "translators"); popout[0].querySelectorAll(BDFDB.dotCN.switchinner + "[option=translators]").forEach((checkbox) => { checkbox.checked = translators[checkbox.value]; $(checkbox).on("click." + this.getName(), () => { this.updateSettings(popout[0]); popout.remove(); button.classList.remove(BDFDB.disCN.optionpopoutopen); this.openTranslatePopout(button); }); }); $(document).on("mousedown.translatepopout" + this.getName(), (e) => { if (popout.has(e.target).length == 0) { $(document).off("mousedown.translatepopout" + this.getName()); popout.remove(); setTimeout(() => {button.classList.remove(BDFDB.disCN.optionpopoutopen);},300); } }); BDFDB.initElements(popout[0]); } openDropdownMenu (selector, e) { var selectControl = e.currentTarget; var selectWrap = selectControl.parentElement; if (selectWrap.classList.contains(BDFDB.disCN.selectisopen)) return; selectWrap.classList.add(BDFDB.disCN.selectisopen); $("li").has(selectWrap).css("overflow", "visible"); var type = selectWrap.getAttribute("type"); var selectMenu = this.createDropdownMenu(selectWrap.getAttribute("value"), type); selectWrap.appendChild(selectMenu); $(selectMenu).addClass(selector).on("mousedown." + this.getName(), BDFDB.dotCN.selectoption, (e2) => { var language = e2.currentTarget.getAttribute("value"); selectWrap.setAttribute("value", language); selectControl.querySelector(BDFDB.dotCN.title).innerText = this.languages[language].name; BDFDB.saveData(type, language, this, "choices"); }); $(document).on("mousedown.select" + this.getName(), (e2) => { if (e2.target.parentElement == selectMenu) return; $(document).off("mousedown.select" + this.getName()); selectMenu.remove(); $("li").has(selectWrap).css("overflow", "auto"); setTimeout(() => {selectWrap.classList.remove(BDFDB.disCN.selectisopen);},100); }); } createDropdownMenu (choice, type) { var menuhtml = `
`; for (var key in this.languages) { if (this.defaults.choices[type].direction == "Output" && key == "auto") continue; var isSelected = key == choice ? ` ${BDFDB.disCN.selectselected}` : ``; menuhtml += `
${this.languages[key].name}
` } menuhtml += `
`; return $(menuhtml)[0]; } string2binary (string) { var binary = ""; for (var character of string) binary += parseInt(character.charCodeAt(0).toString(2)).toPrecision(8).split(".").reverse().join("").toString() + " "; return binary; } binary2string (binary) { var string = ""; binary = binary.replace(new RegExp(" ", "g"), ""); if (/^[0-1]*$/.test(binary)) { var eightdigits = ""; var counter = 0; for (var digit of binary) { eightdigits += digit; counter++; if (counter > 7) { string += String.fromCharCode(parseInt(eightdigits,2).toString(10)); eightdigits = ""; counter = 0; } } } else { BDFDB.showToast("Invalid binary format. Only use 0s and 1s.", {type:"error"}); } return string; } getGoogleTranslateApiURL (input, output, text) { return "https://translate.googleapis.com/translate_a/single?client=gtx&sl=" + input + "&tl=" + output + "&dt=t&ie=UTF-8&oe=UTF-8&q=" + encodeURIComponent(text); } getGoogleTranslatePageURL (input, output, text) { return "https://translate.google.com/#" + input + "/" + output + "/" + encodeURIComponent(text); } setLabelsByLanguage () { switch (BDFDB.getDiscordLanguage().id) { case "hr": //croatian return { context_messagetranslateoption_text: "Prijevod poruke", context_messageuntranslateoption_text: "Prijenos poruke", context_googletranslateoption_text: "Traži prijevod", popout_translateoption_text: "Prevesti", popout_untranslateoption_text: "Prevesti natrag", translated_watermark_text: "preveo" }; case "da": //danish return { context_messagetranslateoption_text: "Oversæt Besked", context_messageuntranslateoption_text: "Oversæt Besked tilbage", context_googletranslateoption_text: "Søg oversættelse", popout_translateoption_text: "Oversætte", popout_untranslateoption_text: "Oversæt tilbage", translated_watermark_text: "oversat" }; case "de": //german return { context_messagetranslateoption_text: "Nachricht übersetzen", context_messageuntranslateoption_text: "Nachricht unübersetzen", context_googletranslateoption_text: "Suche Übersetzung", popout_translateoption_text: "Übersetzen", popout_untranslateoption_text: "Unübersetzen", translated_watermark_text: "übersetzt" }; case "es": //spanish return { context_messagetranslateoption_text: "Traducir mensaje", context_messageuntranslateoption_text: "Traducir mensaje de vuelta", context_googletranslateoption_text: "Buscar traducción", popout_translateoption_text: "Traducir", popout_untranslateoption_text: "Traducir de vuelta", translated_watermark_text: "traducido" }; case "fr": //french return { context_messagetranslateoption_text: "Traduire le message", context_messageuntranslateoption_text: "Traduire le message en retour", context_googletranslateoption_text: "Rechercher une traduction", popout_translateoption_text: "Traduire", popout_untranslateoption_text: "Traduire en arrière", translated_watermark_text: "traduit" }; case "it": //italian return { context_messagetranslateoption_text: "Tradurre il messaggio", context_messageuntranslateoption_text: "Tradurre il messaggio indietro", context_googletranslateoption_text: "Cerca la traduzione", popout_translateoption_text: "Traduci", popout_untranslateoption_text: "Traduci indietro", translated_watermark_text: "tradotto" }; case "nl": //dutch return { context_messagetranslateoption_text: "Vertaal bericht", context_messageuntranslateoption_text: "Vertaal bericht terug", context_googletranslateoption_text: "Zoek vertaling", popout_translateoption_text: "Vertaal", popout_untranslateoption_text: "Vertaal terug", translated_watermark_text: "vertaalde" }; case "no": //norwegian return { context_messagetranslateoption_text: "Oversett melding", context_messageuntranslateoption_text: "Oversett melding tilbake", context_googletranslateoption_text: "Søk oversettelse", popout_translateoption_text: "Oversett", popout_untranslateoption_text: "Oversett tilbake", translated_watermark_text: "oversatt" }; case "pl": //polish return { context_messagetranslateoption_text: "Przetłumacz wiadomość", context_messageuntranslateoption_text: "Przetłumacz wiadomość z powrotem", context_googletranslateoption_text: "Wyszukaj tłumaczenie", popout_translateoption_text: "Przetłumacz", popout_untranslateoption_text: "Przetłumacz ponownie", translated_watermark_text: "przetłumaczony" }; case "pt-BR": //portuguese (brazil) return { context_messagetranslateoption_text: "Traduzir mensagem", context_messageuntranslateoption_text: "Traduzir mensagem de volta", context_googletranslateoption_text: "Pesquisar tradução", popout_translateoption_text: "Traduzir", popout_untranslateoption_text: "Traduzir de volta", translated_watermark_text: "traduzido" }; case "fi": //finnish return { context_messagetranslateoption_text: "Käännä viesti", context_messageuntranslateoption_text: "Käännä viesti takaisin", context_googletranslateoption_text: "Etsi käännös", popout_translateoption_text: "Kääntää", popout_untranslateoption_text: "Käännä takaisin", translated_watermark_text: "käännetty" }; case "sv": //swedish return { context_messagetranslateoption_text: "Översätt meddelande", context_messageuntranslateoption_text: "Översätt meddelandet tillbaka", context_googletranslateoption_text: "Sök översättning", popout_translateoption_text: "Översätt", popout_untranslateoption_text: "Översätt tillbaka", translated_watermark_text: "översatt" }; case "tr": //turkish return { context_messagetranslateoption_text: "Mesajı çevir", context_messageuntranslateoption_text: "İletiyi geri çevir", context_googletranslateoption_text: "Arama tercümesi", popout_translateoption_text: "Çevirmek", popout_untranslateoption_text: "Geri çevir", translated_watermark_text: "tercüme" }; case "cs": //czech return { context_messagetranslateoption_text: "Přeposlat zprávu", context_messageuntranslateoption_text: "Přeposlat zprávu zpátky", context_googletranslateoption_text: "Hledat překlad", popout_translateoption_text: "Přeposlat", popout_untranslateoption_text: "Přeposlat zpět", translated_watermark_text: "přeloženo" }; case "bg": //bulgarian return { context_messagetranslateoption_text: "Преведете на съобщението", context_messageuntranslateoption_text: "Преведете съобщението обратно", context_googletranslateoption_text: "Търсене на превод", popout_translateoption_text: "Превод", popout_untranslateoption_text: "Превод обратно", translated_watermark_text: "преведена" }; case "ru": //russian return { context_messagetranslateoption_text: "Перевести сообщение", context_messageuntranslateoption_text: "Перевести сообщение обратно", context_googletranslateoption_text: "Поиск перевода", popout_translateoption_text: "Перевести", popout_untranslateoption_text: "Перевести обратно", translated_watermark_text: "переведенный" }; case "uk": //ukrainian return { context_messagetranslateoption_text: "Перекласти повідомлення", context_messageuntranslateoption_text: "Перекласти повідомлення назад", context_googletranslateoption_text: "Пошук перекладу", popout_translateoption_text: "Перекласти", popout_untranslateoption_text: "Перекласти назад", translated_watermark_text: "перекладений" }; case "ja": //japanese return { context_messagetranslateoption_text: "メッセージを翻訳する", context_messageuntranslateoption_text: "メッセージを翻訳する", context_googletranslateoption_text: "翻訳の検索", popout_translateoption_text: "翻訳", popout_untranslateoption_text: "翻訳する", translated_watermark_text: "翻訳された" }; case "zh-TW": //chinese (traditional) return { context_messagetranslateoption_text: "翻譯消息", context_messageuntranslateoption_text: "翻譯消息", context_googletranslateoption_text: "搜索翻譯", popout_translateoption_text: "翻譯", popout_untranslateoption_text: "翻譯回來", translated_watermark_text: "翻譯" }; case "ko": //korean return { context_messagetranslateoption_text: "메시지 번역", context_messageuntranslateoption_text: "메시지 번역 뒤로", context_googletranslateoption_text: "검색 번역", popout_translateoption_text: "다시", popout_untranslateoption_text: "다시 번역", translated_watermark_text: "번역 된" }; default: //default: english return { context_messagetranslateoption_text: "Translate Message", context_messageuntranslateoption_text: "Untranslate Message", context_googletranslateoption_text: "Search translation", popout_translateoption_text: "Translate", popout_untranslateoption_text: "Untranslate", translated_watermark_text: "translated" }; } } }