Automatic Simplified Chinese Characters For Wiktionary

When using the English Wiktionary, the search for Simplified Chinese Characters will always suggest the user to navigate to the corresponding Traditional Chinese Characters page. So we automatically redirect the user.

当前为 2024-01-16 提交的版本,查看 最新版本

// ==UserScript==
// @name         Automatic Simplified Chinese Characters For Wiktionary
// @namespace    http://tampermonkey.net/
// @version      2024-01-16-v2
// @description  When using the English Wiktionary, the search for Simplified Chinese Characters will always suggest the user to navigate to the corresponding Traditional Chinese Characters page. So we automatically redirect the user.
// @author       moraesvic
// @source       https://gist.github.com/moraesvic/5a8ff36c17fcd3feace5c5d6369c5583
// @match        http*://*.wiktionary.org/*
// @license      GNU GPLv3
// @grant        none
// ==/UserScript==

/**
 * This script has been published to Greasy Fork镜像 at
 * https://gf.qytechs.cn/en/scripts/484991-automatic-simplified-chinese-characters-for-wiktionary
 */

"use strict";

const DEBUG = true;

/**
 *
 * @param {(...args: any[]) => void} obj
 * @param {any[]} args
 */
const _print = (obj, ...args) => {
  if (DEBUG) {
    obj("[ASCCFW] ", ...args);
  }
};

const debug = (...args) => {
  _print(console.debug, ...args);
};

const group = (...args) => {
  _print(console.group, ...args);
};

const groupEnd = () => {
  if (DEBUG) {
    console.groupEnd();
  }
};

/**
 * @param {string} host The current value of `location.host`
 * @returns {boolean}
 */
const isWiktionary = (host) => {
  return host.match("wiktionary");
};

/**
 * @param {Document} document The current value of `document`
 * @returns {boolean}
 */
const hasChineseEntry = (document) => {
  return document.querySelector("h2 > span#Chinese") !== null;
};

/**
 * @param {Document} document The current value of `document`
 * @returns {HTMLElement[]}
 */
const getChineseContents = (document) => {
  /** @type {HTMLElement} */
  const chineseHeader =
    document.querySelector("h2 > span#Chinese").parentElement;

  /** @type {HTMLElement[]} */
  const chineseContents = [];
  let currentNode = chineseHeader;

  while (true) {
    currentNode = currentNode.nextElementSibling;

    if (currentNode === null) {
      break;
    }

    chineseContents.push(currentNode);
  }

  return chineseContents;
};

/**
 * @typedef {{ simplified: string; traditional: string; }} Redirection
 */

/**
 * @param {HTMLElement[]} nodes
 * @returns {Redirection[]}
 */
const findTraditionalFormRedirections = (nodes) => {
  const tables = nodes.filter((x) => x.nodeName === "TABLE");
  /**
   * In some cases, the text is "(This term, 国家, is the simplified form of 國家)."
   * In other cases, the text is "(This character, 见, is the simplified and variant form of 見)."
   */
  const regex =
    /\(This (?:term|character), (.+), is the simplified (?:.*)form of (.+)\)./;

  /** @type {RegExpMatchArray} */
  const matches = tables
    .map((x) => x.innerText.match(regex))
    .filter((match) => match !== null);

  return matches.map((match) => {
    const [fullMatch, simplified, traditional] = match;
    return { simplified, traditional };
  });
};

/**
 * @param {Redirection[]} redirections
 */
const printRedirections = (redirections) => {
  group(
    `Found ${redirections.length} redirection(s) from ` +
      `simplified to traditional:`
  );

  const s = redirections
    .map(({ simplified, traditional }) => {
      return `Simplified:  ${simplified}\n` + `Traditional: ${traditional}`;
    })
    .join("\n");

  if (DEBUG) {
    console.debug(s);
  }

  groupEnd();
};

/**
 * @param {string} currentHref the current value of `location.href`
 * @param {string} simplified
 * @param {string} traditional
 */
const buildNewHref = (currentHref, simplified, traditional) => {
  const oldDecodedURI = decodeURI(currentHref);
  const newDecodedURI = oldDecodedURI.replace(simplified, traditional);
  const reencodedURI = encodeURI(newDecodedURI);
  return reencodedURI;
};

/**
 * @param {Document} document The current value of `document`
 * @param {Location} location The current value of `location`
 * @returns {string | null}
 */
const getNewHref = (document, location) => {
  debug(
    "Starting user script " +
      '"Automatic Simplified Chinese Characters For Wiktionary".'
  );

  if (!isWiktionary(location.host)) {
    debug("Loaded page is not Wiktionary, leaving.");
    return null;
  }

  if (!hasChineseEntry(document)) {
    debug("Current Wiktionary page has no entry for Chinese, leaving.");
    return null;
  }

  const chineseContents = getChineseContents(document);
  const redirections = findTraditionalFormRedirections(chineseContents);

  if (redirections.length === 0) {
    debug("Chinese entry does not redirect to a traditional form, leaving.");
    return null;
  }

  printRedirections(redirections);

  debug("Working with first match.");
  const redirection = redirections[0];

  const newHref = buildNewHref(
    location.href,
    redirection.simplified,
    redirection.traditional
  );

  debug(`New href is ${newHref}`);
  return newHref;
};

const main = () => {
  const newHref = getNewHref(document, location);
  if (newHref === null) {
    return;
  }

  debug("Assigning new location ", newHref);
  location.assign(newHref);
};

main();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址