Skip to content

Instantly share code, notes, and snippets.

@harukaeru
Created February 4, 2023 18:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harukaeru/bde2565ba53fbf90eb460ca1f4aacc9d to your computer and use it in GitHub Desktop.
Save harukaeru/bde2565ba53fbf90eb460ca1f4aacc9d to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Change hl Query To Japanese When Searching Japanese Letters
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://www.google.com/search*
// @icon https://www.google.com/s2/favicons?sz=64&domain=google.com
// @grant none
// ==/UserScript==
(function () {
const JP_QUERY = { 'hl': 'ja' }
const _test = () => {
const assert = require('assert')
const okList = ['宝', 'ナ', 'あ', 'ぬ', '県', '圏', 'ヰ', 'ゑ', '獄', '髙']
for (let l of okList) {
assert.equal(UnicodeUtils.isMaybeJapanese(UnicodeUtils.letterToUnicodes(l)), true);
}
const ngList = ['🐹', '한', 'A', 'a', '&']
for (let l of ngList) {
assert.equal(UnicodeUtils.isMaybeJapanese(UnicodeUtils.letterToUnicodes(l)), false);
}
}
const UnicodeUtils = {
letterToUnicodes: (letter) => {
return Array.from(letter).map(v => v.codePointAt(0));
},
isExtraKanji: (unicodes) => {
if (unicodes.length !== 1) { return false; }
// https://ja.wikipedia.org/wiki/Unicode
return 0x20000 <= unicodes[0] && unicodes[0] <= 0x3ffff;
},
isCJKKanji: (unicodes) => {
if (unicodes.length !== 1) { return false; }
// https://ja.wikipedia.org/wiki/CJK%E7%B5%B1%E5%90%88%E6%BC%A2%E5%AD%97
return (
(0x4e00 <= unicodes[0] && unicodes[0] <= 0x9fff) ||
(0x3400 <= unicodes[0] && unicodes[0] <= 0x4dbf) ||
(0x20000 <= unicodes[0] && unicodes[0] <= 0x2A6DF) ||
(0x2A700 <= unicodes[0] && unicodes[0] <= 0x2B738) ||
(0x2B740 <= unicodes[0] && unicodes[0] <= 0x2B81D) ||
(0x2B820 <= unicodes[0] && unicodes[0] <= 0x2CEA1) ||
(0x2CEB0 <= unicodes[0] && unicodes[0] <= 0x2EBE0) ||
(0x30000 <= unicodes[0] && unicodes[0] <= 0x3134A) ||
(0x31350 <= unicodes[0] && unicodes[0] <= 0x323AF)
);
},
isKatakana: (unicodes) => {
if (unicodes.length !== 1) { return false; }
// https://ja.wikipedia.org/wiki/%E7%89%87%E4%BB%AE%E5%90%8D
return (
(0x30A0 <= unicodes[0] && unicodes[0] <= 0x30FF) ||
(0x31F0 <= unicodes[0] && unicodes[0] <= 0x31FF) ||
(0x1B164 <= unicodes[0] && unicodes[0] <= 0x1B167)
);
},
isHiragana: (unicodes) => {
if (unicodes.length !== 1) { return false; }
// https://ja.wikipedia.org/wiki/%E5%B9%B3%E4%BB%AE%E5%90%8D
return (
(0x3041 <= unicodes[0] && unicodes[0] <= 0x309F) ||
// これは仮名補助。ひらがななのかカタカナなのかよくわからないけど、今回の問題解決には無関係なので保留している。
// 見たかんじ、どちらかというとひらがななのでこっちに入れておく
(0x1B000 <= unicodes[0] && unicodes[0] <= 0x1B0FF) ||
(0x1B150 <= unicodes[0] && unicodes[0] <= 0x1B152)
);
},
isMaybeJapanese: (unicodes) => {
return UnicodeUtils.isExtraKanji(unicodes) || UnicodeUtils.isCJKKanji(unicodes) || UnicodeUtils.isKatakana(unicodes) || UnicodeUtils.isHiragana(unicodes);
}
};
const MovingUtils = {
insertQuery: (url) => {
const key = 'hl';
const currentUrl = new URL(url);
currentUrl.searchParams.set(key, JP_QUERY[key]);
return currentUrl.href;
},
removeQuery: (url) => {
const key = 'hl';
const currentUrl = new URL(url);
if (currentUrl.searchParams.get(key) === JP_QUERY[key]) {
currentUrl.searchParams.delete(key);
return currentUrl.href;
}
return url;
},
redirect: (targetUrl) => {
location.href = targetUrl;
}
};
const isSetHlJa = (url) => {
const currentUrl = new URL(url);
const searchParams = currentUrl.searchParams;
const hlQuery = searchParams.get('hl');
return hlQuery === JP_QUERY['hl']
}
const isJapaneseSearchTerms = (url) => {
const currentUrl = new URL(url);
const searchParams = currentUrl.searchParams;
const tabMenuQuery = searchParams.get('tbm');
if (!tabMenuQuery) { return false; }
if (tabMenuQuery !== 'isch') { return false; }
const searchQuery = searchParams.get('q');
if (!searchQuery) { return false; }
const segmenter = new Intl.Segmenter();
const segments = segmenter.segment(searchQuery);
const wellSegmented = [...segments];
const maybeJapaneseLanguageContained = wellSegmented.map(s => s.segment).map(UnicodeUtils.letterToUnicodes).some(UnicodeUtils.isMaybeJapanese);
return !!maybeJapaneseLanguageContained;
}
// for debug
// _test();
const move = (url) => {
const hasHlJa = isSetHlJa(url);
const isJapanese = isJapaneseSearchTerms(url);
// 日本語っぽいクエリが入っていて、hl=jaでもないときは、hl=jaをつけてリダイレクト
if (isJapanese && !hasHlJa) {
MovingUtils.redirect(MovingUtils.insertQuery(url));
// 日本語っぽいクエリが入っていないときはhl=jaは消す
} else if (!isJapanese && hasHlJa) {
const prevHref = url;
const advancedHref = MovingUtils.removeQuery(prevHref);
(prevHref !== advancedHref) && MovingUtils.redirect(advancedHref);
}
}
let oldHref = location.href;
const observer = new MutationObserver(mutations => {
mutations.forEach(() => {
if (oldHref !== location.href) {
oldHref = location.href;
move(location.href);
}
});
});
observer.observe(document.body, { childList: true, subtree: true });
// Initial
move(location.href);
})();
@harukaeru
Copy link
Author

@harukaeru
Copy link
Author

使いたい人へ: tampermonkeyで入れてください
動作保証は特にしていません

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment