//META{"name":"GoogleTranslateOption","website":"https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/GoogleTranslateOption","source":"https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/GoogleTranslateOption/GoogleTranslateOption.plugin.js"}*// class GoogleTranslateOption { getName () {return "GoogleTranslateOption";} getVersion () {return "1.7.7";} getAuthor () {return "DevilBro";} 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.";} constructor () { this.changelog = { "improved":[["Right Click","Fixed issue where right click would not quick enable/disable translating"]] }; this.patchedModules = { after: { ChannelTextArea: ["componentDidMount","render"], Message: "componentDidMount", MessageContent: "componentDidMount" } }; } initConstructor () { this.languages = {}; this.doTranslate = false; this.translating = false; this.brailleConverter = { "0":"⠴", "1":"⠂", "2":"⠆", "3":"⠒", "4":"⠲", "5":"⠢", "6":"⠖", "7":"⠶", "8":"⠦", "9":"⠔", "!":"⠮", "\"":"⠐", "#":"⠼", "$":"⠫", "%":"⠩", "&":"⠯", "'":"⠄", "(":"⠷", ")":"⠾", "*":"⠡", "+":"⠬", ",":"⠠", "-":"⠤", ".":"⠨", "/":"⠌", ":":"⠱", ";":"⠰", "<":"⠣", "=":"⠿", ">":"⠜", "?":"⠹", "@":"⠈", "a":"⠁", "b":"⠃", "c":"⠉", "d":"⠙", "e":"⠑", "f":"⠋", "g":"⠛", "h":"⠓", "i":"⠊", "j":"⠚", "k":"⠅", "l":"⠇", "m":"⠍", "n":"⠝", "o":"⠕", "p":"⠏", "q":"⠟", "r":"⠗", "s":"⠎", "t":"⠞", "u":"⠥", "v":"⠧", "w":"⠺", "x":"⠭", "y":"⠽", "z":"⠵", "[":"⠪", "\\":"⠳", "]":"⠻", "^":"⠘", "⠁":"a", "⠂":"1", "⠃":"b", "⠄":"'", "⠅":"k", "⠆":"2", "⠇":"l", "⠈":"@", "⠉":"c", "⠊":"i", "⠋":"f", "⠌":"/", "⠍":"m", "⠎":"s", "⠏":"p", "⠐":"\"", "⠑":"e", "⠒":"3", "⠓":"h", "⠔":"9", "⠕":"o", "⠖":"6", "⠗":"r", "⠘":"^", "⠙":"d", "⠚":"j", "⠛":"g", "⠜":">", "⠝":"n", "⠞":"t", "⠟":"q", "⠠":", ", "⠡":"*", "⠢":"5", "⠣":"<", "⠤":"-", "⠥":"u", "⠦":"8", "⠧":"v", "⠨":".", "⠩":"%", "⠪":"[", "⠫":"$", "⠬":"+", "⠭":"x", "⠮":"!", "⠯":"&", "⠰":";", "⠱":":", "⠲":"4", "⠳":"\\", "⠴":"0", "⠵":"z", "⠶":"7", "⠷":"(", "⠸":"_", "⠹":"?", "⠺":"w", "⠻":"]", "⠼":"#", "⠽":"y", "⠾":")", "⠿":"=", "_":"⠸" }; this.morseConverter = { "0":"−−−−−", "1":"·−−−−", "2":"··−−−", "3":"···−−", "4":"····−", "5":"·····", "6":"−····", "7":"−−···", "8":"−−−··", "9":"−−−−·", "!":"−·−·−−", "\"":"·−··−·", "$":"···−··−", "&":"·−···", "'":"·−−−−·", "(":"−·−−·", ")":"−·−−·−", "+":"·−·−·", ",":"−−··−−", "-":"−····−", ".":"·−·−·−", "/":"−··−·", ":":"−−−···", ";":"−·−·−·", "=":"−···−", "?":"··−−··", "@":"·−−·−·", "a":"·−", "b":"−···", "c":"−·−·", "d":"−··", "e":"·", "f":"··−·", "g":"−−·", "h":"····", "i":"··", "j":"·−−−", "k":"−·−", "l":"·−··", "m":"−−", "n":"−·", "o":"−−−", "p":"·−−·", "q":"−−·−", "r":"·−·", "s":"···", "t":"−", "u":"··−", "v":"···−", "w":"·−−", "x":"−··−", "y":"−·−−", "z":"−−··", "·":"e", "··":"i", "···":"s", "····":"h", "·····":"5", "····−":"4", "···−":"v", "···−··−":"$", "···−−":"3", "··−":"u", "··−·":"f", "··−−··":"?", "··−−·−":"_", "··−−−":"2", "·−":"a", "·−·":"r", "·−··":"l", "·−···":"&", "·−··−·":"\"", "·−·−·":"+", "·−·−·−":".", "·−−":"w", "·−−·":"p", "·−−·−·":"@", "·−−−":"j", "·−−−−":"1", "·−−−−·":"'", "−":"t", "−·":"n", "−··":"d", "−···":"b", "−····":"6", "−····−":"-", "−···−":"=", "−··−":"x", "−··−·":"/", "−·−":"k", "−·−·":"c", "−·−·−·":";", "−·−·−−":"!", "−·−−":"y", "−·−−·":"(", "−·−−·−":")", "−−":"m", "−−·":"g", "−−··":"z", "−−···":"7", "−−··−−":",", "−−·−":"q", "−−−":"o", "−−−··":"8", "−−−···":":", "−−−−·":"9", "−−−−−":"0", "_":"··−−·−" }; this.defaults = { settings: { useChromium: {value:false, description:"Use an inbuilt browser window instead of opening your default browser"}, addTranslateButton: {value:true, description:"Adds an translate button to the chatbar"}, sendOriginalMessage: {value:false, description:"Send the original message together with the translation"} }, choices: { inputContext: {value:"auto", direction:"input", place:"Context", description:"Input Language in received Messages:"}, outputContext: {value:"$discord", direction:"output", place:"Context", description:"Output Language in received Messages:"}, inputMessage: {value:"auto", direction:"input", place:"Message", description:"Input Language in sent Messages:"}, outputMessage: {value:"$discord", direction:"output", place:"Message", description:"Output Language in sent Messages:"} } }; this.css = ` .translate-button.translating-active ${BDFDB.dotCN.textareaicon} { color: #F04747 !important; } .reverse-button { opacity: 0.5; margin-right: 5px; transition: all 200ms ease; } .reverse-button:hover { opacity: 1; } ${BDFDB.dotCN.messagegroup} .GTO-translated-message ${BDFDB.dotCNS.messagebody + BDFDB.dotCN.messagemarkup}, ${BDFDB.dotCN.messagegroup} .GTO-translated-message ${BDFDB.dotCNS.messageaccessory + BDFDB.dotCN.embeddescription} { font-size: 0 !important; line-height: 0 !important; } ${BDFDB.dotCN.messagegroup} .GTO-translated-message ${BDFDB.dotCNS.messagebody + BDFDB.dotCN.messagemarkup} > .GTO-translation { font-size: 1rem !important; line-height: 1.375 !important; } ${BDFDB.dotCN.messagegroup} .GTO-translated-message ${BDFDB.dotCNS.messageaccessory + BDFDB.dotCN.embeddescription} > .GTO-translation { font-size: 0.875rem !important; line-height: 1rem !important; } ${BDFDB.dotCN.messagegroup} .GTO-translated-message ${BDFDB.dotCNS.messagebody + BDFDB.dotCN.messagemarkup} > :not(.GTO-translation)${BDFDB.notCN.messageheadercompact + BDFDB.notCN.messageedited}, ${BDFDB.dotCN.messagegroup} .GTO-translated-message ${BDFDB.dotCNS.messageaccessory + BDFDB.dotCN.embeddescription} > :not(.GTO-translation)${BDFDB.notCN.messageedited} { display: none !important; }`; } getSettingsPanel () { if (!global.BDFDB || typeof BDFDB != "object" || !BDFDB.loaded || !this.started) return; let settings = BDFDB.DataUtils.get(this, "settings"); let settingsitems = []; settingsitems = settingsitems.concat(this.createSelects(false)); for (let key in settings) settingsitems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, { className: BDFDB.disCN.marginbottom8, type: "Switch", plugin: this, keys: ["settings", key], label: this.defaults.settings[key].description, value: settings[key] })); return BDFDB.PluginUtils.createSettingsPanel(this, settingsitems); } //legacy load () {} start () { if (!global.BDFDB) global.BDFDB = {myPlugins:{}}; if (global.BDFDB && global.BDFDB.myPlugins && typeof global.BDFDB.myPlugins == "object") global.BDFDB.myPlugins[this.getName()] = this; var libraryScript = document.querySelector('head script#BDFDBLibraryScript'); if (!libraryScript || (performance.now() - libraryScript.getAttribute("date")) > 600000) { if (libraryScript) libraryScript.remove(); libraryScript = document.createElement("script"); libraryScript.setAttribute("id", "BDFDBLibraryScript"); libraryScript.setAttribute("type", "text/javascript"); libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.min.js"); libraryScript.setAttribute("date", performance.now()); libraryScript.addEventListener("load", () => {this.initialize();}); document.head.appendChild(libraryScript); } else if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) this.initialize(); this.startTimeout = setTimeout(() => { try {return this.initialize();} catch (err) {console.error(`%c[${this.getName()}]%c`, "color: #3a71c1; font-weight: 700;", "", "Fatal Error: Could not initiate plugin! " + err);} }, 30000); } initialize () { if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) { if (this.started) return; BDFDB.PluginUtils.init(this); this.setLanguages(); BDFDB.ModuleUtils.forceAllUpdates(this); } else console.error(`%c[${this.getName()}]%c`, "color: #3a71c1; font-weight: 700;", "", "Fatal Error: Could not load BD functions!"); } stop () { if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) { this.stopping = true; document.querySelectorAll(BDFDB.dotCN.messagegroup + " .GTO-translated-message").forEach(message => { this.resetMessage(message); }); BDFDB.ModuleUtils.forceAllUpdates(this, "ChannelTextArea"); BDFDB.PluginUtils.clear(this); } } // begin of own functions onSettingsClosed (instance, wrapper, returnvalue) { if (this.SettingsUpdated) { delete this.SettingsUpdated; this.setLanguages(); BDFDB.ModuleUtils.forceAllUpdates(this, "ChannelTextArea"); } } onMessageContextMenu (e) { if (e.instance.props.message && e.instance.props.channel && e.instance.props.target) { let {messagediv, pos} = this.getMessageAndPos(e.instance.props.target); if (!messagediv || pos == -1) return; let translated = BDFDB.DOMUtils.containsClass(messagediv, "GTO-translated-message"); let [children, index] = BDFDB.ReactUtils.findChildren(e.returnvalue, {name:"MessagePinItem"}); const translateUntranslateItem = BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.ContextMenuItem, { label: translated ? this.labels.context_messageuntranslateoption_text : this.labels.context_messagetranslateoption_text, hint: BDFDB.BDUtils.isPluginEnabled("MessageUtilities") ? BDFDB.BDUtils.getPlugin("MessageUtilities").getActiveShortcutString("__Translate_Message") : null, action: _ => { BDFDB.ContextMenuUtils.close(e.instance); this.translateMessage(e.instance.props.message, e.instance.props.target, e.instance.props.channel); } }); if (index > -1) children.splice(index, 0, translateUntranslateItem); else children.push(translateUntranslateItem); let text = document.getSelection().toString(); if (text) { let GSRstring = BDFDB.ReactUtils.getValue(BDFDB.BDUtils.getPlugin("GoogleSearchReplace", true), "labels.context_googlesearchreplace_text"); let [children2, index2] = BDFDB.ReactUtils.findChildren(e.returnvalue, {name:"SearchWithGoogle", props: GSRstring ? [["label", GSRstring]] : null}); var foundtranslation, foundinput, foundoutput; const searchTranslationItem = BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.ContextMenuItem, { label: this.labels.context_googletranslateoption_text, action: event => { var item = BDFDB.DOMUtils.getParent(BDFDB.dotCN.contextmenuitem, event.target); if (item) { var createTooltip = () => { BDFDB.TooltipUtils.create(item, `From ${foundinput.name}:\n${text}\n\nTo ${foundoutput.name}:\n${foundtranslation}`, {type:"right", selector:"googletranslate-tooltip"}); }; if (foundtranslation && foundinput && foundoutput) { if (document.querySelector(".googletranslate-tooltip")) { BDFDB.ContextMenuUtils.close(menu); BDFDB.DiscordUtils.openLink(this.getGoogleTranslatePageURL(foundinput.id, foundoutput.id, text), BDFDB.DataUtils.get(this, "settings", "useChromium")); } else createTooltip(); } else this.translateText(text, "context", (translation, input, output) => { if (translation) { foundtranslation = translation, foundinput = input, foundoutput = output; createTooltip(); } }); } } }); if (index2 > -1) children2.splice(index2, 0, searchTranslationItem); else children2.push(searchTranslationItem); } } } onMessageOptionPopout (e) { if (e.instance.props.message && e.instance.props.channel && e.instance.props.target) { let {messagediv, pos} = this.getMessageAndPos(e.instance.props.target); if (!messagediv || pos == -1) return; let translated = BDFDB.DOMUtils.containsClass(messagediv, "GTO-translated-message"); let [children, index] = BDFDB.ReactUtils.findChildren(e.returnvalue, {props:[["label", [BDFDB.LanguageUtils.LanguageStrings.PIN, BDFDB.LanguageUtils.LanguageStrings.UNPIN]]]}); children.splice(index + 1, 0, BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.ContextMenuItem, { label: this.labels[translated ? "popout_untranslateoption_text" : "popout_translateoption_text"], className: BDFDB.disCN.optionpopoutitem, action: _ => { this.translateMessage(e.instance.props.message, e.instance.props.target, e.instance.props.channel); e.instance.props.onClose(); } })); } } processChannelTextArea (e) { if (e.instance.props.type != "normal" || e.instance.props.disabled) return; if (e.node) { let textarea = e.node.querySelector(BDFDB.dotCN.textarea); if (textarea) { BDFDB.ListenerUtils.add(this, textarea, "input", _ => { 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.DataUtils.get(this, "settings", "sendOriginalMessage") ? text + "\n\n" + translation : translation); textarea.focus(); document.execCommand("insertText", false, translation + " "); BDFDB.triggerSend(textarea); }); } } }); BDFDB.ListenerUtils.add(this, textarea, "keydown", event => { if (textarea.value && this.translating && !event.shiftKey && event.which == 13 && !e.node.querySelector(BDFDB.dotCN.autocomplete)) { this.doTranslate = true; textarea.dispatchEvent(new Event("input")); } }); } } if (e.returnvalue) { let [children, index] = BDFDB.ReactUtils.findChildren(e.returnvalue, {props:[["className", BDFDB.disCN.textareapickerbuttons]]}); if (index > -1 && children[index].props && children[index].props.children) children[index].props.children.unshift(this.createTranslateButton()); } } processMessageContent (e) { if (e.instance.props.message && e.instance.props.channel) { let messagediv = BDFDB.DOMUtils.getParent(".GTO-translated-message", e.node); if (messagediv && !e.node.querySelector(".GTO-translation")) BDFDB.DOMUtils.removeClass(messagediv, "GTO-translated-message"); } } createTranslateButton () { return BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.PopoutContainer, { children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.ChannelTextAreaButton, { className: BDFDB.DOMUtils.formatClassName("translate-button", this.translating && "translating-active", BDFDB.disCN.textareapickerbutton), iconClassName: BDFDB.disCN.textareaicon, iconSVG: `` }), width: 400, padding: 10, animation: BDFDB.LibraryComponents.PopoutContainer.Animation.SCALE, position: BDFDB.LibraryComponents.PopoutContainer.Positions.TOP, align: BDFDB.LibraryComponents.PopoutContainer.Align.RIGHT, onClose: instance => { let channelTextareaButtonIns = BDFDB.ReactUtils.findOwner(instance, {name:"BDFDB_ChannelTextAreaButton"}); if (channelTextareaButtonIns) { channelTextareaButtonIns.props.isActive = false; BDFDB.ReactUtils.forceUpdate(channelTextareaButtonIns); } }, onContextMenu: (e, instance) => { this.translating = !this.translating; let channelTextareaButtonIns = BDFDB.ReactUtils.findOwner(instance, {name:"BDFDB_ChannelTextAreaButton"}); if (channelTextareaButtonIns) { channelTextareaButtonIns.props.className = BDFDB.DOMUtils.formatClassName("translate-button", this.translating && "translating-active", BDFDB.disCN.textareapickerbutton); BDFDB.ReactUtils.forceUpdate(channelTextareaButtonIns); instance.close(); } }, renderPopout: instance => { let channelTextareaButtonIns = BDFDB.ReactUtils.findOwner(instance, {name:"BDFDB_ChannelTextAreaButton"}); if (channelTextareaButtonIns) { channelTextareaButtonIns.props.isActive = true; BDFDB.ReactUtils.forceUpdate(channelTextareaButtonIns); } let popoutelements = []; popoutelements.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, { className: BDFDB.disCN.marginbottom8, children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsLabel, { label: `Words starting with "!" will be ignored` }) })); popoutelements.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormComponents.FormDivider, { className: BDFDB.disCN.marginbottom8 })), popoutelements = popoutelements.concat(this.createSelects(true)); popoutelements.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, { type: "Switch", className: BDFDB.disCN.marginbottom8, label: "Translate your Messages before sending", value: this.translating, onChange: value => { this.translating = value; if (channelTextareaButtonIns) { channelTextareaButtonIns.props.className = ["translate-button", this.translating ? "translating-active" : null, BDFDB.disCN.textareapickerbutton].filter(n => n).join(" "); BDFDB.ReactUtils.forceUpdate(channelTextareaButtonIns); } } })); return popoutelements; } }); } createSelects (inPopout) { let selects = []; for (let key in this.defaults.choices) { let isOutput = this.defaults.choices[key].direction == "output"; selects.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormComponents.FormItem, { title: this.defaults.choices[key].description, titlechildren: isOutput ? BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Button, { look: BDFDB.LibraryComponents.Button.Looks.BLANK, size: BDFDB.LibraryComponents.Button.Sizes.NONE, onClick: e => { let place = this.defaults.choices[key].place; let input = this.getLanguageChoice("input", place); let output = this.getLanguageChoice("output", place); input = input == "auto" ? "en" : input; BDFDB.DataUtils.save(output, this, "choices", "input" + place); BDFDB.DataUtils.save(input, this, "choices", "output" + place); for (let selectIns of BDFDB.ReactUtils.findOwner(BDFDB.ReactUtils.findOwner(e._targetInst, {name:["BDFDB_Popout", "BDFDB_SettingsPanel"], up:true}), {name:"BDFDB_Select", all:true, noCopies:true})) if (selectIns && selectIns.props && selectIns.props.id && this.defaults.choices[selectIns.props.id].place == place) { selectIns.props.value = this.defaults.choices[selectIns.props.id].direction == "input" ? output : input; BDFDB.ReactUtils.forceUpdate(selectIns); } this.setLanguages(); }, children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, { iconSVG: `` }) }) : null, className: BDFDB.disCN.marginbottom8, children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Select, { menuPlacement: inPopout ? BDFDB.LibraryComponents.Select.MenuPlacements.TOP : BDFDB.LibraryComponents.Select.MenuPlacements.BOTTOM, value: this.getLanguageChoice(key), id: key, options: BDFDB.ObjectUtils.toArray(BDFDB.ObjectUtils.map(isOutput ? BDFDB.ObjectUtils.filter(this.languages, lang => lang.id != "auto") : this.languages, (lang, id) => {return {value:id, label:lang.name}})), searchable: true, optionRenderer: lang => { return BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, { align: BDFDB.LibraryComponents.Flex.Align.CENTER, children: [ BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, { grow: 1, children: lang.label }), inPopout ? BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FavButton, { isFavorite: this.languages[lang.value].fav == 0, onClick: value => { if (value) BDFDB.DataUtils.save(true, this, "favorites", lang.value); else BDFDB.DataUtils.remove(this, "favorites", lang.value); this.setLanguages(); } }) : null ] }); }, onChange: lang => { BDFDB.DataUtils.save(lang.value, this, "choices", key); } }) })); if (isOutput) selects.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormComponents.FormDivider, { className: BDFDB.disCN.marginbottom8 })); } return selects; } setLanguages () { this.languages = Object.assign({}, {"auto": {name:"Auto", id:"auto", integrated:false, dic:false}}, BDFDB.LanguageUtils.languages, {"binary": {name:"Binary", id:"binary", integrated:false, dic:false}}, {"braille": {name:"Braille 6-dot", id:"braille", integrated:false, dic:false}}, {"morse": {name:"Morse", id:"morse", integrated:false, dic:false}} ); let favorites = BDFDB.DataUtils.load(this, "favorites"); for (let id in this.languages) this.languages[id].fav = favorites[id] != undefined ? 0 : 1; this.languages = BDFDB.ObjectUtils.sort(this.languages, "fav"); } getLanguageChoice (direction, place) { this.setLanguages(); var type = place === undefined ? direction : direction.toLowerCase() + place.charAt(0).toUpperCase() + place.slice(1).toLowerCase(); var choice = BDFDB.DataUtils.get(this, "choices", type); choice = this.languages[choice] ? choice : Object.keys(this.languages)[0]; choice = type.indexOf("output") > -1 && choice == "auto" ? "en" : choice; return choice; } getMessageAndPos (target) { let messagediv = BDFDB.DOMUtils.getParent(BDFDB.dotCN.messagegroup + "> [aria-disabled]," + BDFDB.dotCN.messagegroup + "> * > [aria-disabled]", target); let pos = messagediv ? Array.from(messagediv.parentElement.childNodes).filter(n => n.nodeType != Node.TEXT_NODE).indexOf(messagediv) : -1; 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 : BDFDB.LibraryModules.ChannelStore.getChannel(message.channel_id); if (!messagediv.querySelector(BDFDB.dotCN.messageedited + ".GTO-translated")) { var markup = messagediv.querySelector(BDFDB.dotCN.messagemarkup); var accessory = messagediv.querySelector(BDFDB.dotCN.messageaccessory); var embeddescriptions = messagediv.querySelectorAll(BDFDB.dotCN.embeddescription); var fakemarkup = markup.cloneNode(true); BDFDB.DOMUtils.remove(fakemarkup.querySelectorAll(BDFDB.dotCNC.messageheadercompact + BDFDB.dotCN.messageedited)); let string = fakemarkup.innerHTML; if (embeddescriptions.length) for (let embeddescription of embeddescriptions) { string += "\n__________________ __________________ __________________\n"; string += embeddescription.innerHTML;; } this.translateText(string, "context", (translation, input, output) => { if (translation) { BDFDB.DOMUtils.addClass(messagediv, "GTO-translated-message"); let translations = translation.split("\n__________________ __________________ __________________\n"); let compactheader = markup.querySelector(BDFDB.dotCN.messageheadercompact); markup.insertBefore(BDFDB.DOMUtils.create(``), compactheader ? compactheader.nextSibling : markup.firstChild); if (embeddescriptions.length) for (let embeddescription of embeddescriptions) { embeddescription.insertBefore(BDFDB.DOMUtils.create(``), embeddescription.firstChild); } BDFDB.ListenerUtils.addToChildren(messagediv, "mouseenter", BDFDB.dotCN.messageedited + ".GTO-translated", e => { BDFDB.TooltipUtils.create(e.currentTarget, `