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" , "_" : "··−−·−"
} ;
2020-02-29 19:13:47 +01:00
const googleLanguages = [ "af" , "am" , "ar" , "az" , "be" , "bg" , "bn" , "bs" , "ca" , "ceb" , "co" , "cs" , "cy" , "da" , "de" , "el" , "en" , "eo" , "es" , "et" , "eu" , "fa" , "fi" , "fr" , "fy" , "ga" , "gd" , "gl" , "gu" , "ha" , "haw" , "hi" , "hmn" , "hr" , "ht" , "hu" , "hy" , "id" , "ig" , "is" , "it" , "iw" , "ja" , "jw" , "ka" , "kk" , "km" , "kn" , "ko" , "ku" , "ky" , "la" , "lb" , "lo" , "lt" , "lv" , "mg" , "mi" , "mk" , "ml" , "mn" , "mr" , "ms" , "mt" , "my" , "ne" , "nl" , "no" , "ny" , "or" , "pa" , "pl" , "ps" , "pt" , "ro" , "ru" , "rw" , "sd" , "si" , "sk" , "sl" , "sm" , "sn" , "so" , "sq" , "sr" , "st" , "su" , "sv" , "sw" , "ta" , "te" , "tg" , "th" , "tk" , "tl" , "tr" , "tt" , "ug" , "uk" , "ur" , "uz" , "vi" , "xh" , "yi" , "yo" , "zh-CN" , "zu" ] ;
2020-02-04 08:20:40 +01:00
const translationEngines = {
2020-02-29 19:13:47 +01:00
googleapi : { name : "GoogleApi" , funcName : "googleApiTranslate" , languages : googleLanguages } ,
google : { name : "Google" , funcName : "googleTranslate" , languages : googleLanguages } ,
itranslate : { name : "iTranslate" , funcName : "iTranslateTranslate" , languages : [ ... new Set ( [ "af" , "ar" , "az" , "be" , "bg" , "bn" , "bs" , "ca" , "ceb" , "cs" , "cy" , "da" , "de" , "el" , "en" , "eo" , "es" , "et" , "eu" , "fa" , "fi" , "fil" , "fr" , "ga" , "gl" , "gu" , "ha" , "he" , "hi" , "hmn" , "hr" , "ht" , "hu" , "hy" , "id" , "ig" , "is" , "it" , "ja" , "jw" , "ka" , "kk" , "km" , "kn" , "ko" , "la" , "lo" , "lt" , "lv" , "mg" , "mi" , "mk" , "ml" , "mn" , "mr" , "ms" , "mt" , "my" , "ne" , "nl" , "no" , "ny" , "pa" , "pl" , "pt-BR" , "pt-PT" , "ro" , "ru" , "si" , "sk" , "sl" , "so" , "sq" , "sr" , "st" , "su" , "sv" , "sw" , "ta" , "te" , "tg" , "th" , "tr" , "uk" , "ur" , "uz" , "vi" , "we" , "yi" , "yo" , "zh-CN" , "zh-TW" , "zu" ] . concat ( googleLanguages ) ) ] . sort ( ) } ,
yandex : { name : "Yandex" , funcName : "yandexTranslate" , languages : [ "af" , "am" , "ar" , "az" , "ba" , "be" , "bg" , "bn" , "bs" , "ca" , "ceb" , "cs" , "cy" , "da" , "de" , "el" , "en" , "eo" , "es" , "et" , "eu" , "fa" , "fi" , "fr" , "ga" , "gd" , "gl" , "gu" , "he" , "hi" , "hr" , "ht" , "hu" , "hy" , "id" , "is" , "it" , "ja" , "jv" , "ka" , "kk" , "km" , "kn" , "ko" , "ky" , "la" , "lb" , "lo" , "lt" , "lv" , "mg" , "mhr" , "mi" , "mk" , "ml" , "mn" , "mr" , "ms" , "mt" , "my" , "ne" , "nl" , "no" , "pa" , "pap" , "pl" , "pt" , "ro" , "ru" , "si" , "sk" , "sl" , "sq" , "sr" , "su" , "sv" , "sw" , "ta" , "te" , "tg" , "th" , "tl" , "tr" , "tt" , "udm" , "uk" , "ur" , "uz" , "vi" , "xh" , "yi" , "zh" ] }
2020-02-04 08:20:40 +01:00
} ;
var languages , translating , isTranslating , translatedMessages ;
return class GoogleTranslateOption {
getName ( ) { return "GoogleTranslateOption" ; }
2019-01-11 19:59:30 +01:00
2020-03-28 07:41:31 +01:00
getVersion ( ) { return "1.9.9" ; }
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 . 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" ) ;
2020-03-28 07:55:39 +01:00
let settingsPanel , settingsItems = [ ] ;
2020-02-04 08:20:40 +01:00
2020-03-28 07:55:39 +01:00
settingsItems = settingsItems . concat ( this . createSelects ( false ) ) ;
2020-02-04 08:20:40 +01:00
2020-03-28 07:55:39 +01:00
for ( let key in settings ) settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsSaveItem , {
2020-02-04 08:20:40 +01:00
className : BDFDB . disCN . marginbottom8 ,
type : "Switch" ,
plugin : this ,
keys : [ "settings" , key ] ,
label : this . defaults . settings [ key ] . description ,
value : settings [ key ]
} ) ) ;
2020-03-28 07:55:39 +01:00
return settingsPanel = BDFDB . PluginUtils . createSettingsPanel ( this , settingsItems ) ;
2020-02-04 08:20:40 +01:00
}
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 ) => {
2020-02-29 19:13:47 +01:00
translation = ! translation ? e2 . methodArguments [ 0 ] : ( BDFDB . DataUtils . get ( this , "settings" , "sendOriginalMessage" ) ? ( e2 . methodArguments [ 0 ] + "\n\n" + translation ) : translation ) ;
2020-02-04 08:20:40 +01:00
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 ( ) ;
2020-03-28 07:41:31 +01:00
} } , { force : true , noCache : 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 ) ;
2020-02-29 19:13:47 +01:00
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 ] && this . defaults . choices [ selectIns . props . id ] . place == place ) {
2020-02-04 08:20:40 +01:00
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 ;
2020-02-29 19:13:47 +01:00
embeds [ message . embeds [ i ] . id ] = ( strings . shift ( ) || message . embeds [ i ] . rawDescription ) . trim ( ) ;
2020-02-04 08:20:40 +01:00
}
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 ] ) ;
}
2020-03-10 15:19:50 +01:00
else finishTranslation ( ) ;
2019-12-09 15:56:53 +01:00
}
2018-10-11 10:21:26 +02:00
}
2020-03-10 15:19:50 +01:00
else finishTranslation ( ) ;
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 ;
}
2020-03-04 11:38:19 +01:00
callback ( result . sentences . map ( n => n && n . trans ) . filter ( n => n ) . join ( "" ) ) ;
2020-02-28 15:01:54 +01:00
}
catch ( err ) { 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 : {
2020-02-29 19:13:47 +01:00
"API-KEY" : data . engine . APIkey
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 ) ;
2020-02-29 19:13:47 +01:00
if ( ! data . specialcase && result . source && result . source . dialect && languages [ result . source . dialect ] ) {
data . input . name = languages [ result . source . dialect ] . name ;
data . input . ownlang = languages [ result . source . dialect ] . 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 ( ) ;
2020-02-29 19:13:47 +01:00
else BDFDB . LibraryRequires . request ( "https://www.itranslate.com/js/webapp/main.js" , { gzip : true } , ( error , response , result ) => {
2020-02-04 08:20:40 +01:00
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 => {
2020-03-10 16:13:37 +01:00
if ( word . indexOf ( "<@!" ) == 0 || word . indexOf ( ":" ) == 0 || word . indexOf ( "<:" ) == 0 || word . indexOf ( "<a:" ) == 0 || word . indexOf ( "@" ) == 0 || word . indexOf ( "#" ) == 0 || ( word . indexOf ( "!" ) == 0 && word . length > 1 ) ) {
2020-02-04 08:20:40 +01:00
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
} ) ( ) ;