Pixiv Tag Translation/Replacement

Shows translations of tags on Pixiv and prompts for untranslated tags.

目前为 2016-09-10 提交的版本。查看 最新版本

// ==UserScript==
// @name        Pixiv Tag Translation/Replacement
// @description Shows translations of tags on Pixiv and prompts for untranslated tags.
// @namespace   http://scripts.chris.charabaruk.com/pixiv.net/~tag-translation
// @author      coldacid
// @include     http://www.pixiv.net/
// @include     http://www.pixiv.net/*
// @include     http://pixiv.net/
// @include     http://pixiv.net/*
// @include     https://www.pixiv.net/
// @include     https://www.pixiv.net/*
// @include     https://pixiv.net/
// @include     https://pixiv.net/*
// @version     1
// @grant       none
// ==/UserScript==

var TagsCollection;
{
  const USER_DATA_KEY = 'com.charabaruk.chris.pixiv.net.tag-translation';
  let version = 1;
  let map = null;
  
  let loadMap = function () {
    var userData = window.localStorage[USER_DATA_KEY];
    if (userData) {
      userData = JSON.parse(userData);
    } else {
      userData = {version: 1};
    }
    
    version = userData.version || 1;
    
    var tags = userData.tags || {
      "R-18": null,
      "3D": null
    };
    tags[Symbol.iterator] = function* () { for (var tag in this) yield [tag, this[tag]]; }
    map = new Map(tags);
  }
  let saveMap = function () {
    var userData = {version: version, tags: {}};
    for (var [k, v] of map) { userData.tags[k] = v; }
    
    window.localStorage[USER_DATA_KEY] = JSON.stringify(userData);
  }
  
  TagsCollection = function TagsCollection () {
    loadMap();
  }
  
  Object.defineProperty(TagsCollection.prototype, 'version', {value: version});
  
  TagsCollection.prototype.has = function (tag) { return map.has(tag); }
  TagsCollection.prototype.get = function (tag) { return map.get(tag) || tag; }
  TagsCollection.prototype.set = function (tag, translation) {
    if (translation === undefined) {
      if (tag.entries) {
        for (var [key, value] of tag.entries()) {
          map.set(key, value);
        }
      } else if (tag instanceof Object) {
        for (var key of Object.getOwnPropertyNames(tag)) {
          map.set(key, tag[key]);
        }
      } else {
        throw new Error('missing translation');
      }
    } else {
      map.set(tag, translation);
    }
    
    saveMap();
  }
}

function setTagText($element, tag) {
  var originalTag = $element.text(),
      newText = `${tag} (${originalTag})`;
  if ($element[0].nodeType == Node.TEXT_NODE) {
    $element[0].textContent = newText;
  } else {
    $element.text(newText);
  }
}

function GM_main ($) {
  var tags = new TagsCollection();

  var untranslated = new Map();
  // content page regular tags, home page featured tags, home page favorite tags
  $('li.tag > a.text, div.tag-name, section.favorite-tag > ul.favorite-tags > li > a')
    .contents()
    .filter((i, n) => n.nodeType == Node.TEXT_NODE) // only get the text nodes within the selected elements
    .each((idx, el) => {
      var $el = $(el),
          tag = $el.text();
      
      if (/^[\x20-\x7e]*$/.test(tag)) {
        console.log(`"${tag}" only uses ASCII printable characters, skipping`);
        return;
      }

      if (tags.has(tag)) {
        setTagText($el, tags.get(tag));
      } else {
        let elList = untranslated.has(tag) ? untranslated.get(tag) : [];
        elList.push($el);
        untranslated.set(tag, elList);
      }
    });

  if (untranslated.size > 0) {
    var taglist = Array.from(untranslated.keys()).join(', ');
    if (window.confirm(`There are ${untranslated.size} untranslated tags. Want to translate?\n\nTags: ${taglist}`)) {
      var translations = new Map();
      for (var [tag, $els] of untranslated.entries()) {
        var translated = window.prompt(`Translation for: ${tag}\n\nLeave empty to cancel translating`, tag);
        if (!translated) { break; }

        // only save if the translation is different from the original tag
        if (tag !== translated) {
          translations.set(tag, translated);
          $els.forEach($el => setTagText($el, translated));
        }
      }
      tags.set(translations);
    }
  }
}

if (typeof jQuery === 'function') {
  console.log(`Using local jQuery, version ${jQuery.fn.jquery}`);
  GM_main(jQuery);
} else {
  console.log('Loading jQuery from Google CDN');
  add_jQuery(GM_main, '1.11.1');
}

function add_jQuery(callbackFn, jqVersion) {
  jqVersion      = jqVersion || "1.11.1";
  var D          = document,
      targ       = D.getElementsByTagName('head')[0] || D.body || D.documentElement,
      scriptNode = D.createElement('script');
  
  scriptNode.src = `//ajax.googleapis.com/ajax/libs/jquery/${jqVersion}/jquery.min.js`;
  scriptNode.addEventListener('load', function () {
    var scriptNode         = D.createElement('script');
    scriptNode.textContent =
      'var gm_jQuery = jquery.noConflict(true);\n'
      + '(' + callbackFn.toString() + ')(gm_jQuery);';
    targ.appendChild(scriptNode);
  }, false);
  targ.appendChild(scriptNode);
}

QingJ © 2025

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