2020-02-27 08:44:03 +01:00
//META{"name":"GoogleTranslateOption","authorId":"278543574059057154","invite":"Jx3TjNS","donate":"https://www.paypal.me/MircoWittrien","patreon":"https://www.patreon.com/MircoWittrien","website":"https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/GoogleTranslateOption","source":"https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/GoogleTranslateOption/GoogleTranslateOption.plugin.js"}*//
2018-10-11 10:21:26 +02:00
2020-02-04 08:20:40 +01:00
var GoogleTranslateOption = ( _ => {
const translateIconGeneral = ` <svg x="0" y="0" aria-hidden="false" width="22" height="22" viewBox="0 -1 24 24" fill="currentColor"><mask/><g mask="url(#translateIconMask)"><path d="M 19.794, 3.299 H 9.765 L 8.797, 0 h -6.598 C 0.99, 0, 0, 0.99, 0, 2.199 V 16.495 c 0, 1.21, 0.99, 2.199, 2.199, 2.199 H 9.897 l 1.1, 3.299 H 19.794 c 1.21, 0, 2.199 -0.99, 2.199 -2.199 V 5.498 C 21.993, 4.289, 21.003, 3.299, 19.794, 3.299 z M 5.68, 13.839 c -2.48, 0 -4.492 -2.018 -4.492 -4.492 s 2.018 -4.492, 4.492 -4.492 c 1.144, 0, 2.183, 0.407, 3.008, 1.171 l 0.071, 0.071 l -1.342, 1.298 l -0.066 -0.06 c -0.313 -0.297 -0.858 -0.643 -1.671 -0.643 c -1.441, 0 -2.612, 1.193 -2.612, 2.661 c 0, 1.468, 1.171, 2.661, 2.612, 2.661 c 1.507, 0, 2.161 -0.962, 2.337 -1.606 h -2.43 v -1.704 h 4.344 l 0.016, 0.077 c 0.044, 0.231, 0.06, 0.434, 0.06, 0.665 C 10.001, 12.036, 8.225, 13.839, 5.68, 13.839 z M 11.739, 9.979 h 4.393 c 0, 0 -0.374, 1.446 -1.715, 3.008 c -0.588 -0.676 -0.995 -1.336 -1.254 -1.864 h -1.089 L 11.739, 9.979 z M 13.625, 13.839 l -0.588, 0.583 l -0.72 -2.452 C 12.685, 12.63, 13.13, 13.262, 13.625, 13.839 z M 20.893, 19.794 c 0, 0.605 -0.495, 1.1 -1.1, 1.1 H 12.096 l 2.199 -2.199 l -0.896 -3.041 l 1.012 -1.012 l 2.953, 2.953 l 0.803 -0.803 l -2.975 -2.953 c 0.99 -1.138, 1.759 -2.474, 2.106 -3.854 h 1.397 V 8.841 H 14.697 v -1.144 h -1.144 v 1.144 H 11.398 l -1.309 -4.443 H 19.794 c 0.605, 0, 1.1, 0.495, 1.1, 1.1 V 19.794 z"/></g><extra/></svg> ` ;
const translateIconMask = ` <mask id="translateIconMask" fill="black"><path d="M 0 0 H 24 V 24 H 0 Z" fill="white"></path><path d="M24 12 H 12 V 24 H 24 Z" fill="black"></path></mask> ` ;
const translateIcon = translateIconGeneral . replace ( ` <extra/> ` , ` ` ) . replace ( ` <mask/> ` , ` ` ) . replace ( ` mask="url(#translateIconMask)" ` , ` ` ) ;
const translateIconUntranslate = translateIconGeneral . replace ( ` <extra/> ` , ` <path transform="translate(10, 8)" stroke="#f04747" stroke-width="2" fill="none" d="M 4 4 l 8.666 8.666 m 0 -8.667 l -8.667 8.666 Z"/> ` ) . replace ( ` <mask/> ` , translateIconMask ) ;
const 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" , "⠾" : ")" , "⠿" : "=" , "_" : "⠸"
} ;
const 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" , "_" : "··−−·−"
} ;
const translationEngines = {
2020-02-28 15:01:54 +01:00
googleapi : { name : "GoogleApi" , funcName : "googleApiTranslate" , languages : [ "af" , "sq" , "am" , "ar" , "hy" , "az" , "eu" , "be" , "bn" , "bs" , "bg" , "my" , "ca" , "ceb" , "ny" , "zh-CN" , "co" , "hr" , "cs" , "da" , "nl" , "en" , "eo" , "et" , "fi" , "fr" , "fy" , "gl" , "ka" , "de" , "el" , "gu" , "ht" , "ha" , "haw" , "iw" , "hi" , "hmn" , "hu" , "is" , "ig" , "id" , "ga" , "it" , "ja" , "jw" , "kn" , "kk" , "km" , "ko" , "ku" , "ky" , "lo" , "la" , "lv" , "lt" , "lb" , "mk" , "mg" , "ms" , "ml" , "mt" , "mi" , "mr" , "mn" , "ne" , "no" , "ps" , "fa" , "pl" , "pt" , "pa" , "ro" , "ru" , "sm" , "gd" , "sr" , "st" , "sn" , "sd" , "si" , "sk" , "sl" , "so" , "es" , "sw" , "sv" , "tg" , "ta" , "te" , "th" , "tr" , "uk" , "ur" , "uz" , "vi" , "cy" , "xh" , "yi" , "yo" , "zu" ] } ,
2020-02-04 08:20:40 +01:00
google : { name : "Google" , funcName : "googleTranslate" , languages : [ "af" , "sq" , "am" , "ar" , "hy" , "az" , "eu" , "be" , "bn" , "bs" , "bg" , "my" , "ca" , "ceb" , "ny" , "zh-CN" , "co" , "hr" , "cs" , "da" , "nl" , "en" , "eo" , "et" , "fi" , "fr" , "fy" , "gl" , "ka" , "de" , "el" , "gu" , "ht" , "ha" , "haw" , "iw" , "hi" , "hmn" , "hu" , "is" , "ig" , "id" , "ga" , "it" , "ja" , "jw" , "kn" , "kk" , "km" , "ko" , "ku" , "ky" , "lo" , "la" , "lv" , "lt" , "lb" , "mk" , "mg" , "ms" , "ml" , "mt" , "mi" , "mr" , "mn" , "ne" , "no" , "ps" , "fa" , "pl" , "pt" , "pa" , "ro" , "ru" , "sm" , "gd" , "sr" , "st" , "sn" , "sd" , "si" , "sk" , "sl" , "so" , "es" , "sw" , "sv" , "tg" , "ta" , "te" , "th" , "tr" , "uk" , "ur" , "uz" , "vi" , "cy" , "xh" , "yi" , "yo" , "zu" ] } ,
itranslate : { name : "iTranslate" , funcName : "iTranslateTranslate" , languages : [ "af" , "sq" , "ar" , "hy" , "az" , "eu" , "be" , "bn" , "bs" , "bg" , "ca" , "ceb" , "ny" , "zh-CN" , "zh-TW" , "hr" , "cs" , "da" , "nl" , "en" , "eo" , "et" , "fil" , "fi" , "fr" , "gl" , "ka" , "de" , "el" , "gu" , "ht" , "he" , "ha" , "hi" , "hmn" , "hu" , "is" , "ig" , "id" , "ga" , "it" , "ja" , "jw" , "kn" , "kk" , "km" , "ko" , "lo" , "la" , "lv" , "lt" , "mk" , "mg" , "ms" , "ml" , "mt" , "mi" , "mr" , "mn" , "my" , "ne" , "no" , "fa" , "pl" , "pt-BR" , "pt-PT" , "pa" , "ro" , "ru" , "sr" , "st" , "si" , "sk" , "sl" , "so" , "es" , "su" , "sw" , "sv" , "tg" , "ta" , "te" , "th" , "tr" , "uk" , "ur" , "uz" , "vi" , "we" , "yi" , "yo" , "zu" ] } ,
yandex : { name : "Yandex" , funcName : "yandexTranslate" , languages : [ "af" , "sq" , "am" , "ar" , "hy" , "az" , "ba" , "eu" , "be" , "bn" , "bs" , "bg" , "my" , "ca" , "ceb" , "zh" , "hr" , "cs" , "da" , "nl" , "en" , "eo" , "et" , "fi" , "fr" , "gl" , "ka" , "de" , "el" , "gu" , "ht" , "he" , "hi" , "hu" , "is" , "id" , "ga" , "it" , "ja" , "jv" , "kn" , "kk" , "km" , "ko" , "ky" , "lo" , "la" , "lv" , "lt" , "lb" , "mk" , "mg" , "ms" , "ml" , "mt" , "mi" , "mr" , "mhr" , "mn" , "ne" , "no" , "pap" , "fa" , "pl" , "pt" , "pa" , "ro" , "ru" , "gd" , "sr" , "si" , "sk" , "sl" , "es" , "su" , "sw" , "sv" , "tl" , "tg" , "ta" , "tt" , "te" , "th" , "tr" , "udm" , "uk" , "ur" , "uz" , "vi" , "cy" , "xh" , "yi" ] }
} ;
var languages , translating , isTranslating , translatedMessages ;
return class GoogleTranslateOption {
getName ( ) { return "GoogleTranslateOption" ; }
2019-01-11 19:59:30 +01:00
2020-02-28 15:01:54 +01:00
getVersion ( ) { return "1.9.4" ; }
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
getAuthor ( ) { return "DevilBro" ; }
2019-01-11 19:59:30 +01:00
2020-02-04 08:20:40 +01:00
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." ; }
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
constructor ( ) {
this . changelog = {
2020-02-28 15:01:54 +01:00
"added" : [ [ "GoogleApi" , "Added a new way faster Google Api that uses a translation API provided by Google, which does not rely on using an invisible brower window to translate the text, this API is limited to 100 requests per hour, so you might get rate limited quickly" ] ] ,
2020-02-04 08:20:40 +01:00
"improved" : [ [ "New Library Structure & React" , "Restructured my Library and switched to React rendering instead of DOM manipulation" ] ]
} ;
2019-09-04 12:34:02 +02:00
2020-02-04 08:20:40 +01:00
this . patchedModules = {
before : {
ChannelTextAreaForm : "render" ,
ChannelEditorContainer : "render" ,
Embed : "render"
} ,
after : {
ChannelTextAreaContainer : "render" ,
Messages : "render" ,
MessageContent : "type" ,
Embed : "render"
}
} ;
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
initConstructor ( ) {
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:" }
} ,
engines : {
2020-02-28 15:01:54 +01:00
translator : { value : "googleapi" , description : "Translation Engine:" }
2020-02-04 08:20:40 +01:00
}
} ;
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
this . css = `
$ { BDFDB . dotCN . _googletranslateoptiontranslatebutton + BDFDB . dotCNS . _googletranslateoptiontranslating + BDFDB . dotCN . textareaicon } {
color : # F04747 ! important ;
}
$ { BDFDB . dotCN . _googletranslateoptionreversebutton } {
opacity : 0.5 ;
margin - right : 5 px ;
transition : all 200 ms ease ;
}
$ { BDFDB . dotCN . _googletranslateoptionreversebutton } : hover {
opacity : 1 ;
} ` ;
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
getSettingsPanel ( ) {
if ( ! window . BDFDB || typeof BDFDB != "object" || ! BDFDB . loaded || ! this . started ) return ;
let settings = BDFDB . DataUtils . get ( this , "settings" ) ;
let settingspanel , 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 settingspanel = BDFDB . PluginUtils . createSettingsPanel ( this , settingsitems ) ;
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
//legacy
load ( ) { }
start ( ) {
if ( ! window . BDFDB ) window . BDFDB = { myPlugins : { } } ;
if ( window . BDFDB && window . BDFDB . myPlugins && typeof window . BDFDB . myPlugins == "object" ) window . BDFDB . myPlugins [ this . getName ( ) ] = this ;
let 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 ( window . 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 ) ;
}
2018-10-11 10:21:26 +02:00
2020-02-04 08:20:40 +01:00
initialize ( ) {
if ( window . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) {
if ( this . started ) return ;
BDFDB . PluginUtils . init ( this ) ;
languages = { } ;
translating = false ;
isTranslating = false ;
translatedMessages = { } ;
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
this . setLanguages ( ) ;
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
BDFDB . ModuleUtils . forceAllUpdates ( this ) ;
}
else console . error ( ` %c[ ${ this . getName ( ) } ]%c ` , "color: #3a71c1; font-weight: 700;" , "" , "Fatal Error: Could not load BD functions!" ) ;
2018-10-11 10:21:26 +02:00
}
2020-02-04 08:20:40 +01:00
stop ( ) {
if ( window . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) {
this . stopping = true ;
BDFDB . ModuleUtils . forceAllUpdates ( this ) ;
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
BDFDB . PluginUtils . clear ( this ) ;
}
2018-10-11 10:21:26 +02:00
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
// begin of own functions
onSettingsClosed ( instance , wrapper , returnvalue ) {
if ( this . SettingsUpdated ) {
delete this . SettingsUpdated ;
this . setLanguages ( ) ;
BDFDB . ModuleUtils . forceAllUpdates ( this , [ "ChannelTextAreaForm" , "ChannelTextAreaContainer" ] ) ;
}
2019-11-29 19:11:56 +01:00
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
onMessageContextMenu ( e ) {
if ( e . instance . props . message && e . instance . props . channel ) {
let translated = translatedMessages [ e . instance . props . message . id ] ;
let [ children , index ] = BDFDB . ReactUtils . findChildren ( e . returnvalue , { name : "MessagePinItem" } ) ;
if ( index > - 1 ) children . splice ( index > - 1 ? index : children . length , 0 , BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . ContextMenuItems . Item , {
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 ,
disabled : ! translated && isTranslating ,
action : _ => {
BDFDB . ContextMenuUtils . close ( e . instance ) ;
this . translateMessage ( e . instance . props . message , e . instance . props . channel ) ;
}
} ) ) ;
let text = document . getSelection ( ) . toString ( ) ;
if ( text ) {
let translating , foundtranslation , foundinput , foundoutput ;
2020-02-13 11:48:28 +01:00
let [ children2 , index2 ] = BDFDB . ReactUtils . findChildren ( e . returnvalue , { name : "SearchWithGoogle" } ) ;
2020-02-04 08:20:40 +01:00
if ( index2 > - 1 ) children2 . splice ( index2 > - 1 ? index2 : children2 . length , 0 , BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . ContextMenuItems . Item , {
label : this . labels . context _googletranslateoption _text ,
disabled : isTranslating ,
action : event => {
let item = BDFDB . DOMUtils . getParent ( BDFDB . dotCN . contextmenuitem , event . target ) ;
if ( item ) {
let createTooltip = _ => {
BDFDB . TooltipUtils . create ( item , ` From ${ foundinput . name } : \n ${ text } \n \n To ${ foundoutput . name } : \n ${ foundtranslation } ` , { type : "right" , selector : "googletranslate-tooltip" } ) ;
} ;
if ( foundtranslation && foundinput && foundoutput ) {
if ( document . querySelector ( ".googletranslate-tooltip" ) ) {
BDFDB . ContextMenuUtils . close ( e . instance ) ;
BDFDB . DiscordUtils . openLink ( this . getGoogleTranslatePageURL ( foundinput . id , foundoutput . id , text ) , BDFDB . DataUtils . get ( this , "settings" , "useChromium" ) ) ;
2019-12-09 15:56:53 +01:00
}
2020-02-04 08:20:40 +01:00
else createTooltip ( ) ;
}
else if ( ! translating ) {
translating = true ;
this . translateText ( text , "context" , ( translation , input , output ) => {
if ( translation ) {
foundtranslation = translation , foundinput = input , foundoutput = output ;
createTooltip ( ) ;
}
} ) ;
}
2019-12-09 15:56:53 +01:00
}
2019-09-11 12:14:43 +02:00
}
2020-02-04 08:20:40 +01:00
} ) ) ;
}
}
}
onMessageOptionToolbar ( e ) {
if ( ! e . instance . props . hasMorePopout && e . instance . props . message && e . instance . props . channel ) {
let translated = ! ! translatedMessages [ e . instance . props . message . id ] ;
let [ children , index ] = BDFDB . ReactUtils . findChildren ( e . returnvalue , { key : [ "pin" , "unpin" ] } ) ;
children . splice ( index + 1 , 0 , BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TooltipContainer , {
key : "translate" ,
text : translated ? this . labels . context _messageuntranslateoption _text : this . labels . context _messagetranslateoption _text ,
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Clickable , {
className : BDFDB . disCNS . messagetoolbarbutton ,
disabled : isTranslating ,
onClick : event => {
this . translateMessage ( e . instance . props . message , e . instance . props . channel ) ;
let buttonIns = BDFDB . ReactUtils . getInstance ( BDFDB . DOMUtils . getParent ( BDFDB . dotCN . messagetoolbarbutton , event . target ) ) ;
if ( buttonIns ) {
let isTranslated = ! ! translatedMessages [ e . instance . props . message . id ] ;
let svgInstance = BDFDB . ReactUtils . findOwner ( buttonIns , { props : "iconSVG" } ) ;
let tooltipInstance = BDFDB . ReactUtils . findOwner ( buttonIns , { key : "translate" , up : true } ) ;
if ( svgInstance ) {
svgInstance . props . iconSVG = isTranslated ? translateIconUntranslate : translateIcon ;
BDFDB . ReactUtils . forceUpdate ( svgInstance ) ;
}
if ( tooltipInstance ) {
tooltipInstance . props . text = isTranslated ? this . labels . context _messageuntranslateoption _text : this . labels . context _messagetranslateoption _text ;
BDFDB . ReactUtils . forceUpdate ( tooltipInstance ) ;
}
}
} ,
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SvgIcon , {
className : BDFDB . disCNS . messagetoolbaricon ,
nativeClass : true ,
iconSVG : translated ? translateIconUntranslate : translateIcon
} )
} )
2019-12-09 15:56:53 +01:00
} ) ) ;
2018-10-11 10:21:26 +02:00
}
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
onMessageOptionContextMenu ( e ) {
if ( e . instance . props . message && e . instance . props . channel ) {
let translated = ! ! translatedMessages [ e . instance . props . message . id ] ;
let [ children , index ] = BDFDB . ReactUtils . findChildren ( e . returnvalue , { key : [ "pin" , "unpin" ] } ) ;
children . splice ( index + 1 , 0 , BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . ContextMenuItems . Item , {
label : translated ? this . labels . context _messageuntranslateoption _text : this . labels . context _messagetranslateoption _text ,
disabled : isTranslating ,
hint : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SvgIcon , {
className : BDFDB . disCNS . messagetoolbaricon ,
nativeClass : true ,
iconSVG : translated ? translateIconUntranslate : translateIcon
} ) ,
action : _ => {
e . instance . props . onClose ( ) ;
this . translateMessage ( e . instance . props . message , e . instance . props . channel ) ;
}
} ) ) ;
}
}
processChannelTextAreaForm ( e ) {
if ( ! BDFDB . ModuleUtils . isPatched ( this , e . instance , "handleSendMessage" ) ) BDFDB . ModuleUtils . patch ( this , e . instance , "handleSendMessage" , { instead : e2 => {
if ( translating ) {
e2 . stopOriginalMethodCall ( ) ;
this . translateText ( e2 . methodArguments [ 0 ] , "message" , ( translation , input , output ) => {
translation = ! translation ? e2 . methodArguments [ 0 ] : ( BDFDB . DataUtils . get ( this , "settings" , "sendOriginalMessage" ) ? e2 . methodArguments [ 0 ] + "\n\n" + translation : translation ) ;
e2 . originalMethod ( translation ) ;
} ) ;
return Promise . resolve ( {
shouldClear : true ,
shouldRefocus : true
} ) ;
2019-09-11 12:14:43 +02:00
}
2020-02-04 08:20:40 +01:00
else return e2 . callOriginalMethodAfterwards ( ) ;
} } , true ) ;
2019-09-11 12:14:43 +02:00
}
2020-02-04 08:20:40 +01:00
processChannelEditorContainer ( e ) {
if ( translating && isTranslating ) e . instance . props . disabled = true ;
}
processChannelTextAreaContainer ( e ) {
2020-02-11 09:46:53 +01:00
if ( BDFDB . DataUtils . get ( this , "settings" , "addTranslateButton" ) ) {
let [ children , index ] = BDFDB . ReactUtils . findChildren ( e . returnvalue , { name : "ChannelEditorContainer" } ) ;
if ( index > - 1 && children [ index ] . props . type == BDFDB . DiscordConstants . TextareaTypes . NORMAL && ! children [ index ] . props . disabled ) {
let [ children2 , index2 ] = BDFDB . ReactUtils . findChildren ( e . returnvalue , { props : [ [ "className" , BDFDB . disCN . textareapickerbuttons ] ] } ) ;
if ( index2 > - 1 && children2 [ index2 ] . props && children2 [ index2 ] . props . children ) children2 [ index2 ] . props . children . unshift ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . PopoutContainer , {
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . ChannelTextAreaButton , {
key : "translate-button" ,
className : BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . _googletranslateoptiontranslatebutton , translating && BDFDB . disCN . _googletranslateoptiontranslating , BDFDB . disCN . textareapickerbutton ) ,
iconClassName : BDFDB . disCN . textareaicon ,
iconSVG : translateIconGeneral
} ) ,
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 , { key : "translate-button" } ) ;
if ( channelTextareaButtonIns ) {
channelTextareaButtonIns . props . isActive = false ;
BDFDB . ReactUtils . forceUpdate ( channelTextareaButtonIns ) ;
2020-02-04 08:20:40 +01:00
}
2020-02-11 09:46:53 +01:00
} ,
onContextMenu : ( e , instance ) => {
translating = ! translating ;
let channelTextareaButtonIns = BDFDB . ReactUtils . findOwner ( instance , { key : "translate-button" } ) ;
if ( channelTextareaButtonIns ) {
channelTextareaButtonIns . props . className = BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . _googletranslateoptiontranslatebutton , translating && BDFDB . disCN . _googletranslateoptiontranslating , BDFDB . disCN . textareapickerbutton ) ;
BDFDB . ReactUtils . forceUpdate ( channelTextareaButtonIns ) ;
instance . close ( ) ;
}
} ,
renderPopout : instance => {
let channelTextareaButtonIns = BDFDB . ReactUtils . findOwner ( instance , { key : "translate-button" } ) ;
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" ,
2020-02-17 11:33:49 +01:00
tag : BDFDB . LibraryComponents . FormComponents . FormTitle . Tags . H5 ,
2020-02-11 09:46:53 +01:00
value : translating ,
onChange : value => {
translating = value ;
if ( channelTextareaButtonIns ) {
channelTextareaButtonIns . props . className = BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . _googletranslateoptiontranslatebutton , translating && BDFDB . disCN . _googletranslateoptiontranslating , BDFDB . disCN . textareapickerbutton ) ;
BDFDB . ReactUtils . forceUpdate ( channelTextareaButtonIns ) ;
}
}
} ) ) ;
return popoutelements ;
}
} ) ) ;
}
2019-12-21 02:24:30 +01:00
}
2020-02-04 08:20:40 +01:00
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
processMessages ( e ) {
let [ children , index ] = BDFDB . ReactUtils . findChildren ( e . returnvalue , { props : [ "message" , "channel" ] } ) ;
if ( index > - 1 ) for ( let ele of children ) if ( ele && ele . props && ele . props . message ) {
let translation = translatedMessages [ ele . props . message . id ] ;
if ( translation ) ele . props . message = new BDFDB . DiscordObjects . Message ( Object . assign ( { } , ele . props . message , { content : translation . content } ) ) ;
}
2019-12-21 11:25:13 +01:00
}
2020-02-04 08:20:40 +01:00
processMessageContent ( e ) {
if ( e . instance . props . message ) {
let translation = translatedMessages [ e . instance . props . message . id ] ;
if ( translation ) e . returnvalue . props . children . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TooltipContainer , {
text : ` From: ${ this . getLanguageName ( translation . input ) } \n To: ${ this . getLanguageName ( translation . output ) } ` ,
tooltipConfig : { style : "max-width: 400px" } ,
children : BDFDB . ReactUtils . createElement ( "time" , {
className : BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . messageedited , BDFDB . disCN . _googletranslateoptiontranslated ) ,
children : ` ( ${ this . labels . translated _watermark _text } ) `
} )
} ) ) ;
}
2019-10-24 11:47:57 +02:00
}
2020-02-04 08:20:40 +01:00
processEmbed ( e ) {
if ( e . instance . props . embed && e . instance . props . embed . messageId ) {
let translation = translatedMessages [ e . instance . props . embed . messageId ] ;
if ( translation ) {
if ( ! e . returnvalue ) e . instance . props . embed = Object . assign ( { } , e . instance . props . embed , {
rawDescription : translation . embeds [ e . instance . props . embed . id ] ,
originalDescription : e . instance . props . embed . originalDescription || e . instance . props . embed . rawDescription
} ) ;
else {
let [ children , index ] = BDFDB . ReactUtils . findChildren ( e . returnvalue , { props : [ [ "className" , BDFDB . disCN . embeddescription ] ] } ) ;
if ( index > - 1 ) children [ index ] . props . children . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TooltipContainer , {
text : ` From: ${ this . getLanguageName ( translation . input ) } \n To: ${ this . getLanguageName ( translation . output ) } ` ,
tooltipConfig : { style : "max-width: 400px" } ,
children : BDFDB . ReactUtils . createElement ( "time" , {
className : BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . messageedited , BDFDB . disCN . _googletranslateoptiontranslated ) ,
children : ` ( ${ this . labels . translated _watermark _text } ) `
} )
} ) ) ;
}
2019-10-24 21:30:55 +02:00
}
2020-02-04 08:20:40 +01:00
else if ( ! e . returnvalue && e . instance . props . embed . originalDescription ) {
e . instance . props . embed = Object . assign ( { } , e . instance . props . embed , { rawDescription : e . instance . props . embed . originalDescription } ) ;
delete e . instance . props . embed . originalDescription ;
2019-10-24 21:30:55 +02:00
}
2020-02-04 08:20:40 +01:00
}
}
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 , {
className : BDFDB . disCN . _googletranslateoptionreversebutton ,
iconSVG : ` <svg width="21" height="21" fill="currentColor"><path d="M 0, 10.515 c 0, 2.892, 1.183, 5.521, 3.155, 7.361 L 0, 21.031 h 7.887 V 13.144 l -2.892, 2.892 C 3.549, 14.722, 2.629, 12.75, 2.629, 10.515 c 0 -3.418, 2.235 -6.309, 5.258 -7.492 v -2.629 C 3.418, 1.577, 0, 5.652, 0, 10.515 z M 21.031, 0 H 13.144 v 7.887 l 2.892 -2.892 C 17.482, 6.309, 18.402, 8.281, 18.402, 10.515 c 0, 3.418 -2.235, 6.309 -5.258, 7.492 V 20.768 c 4.469 -1.183, 7.887 -5.258, 7.887 -10.121 c 0 -2.892 -1.183 -5.521 -3.155 -7.361 L 21.031, 0 z"/></svg> `
} )
} ) : null ,
2019-10-28 09:52:23 +01:00
className : BDFDB . disCN . marginbottom8 ,
2020-02-04 08:20:40 +01:00
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 ( languages , lang => lang . id != "auto" ) : languages , ( lang , id ) => { return { value : id , label : this . getLanguageName ( lang ) } } ) ) ,
searchable : true ,
optionRenderer : lang => {
return languages [ lang . value ] ? 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 : 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
]
} ) : null ;
} ,
onChange : lang => {
BDFDB . DataUtils . save ( lang . value , this , "choices" , key ) ;
}
2019-10-24 21:30:55 +02:00
} )
} ) ) ;
2020-02-04 08:20:40 +01:00
if ( isOutput ) selects . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . FormComponents . FormDivider , {
2019-10-24 21:30:55 +02:00
className : BDFDB . disCN . marginbottom8
} ) ) ;
}
2020-02-04 08:20:40 +01:00
let engines = BDFDB . DataUtils . get ( this , "engines" ) ;
for ( let key in engines ) {
selects . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . FormComponents . FormItem , {
title : this . defaults . engines [ key ] . description ,
className : BDFDB . disCN . marginbottom8 ,
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Select , {
menuPlacement : inPopout ? BDFDB . LibraryComponents . Select . MenuPlacements . TOP : BDFDB . LibraryComponents . Select . MenuPlacements . BOTTOM ,
value : engines [ key ] ,
id : key ,
options : Object . keys ( translationEngines ) . map ( engineKey => { return { value : engineKey , label : translationEngines [ engineKey ] . name } } ) ,
searchable : true ,
onChange : ( engine , instance ) => {
BDFDB . DataUtils . save ( engine . value , this , "engines" , key ) ;
this . setLanguages ( ) ;
let popoutInstance = BDFDB . ReactUtils . findOwner ( instance , { name : "BDFDB_PopoutContainer" , up : true } ) ;
if ( popoutInstance ) {
popoutInstance . close ( ) ;
popoutInstance . handleClick ( ) ;
}
2019-10-24 11:47:57 +02:00
}
} )
2020-02-04 08:20:40 +01:00
} ) ) ;
}
return selects ;
2019-12-09 15:56:53 +01:00
}
2019-10-24 11:47:57 +02:00
2020-02-04 08:20:40 +01:00
setLanguages ( ) {
let languageIds = ( translationEngines [ BDFDB . DataUtils . get ( this , "engines" , "translator" ) ] || { } ) . languages || [ ] ;
languages = Object . assign (
{ "auto" : { name : "Auto" , id : "auto" , integrated : false , dic : false } } ,
BDFDB . ObjectUtils . filter ( BDFDB . LanguageUtils . languages , lang => languageIds . includes ( lang . id ) ) ,
{ "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 languages ) languages [ id ] . fav = favorites [ id ] != undefined ? 0 : 1 ;
languages = BDFDB . ObjectUtils . sort ( languages , "fav" ) ;
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
getLanguageChoice ( direction , place ) {
this . setLanguages ( ) ;
let type = place === undefined ? direction : direction . toLowerCase ( ) + place . charAt ( 0 ) . toUpperCase ( ) + place . slice ( 1 ) . toLowerCase ( ) ;
let choice = BDFDB . DataUtils . get ( this , "choices" , type ) ;
choice = languages [ choice ] ? choice : Object . keys ( languages ) [ 0 ] ;
choice = type . indexOf ( "output" ) > - 1 && choice == "auto" ? "en" : choice ;
return choice ;
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
translateMessage ( message , channel ) {
if ( ! message ) return ;
if ( translatedMessages [ message . id ] ) {
delete translatedMessages [ message . id ] ;
BDFDB . ModuleUtils . forceAllUpdates ( this , [ "Messages" , "Embed" ] ) ;
2019-09-27 09:48:32 +02:00
}
2019-12-09 15:56:53 +01:00
else {
2020-02-04 08:20:40 +01:00
let content = message . content || "" ;
for ( let embed of message . embeds ) content += ( "\n__________________ __________________ __________________\n" + embed . rawDescription ) ;
this . translateText ( content , "context" , ( translation , input , output ) => {
2019-12-09 15:56:53 +01:00
if ( translation ) {
2020-02-04 08:20:40 +01:00
let strings = translation . split ( "\n__________________ __________________ __________________\n" ) ;
let content = strings . shift ( ) . trim ( ) , embeds = { } ;
for ( let i in message . embeds ) {
message . embeds [ i ] . messageId = message . id ;
embeds [ message . embeds [ i ] . id ] = strings . shift ( ) . trim ( ) || message . embeds [ i ] . rawDescription ;
}
translatedMessages [ message . id ] = { content , embeds , message , input , output } ;
BDFDB . ModuleUtils . forceAllUpdates ( this , [ "Messages" , "Embed" ] ) ;
2019-09-27 09:48:32 +02:00
}
2019-12-09 15:56:53 +01:00
} ) ;
}
2019-01-02 23:28:11 +01:00
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
translateText ( text , type , callback ) {
let toast = null , finishTranslation = translation => {
isTranslating = false ;
if ( translation ) translation = this . addExceptions ( translation , exceptions ) ;
if ( toast ) {
BDFDB . TimeUtils . clear ( toast . interval ) ;
toast . close ( ) ;
2019-12-10 13:21:59 +01:00
}
2020-02-04 08:20:40 +01:00
callback ( translation == text ? "" : translation , input , output ) ;
} ;
let [ newtext , exceptions , translate ] = this . removeExceptions ( text . trim ( ) , type ) ;
let input = Object . assign ( { } , languages [ this . getLanguageChoice ( "input" , type ) ] ) ;
let output = Object . assign ( { } , languages [ this . getLanguageChoice ( "output" , type ) ] ) ;
if ( translate ) {
let timer = 0 ;
toast = BDFDB . NotificationUtils . toast ( "Translating. Please wait" , { timeout : 0 } ) ;
toast . interval = BDFDB . TimeUtils . interval ( _ => {
if ( timer ++ > 40 ) {
finishTranslation ( "" ) ;
BDFDB . NotificationUtils . toast ( "Failed to translate text. Try another Translate Engine." , { type : "error" } ) ;
}
else toast . textContent = toast . textContent . indexOf ( "....." ) > - 1 ? "Translating. Please wait" : toast . textContent + "." ;
} , 500 ) ;
let 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 ;
}
2019-04-13 07:09:34 +02:00
}
2020-02-04 08:20:40 +01:00
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 ) ;
2019-04-13 07:09:34 +02:00
}
2020-02-04 08:20:40 +01:00
else {
let translator = BDFDB . DataUtils . get ( this , "engines" , "translator" ) ;
if ( translationEngines [ translator ] && typeof this [ translationEngines [ translator ] . funcName ] == "function" ) {
isTranslating = true ;
this [ translationEngines [ translator ] . funcName ] . apply ( this , [ { input , output , text : newtext , specialcase , engine : translationEngines [ translator ] } , finishTranslation ] ) ;
}
else finishTranslation ( "" ) ;
2019-12-09 15:56:53 +01:00
}
2018-10-11 10:21:26 +02:00
}
2020-02-04 08:20:40 +01:00
else finishTranslation ( text ) ;
2018-10-11 10:21:26 +02:00
}
2020-02-04 08:20:40 +01:00
googleTranslate ( data , callback ) {
let googleTranslateWindow = BDFDB . WindowUtils . open ( this , this . getGoogleTranslatePageURL ( data . input . id , data . output . id , data . text ) ) ;
googleTranslateWindow . webContents . on ( "did-finish-load" , _ => {
googleTranslateWindow . webContents . executeJavaScript ( ` require("electron").ipcRenderer.sendTo( ${ BDFDB . LibraryRequires . electron . remote . getCurrentWindow ( ) . webContents . id } , "GTO-translation", [(document.querySelector(".translation") || {}).innerText, [(new RegExp("{code:'([^']*)',name:'" + [(new RegExp((window.source_language_detected || "").replace("%1 $ s", "([A-z]{2,})"), "g")).exec(document.body.innerHTML)].flat()[1] +"'}", "g")).exec(document.body.innerHTML)].flat()[1]]); ` ) ;
} ) ;
BDFDB . WindowUtils . addListener ( this , "GTO-translation" , ( event , messagedata ) => {
BDFDB . WindowUtils . close ( googleTranslateWindow ) ;
BDFDB . WindowUtils . removeListener ( this , "GTO-translation" ) ;
if ( ! data . specialcase && messagedata [ 1 ] && languages [ messagedata [ 1 ] ] ) {
data . input . name = languages [ messagedata [ 1 ] ] . name ;
data . input . ownlang = languages [ messagedata [ 1 ] ] . ownlang ;
}
callback ( messagedata [ 0 ] ) ;
} ) ;
}
2020-02-28 15:01:54 +01:00
googleApiTranslate ( data , callback ) {
BDFDB . LibraryRequires . request ( ` https://translate.googleapis.com/translate_a/single?client=gtx&sl= ${ data . input . id } &tl= ${ data . output . id } &dt=t&dj=1&source=input&q= ${ encodeURIComponent ( data . text ) } ` , ( error , response , result ) => {
if ( ! error && result && response . statusCode == 200 ) {
try {
result = JSON . parse ( result ) ;
if ( ! data . specialcase && result . src && result . src && languages [ result . src ] ) {
data . input . name = languages [ result . src ] . name ;
data . input . ownlang = languages [ result . src ] . ownlang ;
}
callback ( result . sentences [ 0 ] . trans ) ;
}
catch ( err ) { callback ( "" ) ; }
callback ( "" ) ;
}
else {
BDFDB . NotificationUtils . toast ( "Failed to translate text. Translation Server is down or Request Limit per Hour is reached. Try another Translate Engine." , { type : "error" } ) ;
callback ( "" ) ;
}
} ) ;
}
2020-02-04 08:20:40 +01:00
iTranslateTranslate ( data , callback ) {
let translate = _ => {
BDFDB . LibraryRequires . request ( {
method : "POST" ,
url : "https://web-api.itranslateapp.com/v3/texts/translate" ,
headers : {
"API-KEY" : "d2aefeac9dc661bc98eebd6cc12f0b82"
2019-12-17 11:07:41 +01:00
} ,
2020-02-04 08:20:40 +01:00
body : JSON . stringify ( {
source : {
dialect : data . input . id ,
text : data . text
} ,
target : {
dialect : data . output . id
}
} )
} , ( error , response , result ) => {
if ( ! error && response && response . statusCode == 200 ) {
try {
2020-02-28 15:01:54 +01:00
result = JSON . parse ( result ) ;
if ( ! data . specialcase && result . source && result . source . detected && languages [ result . source . detected ] ) {
data . input . name = languages [ result . source . detected ] . name ;
data . input . ownlang = languages [ result . source . detected ] . ownlang ;
2020-02-04 08:20:40 +01:00
}
2020-02-28 15:01:54 +01:00
callback ( result . target . text ) ;
2020-02-04 08:20:40 +01:00
}
catch ( err ) { callback ( "" ) ; }
}
else {
BDFDB . NotificationUtils . toast ( "Failed to translate text. Translation Server is down or API-key outdated. Try another Translate Engine." , { type : "error" } ) ;
callback ( "" ) ;
}
} ) ;
} ;
if ( data . engine . APIkey ) translate ( ) ;
else BDFDB . LibraryRequires . request ( "https://www.itranslate.com/themes/itranslate2016/assets/webapp/js/main.js" , { gzip : true } , ( error , response , result ) => {
if ( ! error && result ) {
let APIkey = /var API_KEY = "(.+)"/ . exec ( result ) ;
if ( APIkey ) {
data . engine . APIkey = APIkey [ 1 ] ;
translate ( ) ;
2019-12-17 11:07:41 +01:00
}
2020-02-04 08:20:40 +01:00
else callback ( "" ) ;
}
else callback ( "" ) ;
} ) ;
}
yandexTranslate ( data , callback ) {
BDFDB . LibraryRequires . request ( ` https://translate.yandex.net/api/v1.5/tr/translate?key=trnsl.1.1.20191206T223907Z.52bd512eca953a5b.1ec123ce4dcab3ae859f312d27cdc8609ab280de&text= ${ encodeURIComponent ( data . text ) } &lang= ${ data . specialcase || data . input . id == "auto" ? data . output . id : ( data . input . id + "-" + data . output . id ) } &options=1 ` , ( error , response , result ) => {
if ( ! error && result && response . statusCode == 200 ) {
result = BDFDB . DOMUtils . create ( result ) ;
let translation = result . querySelector ( "text" ) ;
let detected = result . querySelector ( "detected" ) ;
if ( translation && detected ) {
let detectedlang = detected . getAttribute ( "lang" ) ;
if ( ! data . specialcase && detectedlang && languages [ detectedlang ] ) {
data . input . name = languages [ detectedlang ] . name ;
data . input . ownlang = languages [ detectedlang ] . ownlang ;
2019-12-10 13:21:59 +01:00
}
2020-02-04 08:20:40 +01:00
callback ( translation . innerText ) ;
2019-12-10 13:21:59 +01:00
}
2020-02-04 08:20:40 +01:00
else callback ( "" ) ;
2019-12-10 13:21:59 +01:00
}
2019-12-17 11:07:41 +01:00
else {
BDFDB . NotificationUtils . toast ( "Failed to translate text. Translation Server is down or API-key outdated. Try another Translate Engine." , { type : "error" } ) ;
callback ( "" ) ;
}
} ) ;
2020-02-04 08:20:40 +01:00
}
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" } ;
2019-12-10 13:21:59 +01:00
}
2020-02-04 08:20:40 +01:00
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" } ;
2019-12-10 13:21:59 +01:00
}
2019-04-16 00:30:33 +02:00
}
2020-02-04 08:20:40 +01:00
return null ;
2019-04-16 00:30:33 +02:00
}
2020-02-04 08:20:40 +01:00
string2binary ( string ) {
var binary = "" ;
for ( let character of string ) binary += parseInt ( character . charCodeAt ( 0 ) . toString ( 2 ) ) . toPrecision ( 8 ) . split ( "." ) . reverse ( ) . join ( "" ) . toString ( ) + " " ;
return binary ;
}
2019-04-16 00:30:33 +02:00
2020-02-04 08:20:40 +01:00
string2braille ( string ) {
var braille = "" ;
for ( let character of string ) braille += brailleConverter [ character . toLowerCase ( ) ] ? brailleConverter [ character . toLowerCase ( ) ] : character ;
return braille ;
}
2019-04-16 00:30:33 +02:00
2020-02-04 08:20:40 +01:00
string2morse ( string ) {
string = string . replace ( / /g , "%%%%%%%%%%" ) ;
var morse = "" ;
for ( let character of string ) morse += ( morseConverter [ character . toLowerCase ( ) ] ? morseConverter [ character . toLowerCase ( ) ] : character ) + " " ;
morse = morse . split ( "\n" ) ;
for ( let i in morse ) morse [ i ] = morse [ i ] . trim ( ) ;
return morse . join ( "\n" ) . replace ( /% % % % % % % % % % /g , "/ " ) ;
}
2019-04-16 00:30:33 +02:00
2020-02-04 08:20:40 +01:00
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 ;
}
2019-04-16 00:30:33 +02:00
}
}
2020-02-04 08:20:40 +01:00
else BDFDB . NotificationUtils . toast ( "Invalid binary format. Only use 0s and 1s." , { type : "error" } ) ;
return string ;
2019-04-16 00:30:33 +02:00
}
2020-02-04 08:20:40 +01:00
braille2string ( braille ) {
var string = "" ;
for ( let character of braille ) string += brailleConverter [ character . toLowerCase ( ) ] ? brailleConverter [ character . toLowerCase ( ) ] : character ;
return string ;
2019-04-16 00:30:33 +02:00
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
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 += morseConverter [ characterstr ] ? morseConverter [ characterstr ] : characterstr ;
string += " " ;
}
return string . trim ( ) ;
2019-12-11 10:51:40 +01:00
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
addExceptions ( string , exceptions ) {
for ( let count in exceptions ) {
let exception = exceptions [ count ] . indexOf ( "!" ) == 0 ? exceptions [ count ] . slice ( 1 ) : exceptions [ count ] ;
let newstring = string . replace ( new RegExp ( ` \[ /////[ ]* ${ count } \] ` ) , exception ) ;
if ( newstring == string ) string = newstring + " " + exception ;
else string = newstring ;
2018-10-11 10:21:26 +02:00
}
2020-02-04 08:20:40 +01:00
return string ;
2019-01-02 23:28:11 +01:00
}
2020-02-04 08:20:40 +01:00
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 ( ` [///// ${ count } ] ` ) ;
exceptions [ count ] = text [ j ] ;
count ++ ;
}
else newString . push ( text [ j ] ) ;
2019-01-02 23:28:11 +01:00
}
2020-02-04 08:20:40 +01:00
}
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 ( ` [///// ${ count } ] ` ) ;
exceptions [ count ] = word ;
count ++ ;
}
else newString . push ( word ) ;
} ) ;
}
return [ newString . join ( " " ) , exceptions , newString . length - count != 0 ] ;
2019-01-02 23:28:11 +01:00
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
getGoogleTranslatePageURL ( input , output , text ) {
input = BDFDB . LanguageUtils . languages [ input ] ? input : "auto" ;
return "https://translate.google.com/#" + input + "/" + output + "/" + encodeURIComponent ( text ) ;
}
getLanguageName ( language ) {
if ( language . name . startsWith ( "Discord" ) ) return language . name . slice ( 0 , - 1 ) + ( language . ownlang && languages [ language . id ] . name != language . ownlang ? ` / ${ language . ownlang } ` : "" ) + ")" ;
else return language . name + ( language . ownlang && language . name != language . ownlang ? ` / ${ language . ownlang } ` : "" ) ;
}
2019-01-26 22:45:19 +01:00
2020-02-04 08:20:40 +01:00
setLabelsByLanguage ( ) {
switch ( BDFDB . LanguageUtils . getLanguage ( ) . 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"
} ;
}
2018-10-11 10:21:26 +02:00
}
}
2020-02-04 08:20:40 +01:00
} ) ( ) ;