Greasy Fork

Greasy Fork is available in English.

Pixiv Tag Translation/Replacement

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

当前为 2016-09-10 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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);
}