Vue.jsで翻訳も辞書引きもできるブラウザ拡張機能を作りました

# 🚩前置き

初記事なので前置きが長いです。本編を見たい方は[📄要件](#要件)まで飛んで下さいね。

## 🤔これはなにか

javascriptにほんの少し慣れ、なにか実用性のあるものを作ってみようとし、**📖辞書+🏳️‍🌈翻訳**の両方ができる器用貧乏な拡張機能を自作した記録

こんなんができました。

![o.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264764/c6be1cf1-61e9-69bb-c7a9-5c10176edb36.gif)

辞書データをインポートし、選択した部分の単語が辞書内に存在すれば、その結果を表示します
単語or熟語が見つからなかったらGoogle翻訳に投げて、翻訳結果を取得します

[GitHubリポジトリ](https://github.com/maemaemae3/LazyTranslator)
[Chrome ウェブストア](https://chrome.google.com/webstore/detail/lazytranslator/icopppeohpnnliligpcnikdgjefmhbin?hl=ja)
[Firefox Addons](https://addons.mozilla.org/ja/firefox/addon/lazytranslator/)

# 📄要件

- Webページ内で、選択した部分を(できれば**ワンクリック**で)**パッと**翻訳したい  
- 普段のブラウジングは邪魔してほしくない
- 単語の意味も覚えたいので辞書も引きたい
- ドイツ語やその他の言語も自動判別して翻訳できたらしたい

(・・・どんだけわがままやねん)

## 🔍偉大な先輩方が作ったものを覗いてみる

- [Mouse Dictionary](https://qiita.com/wtetsu/items/c43232c6c44918e977c9)  
  辞書データを読み込んで、マウスオーバーした単語の意味を爆速で表示していってくれるツール  
  もうこれ使えばいいんじゃないかと思うくらい完成されている・・・すごい・・・  
  
この作者さんが作ったゲームを昔めっちゃやり込・・・話が脱線するのでまたの機会にします

- [Simple Translate](http://sienori.hatenablog.com/entry/2018/01/19/034419)  
  今までこれ使ってました  
  これに辞書機能足せたらええなーと言うのが発端でもあります

この2つを合わせた拡張機能が作れたらめっちゃ便利なのでは・・・？？？？
(多分既にある・・・？私の調べ方が足りないだけな気がしている)

# 📑基本的な仕組み

極力シンプルに作りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264764/4c58dfa3-691b-769e-ef93-d899be176ee0.png)

基本機能は2週間足らずで完成しましたが、

- 途中から突然思い立って[vue-web-extension](https://github.com/Kocal/vue-web-extension)を使うように変更したり、
- 辞書データの管理に[storage API](https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/API/storage)を使ったら速度がとんでもなく遅くて無限に最適化が必要になったり、
- ↑の挙動がFirefoxとChromeでぜんぜん違うので対応に苦労したり、
- 権限周りのせいで拡張機能の審査に1ヶ月位待たされたり( これが一番時間かかった )

で残り１割の完成にものすごく時間がかかりました。

最初に設計をしっかりしなかったせいです。エンジニア失格ですね。

# 👩‍🏫使い方

## ⚙️オプションを開く

オプションページはこんな感じになっています。
シンプルイズベストが信条なので、ゴチャゴチャ作り込むのはやめました
<sub><sup>めんどくさかったとも言う</sup></sub>


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264764/906e8156-416f-8907-1a80-689d68ba33e3.png)

- chromeの場合  
アイコンを右クリックし、オプションを開く  

  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264764/33fd33ae-7f2b-9e0d-cd78-4e3da9cf911b.png)
  
- Firefoxの場合  
アドレスバーに `about:addons`と入力後、オプションを開く  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264764/06e2c2ec-320a-db1d-98ff-9af54de18e69.png)

## 📖辞書データの登録

※ 現在は英辞郎データ ( 有料、https://booth.pm/ja/items/777563 )、ejdic-hand ( 無料、https://kujirahand.com/web-tools/EJDictFreeDL.php ) にのみ対応しています 
需要があればJSONにも対応できればいいのですが、私自身の需要がないので未実装です

1. 辞書データを選択します  
   ※ 選択した時点で登録が開始します
2. 暫く待つと登録が完了します  
3. 単語を選択すると、辞書に載っていた場合にその意味を表示できます

## 🏳️‍🌈翻訳機能

1. Google App Scriptで翻訳スクリプトを作ります。  
[Google翻訳APIを無料で作る方法](https://qiita.com/tanabee/items/c79c5c28ba0537112922)  
[3 分で作る無料の翻訳 API with Google Apps Script](https://qiita.com/satto_sann/items/be4177360a0bc3691fdf)  
この辺りを参考にしてAPIを作ります。

下図はその一例です。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264764/31f67347-2850-6750-427c-331c00e76014.png)

```javascript:main.gs
function doPost(e) {
  const text = e.postData.getDataAsString();
  const translatedText = LanguageApp.translate(text, "", "ja");
    
  const output = ContentService.createTextOutput();
  output.setMimeType(ContentService.MimeType.TEXT);
  output.setContent(translatedText);
  return output;
}
```

確認はPowerShellでやりました。
curlだったら
`$ curl -L -d "this is a pen." https://script.google.com/macros/s/[生成されたURL]`
みたいな感じですかね。

```powershell:check
> Invoke-WebRequest -Method Post -Body 'this is a pen.' https://script.google.com/macros/s/[生成されたURL]
StatusCode        : 200
StatusDescription : OK
Content           : これはペンです。
...
```

2. 実行URLをオプションページの**translate API settings**のテキストボックスに貼り付け、  
   **API動作テスト**ボタンを押下します
3. テストが行われ、成功した場合にそのURLが登録されます  
   失敗した場合はその旨が表示されます
4. 文章を選択すると、辞書に選択部分の単語が載っていなかった場合に翻訳を行い、その結果を表示します

## 🛑機能の一時停止
**ちょっと邪魔！今は出てこないで！！！**
っていう時に、拡張機能のアイコンを押すと、翻訳機能のオンオフが切り替えられるようにしました。
地味だけどあるとほんの少し便利なので加えました。

# 🍜おわりに 
- こういうのをサクッと見通しよく書けるVueってやっぱりすごいですね。  
ほんとにほんとに便利な時代になりました。
- 辞書データの文字コード自動検出は、辞書データの最初の数文字を読み込んで、そのバイト列で判断するという仕様。  
もしその数文字が全部英語だったら**勝手にUTF8**になる。文字コード周りはどうやら闇が深いようなので戦うのをやめましたが、いつか直したい。
- iframeに対応してなかったり、カスタマイズ性が低かったりするのはそのうち対応します。**頭の悪いコードを書いてたら石を投げてください**。
- 昔の人間な上に何年もCOBOLを触っていたせいで、原始人が高度文明に触れて途方に暮れるみたいな気持ちで作っていました。  
作り上げるにあたって色んな壁にぶち当たってるので、いつかそういう技術内容の記事も書きたい。