Closed15

初めてのChrome Extention作成:AWSの公式ドキュメントを日本語表示したい

Gekitenius.YGekitenius.Y

GWで時間があるのでChromeの拡張機能を作ってみようと思う。

なお、大したことをしたい訳ではなく、、
AWS公式のドキュメントをサクッと読みたいときに英語表示されると、わざわざURL欄に手打ちで/ja_jp/って入れるのが面倒だと思って、それをするだけの拡張機能を自作してみようと思っただけです(怠惰の極み)

Gekitenius.YGekitenius.Y

やりたいこと

AWSの公式ドキュメントのページを日本語表示したい

現状

  • 公式ドキュメントのページを開いた時、英語のページが表示されることがある

解決方法

  • 日本語ページにURLを変換して表示する(ドメイン名のあとに/ja_jp/が付されている状態にする)
Gekitenius.YGekitenius.Y

今や大人気のChatGPTさんにコード作ってもらう。
以下はプロンプトと生成したコード。

あなたはJavaScriptのエキスパートで、Chromeブラウザの拡張機能を作成することができます。
以下の要件を満たすChromeの拡張機能を実装するためのコードを教えて下さい。

【要件】
拡張機能のアイコンを表示したときにポップアップを表示する。
ポップアップには”日本語のページに切り替えますか?”と表示し、”Yes”と”No”の選択肢がある。
Yesの選択肢を選んだ場合には、現在表示しているWebページのURLに含まれるドメイン名のあとに、ロケールを示す/ja_jp/の文字列を追加して、再読み込みを行う。
Noの選択肢を選んだ場合には、何も処理を行わない。

manifest.json
{
  "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"
  }
}
doc_changer.js
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();
  });
});
popup.html
<!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>
Gekitenius.YGekitenius.Y

これを読み込ませたところ、エラーが出てしまった。
どうやらマニフェストファイルのバージョンが更新されていて、最新は3らしい。

Gekitenius.YGekitenius.Y

修正後のコードはこちら。

manifest.json
{
    "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"
        ]
      }]
  }
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();
});

popup.html
<!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>

Gekitenius.YGekitenius.Y

ここまでで最低限の動作はしたものの、エラーが出てしまう。

Gekitenius.YGekitenius.Y

調べたところ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" });
Gekitenius.YGekitenius.Y

このままでも良いんだけども下記のコードでタブを更新したときに、これまでのページ遷移の履歴が保持されてなくて、新しいタブでURLを叩いたような状態になってしまう。これに対処したい。

chrome.tabs.update(tabs[0].id, { url: newUrl });
Gekitenius.YGekitenius.Y

ChatGPTに聞いたらそれっぽい回答返ってきた。2つ目の対処で行こう

Q:
chrome.tabs.updateでこれまでの履歴を残すには?

A:

回答

chrome.tabs.updateを使用してページのURLを変更した場合、通常は新しいURLに対応するページの履歴が作成され、元のページの履歴は残りません。しかし、以下の方法でこれまでの履歴を残すことができます。

  1. 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を含んだ情報を保持することができます。

  1. 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を履歴に残すことができます。

Gekitenius.YGekitenius.Y

ChatGPTに前述の2の方法で修正までしてもらった(怠惰の極み)
ただ、これだけだとError handling response: TypeError: Cannot read properties of undefined (reading "'addUrl" ')とエラーが表示されて怒られてしまう。
ググっていくとマニフェストファイルでpermission属性の記載が必要みたいなので、そちらも追記。

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(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();
  });
});


manifest.json
{
    "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"
    }
  }
Gekitenius.YGekitenius.Y

これで日本語ドキュメントのページに遷移しても、これまでの画面遷移履歴を失わずに動作することが確認できた。

荒削りとかっていうレベル以前に色々と考慮されてないコードだけども、自分で使う分には納得できるものが作れたのでヨシ。

Gekitenius.YGekitenius.Y

せっかくなので作った拡張機能をChrome Webstoreに申請してみた

このスクラップは2023/05/03にクローズされました