Greasy Fork 支持简体中文。

suya.place - custom languages for toots

Customize the number of languages for your toots and remember last used.

// ==UserScript==
// @name        suya.place - custom languages for toots
// @description Customize the number of languages for your toots and remember last used.
// @version     1.0
// @icon        https://suya.place/favicon.png
// @namespace   https://suya.place/
// @grant       none
// @license     LGPL-3.0-only
// @author      Denis Drakhnia <[email protected]>
// @encoding    utf-8
// @match       https://suya.place/*
// ==/UserScript==

const LANGUAGES = {
  en: "English",
  ru: "Русский",
  uk: "Українська",
};

const REMEMBER_LAST = true;

function replaceLangList(root) {
  root.querySelectorAll("#post-language > select").forEach(function(list) {
    if (typeof LANGUAGES !== "undefined") {
      while (list.lastChild)
        list.removeChild(list.lastChild);

      for (let lang in LANGUAGES) {
        let elem = document.createElement("option");
        elem.setAttribute("value", lang);
        elem.innerText = LANGUAGES[lang];
        list.appendChild(elem);
      }
    }

    if (REMEMBER_LAST) {
      const last = localStorage.getItem("last_lang");
      if (last) {
        list.value = last;
      }

      list.addEventListener("change", function() {
        localStorage.setItem("last_lang", list.value);
      });
    }
  });
}

function observeStatus(status) {
  if (status.tagName !== "DIV" || !status.classList.contains("Status"))
    return;

  const callback = function(mutationsList, observer) {
    for (let mutation of mutationsList) {
      if (mutation.type === "childList") {
        for (let node of mutation.addedNodes) {
          console.log("Reply", node);
          if (node.tagName === "DIV" && node.classList.contains("reply-form")) {
            replaceLangList(node);
          }
        }
      }
    }
  };

  new MutationObserver(callback)
    .observe(status, { childList: true });
}

function observeConversation(root) {
  if (root.tagName !== "DIV" || !root.classList.contains("Conversation"))
    return;

  let thread_body = root.querySelector(".thread-body");
  if (!thread_body)
    return;

  for (let status of thread_body.children) {
    observeStatus(status);
  }

  const callback = function(mutationsList, observer) {
    for (let mutation of mutationsList) {
      if (mutation.type === "childList") {
        for (let node of mutation.addedNodes) {
          observeStatus(node);
        }
      }
    }
  };

  new MutationObserver(callback)
    .observe(thread_body, { childList: true });
}

function observeTimeline(root) {
  let timeline = root.querySelector(".timeline-body .timeline");
  if (!timeline)
    return;

  for (let node of timeline.children) {
    observeConversation(node);
  }

  const callback = function(mutationsList, observer) {
    for (let mutation of mutationsList) {
      if (mutation.type === "childList") {
        for (let node of mutation.addedNodes) {
          observeConversation(node);
        }
      }
    }
  };

  new MutationObserver(callback)
    .observe(timeline, { childList: true });
}

function observeNotifications(root) {
  let panel_body = root.querySelector(".panel-body");
  if (!panel_body)
    return;

  panel_body.querySelectorAll(".Status").forEach(observeStatus);

  const callback = function(mutationsList, observer) {
    for (let mutation of mutationsList) {
      if (mutation.type === "childList") {
        for (let node of mutation.addedNodes) {
          if (!node.querySelector)
            continue;

          let status = node.querySelector(".Status");
          if (status)
            observeStatus(status);
        }
      }
    }
  };

  new MutationObserver(callback)
    .observe(panel_body, { childList: true });
}

function observeContent(content) {
  const callback = function(mutationsList, observer) {
    for (let mutation of mutationsList) {
      if (mutation.type === "childList") {
        for (let node of mutation.addedNodes) {
          if (node.classList.contains("Timeline")) {
            observeTimeline(node);
          } else if (node.classList.contains("Conversation")) {
            observeConversation(node);
          } else {
            observeNotifications(node);
          }
        }
      }
    }
  };

  new MutationObserver(callback)
    .observe(content, { childList: true });
}

const callback = (function() {
  let sidebar = null;
  let content = null;

  return function(mutationsList, observer) {
    for (let mutation of mutationsList) {
      if (mutation.type === "childList") {
        for (let node of mutation.addedNodes) {
          if (!node.querySelector)
            continue;

          if (!sidebar) {
            sidebar = node.querySelector("#sidebar");
          }

          if (!content) {
            content = node.querySelector("#main-scroller");
          }

          if (sidebar && content)
            break;
        }
      }
    }

    if (sidebar && content) {
      observer.disconnect();

      replaceLangList(sidebar);
      observeContent(content);
    }
  };
})();

new MutationObserver(callback)
  .observe(document.querySelector("body"), {
    childList: true,
    subtree: true,
  });