//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.5";}
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 = {
"added":[["Favorites","You can now add languages to your own favorites list, these languages will appear at the top of your choicemenu"]]
};
this.labels = {};
this.patchModules = {
"ChannelTextArea":"componentDidMount",
"Message":"componentDidMount",
"MessageContent":"componentDidMount",
"StandardSidebarView":"componentWillUnmount"
};
}
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: {
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", 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.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) : ""}
${BDFDB.createSelectMenu(`
`, this.defaults.choices[key].value, key)}
`).join("")}
`;
this.css = `
${BDFDB.dotCNS.textareawrapall + BDFDB.dotCN.textareainner} {
align-items: center;
}
${BDFDB.dotCNS.textareawrapall + BDFDB.dotCN.textareainner} .send-button {
top: 0;
bottom: 0;
right: 9px;
}
${BDFDB.dotCN.textareabuttonwrapper}.translate-button.translating-active ${BDFDB.dotCN.textareaicon} {
color: #F04747 !important;
}
.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.messagegroup} .GTO-translated-message ${BDFDB.dotCNS.messagebody + BDFDB.dotCN.messagemarkup} {
font-size: 0 !important;
}
${BDFDB.dotCN.messagegroup} .GTO-translated-message ${BDFDB.dotCNS.messagebody + BDFDB.dotCN.messagemarkup} > .GTO-translation {
font-size: 1rem !important;
}
${BDFDB.dotCN.messagegroup} .GTO-translated-message ${BDFDB.dotCNS.messagebody + BDFDB.dotCN.messagemarkup} > :not(.GTO-translation)${BDFDB.notCN.messageheadercompact + BDFDB.notCN.messageedited} {
display: none !important;
}`;
}
getSettingsPanel () {
if (!global.BDFDB || typeof BDFDB != "object" || !BDFDB.loaded || !this.started) return;
var choices = BDFDB.getAllData(this, "choices");
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `${this.name}
`;
for (let key in choices) {
let choice = this.getLanguageChoice(key);
settingshtml += `
${this.defaults.choices[key].description}
${BDFDB.createSelectMenu(this.createSelectChoice(choice), choice, key)}
`
}
for (let key in settings) {
settingshtml += `
`;
}
settingshtml += `
`;
let settingspanel = BDFDB.htmlToElement(settingshtml);
BDFDB.initElements(settingspanel, this);
BDFDB.addEventListener(this, settingspanel, "click", BDFDB.dotCN.selectcontrol, e => {
let type = BDFDB.getParentEle(BDFDB.dotCN.select, e.currentTarget).getAttribute("type");
let menulanguages = this.defaults.choices[type].direction == "Output" ? BDFDB.filterObject(this.languages, lang => {return lang.id != "auto";}) : this.languages;
BDFDB.openDropdownMenu(e, this.saveSelectChoice.bind(this), this.createSelectChoice.bind(this), menulanguages);
});
return settingspanel;
}
//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.js");
libraryScript.setAttribute("date", performance.now());
libraryScript.addEventListener("load", () => {this.initialize();});
document.head.appendChild(libraryScript);
this.libLoadTimeout = setTimeout(() => {
libraryScript.remove();
BDFDB.LibraryRequires.request("https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js", (error, response, body) => {
if (body) {
libraryScript = document.createElement("script");
libraryScript.setAttribute("id", "BDFDBLibraryScript");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("date", performance.now());
libraryScript.innerText = body;
document.head.appendChild(libraryScript);
}
this.initialize();
});
}, 15000);
}
else if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) this.initialize();
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
}
initialize () {
if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) {
if (this.started) return;
BDFDB.loadMessage(this);
this.setLanguages();
BDFDB.WebModules.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) {
document.querySelectorAll(BDFDB.dotCN.messagegroup + " .GTO-translated-message").forEach(message => {
this.resetMessage(message);
});
BDFDB.removeEles(".translate-button", ".popout-googletranslate");
BDFDB.unloadMessage(this);
}
}
// begin of own functions
onMessageContextMenu (instance, menu, returnvalue) {
if (instance.props && instance.props.message && instance.props.channel && instance.props.target && !menu.querySelector(`${this.name}-contextMenuItem`)) {
let {messagediv, pos} = this.getMessageAndPos(instance.props.target);
if (!messagediv || pos == -1) return;
let translated = BDFDB.containsClass(messagediv, "GTO-translated-message");
let [children, index] = BDFDB.getContextMenuGroupAndIndex(returnvalue, "MessagePinItem");
const translateUntranslateItem = BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuItem, {
label: translated ? this.labels.context_messageuntranslateoption_text : this.labels.context_messagetranslateoption_text,
hint: BDFDB.isPluginEnabled("MessageUtilities") ? window.bdplugins.MessageUtilities.plugin.getActiveShortcutString("__Translate_Message") : null,
className: `BDFDB-contextMenuItem ${this.name}-contextMenuItem ${this.name}-${translated ? "untranslate" : "translate"}-contextMenuItem`,
action: e => {
BDFDB.closeContextMenu(menu);
this.translateMessage(instance.props.message, instance.props.target, 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.getReactValue(bdplugins, "GoogleSearchReplace.plugin.labels.context_googlesearchreplace_text");
let [children2, index2] = BDFDB.getContextMenuGroupAndIndex(returnvalue, GSRstring ? ["SearchWithGoogle", GSRstring] : "SearchWithGoogle");
var foundtranslation, foundinput, foundoutput;
const searchTranslationItem = BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuItem, {
label: this.labels.context_googletranslateoption_text,
className: `BDFDB-contextMenuItem ${this.name}-contextMenuItem ${this.name}-searchtranslation-contextMenuItem`,
action: e => {
var item = BDFDB.getParentEle(BDFDB.dotCN.contextmenuitem, e.target);
if (item) {
var createTooltip = () => {
BDFDB.createTooltip(`From ${foundinput.name}:\n${text}\n\nTo ${foundoutput.name}:\n${foundtranslation}`, item, {type:"right", selector:"googletranslate-tooltip"});
};
if (foundtranslation && foundinput && foundoutput) {
if (document.querySelector(".googletranslate-tooltip")) {
BDFDB.closeContextMenu(menu);
window.open(this.getGoogleTranslatePageURL(foundinput.id, foundoutput.id, text), "_blank");
}
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 (instance, popout, returnvalue) {
if (instance.props.message && instance.props.channel && instance.props.target && !popout.querySelector(`${this.name}-popoutMenuItem`)) {
let {messagediv, pos} = this.getMessageAndPos(instance.props.target);
if (!messagediv || pos == -1) return;
let translated = BDFDB.containsClass(messagediv, "GTO-translated-message");
let [children, index] = BDFDB.getContextMenuGroupAndIndex(returnvalue, [BDFDB.LanguageStrings.PIN, BDFDB.LanguageStrings.UNPIN]);
const translateUntranslateItem = BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuItem, {
label: this.labels[translated ? "popout_untranslateoption_text" : "popout_translateoption_text"],
className: `${BDFDB.disCN.optionpopoutitem} BDFDB-popoutMenuItem ${this.name}-popoutMenuItem ${this.name}-${translated ? "untranslate" : "translate"}-popoutMenuItem`,
action: e => {
this.translateMessage(instance.props.message, instance.props.target, instance.props.channel);
instance.props.onClose();
}
});
children.splice(index + 1, 0, translateUntranslateItem);
}
}
setLanguages () {
this.languages = Object.assign({},
{"auto": {name:"Auto", id:"auto", integrated:false, dic:false}},
BDFDB.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.loadAllData(this, "favorites")
for (let id in this.languages) this.languages[id].fav = favorites[id] != undefined ? 0 : 1;
this.languages = BDFDB.sortObject(this.languages, "fav");
}
getLanguageChoice (direction, place) {
this.setLanguages();
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;
}
processStandardSidebarView (instance, wrapper, returnvalue) {
if (this.SettingsUpdated) {
delete this.SettingsUpdated;
this.setLanguages();
BDFDB.removeEles(".translate-button");
BDFDB.WebModules.forceAllUpdates(this, "ChannelTextArea");
}
}
processChannelTextArea (instance, wrapper, returnvalue) {
if (instance.props && instance.props.type && instance.props.type == "normal" && !instance.props.disabled && !wrapper.querySelector(".translate-button") && BDFDB.getData("addTranslateButton", this, "settings")) {
let textarea = wrapper.querySelector("textarea");
if (textarea) {
var buttoncontainer = wrapper.querySelector(BDFDB.dotCN.textareapickerbuttons);
if (!buttoncontainer) return;
var translateButton = BDFDB.htmlToElement(this.translateButtonMarkup);
translateButton.addEventListener("click", () => {
this.openTranslatePopout(translateButton);
});
translateButton.addEventListener("contextmenu", () => {
this.translating = !this.translating;
BDFDB.toggleClass(document.querySelectorAll(BDFDB.dotCNS.textareawrapchat + ".translate-button"), "translating-active", this.translating);
});
buttoncontainer.insertBefore(translateButton, buttoncontainer.firstElementChild);
BDFDB.addClass(translateButton, instance.props.type);
BDFDB.toggleClass(translateButton, "translating-active", this.translating);
BDFDB.addEventListener(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.getData("sendOriginalMessage", this, "settings") ? text + "\n\n" + translation : translation);
textarea.focus();
document.execCommand("insertText", false, translation + " ");
BDFDB.triggerSend(textarea);
});
}
}
});
BDFDB.addEventListener(this, textarea, "keydown", e => {
if (textarea.value && this.translating && !e.shiftKey && e.which == 13 && !wrapper.querySelector(BDFDB.dotCN.autocomplete)) {
this.doTranslate = true;
textarea.dispatchEvent(new Event("input"));
}
});
}
}
}
processMessage (instance, wrapper, returnvalue) {
if (instance.props && typeof instance.props.renderButtons == "function" && !wrapper.querySelector(BDFDB.dotCN.optionpopoutbutton) && BDFDB.getReactValue(instance, "props.message.author.id") != 1) {
let buttonwrap = wrapper.querySelector(BDFDB.dotCN.messagebuttoncontainer);
if (buttonwrap) {
let optionPopoutButton = BDFDB.htmlToElement(``);
optionPopoutButton.addEventListener("click", () => {BDFDB.createMessageOptionPopout(optionPopoutButton);});
buttonwrap.appendChild(optionPopoutButton);
}
}
}
processMessageContent (instance, wrapper, returnvalue) {
if (instance.props && instance.props.message && instance.props.channel) {
let messagediv = BDFDB.getParentEle(".GTO-translated-message", wrapper);
if (messagediv && !wrapper.querySelector(".GTO-translation")) BDFDB.removeClass(messagediv, "GTO-translated-message");
}
}
getMessageAndPos (target) {
let messagediv = BDFDB.getParentEle(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 fakemarkup = markup.cloneNode(true);
BDFDB.removeEles(fakemarkup.querySelectorAll(BDFDB.dotCNC.messageheadercompact + BDFDB.dotCN.messageedited));
this.translateText(fakemarkup.innerHTML, "context", (translation, input, output) => {
if (translation) {
let compactheader = markup.querySelector(BDFDB.dotCN.messageheadercompact);
markup.insertBefore(BDFDB.htmlToElement(``), compactheader ? compactheader.nextSibling : markup.firstChild);
markup.querySelector(BDFDB.dotCN.messageedited + ".GTO-translated").addEventListener("mouseenter", e => {
BDFDB.createTooltip(`From: ${input.name}
To: ${output.name}
`, e.currentTarget, {html:true, type:"top", selector:"translation-tooltip"});
});
BDFDB.addClass(messagediv, "GTO-translated-message");
}
});
}
else this.resetMessage(messagediv);
}
resetMessage (messagediv) {
BDFDB.removeEles(messagediv.querySelector(".GTO-translation"));
BDFDB.removeClass(messagediv, "GTO-translated-message");
}
translateText (text, type, callback) {
var toast = null;
var finishTranslation = (translation, exceptions, input, output, toast) => {
if (translation) translation = this.addExceptions(translation, exceptions);
if (toast) {
clearInterval(toast.interval);
toast.close();
}
callback(translation, input, output);
};
var translationError = (exceptions, input, output, toast, test) => {
BDFDB.showToast("Could not translate message, you most likely got rate limited by Google for today due to too frequent usage of their Translate-API.", {type:"error",timeout:15000});
finishTranslation(null, exceptions, input, output, toast);
};
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) {
toast = BDFDB.showToast("Translating. Please wait", {timeout:0});
toast.interval = setInterval(() => {
toast.textContent = toast.textContent.indexOf(".....") > -1 ? "Translating. Please wait" : toast.textContent + ".";
},500);
var specialcase = this.checkForSpecialCase(newtext, input);
if (specialcase) {
input.name = specialcase.name;
switch (specialcase.id) {
case "binary": newtext = this.binary2string(newtext); break;
case "braille": newtext = this.braille2string(newtext); break;
case "morse": newtext = this.morse2string(newtext); break;
}
}
if (output.id == "binary" || output.id == "braille" || output.id == "morse") {
switch (output.id) {
case "binary": newtext = this.string2binary(newtext); break;
case "braille": newtext = this.string2braille(newtext); break;
case "morse": newtext = this.string2morse(newtext); break;
}
finishTranslation(newtext, exceptions, input, output, toast);
}
else {
BDFDB.LibraryRequires.request(this.getGoogleTranslateApiURL(input.id, output.id, newtext), (error, response, result) => {
if (!error && result) {
try {
result = JSON.parse(result);
if (result) {
result[0].forEach((array) => {translation += array[0];});
if (!specialcase && this.languages[result[2]]) input.name = this.languages[result[2]].name;
}
else translation = text;
finishTranslation(translation, exceptions, input, output, toast);
}
catch (err) {
translationError(exceptions, input, output, toast, "a");
}
}
else translationError(exceptions, input, output, toast, "b");
});
}
}
else {
translation = text;
finishTranslation(translation, exceptions, input, output, toast);
}
}
checkForSpecialCase (text, input) {
if (input.id == "binary" || input.id == "braille" || input.id == "morse") return input;
else if (input.id == "auto") {
if (/^[0-1]*$/.test(text.replace(/\s/g, ""))) {
return {id: "binary", name: "Binary"};
}
else if (/^[⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿]*$/.test(text.replace(/\s/g, ""))) {
return {id: "braille", name: "Braille 6-dot"};
}
else if (/^[/|·−._-]*$/.test(text.replace(/\s/g, ""))) {
return {id: "morse", name: "Morse"};
}
}
return null;
}
string2binary (string) {
var binary = "";
for (let character of string) binary += parseInt(character.charCodeAt(0).toString(2)).toPrecision(8).split(".").reverse().join("").toString() + " ";
return binary;
}
string2braille (string) {
var braille = "";
for (let character of string) braille += this.brailleConverter[character.toLowerCase()] ? this.brailleConverter[character.toLowerCase()] : character;
return braille;
}
string2morse (string) {
string = string.replace(/ /g, "%%%%%%%%%%");
var morse = "";
for (let character of string) morse += (this.morseConverter[character.toLowerCase()] ? this.morseConverter[character.toLowerCase()] : character) + " ";
morse = morse.split("\n");
for (let i in morse) morse[i] = morse[i].trim();
return morse.join("\n").replace(/% % % % % % % % % % /g, "/ ");
}
binary2string (binary) {
var string = "";
binary = binary.replace(/\n/g, "00001010").replace(/\r/g, "00001101").replace(/\t/g, "00001001").replace(/\s/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;
}
braille2string (braille) {
var string = "";
for (let character of braille) string += this.brailleConverter[character.toLowerCase()] ? this.brailleConverter[character.toLowerCase()] : character;
return string;
}
morse2string (morse) {
var string = "";
for (let word of morse.replace(/[_-]/g, "−").replace(/\./g, "·").replace(/\r|\t/g, "").split(/\/|\||\n/g)) {
for (let characterstr of word.trim().split(" ")) string += this.morseConverter[characterstr] ? this.morseConverter[characterstr] : characterstr;
string += " ";
}
return string.trim();
}
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) {
let container = document.querySelector(BDFDB.dotCN.popouts);
if (!container || BDFDB.containsClass(button, BDFDB.disCN.textareabuttonactive)) return;
BDFDB.addClass(button, BDFDB.disCN.textareabuttonactive);
let translatepopout = BDFDB.htmlToElement(this.translatePopoutMarkup);
container.appendChild(translatepopout);
let buttonrects = BDFDB.getRects(button);
translatepopout.style.setProperty("left", buttonrects.left + buttonrects.width + "px");
translatepopout.style.setProperty("top", buttonrects.top - buttonrects.height/2 + "px")
BDFDB.addChildEventListener(translatepopout, "click", BDFDB.dotCN.selectcontrol, e => {
let type = BDFDB.getParentEle(BDFDB.dotCN.select, e.currentTarget).getAttribute("type");
let menulanguages = this.defaults.choices[type].direction == "Output" ? BDFDB.filterObject(this.languages, lang => {return lang.id != "auto";}) : this.languages;
let menu = BDFDB.openDropdownMenu(e, this.saveSelectChoice.bind(this), this.createSelectChoice.bind(this), menulanguages, true);
BDFDB.addChildEventListener(menu, "click", BDFDB.dotCN.giffavoritebutton, e => {
let choice = e.currentTarget.parentElement.getAttribute("value");
if (choice) {
let favorize = !BDFDB.loadData(choice, this, "favorites")
if (favorize) BDFDB.saveData(choice, true, this, "favorites");
else BDFDB.removeData(choice, this, "favorites");
this.setLanguages();
}
});
});
BDFDB.addChildEventListener(translatepopout, "click", ".reverse-button", e => {
let place = e.currentTarget.getAttribute("type").replace("output","");
let input = this.getLanguageChoice("output", place);
let output = this.getLanguageChoice("input", place);
output = output == "auto" ? "en" : output;
let inputselect = translatepopout.querySelector(BDFDB.dotCN.select + "[type='input" + place + "']");
let outputselect = translatepopout.querySelector(BDFDB.dotCN.select + "[type='output" + place + "']");
inputselect.setAttribute("value", input);
inputselect.querySelector(BDFDB.dotCN.title).innerText = this.languages[input].name;
outputselect.setAttribute("value", output);
outputselect.querySelector(BDFDB.dotCN.title).innerText = this.languages[output].name;
BDFDB.saveData("input" + place, input, this, "choices");
BDFDB.saveData("output" + place, output, this, "choices");
});
translatepopout.querySelectorAll(BDFDB.dotCN.select).forEach(selectWrap => {
let language = this.getLanguageChoice(selectWrap.getAttribute("type"));
selectWrap.setAttribute("value", language);
selectWrap.querySelector(BDFDB.dotCN.title).innerText = this.languages[language].name;
});
var translatecheckbox = translatepopout.querySelector("#translating-checkbox");
translatecheckbox.checked = this.translating;
translatecheckbox.addEventListener("click", () => {
BDFDB.toggleClass(button, "translating-active", translatecheckbox.checked);
this.translating = translatecheckbox.checked;
});
var removePopout = e => {
if (!translatepopout.contains(e.target)) {
document.removeEventListener("mousedown", removePopout);
translatepopout.remove();
setTimeout(() => {BDFDB.removeClass(button, BDFDB.disCN.textareabuttonactive);},300);
}
};
document.addEventListener("mousedown", removePopout);
BDFDB.initElements(translatepopout, this);
}
saveSelectChoice (selectWrap, type, choice) {
if (type && choice) {
selectWrap.querySelector(BDFDB.dotCN.title).innerText = this.languages[choice].name;
BDFDB.saveData(type, choice, this, "choices");
}
}
createSelectChoice (key) {
return `${this.languages[key].name}
`;
}
getGoogleTranslateApiURL (input, output, text) {
input = BDFDB.languages[input] ? input : "auto";
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) {
input = BDFDB.languages[input] ? input : "auto";
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"
};
}
}
}