SerialCom

Traduzir páginas da web

May 26th, 2022
34
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 38.37 KB | None | 0 0
  1. contentScript/translateSelected.js:822 (função anônima)
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9
  11. 10
  12. 11
  13. 12
  14. 13
  15. 14
  16. 15
  17. 16
  18. 17
  19. 18
  20. 19
  21. 20
  22. 21
  23. 22
  24. 23
  25. 24
  26. 25
  27. 26
  28. 27
  29. 28
  30. 29
  31. 30
  32. 31
  33. 32
  34. 33
  35. 34
  36. 35
  37. 36
  38. 37
  39. 38
  40. 39
  41. 40
  42. 41
  43. 42
  44. 43
  45. 44
  46. 45
  47. 46
  48. 47
  49. 48
  50. 49
  51. 50
  52. 51
  53. 52
  54. 53
  55. 54
  56. 55
  57. 56
  58. 57
  59. 58
  60. 59
  61. 60
  62. 61
  63. 62
  64. 63
  65. 64
  66. 65
  67. 66
  68. 67
  69. 68
  70. 69
  71. 70
  72. 71
  73. 72
  74. 73
  75. 74
  76. 75
  77. 76
  78. 77
  79. 78
  80. 79
  81. 80
  82. 81
  83. 82
  84. 83
  85. 84
  86. 85
  87. 86
  88. 87
  89. 88
  90. 89
  91. 90
  92. 91
  93. 92
  94. 93
  95. 94
  96. 95
  97. 96
  98. 97
  99. 98
  100. 99
  101. 100
  102. 101
  103. 102
  104. 103
  105. 104
  106. 105
  107. 106
  108. 107
  109. 108
  110. 109
  111. 110
  112. 111
  113. 112
  114. 113
  115. 114
  116. 115
  117. 116
  118. 117
  119. 118
  120. 119
  121. 120
  122. 121
  123. 122
  124. 123
  125. 124
  126. 125
  127. 126
  128. 127
  129. 128
  130. 129
  131. 130
  132. 131
  133. 132
  134. 133
  135. 134
  136. 135
  137. 136
  138. 137
  139. 138
  140. 139
  141. 140
  142. 141
  143. 142
  144. 143
  145. 144
  146. 145
  147. 146
  148. 147
  149. 148
  150. 149
  151. 150
  152. 151
  153. 152
  154. 153
  155. 154
  156. 155
  157. 156
  158. 157
  159. 158
  160. 159
  161. 160
  162. 161
  163. 162
  164. 163
  165. 164
  166. 165
  167. 166
  168. 167
  169. 168
  170. 169
  171. 170
  172. 171
  173. 172
  174. 173
  175. 174
  176. 175
  177. 176
  178. 177
  179. 178
  180. 179
  181. 180
  182. 181
  183. 182
  184. 183
  185. 184
  186. 185
  187. 186
  188. 187
  189. 188
  190. 189
  191. 190
  192. 191
  193. 192
  194. 193
  195. 194
  196. 195
  197. 196
  198. 197
  199. 198
  200. 199
  201. 200
  202. 201
  203. 202
  204. 203
  205. 204
  206. 205
  207. 206
  208. 207
  209. 208
  210. 209
  211. 210
  212. 211
  213. 212
  214. 213
  215. 214
  216. 215
  217. 216
  218. 217
  219. 218
  220. 219
  221. 220
  222. 221
  223. 222
  224. 223
  225. 224
  226. 225
  227. 226
  228. 227
  229. 228
  230. 229
  231. 230
  232. 231
  233. 232
  234. 233
  235. 234
  236. 235
  237. 236
  238. 237
  239. 238
  240. 239
  241. 240
  242. 241
  243. 242
  244. 243
  245. 244
  246. 245
  247. 246
  248. 247
  249. 248
  250. 249
  251. 250
  252. 251
  253. 252
  254. 253
  255. 254
  256. 255
  257. 256
  258. 257
  259. 258
  260. 259
  261. 260
  262. 261
  263. 262
  264. 263
  265. 264
  266. 265
  267. 266
  268. 267
  269. 268
  270. 269
  271. 270
  272. 271
  273. 272
  274. 273
  275. 274
  276. 275
  277. 276
  278. 277
  279. 278
  280. 279
  281. 280
  282. 281
  283. 282
  284. 283
  285. 284
  286. 285
  287. 286
  288. 287
  289. 288
  290. 289
  291. 290
  292. 291
  293. 292
  294. 293
  295. 294
  296. 295
  297. 296
  298. 297
  299. 298
  300. 299
  301. 300
  302. 301
  303. 302
  304. 303
  305. 304
  306. 305
  307. 306
  308. 307
  309. 308
  310. 309
  311. 310
  312. 311
  313. 312
  314. 313
  315. 314
  316. 315
  317. 316
  318. 317
  319. 318
  320. 319
  321. 320
  322. 321
  323. 322
  324. 323
  325. 324
  326. 325
  327. 326
  328. 327
  329. 328
  330. 329
  331. 330
  332. 331
  333. 332
  334. 333
  335. 334
  336. 335
  337. 336
  338. 337
  339. 338
  340. 339
  341. 340
  342. 341
  343. 342
  344. 343
  345. 344
  346. 345
  347. 346
  348. 347
  349. 348
  350. 349
  351. 350
  352. 351
  353. 352
  354. 353
  355. 354
  356. 355
  357. 356
  358. 357
  359. 358
  360. 359
  361. 360
  362. 361
  363. 362
  364. 363
  365. 364
  366. 365
  367. 366
  368. 367
  369. 368
  370. 369
  371. 370
  372. 371
  373. 372
  374. 373
  375. 374
  376. 375
  377. 376
  378. 377
  379. 378
  380. 379
  381. 380
  382. 381
  383. 382
  384. 383
  385. 384
  386. 385
  387. 386
  388. 387
  389. 388
  390. 389
  391. 390
  392. 391
  393. 392
  394. 393
  395. 394
  396. 395
  397. 396
  398. 397
  399. 398
  400. 399
  401. 400
  402. 401
  403. 402
  404. 403
  405. 404
  406. 405
  407. 406
  408. 407
  409. 408
  410. 409
  411. 410
  412. 411
  413. 412
  414. 413
  415. 414
  416. 415
  417. 416
  418. 417
  419. 418
  420. 419
  421. 420
  422. 421
  423. 422
  424. 423
  425. 424
  426. 425
  427. 426
  428. 427
  429. 428
  430. 429
  431. 430
  432. 431
  433. 432
  434. 433
  435. 434
  436. 435
  437. 436
  438. 437
  439. 438
  440. 439
  441. 440
  442. 441
  443. 442
  444. 443
  445. 444
  446. 445
  447. 446
  448. 447
  449. 448
  450. 449
  451. 450
  452. 451
  453. 452
  454. 453
  455. 454
  456. 455
  457. 456
  458. 457
  459. 458
  460. 459
  461. 460
  462. 461
  463. 462
  464. 463
  465. 464
  466. 465
  467. 466
  468. 467
  469. 468
  470. 469
  471. 470
  472. 471
  473. 472
  474. 473
  475. 474
  476. 475
  477. 476
  478. 477
  479. 478
  480. 479
  481. 480
  482. 481
  483. 482
  484. 483
  485. 484
  486. 485
  487. 486
  488. 487
  489. 488
  490. 489
  491. 490
  492. 491
  493. 492
  494. 493
  495. 494
  496. 495
  497. 496
  498. 497
  499. 498
  500. 499
  501. 500
  502. 501
  503. 502
  504. 503
  505. 504
  506. 505
  507. 506
  508. 507
  509. 508
  510. 509
  511. 510
  512. 511
  513. 512
  514. 513
  515. 514
  516. 515
  517. 516
  518. 517
  519. 518
  520. 519
  521. 520
  522. 521
  523. 522
  524. 523
  525. 524
  526. 525
  527. 526
  528. 527
  529. 528
  530. 529
  531. 530
  532. 531
  533. 532
  534. 533
  535. 534
  536. 535
  537. 536
  538. 537
  539. 538
  540. 539
  541. 540
  542. 541
  543. 542
  544. 543
  545. 544
  546. 545
  547. 546
  548. 547
  549. 548
  550. 549
  551. 550
  552. 551
  553. 552
  554. 553
  555. 554
  556. 555
  557. 556
  558. 557
  559. 558
  560. 559
  561. 560
  562. 561
  563. 562
  564. 563
  565. 564
  566. 565
  567. 566
  568. 567
  569. 568
  570. 569
  571. 570
  572. 571
  573. 572
  574. 573
  575. 574
  576. 575
  577. 576
  578. 577
  579. 578
  580. 579
  581. 580
  582. 581
  583. 582
  584. 583
  585. 584
  586. 585
  587. 586
  588. 587
  589. 588
  590. 589
  591. 590
  592. 591
  593. 592
  594. 593
  595. 594
  596. 595
  597. 596
  598. 597
  599. 598
  600. 599
  601. 600
  602. 601
  603. 602
  604. 603
  605. 604
  606. 605
  607. 606
  608. 607
  609. 608
  610. 609
  611. 610
  612. 611
  613. 612
  614. 613
  615. 614
  616. 615
  617. 616
  618. 617
  619. 618
  620. 619
  621. 620
  622. 621
  623. 622
  624. 623
  625. 624
  626. 625
  627. 626
  628. 627
  629. 628
  630. 629
  631. 630
  632. 631
  633. 632
  634. 633
  635. 634
  636. 635
  637. 636
  638. 637
  639. 638
  640. 639
  641. 640
  642. 641
  643. 642
  644. 643
  645. 644
  646. 645
  647. 646
  648. 647
  649. 648
  650. 649
  651. 650
  652. 651
  653. 652
  654. 653
  655. 654
  656. 655
  657. 656
  658. 657
  659. 658
  660. 659
  661. 660
  662. 661
  663. 662
  664. 663
  665. 664
  666. 665
  667. 666
  668. 667
  669. 668
  670. 669
  671. 670
  672. 671
  673. 672
  674. 673
  675. 674
  676. 675
  677. 676
  678. 677
  679. 678
  680. 679
  681. 680
  682. 681
  683. 682
  684. 683
  685. 684
  686. 685
  687. 686
  688. 687
  689. 688
  690. 689
  691. 690
  692. 691
  693. 692
  694. 693
  695. 694
  696. 695
  697. 696
  698. 697
  699. 698
  700. 699
  701. 700
  702. 701
  703. 702
  704. 703
  705. 704
  706. 705
  707. 706
  708. 707
  709. 708
  710. 709
  711. 710
  712. 711
  713. 712
  714. 713
  715. 714
  716. 715
  717. 716
  718. 717
  719. 718
  720. 719
  721. 720
  722. 721
  723. 722
  724. 723
  725. 724
  726. 725
  727. 726
  728. 727
  729. 728
  730. 729
  731. 730
  732. 731
  733. 732
  734. 733
  735. 734
  736. 735
  737. 736
  738. 737
  739. 738
  740. 739
  741. 740
  742. 741
  743. 742
  744. 743
  745. 744
  746. 745
  747. 746
  748. 747
  749. 748
  750. 749
  751. 750
  752. 751
  753. 752
  754. 753
  755. 754
  756. 755
  757. 756
  758. 757
  759. 758
  760. 759
  761. 760
  762. 761
  763. 762
  764. 763
  765. 764
  766. 765
  767. 766
  768. 767
  769. 768
  770. 769
  771. 770
  772. 771
  773. 772
  774. 773
  775. 774
  776. 775
  777. 776
  778. 777
  779. 778
  780. 779
  781. 780
  782. 781
  783. 782
  784. 783
  785. 784
  786. 785
  787. 786
  788. 787
  789. 788
  790. 789
  791. 790
  792. 791
  793. 792
  794. 793
  795. 794
  796. 795
  797. 796
  798. 797
  799. 798
  800. 799
  801. 800
  802. 801
  803. 802
  804. 803
  805. 804
  806. 805
  807. 806
  808. 807
  809. 808
  810. 809
  811. 810
  812. 811
  813. 812
  814. 813
  815. 814
  816. 815
  817. 816
  818. 817
  819. 818
  820. 819
  821. 820
  822. 821
  823. 822
  824. 823
  825. 824
  826. 825
  827. 826
  828. 827
  829. 828
  830. 829
  831. 830
  832. 831
  833. 832
  834. 833
  835. 834
  836. 835
  837. 836
  838. 837
  839. 838
  840. 839
  841. 840
  842. 841
  843. 842
  844. 843
  845. 844
  846. 845
  847. 846
  848. 847
  849. 848
  850. 849
  851. 850
  852. 851
  853. 852
  854. 853
  855. 854
  856. 855
  857. 856
  858. 857
  859. 858
  860. 859
  861. 860
  862. 861
  863. 862
  864. 863
  865. 864
  866. 865
  867. 866
  868. 867
  869. 868
  870. 869
  871. 870
  872. 871
  873. 872
  874. 873
  875. 874
  876. 875
  877. 876
  878. 877
  879. 878
  880. 879
  881. 880
  882. "use strict";
  883.  
  884. //TODO desativar o botão caso a pagina esteja traduzida
  885.  
  886. var translateSelected = {}
  887.  
  888. function getTabHostName() {
  889. return new Promise(resolve => chrome.runtime.sendMessage({action: "getTabHostName"}, result => resolve(result)))
  890. }
  891.  
  892. Promise.all([twpConfig.onReady(), getTabHostName()])
  893. .then(function (_) {
  894. const tabHostName = _[1]
  895. let styleTextContent = ""
  896. fetch(chrome.runtime.getURL("/contentScript/css/translateSelected.css"))
  897. .then(response => response.text())
  898. .then(response => {
  899. styleTextContent = response.replace('/icons/icon-32.png', chrome.runtime.getURL("/icons/icon-32.png"))
  900. })
  901. .catch(e => console.error(e))
  902.  
  903. let divElement
  904. let eButtonTransSelText
  905. let eDivResult
  906. let eSelTextTrans
  907. let eOrigText
  908. let eOrigTextDiv
  909.  
  910. let originalTabLanguage = "und"
  911. let currentTargetLanguages = twpConfig.get("targetLanguages")
  912. let currentTargetLanguage = twpConfig.get("targetLanguageTextTranslation")
  913. let currentTextTranslatorService = twpConfig.get("textTranslatorService")
  914. let awaysTranslateThisSite = twpConfig.get("alwaysTranslateSites").indexOf(tabHostName) !== -1
  915. let translateThisSite = twpConfig.get("neverTranslateSites").indexOf(tabHostName) === -1
  916. let translateThisLanguage = twpConfig.get("neverTranslateLangs").indexOf(originalTabLanguage) === -1
  917. let showTranslateSelectedButton = twpConfig.get("showTranslateSelectedButton")
  918. let dontShowIfPageLangIsTargetLang = twpConfig.get("dontShowIfPageLangIsTargetLang")
  919. let dontShowIfPageLangIsUnknown = twpConfig.get("dontShowIfPageLangIsUnknown")
  920. let dontShowIfSelectedTextIsTargetLang = twpConfig.get("dontShowIfSelectedTextIsTargetLang")
  921. let dontShowIfSelectedTextIsUnknown = twpConfig.get("dontShowIfSelectedTextIsUnknown")
  922. let fooCount = 0
  923.  
  924. pageTranslator.onGetOriginalTabLanguage(function (tabLanguage) {
  925. originalTabLanguage = tabLanguage
  926. translateThisLanguage = twpConfig.get("neverTranslateLangs").indexOf(originalTabLanguage) === -1
  927. updateEventListener()
  928. })
  929.  
  930. async function detectTextLanguage(text) {
  931. if (!chrome.i18n.detectLanguage) return "und"
  932.  
  933. return await new Promise(resolve => {
  934. chrome.i18n.detectLanguage(text, result => {
  935. if (!result) return resolve("und")
  936.  
  937. for (const langInfo of result.languages) {
  938. const langCode = twpLang.checkLanguageCode(langInfo.language)
  939. if (langCode) {
  940. return resolve(langCode)
  941. }
  942. }
  943.  
  944. return resolve("und")
  945. })
  946. })
  947. }
  948.  
  949. let audioDataUrls = null
  950. let isPlayingAudio = false
  951.  
  952. function stopAudio() {
  953. if (isPlayingAudio) {
  954. chrome.runtime.sendMessage({
  955. action: "stopAudio"
  956. })
  957. }
  958. isPlayingAudio = false
  959. }
  960.  
  961. function dragElement(elmnt, elmnt2) {
  962. var pos1 = 0,
  963. pos2 = 0,
  964. pos3 = 0,
  965. pos4 = 0;
  966. if (elmnt2) {
  967. elmnt2.addEventListener("mousedown", dragMouseDown);
  968. } else {
  969. elmnt.addEventListener("mousedown", dragMouseDown);
  970. }
  971.  
  972. function dragMouseDown(e) {
  973. e = e || window.event;
  974. e.preventDefault();
  975. // get the mouse cursor position at startup:
  976. pos3 = e.clientX;
  977. pos4 = e.clientY;
  978. document.addEventListener("mouseup", closeDragElement);
  979. // call a function whenever the cursor moves:
  980. document.addEventListener("mousemove", elementDrag);
  981. }
  982.  
  983. function elementDrag(e) {
  984. e = e || window.event;
  985. e.preventDefault();
  986. // calculate the new cursor position:
  987. pos1 = pos3 - e.clientX;
  988. pos2 = pos4 - e.clientY;
  989. pos3 = e.clientX;
  990. pos4 = e.clientY;
  991. // set the element's new position:
  992. elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
  993. elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  994. }
  995.  
  996. function closeDragElement() {
  997. // stop moving when mouse button is released:
  998. document.removeEventListener("mouseup", closeDragElement);
  999. document.removeEventListener("mousemove", elementDrag);
  1000. }
  1001. }
  1002.  
  1003. function setCaretAtEnd() {
  1004. const el = eOrigText
  1005. const range = document.createRange()
  1006. const sel = window.getSelection()
  1007. range.setStart(el, 1)
  1008. range.collapse(true)
  1009. sel.removeAllRanges()
  1010. sel.addRange(range)
  1011. el.focus()
  1012. }
  1013.  
  1014. function init() {
  1015. destroy()
  1016.  
  1017. window.isTranslatingSelected = true
  1018.  
  1019. divElement = document.createElement("div")
  1020. divElement.style = "all: initial"
  1021. divElement.classList.add("notranslate")
  1022.  
  1023. const shadowRoot = divElement.attachShadow({
  1024. mode: "closed"
  1025. })
  1026. shadowRoot.innerHTML = `
  1027. <link rel="stylesheet" href="${chrome.runtime.getURL("/contentScript/css/translateSelected.css")}">
  1028.  
  1029. <div id="eButtonTransSelText"></div>
  1030. <div id="eDivResult">
  1031. <div id="eOrigTextDiv">
  1032. <div id="eOrigText" contentEditable="true" spellcheck="false" dir="auto"></div>
  1033. <hr>
  1034. </div>
  1035. <div id="eSelTextTrans" dir="auto"></div>
  1036. <hr>
  1037. <div id="drag">
  1038. <ul id="setTargetLanguage">
  1039. <li value="en" title="English">en</li>
  1040. <li value="es" title="Spanish">es</li>
  1041. <li value="de" title="German">de</li>
  1042. </ul>
  1043. <div id="moreOrLess"><i class="arrow up" id="more"></i><i class="arrow down" id="less"></i></div>
  1044. <ul>
  1045. <li title="Google" id="sGoogle">g</li>
  1046. <li title="Yandex" id="sYandex">y</li>
  1047. <li title="Bing" id="sBing">b</li>
  1048. <li title="DeepL" id="sDeepL" hidden>d</li>
  1049. <li title="Listen" data-i18n-title="btnListen" id="listen">
  1050. <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
  1051. width="14px" height="12px" viewBox="0 0 93.038 93.038" xml:space="preserve">
  1052. <g>
  1053. <path d="M46.547,75.521c0,1.639-0.947,3.128-2.429,3.823c-0.573,0.271-1.187,0.402-1.797,0.402c-0.966,0-1.923-0.332-2.696-0.973
  1054. l-23.098-19.14H4.225C1.892,59.635,0,57.742,0,55.409V38.576c0-2.334,1.892-4.226,4.225-4.226h12.303l23.098-19.14
  1055. c1.262-1.046,3.012-1.269,4.493-0.569c1.481,0.695,2.429,2.185,2.429,3.823L46.547,75.521L46.547,75.521z M62.784,68.919
  1056. c-0.103,0.007-0.202,0.011-0.304,0.011c-1.116,0-2.192-0.441-2.987-1.237l-0.565-0.567c-1.482-1.479-1.656-3.822-0.408-5.504
  1057. c3.164-4.266,4.834-9.323,4.834-14.628c0-5.706-1.896-11.058-5.484-15.478c-1.366-1.68-1.24-4.12,0.291-5.65l0.564-0.565
  1058. c0.844-0.844,1.975-1.304,3.199-1.231c1.192,0.06,2.305,0.621,3.061,1.545c4.977,6.09,7.606,13.484,7.606,21.38
  1059. c0,7.354-2.325,14.354-6.725,20.24C65.131,68.216,64.007,68.832,62.784,68.919z M80.252,81.976
  1060. c-0.764,0.903-1.869,1.445-3.052,1.495c-0.058,0.002-0.117,0.004-0.177,0.004c-1.119,0-2.193-0.442-2.988-1.237l-0.555-0.555
  1061. c-1.551-1.55-1.656-4.029-0.246-5.707c6.814-8.104,10.568-18.396,10.568-28.982c0-11.011-4.019-21.611-11.314-29.847
  1062. c-1.479-1.672-1.404-4.203,0.17-5.783l0.554-0.555c0.822-0.826,1.89-1.281,3.115-1.242c1.163,0.033,2.263,0.547,3.036,1.417
  1063. c8.818,9.928,13.675,22.718,13.675,36.01C93.04,59.783,88.499,72.207,80.252,81.976z"/>
  1064. </g>
  1065. <g>
  1066. </g>
  1067. <g>
  1068. </g>
  1069. <g>
  1070. </g>
  1071. <g>
  1072. </g>
  1073. <g>
  1074. </g>
  1075. <g>
  1076. </g>
  1077. <g>
  1078. </g>
  1079. <g>
  1080. </g>
  1081. <g>
  1082. </g>
  1083. <g>
  1084. </g>
  1085. <g>
  1086. </g>
  1087. <g>
  1088. </g>
  1089. <g>
  1090. </g>
  1091. <g>
  1092. </g>
  1093. <g>
  1094. </g>
  1095. </svg>
  1096. </li>
  1097. </ul>
  1098. </div>
  1099. </div>
  1100. `
  1101.  
  1102. {
  1103. const style = document.createElement("style")
  1104. style.textContent = styleTextContent
  1105. shadowRoot.insertBefore(style, shadowRoot.getElementById("eButtonTransSelText"))
  1106. }
  1107.  
  1108. dragElement(shadowRoot.getElementById("eDivResult"), shadowRoot.getElementById("drag"))
  1109.  
  1110. function enableDarkMode() {
  1111. if (!shadowRoot.getElementById("darkModeElement")) {
  1112. const el = document.createElement("style")
  1113. el.setAttribute("id", "darkModeElement")
  1114. el.setAttribute("rel", "stylesheet")
  1115. el.textContent = `
  1116. * {
  1117. scrollbar-color: #202324 #454a4d;
  1118. }
  1119. #eDivResult {
  1120. color: rgb(231, 230, 228) !important;
  1121. background-color: #181a1b !important;
  1122. }
  1123. hr {
  1124. border-color: #666;
  1125. }
  1126. li:hover, #moreOrLess:hover {
  1127. color: rgb(231, 230, 228) !important;
  1128. background-color: #454a4d !important;
  1129. }
  1130. .selected {
  1131. background-color: #454a4d !important;
  1132. }
  1133. .arrow {
  1134. border: solid rgb(231, 230, 228);
  1135. border-width: 0 1px 1px 0;
  1136. }
  1137. `
  1138. shadowRoot.appendChild(el)
  1139. shadowRoot.querySelector("#listen svg").style = "fill: rgb(231, 230, 228)"
  1140. }
  1141. }
  1142.  
  1143. function disableDarkMode() {
  1144. if (shadowRoot.getElementById("#darkModeElement")) {
  1145. shadowRoot.getElementById("#darkModeElement").remove()
  1146. shadowRoot.querySelector("#listen svg").style = "fill: black"
  1147. }
  1148. }
  1149.  
  1150. switch (twpConfig.get("darkMode")) {
  1151. case "auto":
  1152. if (matchMedia("(prefers-color-scheme: dark)").matches) {
  1153. enableDarkMode()
  1154. } else {
  1155. disableDarkMode()
  1156. }
  1157. break
  1158. case "yes":
  1159. enableDarkMode()
  1160. break
  1161. case "no":
  1162. disableDarkMode()
  1163. break
  1164. default:
  1165. break
  1166. }
  1167.  
  1168. eButtonTransSelText = shadowRoot.getElementById("eButtonTransSelText")
  1169. eDivResult = shadowRoot.getElementById("eDivResult")
  1170. eSelTextTrans = shadowRoot.getElementById("eSelTextTrans")
  1171. eOrigText = shadowRoot.getElementById("eOrigText")
  1172. eOrigTextDiv = shadowRoot.getElementById("eOrigTextDiv")
  1173.  
  1174. const eMoreOrLess = shadowRoot.getElementById("moreOrLess")
  1175. const eMore = shadowRoot.getElementById("more")
  1176. const eLess = shadowRoot.getElementById("less")
  1177.  
  1178. const sGoogle = shadowRoot.getElementById("sGoogle")
  1179. const sYandex = shadowRoot.getElementById("sYandex")
  1180. const sBing = shadowRoot.getElementById("sBing")
  1181. const sDeepL = shadowRoot.getElementById("sDeepL")
  1182.  
  1183. eOrigText.onkeypress = e => {
  1184. e.stopPropagation()
  1185. }
  1186.  
  1187. eOrigText.onkeydown = e => {
  1188. e.stopPropagation()
  1189. }
  1190.  
  1191. let translateNewInputTimerHandler
  1192. eOrigText.oninput = () => {
  1193. clearTimeout(translateNewInputTimerHandler)
  1194. translateNewInputTimerHandler = setTimeout(translateNewInput, 800)
  1195. }
  1196.  
  1197. eMoreOrLess.onclick = () => {
  1198. if (twpConfig.get("expandPanelTranslateSelectedText") === "no") {
  1199. twpConfig.set("expandPanelTranslateSelectedText", "yes")
  1200. } else {
  1201. twpConfig.set("expandPanelTranslateSelectedText", "no")
  1202. }
  1203.  
  1204. setCaretAtEnd()
  1205. }
  1206.  
  1207. sGoogle.onclick = () => {
  1208. currentTextTranslatorService = "google"
  1209. twpConfig.set("textTranslatorService", "google")
  1210. translateNewInput()
  1211.  
  1212. sGoogle.classList.remove("selected")
  1213. sYandex.classList.remove("selected")
  1214. sBing.classList.remove("selected")
  1215. sDeepL.classList.remove("selected")
  1216.  
  1217. sGoogle.classList.add("selected")
  1218. }
  1219. sYandex.onclick = () => {
  1220. currentTextTranslatorService = "yandex"
  1221. twpConfig.set("textTranslatorService", "yandex")
  1222. translateNewInput()
  1223.  
  1224. sGoogle.classList.remove("selected")
  1225. sYandex.classList.remove("selected")
  1226. sBing.classList.remove("selected")
  1227. sDeepL.classList.remove("selected")
  1228.  
  1229. sYandex.classList.add("selected")
  1230. }
  1231. sBing.onclick = () => {
  1232. currentTextTranslatorService = "bing"
  1233. twpConfig.set("textTranslatorService", "bing")
  1234. translateNewInput()
  1235.  
  1236. sGoogle.classList.remove("selected")
  1237. sYandex.classList.remove("selected")
  1238. sBing.classList.remove("selected")
  1239. sDeepL.classList.remove("selected")
  1240.  
  1241. sBing.classList.add("selected")
  1242. }
  1243. sDeepL.onclick = () => {
  1244. currentTextTranslatorService = "deepl"
  1245. twpConfig.set("textTranslatorService", "deepl")
  1246. translateNewInput()
  1247.  
  1248. sGoogle.classList.remove("selected")
  1249. sYandex.classList.remove("selected")
  1250. sBing.classList.remove("selected")
  1251. sDeepL.classList.remove("selected")
  1252.  
  1253. sDeepL.classList.add("selected")
  1254. }
  1255.  
  1256. const setTargetLanguage = shadowRoot.getElementById("setTargetLanguage")
  1257. setTargetLanguage.onclick = e => {
  1258. if (e.target.getAttribute("value")) {
  1259. const langCode = twpLang.checkLanguageCode(e.target.getAttribute("value"))
  1260. if (langCode) {
  1261. currentTargetLanguage = langCode
  1262. twpConfig.setTargetLanguageTextTranslation(langCode)
  1263. translateNewInput()
  1264. }
  1265.  
  1266. shadowRoot.querySelectorAll("#setTargetLanguage li").forEach(li => {
  1267. li.classList.remove("selected")
  1268. })
  1269.  
  1270. e.target.classList.add("selected")
  1271. }
  1272. }
  1273.  
  1274. const eListen = shadowRoot.getElementById("listen")
  1275. eListen.onclick = () => {
  1276. const msgListen = chrome.i18n.getMessage("btnListen")
  1277. const msgStopListening = chrome.i18n.getMessage("btnStopListening")
  1278.  
  1279. eListen.classList.remove("selected")
  1280. eListen.setAttribute("title", msgStopListening)
  1281.  
  1282. if (audioDataUrls) {
  1283. if (isPlayingAudio) {
  1284. stopAudio()
  1285. eListen.setAttribute("title", msgListen)
  1286. } else {
  1287. isPlayingAudio = true
  1288. chrome.runtime.sendMessage({
  1289. action: "playAudio",
  1290. audioDataUrls
  1291. }, () => {
  1292. eListen.classList.remove("selected")
  1293. eListen.setAttribute("title", msgListen)
  1294. })
  1295. eListen.classList.add("selected")
  1296. }
  1297. } else {
  1298. stopAudio()
  1299. isPlayingAudio = true
  1300. chrome.runtime.sendMessage({
  1301. action: "textToSpeech",
  1302. text: eSelTextTrans.textContent,
  1303. targetLanguage: currentTargetLanguage
  1304. }, result => {
  1305. if (!result) return;
  1306.  
  1307. audioDataUrls = result
  1308. chrome.runtime.sendMessage({
  1309. action: "playAudio",
  1310. audioDataUrls
  1311. }, () => {
  1312. isPlayingAudio = false
  1313. eListen.classList.remove("selected")
  1314. eListen.setAttribute("title", msgListen)
  1315. })
  1316. })
  1317. eListen.classList.add("selected")
  1318. }
  1319. }
  1320.  
  1321. document.body.appendChild(divElement)
  1322.  
  1323. chrome.i18n.translateDocument(shadowRoot)
  1324.  
  1325. if (platformInfo.isMobile.any) {
  1326. eButtonTransSelText.style.width = "30px"
  1327. eButtonTransSelText.style.height = "30px"
  1328. document.addEventListener("touchstart", onTouchstart)
  1329. }
  1330.  
  1331. eButtonTransSelText.addEventListener("click", onClick)
  1332. document.addEventListener("mousedown", onDown)
  1333.  
  1334. const targetLanguageButtons = shadowRoot.querySelectorAll("#setTargetLanguage li")
  1335.  
  1336. for (let i = 0; i < 3; i++) {
  1337. if (currentTargetLanguages[i] == currentTargetLanguage) {
  1338. targetLanguageButtons[i].classList.add("selected")
  1339. }
  1340. targetLanguageButtons[i].textContent = currentTargetLanguages[i]
  1341. targetLanguageButtons[i].setAttribute("value", currentTargetLanguages[i])
  1342. targetLanguageButtons[i].setAttribute("title", twpLang.codeToLanguage(currentTargetLanguages[i]))
  1343. }
  1344.  
  1345. if (currentTextTranslatorService === "yandex") {
  1346. sYandex.classList.add("selected")
  1347. } else if (currentTextTranslatorService == "deepl") {
  1348. sDeepL.classList.add("selected")
  1349. } else if (currentTextTranslatorService == "bing") {
  1350. sBing.classList.add("selected")
  1351. } else {
  1352. sGoogle.classList.add("selected")
  1353. }
  1354.  
  1355. if (twpConfig.get("enableDeepL") === "yes") {
  1356. sDeepL.removeAttribute("hidden")
  1357. } else {
  1358. sDeepL.setAttribute("hidden", "")
  1359. }
  1360. if (twpConfig.get("expandPanelTranslateSelectedText") === "yes") {
  1361. eOrigTextDiv.style.display = "block"
  1362. eMore.style.display = "none"
  1363. eLess.style.display = "block"
  1364. eMoreOrLess.setAttribute("title", chrome.i18n.getMessage("less"))
  1365. } else {
  1366. eOrigTextDiv.style.display = "none"
  1367. eMore.style.display = "block"
  1368. eLess.style.display = "none"
  1369. eMoreOrLess.setAttribute("title", chrome.i18n.getMessage("more"))
  1370. }
  1371. twpConfig.onChanged((name, newvalue) => {
  1372. switch (name) {
  1373. case "enableDeepL":
  1374. if (newvalue === "yes") {
  1375. sDeepL.removeAttribute("hidden")
  1376. } else {
  1377. sDeepL.setAttribute("hidden", "")
  1378. }
  1379. break
  1380. case "expandPanelTranslateSelectedText":
  1381. if (newvalue === "yes") {
  1382. eOrigTextDiv.style.display = "block"
  1383. eMore.style.display = "none"
  1384. eLess.style.display = "block"
  1385. eMoreOrLess.setAttribute("title", chrome.i18n.getMessage("less"))
  1386. } else {
  1387. eOrigTextDiv.style.display = "none"
  1388. eMore.style.display = "block"
  1389. eLess.style.display = "none"
  1390. eMoreOrLess.setAttribute("title", chrome.i18n.getMessage("more"))
  1391. }
  1392. break
  1393. }
  1394. })
  1395. }
  1396.  
  1397. function destroy() {
  1398. window.isTranslatingSelected = false
  1399. fooCount++
  1400. stopAudio()
  1401. audioDataUrls = null
  1402. if (!divElement) return;
  1403.  
  1404. eButtonTransSelText.removeEventListener("click", onClick)
  1405. document.removeEventListener("mousedown", onDown)
  1406. if (platformInfo.isMobile.any) {
  1407. document.removeEventListener("touchstart", onTouchstart)
  1408. }
  1409. divElement.remove()
  1410. divElement = eButtonTransSelText = eDivResult = null
  1411. }
  1412.  
  1413. function destroyIfButtonIsShowing(e) {
  1414. if (eButtonTransSelText && e.target !== divElement && eButtonTransSelText.style.display === "block") {
  1415. destroy()
  1416. }
  1417. }
  1418.  
  1419. twpConfig.onChanged(function (name, newValue) {
  1420. switch (name) {
  1421. case "textTranslatorService":
  1422. currentTextTranslatorService = newValue
  1423. break
  1424. case "targetLanguages":
  1425. currentTargetLanguages = newValue
  1426. break
  1427. case "targetLanguageTextTranslation":
  1428. currentTargetLanguage = newValue
  1429. break
  1430. case "alwaysTranslateSites":
  1431. awaysTranslateThisSite = newValue.indexOf(tabHostName) !== -1
  1432. updateEventListener()
  1433. break
  1434. case "neverTranslateSites":
  1435. translateThisSite = newValue.indexOf(tabHostName) === -1
  1436. updateEventListener()
  1437. break
  1438. case "neverTranslateLangs":
  1439. translateThisLanguage = newValue.indexOf(originalTabLanguage) === -1
  1440. updateEventListener()
  1441. break
  1442. case "showTranslateSelectedButton":
  1443. showTranslateSelectedButton = newValue
  1444. updateEventListener()
  1445. break
  1446. case "dontShowIfPageLangIsTargetLang":
  1447. dontShowIfPageLangIsTargetLang = newValue
  1448. updateEventListener()
  1449. break
  1450. case "dontShowIfPageLangIsUnknown":
  1451. dontShowIfPageLangIsUnknown = newValue
  1452. updateEventListener()
  1453. break
  1454. case "dontShowIfSelectedTextIsTargetLang":
  1455. dontShowIfSelectedTextIsTargetLang = newValue
  1456. break
  1457. case "dontShowIfSelectedTextIsUnknown":
  1458. dontShowIfSelectedTextIsUnknown = newValue
  1459. break
  1460. }
  1461. })
  1462.  
  1463. function update_eDivResult(result = "") {
  1464. if (eDivResult.style.display !== "block") {
  1465. init()
  1466. }
  1467. const eTop = prevSelectionInfo.bottom
  1468. const eLeft = prevSelectionInfo.left
  1469.  
  1470. if (twpLang.isRtlLanguage(currentTargetLanguage)) {
  1471. eSelTextTrans.setAttribute("dir", "rtl")
  1472. } else {
  1473. eSelTextTrans.setAttribute("dir", "ltr")
  1474. }
  1475. eSelTextTrans.textContent = result
  1476. if (eDivResult.style.display !== "block") {
  1477. eDivResult.style.display = "block"
  1478. eDivResult.style.top = "0px"
  1479. eDivResult.style.left = "0px"
  1480. eOrigText.textContent = prevSelectionInfo.text
  1481.  
  1482. setCaretAtEnd()
  1483.  
  1484. const height = parseInt(eDivResult.offsetHeight)
  1485. let top = eTop + 5
  1486. top = Math.max(0, top)
  1487. top = Math.min(window.innerHeight - height, top)
  1488.  
  1489. const width = parseInt(eDivResult.offsetWidth)
  1490. let left = parseInt(eLeft /*- width / 2*/ )
  1491. left = Math.max(0, left)
  1492. left = Math.min(window.innerWidth - width, left)
  1493.  
  1494. eDivResult.style.top = top + "px"
  1495. eDivResult.style.left = left + "px"
  1496. }
  1497. }
  1498.  
  1499. function translateNewInput() {
  1500. fooCount++
  1501. let currentFooCount = fooCount
  1502. stopAudio()
  1503. audioDataUrls = null
  1504.  
  1505. backgroundTranslateSingleText(currentTextTranslatorService, currentTargetLanguage, eOrigText.textContent)
  1506. .then(result => {
  1507. if (currentFooCount !== fooCount) return;
  1508.  
  1509. update_eDivResult(result)
  1510. })
  1511. }
  1512.  
  1513. let gSelectionInfo
  1514. let prevSelectionInfo
  1515.  
  1516. function translateSelText(usePrevSelectionInfo = false) {
  1517. if (!usePrevSelectionInfo && gSelectionInfo) {
  1518. prevSelectionInfo = gSelectionInfo
  1519. } else if (!(usePrevSelectionInfo && prevSelectionInfo)) {
  1520. return
  1521. }
  1522.  
  1523. eOrigText.textContent = prevSelectionInfo.text
  1524.  
  1525. translateNewInput()
  1526. const currentFooCount = fooCount
  1527. setTimeout(() => {
  1528. if (currentFooCount !== fooCount) return;
  1529. update_eDivResult(eSelTextTrans.textContent)
  1530. fooCount = currentFooCount
  1531. }, 1000)
  1532. }
  1533.  
  1534. function onClick(e) {
  1535. translateSelText()
  1536. eButtonTransSelText.style.display = "none"
  1537. }
  1538.  
  1539. function onDown(e) {
  1540. if (e.target != divElement) {
  1541. eDivResult.style.display = "none"
  1542. eButtonTransSelText.style.display = "none"
  1543. destroy()
  1544. }
  1545. }
  1546.  
  1547.  
  1548. let isTouchSelection = false
  1549.  
  1550. function onTouchstart(e) {
  1551. isTouchSelection = true
  1552. onDown(e)
  1553. }
  1554.  
  1555. function getSelectionText() {
  1556. let text = "";
  1557. const activeEl = document.activeElement;
  1558. const activeElTagName = activeEl ? activeEl.tagName.toLowerCase() : null;
  1559. if (
  1560. (activeElTagName == "textarea") || (activeElTagName == "input" &&
  1561. /^(?:text|search)$/i.test(activeEl.type)) &&
  1562. (typeof activeEl.selectionStart == "number")
  1563. ) {
  1564. text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd);
  1565. } else if (window.getSelection) {
  1566. text = window.getSelection().toString();
  1567. }
  1568. return text;
  1569. }
  1570.  
  1571. function readSelection(dontReadIfSelectionDontChange = false) {
  1572. let newSelectionInfo = null
  1573.  
  1574. const activeEl = document.activeElement;
  1575. const activeElTagName = activeEl ? activeEl.tagName.toLowerCase() : null;
  1576. if (
  1577. (activeElTagName == "textarea") || (activeElTagName == "input" &&
  1578. /^(?:text|search)$/i.test(activeEl.type)) &&
  1579. (typeof activeEl.selectionStart == "number")
  1580. ) {
  1581. const text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd);
  1582. const rect = activeEl.getBoundingClientRect()
  1583. newSelectionInfo = {
  1584. text: text,
  1585. top: rect.top,
  1586. left: rect.left,
  1587. bottom: rect.bottom,
  1588. right: rect.right
  1589. }
  1590. } else if (window.getSelection) {
  1591. const selection = window.getSelection()
  1592. if (selection.type == "Range") {
  1593. const text = selection.toString();
  1594. const rect = selection.getRangeAt(0).getBoundingClientRect()
  1595. newSelectionInfo = {
  1596. text: text,
  1597. top: rect.top,
  1598. left: rect.left,
  1599. bottom: rect.bottom,
  1600. right: rect.right
  1601. }
  1602. }
  1603. }
  1604.  
  1605. if (dontReadIfSelectionDontChange && gSelectionInfo && newSelectionInfo && gSelectionInfo.text === newSelectionInfo.text) {
  1606. gSelectionInfo = newSelectionInfo
  1607. return false
  1608. }
  1609. gSelectionInfo = newSelectionInfo
  1610. return true
  1611. }
  1612.  
  1613. async function onUp(e) {
  1614. if (e.target == divElement) return;
  1615.  
  1616. const clientX = Math.max((typeof e.clientX === 'undefined' ? 0 : e.clientX), (typeof e.changedTouches === 'undefined' ? 0 : e.changedTouches[0].clientX));
  1617. const clientY = Math.max((typeof e.clientY === 'undefined' ? 0 : e.clientY), (typeof e.changedTouches === 'undefined' ? 0 : e.changedTouches[0].clientY));
  1618.  
  1619. const selectedText = getSelectionText().trim()
  1620. if (!selectedText || selectedText.length < 1) return;
  1621. let detectedLanguage = await detectTextLanguage(selectedText)
  1622. if (!detectedLanguage) detectedLanguage = "und";
  1623.  
  1624. if (((dontShowIfSelectedTextIsTargetLang == "yes" && detectedLanguage !== currentTargetLanguage) || dontShowIfSelectedTextIsTargetLang != "yes") &&
  1625. ((dontShowIfSelectedTextIsUnknown == "yes" && detectedLanguage !== "und") || dontShowIfSelectedTextIsUnknown != "yes")
  1626. ) {
  1627. init()
  1628. if (platformInfo.isMobile.any) {
  1629. eButtonTransSelText.style.left = window.innerWidth - 45 + "px"
  1630. eButtonTransSelText.style.top = clientY + "px"
  1631. } else {
  1632. eButtonTransSelText.style.left = clientX + 20 + "px"
  1633. eButtonTransSelText.style.top = clientY - 30 + "px"
  1634. }
  1635.  
  1636. eButtonTransSelText.style.display = "block"
  1637. }
  1638. }
  1639.  
  1640. let showButtonTimerHandler = null
  1641.  
  1642. function onMouseup(e) {
  1643. if (e.button != 0) return;
  1644. if (e.target == divElement) return;
  1645. if (readSelection(true)) {
  1646. clearTimeout(showButtonTimerHandler)
  1647. showButtonTimerHandler = setTimeout(() => onUp(e), 150)
  1648. }
  1649. }
  1650.  
  1651. function onTouchend(e) {
  1652. if (e.target == divElement) return;
  1653. readSelection()
  1654. clearTimeout(showButtonTimerHandler)
  1655. showButtonTimerHandler = setTimeout(() => onUp(e), 150)
  1656. }
  1657.  
  1658. function onSelectionchange(e) {
  1659. if (isTouchSelection) {
  1660. readSelection()
  1661. }
  1662. }
  1663.  
  1664. function isSelectingText() {
  1665. const activeEl = document.activeElement;
  1666. const activeElTagName = activeEl ? activeEl.tagName.toLowerCase() : null;
  1667. if (
  1668. (activeElTagName == "textarea") || (activeElTagName == "input" &&
  1669. /^(?:text|search)$/i.test(activeEl.type)) &&
  1670. (typeof activeEl.selectionStart == "number")
  1671. ) {
  1672. const text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd);
  1673. if (text) return true;
  1674. } else if (window.getSelection) {
  1675. const selection = window.getSelection()
  1676. if (selection.type == "Range") {
  1677. const text = selection.toString();
  1678. if (text) return true;
  1679. }
  1680. }
  1681. return false
  1682. }
  1683.  
  1684. let lastTimePressedCtrl = null
  1685.  
  1686. function onKeyUp(e) {
  1687. if (twpConfig.get("translateSelectedWhenPressTwice") !== "yes") return;
  1688. if (e.key == "Control") {
  1689. if (lastTimePressedCtrl && performance.now() - lastTimePressedCtrl < 280 && isSelectingText()) {
  1690. lastTimePressedCtrl = performance.now()
  1691. readSelection()
  1692. init()
  1693. translateSelText()
  1694. }
  1695. lastTimePressedCtrl = performance.now()
  1696. }
  1697. }
  1698. document.addEventListener("keyup", onKeyUp)
  1699.  
  1700. let windowIsInFocus = true
  1701. window.addEventListener("focus", function (e) {
  1702. windowIsInFocus = true
  1703. chrome.runtime.sendMessage({action: "thisFrameIsInFocus"})
  1704. })
  1705. window.addEventListener("blur", function (e) {
  1706. windowIsInFocus = false
  1707. })
  1708.  
  1709. window.addEventListener("beforeunload", function (e) {
  1710. destroy()
  1711. })
  1712.  
  1713. function updateEventListener() {
  1714. if (showTranslateSelectedButton == "yes" && (awaysTranslateThisSite || (translateThisSite && translateThisLanguage)) &&
  1715. ((dontShowIfPageLangIsTargetLang == "yes" && originalTabLanguage !== currentTargetLanguage) || dontShowIfPageLangIsTargetLang != "yes") &&
  1716. ((dontShowIfPageLangIsUnknown == "yes" && originalTabLanguage !== "und") || dontShowIfPageLangIsUnknown != "yes")
  1717. ) {
  1718. document.addEventListener("mouseup", onMouseup)
  1719.  
  1720. document.addEventListener("blur", destroyIfButtonIsShowing)
  1721. document.addEventListener("visibilitychange", destroyIfButtonIsShowing)
  1722.  
  1723. document.addEventListener("keydown", destroyIfButtonIsShowing)
  1724. document.addEventListener("mousedown", destroyIfButtonIsShowing)
  1725. document.addEventListener("wheel", destroyIfButtonIsShowing)
  1726.  
  1727. if (platformInfo.isMobile.any) {
  1728. document.addEventListener("touchend", onTouchend)
  1729. document.addEventListener("selectionchange", onSelectionchange)
  1730. }
  1731. } else {
  1732. document.removeEventListener("mouseup", onMouseup)
  1733.  
  1734. document.removeEventListener("blur", destroyIfButtonIsShowing)
  1735. document.removeEventListener("visibilitychange", destroyIfButtonIsShowing)
  1736.  
  1737. document.removeEventListener("keydown", destroyIfButtonIsShowing)
  1738. document.removeEventListener("mousedown", destroyIfButtonIsShowing)
  1739. document.removeEventListener("wheel", destroyIfButtonIsShowing)
  1740.  
  1741. if (platformInfo.isMobile.any) {
  1742. document.removeEventListener("touchend", onTouchend)
  1743. document.removeEventListener("selectionchange", onSelectionchange)
  1744. }
  1745. }
  1746. }
  1747. updateEventListener()
  1748.  
  1749. chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  1750. if (request.action === "TranslateSelectedText") {
  1751. readSelection()
  1752. init()
  1753. translateSelText()
  1754. } else if (request.action === "anotherFrameIsInFocus") {
  1755. if (!windowIsInFocus) {
  1756. destroy()
  1757. }
  1758. }
  1759. })
  1760. })
Add Comment
Please, Sign In to add comment