初めてのChrome Extention作成:AWSの公式ドキュメントを日本語表示したい
GWで時間があるのでChromeの拡張機能を作ってみようと思う。
なお、大したことをしたい訳ではなく、、
AWS公式のドキュメントをサクッと読みたいときに英語表示されると、わざわざURL欄に手打ちで/ja_jp/って入れるのが面倒だと思って、それをするだけの拡張機能を自作してみようと思っただけです(怠惰の極み)
補足:
当初はChromeの機能を使用して、URL欄で検索をかけるときに日本語ドキュメントだけ表示されるようにしたら自分のニーズを満たせそうだと思った。で、一応それは実現してて、別記事にまとめてます。
やりたいこと
AWSの公式ドキュメントのページを日本語表示したい
現状
- 公式ドキュメントのページを開いた時、英語のページが表示されることがある
解決方法
- 日本語ページにURLを変換して表示する(ドメイン名のあとに/ja_jp/が付されている状態にする)
最初のとっかかり。
なるほどね、ファイル2つで拡張機能が作れると。かなりお手軽じゃないか。
.
└── src
├── content.js
└── manifest.json
今や大人気のChatGPTさんにコード作ってもらう。
以下はプロンプトと生成したコード。
あなたはJavaScriptのエキスパートで、Chromeブラウザの拡張機能を作成することができます。
以下の要件を満たすChromeの拡張機能を実装するためのコードを教えて下さい。
【要件】
拡張機能のアイコンを表示したときにポップアップを表示する。
ポップアップには”日本語のページに切り替えますか?”と表示し、”Yes”と”No”の選択肢がある。
Yesの選択肢を選んだ場合には、現在表示しているWebページのURLに含まれるドメイン名のあとに、ロケールを示す/ja_jp/の文字列を追加して、再読み込みを行う。
Noの選択肢を選んだ場合には、何も処理を行わない。
{
"manifest_version": 2,
"name": "Japanese Locale Switcher",
"version": "1.0",
"description": "Switches current page to Japanese locale",
"icons": {
"16": "icon16.png",
"32": "icon32.png",
"48": "icon48.png",
"128": "icon128.png"
},
"permissions": [
"activeTab"
],
"browser_action": {
"default_popup": "popup.html"
}
}
document.addEventListener('DOMContentLoaded', function() {
var yesButton = document.getElementById('yesButton');
var noButton = document.getElementById('noButton');
yesButton.addEventListener('click', function() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var currentUrl = tabs[0].url;
var newUrl = currentUrl.replace(/(\/\/[^\/]+)(\/.*)/, "$1/ja_jp$2");
chrome.tabs.update(tabs[0].id, {url: newUrl});
});
});
noButton.addEventListener('click', function() {
window.close();
});
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Japanese Locale Switcher</title>
<style>
body {
font-family: Arial, sans-serif;
font-size: 14px;
padding: 10px;
}
h1 {
font-size: 18px;
}
button {
margin-top: 10px;
padding: 5px 10px;
font-size: 14px;
}
</style>
</head>
<body>
<h1>日本語のページに切り替えますか?</h1>
<button id="yesButton">Yes</button>
<button id="noButton">No</button>
<script src="popup.js"></script>
</body>
</html>
これを読み込ませたところ、エラーが出てしまった。
どうやらマニフェストファイルのバージョンが更新されていて、最新は3らしい。
こちらの記事を参考にしながらコードを修正してみた。
修正後のコードはこちら。
{
"name": "AWS Doc Language Switcher",
"version": "1.0",
"manifest_version": 3,
"description": "Switch language to Japanese if the page is in English on a specific domain.",
"icons": {
"16": "icon_16.png",
"48": "icon_48.png",
"128": "icon_128.png"
},
"host_permissions": [
"*://*/*"
],
"action": {
"default_icon": "icon_16.png",
"default_popup": "popup.html"
},
"content_scripts": [{
"matches": ["https://docs.aws.amazon.com/*"],
"js": [
"doc_changer.js"
]
}]
}
chrome.action.onClicked.addListener((tab) => {
chrome.windows.create({
url: chrome.runtime.getURL("popup.html"),
type: "popup",
width: 600,
height: 100
});
});
function switchToJapanese() {
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
var currentUrl = tabs[0].url;
var newUrl = currentUrl.replace(/(\/\/[^\/]*)/, '$1/ja_jp');
chrome.tabs.update(tabs[0].id, { url: newUrl });
});
}
const yesButton = document.getElementById("yesButton");
const noButton = document.getElementById("noButton");
yesButton.addEventListener("click", () => {
switchToJapanese();
chrome.runtime.sendMessage({ message: "switchLocale" });
window.close();
});
noButton.addEventListener("click", () => {
window.close();
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Japanese Locale Switcher</title>
<style>
body {
font-family: Arial, sans-serif;
font-size: 14px;
padding: 10px;
width: 300px;
height: 100px;
}
h1 {
font-size: 18px;
}
button {
margin-top: 10px;
padding: 5px 10px;
font-size: 14px;
}
</style>
</head>
<body>
<h1>日本語のページに切り替えますか?</h1>
<button id="yesButton">Yes</button>
<button id="noButton">No</button>
<script src="doc_changer.js"></script>
</body>
</html>
ここまでで最低限の動作はしたものの、エラーが出てしまう。
調べたところmanifestファイルのaction周りの記述に問題がありそう。
→記載を変更するも改善せず。
ChatGPTで生成していたコードのうち、不要そうなところを削除したらエラーが出なくなった。
- 不要な箇所1
manifest.jsonの下記の部分
"content_scripts": [{
"matches": ["https://docs.aws.amazon.com/*"],
"js": [
"doc_changer.js"
]
}]
- 不要な箇所2
doc_changer.jsの下記の部分
chrome.runtime.sendMessage({ message: "switchLocale" });
このままでも良いんだけども下記のコードでタブを更新したときに、これまでのページ遷移の履歴が保持されてなくて、新しいタブでURLを叩いたような状態になってしまう。これに対処したい。
chrome.tabs.update(tabs[0].id, { url: newUrl });
ChatGPTに聞いたらそれっぽい回答返ってきた。2つ目の対処で行こう
Q:
chrome.tabs.updateでこれまでの履歴を残すには?
A:
回答
chrome.tabs.updateを使用してページのURLを変更した場合、通常は新しいURLに対応するページの履歴が作成され、元のページの履歴は残りません。しかし、以下の方法でこれまでの履歴を残すことができます。
- chrome.tabs.updateのurlパラメータに、現在のURLと新しいURLの両方を含める
chrome.tabs.updateのurlパラメータに、現在のURLと新しいURLの両方を含めることができます。例えば、以下のようにします。
chrome.tabs.update(tabId, {url: 'https://example.com/new-page#prev-page=https://example.com/old-page'});
このようにすることで、新しいページのURLに加えて、#で区切って元のページのURLを含めることができます。これにより、新しいページに遷移すると同時に、元のページのURLを含んだ情報を保持することができます。
- chrome.history APIを使用する
chrome.history APIを使用して、現在のURLを履歴に追加し、新しいURLに遷移することができます。以下のように、現在のURLをchrome.history.addUrlメソッドで履歴に追加し、chrome.tabs.updateで新しいURLに遷移することができます。
chrome.history.addUrl({url: currentUrl}, function() {
chrome.tabs.update(tabId, {url: newUrl});
});
この方法を使用することで、新しいURLに遷移しながら、現在のURLを履歴に残すことができます。
ChatGPTに前述の2の方法で修正までしてもらった(怠惰の極み)
ただ、これだけだとError handling response: TypeError: Cannot read properties of undefined (reading "'addUrl" ')とエラーが表示されて怒られてしまう。
ググっていくとマニフェストファイルでpermission属性の記載が必要みたいなので、そちらも追記。
chrome.action.onClicked.addListener((tab) => {
chrome.windows.create({
url: chrome.runtime.getURL("popup.html"),
type: "popup",
width: 600,
height: 100
});
});
function switchToJapanese(currentUrl, callback) {
var newUrl = currentUrl.replace(/(\/\/[^\/]*)/, '$1/ja_jp');
chrome.history.addUrl({url: currentUrl}, function() {
chrome.tabs.update({url: newUrl}, callback);
});
}
document.addEventListener("DOMContentLoaded", function() {
const yesButton = document.getElementById("yesButton");
const noButton = document.getElementById("noButton");
yesButton.addEventListener("click", () => {
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
var currentUrl = tabs[0].url;
switchToJapanese(currentUrl, function() {
window.close();
});
});
});
noButton.addEventListener("click", () => {
window.close();
});
});
{
"name": "AWS Doc Language Switcher",
"version": "1.0",
"manifest_version": 3,
"description": "Switch language to Japanese if the page is in English on a specific domain.",
"icons": {
"48": "icon_48.png",
"128": "icon_128.png"
},
"host_permissions": [
"*://*/*"
],
"permissions": [
"history"
],
"action": {
"default_icon": "icon_48.png",
"default_popup": "popup.html"
}
}
これで日本語ドキュメントのページに遷移しても、これまでの画面遷移履歴を失わずに動作することが確認できた。
荒削りとかっていうレベル以前に色々と考慮されてないコードだけども、自分で使う分には納得できるものが作れたのでヨシ。
せっかくなので作った拡張機能をChrome Webstoreに申請してみた