Wikipedia multi language view

View a Wikipedia entry with two (or more?) languages side by side for comparison and language learning.

当前为 2025-05-26 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Wikipedia multi language view
  3. // @name:zh Wikipedia 多语言浏览
  4. // @namespace https://userscript.snomiao.com/
  5. // @author snomiao@gmail.com
  6. // @version 0.0.6
  7. // @description View a Wikipedia entry with two (or more?) languages side by side for comparison and language learning.
  8. // @description:zh 以并列多语言视角浏览维基百科
  9. // @match https://*.wikipedia.org/wiki/*
  10. // @match https://zh.wikipedia.org/zh-*/*
  11. // @grant none
  12. // @run-at document-start
  13. // @license GPL-3.0+
  14. // @supportURL https://github.com/snomiao/userscript.js/issues
  15. // @contributionURL https://snomiao.com/donate
  16. // ==/UserScript==
  17. //
  18. // MAINTAINING NOTE: this file have been moved to https://github.com/snomiao/multilang-wiki/tree/main
  19. // please contribute there if you want to improve this script.
  20. //
  21. // ref:
  22. // [javascript - Resize Cross Domain Iframe Height - Stack Overflow]( https://stackoverflow.com/questions/22086722/resize-cross-domain-iframe-height )
  23. //
  24.  
  25. // const Langs = ['en', 'ja', 'zh', 'de', 'fr', 'es', 'ru', 'it', 'ko', 'pt', 'ar', 'vi', 'pl', 'uk', 'nl', 'sv', 'id', 'fi', 'no', 'tr', 'cs', 'da', 'he', 'hu', 'ro', 'th']
  26. const langs = ['en', 'ja', 'zh'] // modify this to your preferred languages, will be used to load the 2nd language iframe
  27. //
  28.  
  29. if (location.hash.match("#langIfr")) {
  30. // iframe code send height
  31. const sendHeight = () =>
  32. parent.postMessage?.(
  33. { langIfr: { height: document.body.scrollHeight } },
  34. "*"
  35. );
  36. window.addEventListener("resize", sendHeight, false);
  37. window.addEventListener("load", sendHeight, false);
  38. sendHeight();
  39. document.head.appendChild(createHtmlElement('<base target="_parent" />'))
  40. } else {
  41. // parent code recv iframe's height
  42. const msgHandler = (e) => {
  43. const setHeight = (height) =>
  44. height &&
  45. document.querySelector("#langIfr")?.setAttribute("height", height);
  46. setHeight(e.data?.langIfr?.height);
  47. };
  48. window.addEventListener("message", msgHandler, false);
  49. // load iframe
  50. const langLnksGet = () =>
  51. Object.fromEntries(
  52. [...document.querySelectorAll("a.interlanguage-link-target")]
  53. .map((e) => ({
  54. lang: e.getAttribute("lang"),
  55. href: e.href,
  56. language: e.textContent,
  57. }))
  58. .map((e) => [e.lang, e])
  59. );
  60. const exlangFrameLoad = () => {
  61. const langLnks = langLnksGet();
  62. const langIframeLoad = (lang = "en") => {
  63. if (!langLnks[lang]) return false;
  64. document.body.setAttribute("style", "width: 50vw");
  65. document.body.querySelector("#langIfr")?.remove();
  66. document.querySelector("#sidebarCollapse")?.click();
  67. const langIfr = Object.assign(document.createElement("iframe"), {
  68. id: "langIfr",
  69. src: langLnks[lang].href + "#langIfr",
  70. });
  71. langIfr.setAttribute(
  72. "style",
  73. "border: none; position:absolute; left: 50vw; top: 0vh; width: 50vw"
  74. );
  75. document.body.appendChild(langIfr);
  76. return true;
  77. };
  78.  
  79. // the load 2st language for current page
  80. langs.find(lang => langIframeLoad(lang))
  81. };
  82. window.addEventListener("load", exlangFrameLoad, false);
  83. }
  84.  
  85. function createHtmlElement(innerHTML= '<span>hello</span>'){
  86. return Object.assign(document.createElement('div'), {innerHTML}).children[0]
  87. }