🏠 Home 

MAL English Titles

Add English Titles to various MyAnimeList pages, whilst still displaying Japanese Titles


Install this script?
  1. // ==UserScript==
  2. // @name MAL English Titles
  3. // @version 2.2.0
  4. // @description Add English Titles to various MyAnimeList pages, whilst still displaying Japanese Titles
  5. // @author Animorphs
  6. // @grant GM_setValue
  7. // @grant GM_getValue
  8. // @namespace https://github.com/Animorphs/MAL-English-Titles
  9. // @match https://myanimelist.net/*
  10. // ==/UserScript==
  11. // Get Japanese titles from page, and send to be translated (addTranslation)
  12. function translate()
  13. {
  14. const LOCATION_HREF = location.href;
  15. const URL_REGEX = /https:\/\/myanimelist\.net\/(anime|manga)\/([1-9][0-9]?[0-9]?[0-9]?[0-9]?[0-9]?)\/?.*/;
  16. const URL_PHP_REGEX = /https:\/\/myanimelist\.net\/(anime|manga)\.php\?id\=([1-9][0-9]?[0-9]?[0-9]?[0-9]?[0-9]?)\/?.*/;
  17. // Anime/Manga Page (store only, don't display)
  18. if (URL_REGEX.test(LOCATION_HREF) || URL_PHP_REGEX.test(LOCATION_HREF))
  19. {
  20. let titleHtml = document.getElementsByClassName('title-english')[0];
  21. let id = LOCATION_HREF.includes('.php') ? LOCATION_HREF.split('id=')[1] : LOCATION_HREF.split('/')[4];
  22. let type = LOCATION_HREF.includes('/anime') ? "anime" : "manga";
  23. if (titleHtml)
  24. {
  25. let title = titleHtml.innerText;
  26. console.log(`Updated ${type} ${id}: ${title}`);
  27. type == 'anime' ? storeAnime(id, title) : storeManga(id, title);
  28. }
  29. else if (storedAnime[id][0] === '' || !storedAnime.hasOwnProperty(id))
  30. {
  31. console.log(`Updated ${type} ${id}`);
  32. type == 'anime' ? storeAnime(id, '') : storeManga(id, '');
  33. }
  34. }
  35. // // Anime/Manga Page User Recommendations
  36. if ((URL_REGEX.test(LOCATION_HREF) || URL_PHP_REGEX.test(LOCATION_HREF)) && LOCATION_HREF.includes('/userrecs'))
  37. {
  38. let r###lts = document.querySelectorAll('[style*="margin-bottom: 2px"]');
  39. let type = LOCATION_HREF.includes('/anime') ? 'anime' : 'manga';
  40. for (let i = 0; i < r###lts.length; i++)
  41. {
  42. if (!document.getElementById(type + i))
  43. {
  44. let url = r###lts[i].children[0].href;
  45. let urlDecoded = decodeURIComponent(url);
  46. let id = url.split('/')[4];
  47. //console.log(id)
  48. let selector = 'div[style="margin-bottom: 2px;"] > a[href="' + urlDecoded + '"]';
  49. addTranslation(type, i, url, id, selector);
  50. }
  51. }
  52. }
  53. // Recommendations
  54. else if (LOCATION_HREF.includes('https://myanimelist.net/recommendations.php'))
  55. {
  56. let r###lts = document.querySelectorAll('.spaceit.borderClass a:has(strong)');
  57. let arr = []
  58. let type = LOCATION_HREF.includes('&t=anime') ? 'anime' : 'manga';
  59. for (let i = 0; i < r###lts.length; i++)
  60. {
  61. if (!document.getElementById(type + i))
  62. {
  63. let url = r###lts[i].href;
  64. let urlDecoded = decodeURIComponent(url);
  65. let parts = urlDecoded.split('/' + type);
  66. let urlShort = '/' + type + parts[1];
  67. if (!arr.includes(urlShort))
  68. {
  69. arr.push(urlShort)
  70. let id = url.split('/')[4];
  71. let selector = 'td > a[href*="' + urlShort + '"]:not(:has(+ div[style="font-weight:bold"]))';
  72. addTranslation(type, i, url, id, selector);
  73. }
  74. }
  75. }
  76. }
  77. // Anime Top
  78. else if (LOCATION_HREF.includes('https://myanimelist.net/topanime.php'))
  79. {
  80. let r###lts = document.getElementsByClassName('fl-l fs14 fw-b anime_ranking_h3');
  81. for (let i = 0; i < r###lts.length; i++)
  82. {
  83. if (!document.getElementById('anime' + i))
  84. {
  85. let url = r###lts[i].children[0].href;
  86. let urlDecoded = decodeURIComponent(url);
  87. let id = url.split('/')[4];
  88. let selector = '.fl-l.fs14.fw-b.anime_ranking_h3 > a[href="' + urlDecoded + '"]';
  89. addTranslation('anime', i, url, id, selector);
  90. }
  91. }
  92. }
  93. // Manga Top
  94. else if (LOCATION_HREF.includes('https://myanimelist.net/topmanga.php'))
  95. {
  96. let r###lts = document.getElementsByClassName('hoverinfo_trigger fs14 fw-b');
  97. for (let i = 0; i < r###lts.length; i++)
  98. {
  99. if (!document.getElementById('manga' + i))
  100. {
  101. let url = r###lts[i].href;
  102. let urlDecoded = decodeURIComponent(url);
  103. let id = url.split('/')[4];
  104. let selector = 'a[href="' + urlDecoded + '"].hoverinfo_trigger.fs14.fw-b';
  105. addTranslation('manga', i, url, id, selector);
  106. }
  107. }
  108. }
  109. // Anime List and Manga List
  110. else if (LOCATION_HREF.includes('https://myanimelist.net/animelist') || LOCATION_HREF.includes('https://myanimelist.net/mangalist'))
  111. {
  112. let type = LOCATION_HREF.substring(24, 29);
  113. let r###lts = document.querySelectorAll('tbody:not([style]) .data.title');
  114. function processR###lts(tempR###lts)
  115. {
  116. for (let i = 0; i < tempR###lts.length; i++)
  117. {
  118. let url = tempR###lts[i].children[0].href;
  119. let urlShort = url.slice(23);
  120. let urlShortDecoded = decodeURIComponent(urlShort);
  121. let id = url.split('/')[4];
  122. let selector = '.data.title > a[href="' + urlShortDecoded + '"]';
  123. addTranslation(type, i, url, id, selector);
  124. }
  125. }
  126. function attachMutationObserver(listTable)
  127. {
  128. new MutationObserver(function(mutationsList, observer)
  129. {
  130. mutationsList.forEach(function(mutation)
  131. {
  132. processR###lts(
  133. Array.from(
  134. mutation.addedNodes,
  135. (addedNode) => addedNode.children[0].children[3]
  136. )
  137. );
  138. });
  139. if ((listTable.children.length - 1) % 150 !== 0)
  140. {
  141. observer.disconnect();
  142. }
  143. }).observe(
  144. listTable,
  145. {childList: true}
  146. );
  147. }
  148. let table = document.querySelector('table');
  149. if (r###lts.length)
  150. {
  151. processR###lts(r###lts);
  152. if (r###lts.length === 150)
  153. {
  154. attachMutationObserver(table);
  155. }
  156. }
  157. else if (table)
  158. {
  159. new MutationObserver(function(mutationsList, observer)
  160. {
  161. mutationsList.some(function(mutation)
  162. {
  163. return Array.from(mutation.addedNodes).some(function(addedNode)
  164. {
  165. if (addedNode.tagName === 'TABLE')
  166. {
  167. let r###lts = addedNode.querySelectorAll('.data.title');
  168. processR###lts(r###lts);
  169. if (r###lts.length === 150)
  170. {
  171. attachMutationObserver(addedNode);
  172. }
  173. observer.disconnect();
  174. return true;
  175. }
  176. });
  177. });
  178. }).observe(
  179. table.parentElement,
  180. {childList: true}
  181. );
  182. }
  183. }
  184. // Search
  185. else if (LOCATION_HREF.includes('https://myanimelist.net/search/'))
  186. {
  187. // Anime R###lts
  188. let r###ltsAnime = document.querySelectorAll('[class="hoverinfo_trigger fw-b fl-l"][href*="/anime/"]');
  189. for (let i = 0; i < r###ltsAnime.length; i++)
  190. {
  191. if (!document.getElementById('anime' + i))
  192. {
  193. let url = r###ltsAnime[i].href;
  194. let urlDecoded = decodeURIComponent(url);
  195. let id = url.split('/')[4];
  196. let selector = 'a[href="' + urlDecoded + '"].hoverinfo_trigger.fw-b.fl-l';
  197. addTranslation('anime', i, url, id, selector, true);
  198. }
  199. }
  200. // Manga R###lts
  201. let r###ltsManga = document.querySelectorAll('[class="hoverinfo_trigger fw-b"][href*="/manga/"]');
  202. for (let i = 0; i < r###ltsManga.length; i++)
  203. {
  204. if (!document.getElementById('manga' + i))
  205. {
  206. let url = r###ltsManga[i].href;
  207. let urlDecoded = decodeURIComponent(url);
  208. let id = url.split('/')[4];
  209. let selector = 'a[href="' + urlDecoded + '"].hoverinfo_trigger.fw-b';
  210. addTranslation('manga', i, url, id, selector);
  211. }
  212. }
  213. }
  214. // Anime Search
  215. else if (LOCATION_HREF.includes('https://myanimelist.net/anime.php?q') || LOCATION_HREF.includes('https://myanimelist.net/anime.php?cat'))
  216. {
  217. let r###lts = document.getElementsByClassName('hoverinfo_trigger fw-b fl-l');
  218. for (let i = 0; i < r###lts.length; i++)
  219. {
  220. if (!document.getElementById('anime' + i))
  221. {
  222. let url = r###lts[i].href;
  223. let urlDecoded = decodeURIComponent(url);
  224. let id = url.split('/')[4];
  225. let selector = 'a[href="' + urlDecoded + '"].hoverinfo_trigger.fw-b.fl-l';
  226. addTranslation('anime', i, url, id, selector, true);
  227. }
  228. }
  229. }
  230. // Manga Search
  231. else if (LOCATION_HREF.includes('https://myanimelist.net/manga.php?q') || LOCATION_HREF.includes('https://myanimelist.net/manga.php?cat'))
  232. {
  233. let r###lts = document.getElementsByClassName('hoverinfo_trigger fw-b');
  234. for (let i = 0; i < r###lts.length; i++)
  235. {
  236. if (!document.getElementById('manga' + i))
  237. {
  238. let url = r###lts[i].href;
  239. let urlDecoded = decodeURIComponent(url);
  240. let id = url.split('/')[4];
  241. let selector = 'a[href="' + urlDecoded + '"].hoverinfo_trigger.fw-b';
  242. addTranslation('manga', i, url, id, selector);
  243. }
  244. }
  245. }
  246. // Anime Seasonal
  247. else if (LOCATION_HREF.includes('https://myanimelist.net/anime/season'))
  248. {
  249. let r###lts = document.getElementsByClassName('link-title');
  250. for (let i = 0; i < r###lts.length; i++)
  251. {
  252. if (!document.getElementById('anime' + i))
  253. {
  254. let url = r###lts[i].href;
  255. let urlDecoded = decodeURIComponent(url);
  256. let id = url.split('/')[4];
  257. let selector = 'a[href="' + urlDecoded + '"].link-title';
  258. addTranslation('anime', i, url, id, selector, false, true);
  259. }
  260. }
  261. }
  262. // Anime Genres
  263. else if (LOCATION_HREF.includes('https://myanimelist.net/anime/genre'))
  264. {
  265. // Seasonal View
  266. if (document.getElementsByClassName('js-btn-view-style seasonal on')[0])
  267. {
  268. let r###lts = document.getElementsByClassName('link-title');
  269. for (let i = 0; i < r###lts.length; i++)
  270. {
  271. if (!document.getElementById('anime' + i))
  272. {
  273. let url = r###lts[i].href;
  274. let urlDecoded = decodeURIComponent(url);
  275. let id = url.split('/')[4];
  276. let selector = 'a[href="' + urlDecoded + '"].link-title';
  277. addTranslation('anime', i, url, id, selector, true, true);
  278. }
  279. }
  280. }
  281. // List View
  282. else if (document.getElementsByClassName('js-btn-view-style list on')[0])
  283. {
  284. let r###lts = document.getElementsByClassName('hoverinfo_trigger fw-b');
  285. for (let i = 0; i < r###lts.length; i++)
  286. {
  287. if (!document.getElementById('anime' + i))
  288. {
  289. let url = r###lts[i].href;
  290. let urlDecoded = decodeURIComponent(url);
  291. let id = url.split('/')[4];
  292. let selector = 'a[href="' + urlDecoded + '"].hoverinfo_trigger.fw-b';
  293. addTranslation('anime', i, url, id, selector);
  294. }
  295. }
  296. }
  297. }
  298. // Manga Genres
  299. else if (LOCATION_HREF.includes('https://myanimelist.net/manga/genre') || LOCATION_HREF.includes('https://myanimelist.net/manga/adapted'))
  300. {
  301. // Seasonal View
  302. if (document.getElementsByClassName('js-btn-view-style seasonal on')[0])
  303. {
  304. let r###lts = document.getElementsByClassName('link-title');
  305. for (let i = 0; i < r###lts.length; i++)
  306. {
  307. if (!document.getElementById('manga' + i))
  308. {
  309. let url = r###lts[i].href;
  310. let urlDecoded = decodeURIComponent(url);
  311. let id = url.split('/')[4];
  312. let selector = 'a[href="' + urlDecoded + '"].link-title';
  313. addTranslation('manga', i, url, id, selector, false, true);
  314. }
  315. }
  316. }
  317. // List View
  318. else if (document.getElementsByClassName('js-btn-view-style list on')[0])
  319. {
  320. let r###lts = document.getElementsByClassName('hoverinfo_trigger fw-b');
  321. for (let i = 0; i < r###lts.length; i++)
  322. {
  323. if (!document.getElementById('manga' + i))
  324. {
  325. let url = r###lts[i].href;
  326. let urlDecoded = decodeURIComponent(url);
  327. let id = url.split('/')[4];
  328. let selector = 'a[href="' + urlDecoded + '"].hoverinfo_trigger.fw-b';
  329. addTranslation('manga', i, url, id, selector);
  330. }
  331. }
  332. }
  333. }
  334. // Anime Producers
  335. else if (LOCATION_HREF.includes('https://myanimelist.net/anime/producer'))
  336. {
  337. // Tile View
  338. if (document.getElementsByClassName('js-btn-view-style2 tile on')[0])
  339. {
  340. let r###lts = document.getElementsByClassName('seasonal-anime js-seasonal-anime js-anime-type-all ');
  341. for (let i = 0; i < r###lts.length; i++)
  342. {
  343. if (!document.getElementById('anime' + i))
  344. {
  345. let url = r###lts[i].children[0].children[0].href
  346. let urlDecoded = decodeURIComponent(url);
  347. let id = url.split('/')[4];
  348. let selector = '.seasonal-anime.js-seasonal-anime.js-anime-type-all > .title > a[href="' + urlDecoded + '"]';
  349. addTranslation('anime', i, url, id, selector, false, false, true);
  350. }
  351. }
  352. }
  353. //
  354. // Seasonal View
  355. if (document.getElementsByClassName('js-btn-view-style2 seasonal on')[0])
  356. {
  357. let r###lts = document.getElementsByClassName('link-title');
  358. for (let i = 0; i < r###lts.length; i++)
  359. {
  360. if (!document.getElementById('anime' + i))
  361. {
  362. let url = r###lts[i].href;
  363. let urlDecoded = decodeURIComponent(url);
  364. let id = url.split('/')[4];
  365. let selector = 'a[href="' + urlDecoded + '"].link-title';
  366. addTranslation('anime', i, url, id, selector, false, true);
  367. }
  368. }
  369. }
  370. // List View
  371. else if (document.getElementsByClassName('js-btn-view-style2 list on')[0])
  372. {
  373. let r###lts = document.getElementsByClassName('seasonal-anime js-seasonal-anime js-anime-type-all');
  374. for (let i = 0; i < r###lts.length; i++)
  375. {
  376. if (!document.getElementById('anime' + i))
  377. {
  378. let url = r###lts[i].children[0].children[0].children[0].href;
  379. let urlDecoded = decodeURIComponent(url);
  380. let id = url.split('/')[4];
  381. let selector = '.spaceit_pad > a[href="' + urlDecoded + '"]';
  382. addTranslation('anime', i, url, id, selector);
  383. }
  384. }
  385. }
  386. }
  387. // Anime Shared
  388. else if (LOCATION_HREF.includes('https://myanimelist.net/shared.php') && !LOCATION_HREF.includes('&type=manga'))
  389. {
  390. let r###lts = document.querySelectorAll('[href*="/anime/"]:not(.Lightbox_AddEdit):not([href*="anime/season"])');
  391. for (let i = 0; i < r###lts.length; i++)
  392. {
  393. if (!document.getElementById('anime' + i))
  394. {
  395. let url = r###lts[i].href;
  396. let urlShort = url.slice(23);
  397. let urlShortDecoded = decodeURIComponent(urlShort);
  398. let id = url.split('/')[4];
  399. let selector = 'a[href="' + urlShortDecoded + '"]';
  400. addTranslation('anime', i, url, id, selector);
  401. }
  402. }
  403. }
  404. // Manga Shared
  405. else if (LOCATION_HREF.includes('https://myanimelist.net/shared.php') && LOCATION_HREF.includes('&type=manga'))
  406. {
  407. let r###lts = document.querySelectorAll('[href*="/manga/"]:not(.Lightbox_AddEdit)');
  408. for (let i = 0; i < r###lts.length; i++)
  409. {
  410. if (!document.getElementById('manga' + i))
  411. {
  412. let url = r###lts[i].href;
  413. let urlShort = url.slice(23);
  414. let urlShortDecoded = decodeURIComponent(urlShort);
  415. let id = url.split('/')[4];
  416. let selector = 'a[href="' + urlShortDecoded + '"]';
  417. addTranslation('manga', i, url, id, selector);
  418. }
  419. }
  420. }
  421. // History
  422. else if (LOCATION_HREF.includes('https://myanimelist.net/history'))
  423. {
  424. // Anime R###lts
  425. let r###ltsAnime = document.querySelectorAll('[href*="/anime.php?id="]');
  426. let animeIds = [];
  427. for (let i = 0; i < r###ltsAnime.length; i++)
  428. {
  429. if (!document.getElementById('anime' + i))
  430. {
  431. let url = r###ltsAnime[i].href;
  432. let urlShort = url.slice(23);
  433. let urlShortDecoded = decodeURIComponent(urlShort);
  434. let id = url.split('=')[1];
  435. let selector = 'a[href="' + urlShortDecoded + '"]';
  436. if (!animeIds.includes(id))
  437. {
  438. addTranslation('anime', i, url, id, selector);
  439. }
  440. animeIds.push(id);
  441. }
  442. }
  443. // Manga R###lts
  444. let r###ltsManga = document.querySelectorAll('[href*="/manga.php?id="]');
  445. let mangaIds = [];
  446. for (let i = 0; i < r###ltsManga.length-1; i++)
  447. {
  448. if (!document.getElementById('manga' + i))
  449. {
  450. let url = r###ltsManga[i].href;
  451. let urlShort = url.slice(23);
  452. let urlShortDecoded = decodeURIComponent(urlShort);
  453. let id = url.split('=')[1];
  454. let selector = 'a[href="' + urlShortDecoded + '"]';
  455. if (!mangaIds.includes(id))
  456. {
  457. addTranslation('manga', i, url, id, selector);
  458. }
  459. mangaIds.push(id);
  460. }
  461. }
  462. }
  463. // People
  464. else if (LOCATION_HREF.includes('https://myanimelist.net/people'))
  465. {
  466. // Anime R###lts
  467. let r###ltsAnime = document.querySelectorAll('[href*="/anime/"]:not(.Lightbox_AddEdit):not([href*="anime/season"])');
  468. let animeIds = [];
  469. for (let i = 0; i < r###ltsAnime.length; i++)
  470. {
  471. if (!document.getElementById('anime' + i))
  472. {
  473. let url = r###ltsAnime[i].href;
  474. let urlDecoded = decodeURIComponent(url);
  475. let id = url.split('/')[4];
  476. let selector = 'a[href="' + urlDecoded + '"]:not(.picSurround > a)';
  477. if (!animeIds.includes(id))
  478. {
  479. addTranslation('anime', i, url, id, selector);
  480. }
  481. animeIds.push(id);
  482. }
  483. }
  484. // Manga R###lts
  485. let r###ltsManga = document.querySelectorAll('[href*="/manga/"]:not(.Lightbox_AddEdit)');
  486. let mangaIds = [];
  487. for (let i = 0; i < r###ltsManga.length; i+=2)
  488. {
  489. if (!document.getElementById('manga' + i))
  490. {
  491. let url = r###ltsManga[i].href;
  492. let urlDecoded = decodeURIComponent(url);
  493. let id = url.split('/')[4];
  494. let selector = 'a[href="' + urlDecoded + '"]:not(.picSurround > a)';
  495. if (!mangaIds.includes(id))
  496. {
  497. addTranslation('manga', i, url, id, selector);
  498. }
  499. mangaIds.push(id);
  500. }
  501. }
  502. }
  503. }
  504. // Get English title (storedAnime and getEnglishTitle) and add to page
  505. function addTranslation(type, count, url, id, selector, parent=false, tile=false, producer=false)
  506. {
  507. let styleId = ""
  508. let styleIdEnd = ""
  509. if (tile)
  510. {
  511. styleId = '<h3 class="h3_anime_subtitle" id="' + type + count + '">';
  512. styleIdEnd = '</h3>';
  513. }
  514. else
  515. {
  516. styleId = '<div style="font-weight:bold" id="' + type + count + '">';
  517. styleIdEnd = '</div>';
  518. }
  519. if (type === 'anime')
  520. {
  521. if (producer)
  522. {
  523. document.getElementsByClassName('category')[count].style.visibility = 'hidden'
  524. }
  525. if (checkAnime(id))
  526. {
  527. document.querySelectorAll(selector).forEach(function(element)
  528. {
  529. if (parent)
  530. {
  531. element = element.parentElement;
  532. }
  533. element.insertAdjacentHTML('beforebegin', styleId + storedAnime[id][0] + styleIdEnd);
  534. });
  535. }
  536. else
  537. {
  538. getEnglishTitle(type, url, id, selector, parent, styleId, styleIdEnd);
  539. }
  540. }
  541. else if (type === 'manga')
  542. {
  543. if (checkManga(id))
  544. {
  545. document.querySelectorAll(selector).forEach(function(element)
  546. {
  547. if (parent)
  548. {
  549. element = element.parentElement;
  550. }
  551. element.insertAdjacentHTML('beforebegin', styleId + storedManga[id][0] + styleIdEnd);
  552. });
  553. }
  554. else
  555. {
  556. getEnglishTitle(type, url, id, selector, parent, styleId, styleIdEnd);
  557. }
  558. }
  559. }
  560. // Request English title from MAL and send to be stored (storeAnime)
  561. function getEnglishTitle(type, url, id, selector, parent, styleId, styleIdEnd)
  562. {
  563. // Create new request
  564. let xhr = new XMLHttpRequest();
  565. xhr.responseType = 'document';
  566. // Set the callback
  567. xhr.onload = function()
  568. {
  569. if (xhr.readyState === xhr.DONE && xhr.status === 200 && xhr.responseXML !== null)
  570. {
  571. let englishTitleElement = xhr.responseXML.querySelector('.title-english');
  572. let englishTitle;
  573. if (englishTitleElement)
  574. {
  575. englishTitle = englishTitleElement.innerText;
  576. }
  577. else
  578. {
  579. englishTitle = '';
  580. }
  581. if (type === 'anime')
  582. {
  583. storeAnime(id, englishTitle);
  584. }
  585. else if (type === 'manga')
  586. {
  587. storeManga(id, englishTitle);
  588. }
  589. document.querySelectorAll(selector).forEach(function(element)
  590. {
  591. if (parent)
  592. {
  593. element = element.parentElement;
  594. }
  595. element.insertAdjacentHTML('beforebegin', styleId + englishTitle + styleIdEnd);
  596. });
  597. }
  598. };
  599. // Send the request
  600. xhr.open('GET', url);
  601. xhr.send();
  602. }
  603. // Store English titles for anime in cache
  604. function storeAnime(id, engTitle)
  605. {
  606. storedAnime[id] = [engTitle, Date.now()];
  607. GM_setValue('anime', storedAnime);
  608. }
  609. // Store English titles for manga in cache
  610. function storeManga(id, engTitle)
  611. {
  612. storedManga[id] = [engTitle, Date.now()];
  613. GM_setValue('manga', storedManga);
  614. }
  615. // Check if English title for anime is cached, and recheck if empty + last check was >3 weeks
  616. function checkAnime(id)
  617. {
  618. if (storedAnime.hasOwnProperty(id))
  619. {
  620. if (storedAnime[id][0] === '')
  621. {
  622. let dateNow = Date.now();
  623. let dateOld = storedAnime[id][1];
  624. if (dateNow - dateOld > 2628000000)
  625. {
  626. console.log('Updated anime ' + id);
  627. return false;
  628. }
  629. }
  630. return true;
  631. }
  632. console.log('New anime ' + id);
  633. return false;
  634. }
  635. // Check if English title for manga is cached, and recheck if empty + last check was >3 weeks
  636. function checkManga(id)
  637. {
  638. if (storedManga.hasOwnProperty(id))
  639. {
  640. if (storedManga[id][0] === '')
  641. {
  642. let dateNow = Date.now();
  643. let dateOld = storedManga[id][1];
  644. if (dateNow - dateOld > 2628000000)
  645. {
  646. console.log('Updated manga ' + id);
  647. return false;
  648. }
  649. }
  650. return true;
  651. }
  652. console.log('New manga ' + id);
  653. return false;
  654. }
  655. // Get cached English titles if they exist, else create empty dictionary
  656. var storedAnime = GM_getValue('anime');
  657. var storedManga = GM_getValue('manga');
  658. if (!storedAnime)
  659. {
  660. GM_setValue('anime',{});
  661. storedAnime = {};
  662. }
  663. if (!storedManga)
  664. {
  665. GM_setValue('manga',{});
  666. storedManga = {};
  667. }
  668. // Launch actual script
  669. translate();