ボタン一つで画像から文字起こし＆翻訳できるアプリを作った話

こんにちは、[Yui](https://twitter.com/yui_active)です。

この度、**[ボタン一つで画像から文字起こし＆翻訳できるアプリ](https://www.pictranslator.info/)**を作りました！

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">ボタン一つで写真から文字起こししたり、母国語に翻訳するアプリ作りました！！<br>ボタン一つでコピー可能、多言語に対応してます。<br>登録不要で利用できます。<a href="https://twitter.com/hashtag/PicTranslator?src=hash&amp;ref_src=twsrc%5Etfw">#PicTranslator</a><br>拡散してもらえると私が喜びます！<a href="https://t.co/A28rXwMMB5">https://t.co/A28rXwMMB5</a><br><br>100日目<a href="https://twitter.com/hashtag/100%E6%97%A5%E5%BE%8C%E3%81%AB%E8%A9%B1%E9%A1%8C%E3%81%AEweb%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%82%92%E7%AB%8B%E3%81%A1%E4%B8%8A%E3%81%92%E3%82%8B%E3%83%AF%E3%83%8B?src=hash&amp;ref_src=twsrc%5Etfw">#100日後に話題のwebサービスを立ち上げるワニ</a></p>&mdash; Yui🌘個人開発 (@yui_active) <a href="https://twitter.com/yui_active/status/1316547840995278848?ref_src=twsrc%5Etfw">October 15, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

機能としては下記のものをつけています。

* 自動で利用者のブラウザの言語を読み取ってデフォルト言語に設定
* ボタン一つで文字起こしされる
* ボタン一つでデフォルト言語（利用者が普段使っている言語）に翻訳される
* デフォルト言語以外に言語を変えたい場合、クリックで言語を変えることができる
* 言語を変えた場合、全体的に多言語化される
* 文字起こし＆翻訳した後の文章はボタン一つで簡単にコピーできる

**シンプルな作りで、誰が見てもすぐに使うことができる**ようなサービスを目指して作りました。

# 使った技術スタック

今回、APIの接続だけで完了するような簡単なアプリなので、DB設計は必要ありませんでした。
というわけで、使ったのは下記だけです。

* Vue.js（フレームワークはVuetify利用）→フロントエンド
* vue-clipboard2→クリックしたらコピーできるように利用
* axios→APIとの通信のために利用
* vue-i18n→多言語化のために利用
* API→Cloud Vision APIとCloud Translation APIを利用

上記で大体かかった時間は**合計30時間**ぐらいでした。
デザイン→1時間
画面設計→5時間
API接続→10分
多言語化→2時間
残りはレイアウトの微調整とかでこだわった部分で時間がかかりました。笑

# 若干ハマったところ

今回少し詰まったところとしては**placeholderだけv-bindさせて使う必要がある**ということと、**自動で利用者のブラウザの言語を読み取る**という部分があります。

まず、今回多言語化をしたので、i18nの書き方に従い、

```
<div>{{$t('message.welcome')}}</div>
```
のように書く必要があります。

ただ、placeholderの文字を多言語化するにあたって、どういう風にかけば良いか悩みました。

```Vue
//ファイルアップロード部分
<v-file-input
  v-model="file"
  @change="setImage"
  @click:clear="clearData"
  accept="image/*"
  prepend-icon="mdi-camera"
  placeholder="ここにプレースホルダーに表示させる文字" //<=この部分をどう多言語化する？
></v-file-input>
```

その部分に関して書いてあるものが少なく少し悩んだのですが、公式ドキュメントを見るとどうやらv-bindさせて書けば良さそうだったので、以下のようにして書きました。

```Vue
//ファイルアップロード部分
<v-file-input
  v-model="file"
  @change="setImage"
  @click:clear="clearData"
  accept="image/*"
  prepend-icon="mdi-camera"
  :placeholder="$t('message.welcome')"
></v-file-input>
```

これでOK。ちなみに今回すでに文字起こしや翻訳をした後に再度違う画像をアップしたときに、過去の文字起こし・翻訳結果のデータが画面に残ってるままでは奇妙だったので、新しい写真をアップした段階でその結果を消すために``@click:clear="clearData"``を書いています。

また、**自動で利用者のブラウザの言語を読み取る**部分に関しては、今回多言語化対応をしていますが、もし自分が英語話者だったとして、デフォルト言語が日本語だったらその時点で見る気失せますよね？
ということで、**利用者の言語に合わせて表示を切り替える必要**がありました。

そのために``main.js``に以下を追加

```javascript:main.js
const browserLanguage = function() {
  var ua = window.navigator.userAgent.toLowerCase();
  try {
    // chromeは以下で利用者のブラウザ言語を取得できる
    if (ua.indexOf('chrome') != -1) {
      return (
        navigator.languages[0] ||
        navigator.browserLanguage ||
        navigator.language ||
        navigator.userLanguage
      ).substr(0, 2);
    }
    // それ以外（例えばIEなど）は下記で取得する必要がある
    else {
      return (
        navigator.browserLanguage ||
        navigator.language ||
        navigator.userLanguage
      ).substr(0, 2);
    }
  } catch (e) {
    return undefined;
  }
};

//上記で取得した言語をデフォルト言語として設定
let defaultLang;
//今回日本語、英語、フランス語、ドイツ語、中国語のみに対応してるので、その中にブラウザで検出した言語が入ってるかどうか確認
const langs = ['ja', 'en', 'fr', 'de', 'zh']
if (langs.includes(browserLanguage())) {
  defaultLang = browserLanguage();
} else {
//もし上記の言語外の場合はデフォルト言語を英語にする
  defaultLang = 'en';
}
```

jsでブラウザの取得できるのは知ってたんですが、chromeしかやり方を知らなかったので、それ以外に対応させるのに色々と調べました。

また、条件文で以下のようにざっくりと書いたらうごくには動くんですが、**ESLintでno-constant-conditionで怒られたので**上記のように書き直しました。

```javascript
if ( browserLanguage() == 'ja' || 'en' || 'fr' || 'de' || 'zh') {
  defaultLang = browserLanguage();
} else {
  defaultLang = 'en';
}
```

ほかは特に詰まることはなかったです。

# 工夫した点

今回は**できるだけシンプルに！**というのを目指して作りました。

なので、**説明文はなくてもわかるように**作りました。

結果、このようになりました。

![スクリーンショット 2020-10-17 0.26.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670446/21c44792-c75e-aed6-e880-0c77b334ae53.png)

画像をドラッグすると、こんな感じで**文字起こしする**と**翻訳する**のボタンが選べるようになります。

![スクリーンショット 2020-10-17 0.27.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670446/0fd18794-234b-b976-ce06-ef25a242a70b.png)

また、翻訳言語に関しては、もちろん英語やドイツ語など多言語にその場で選ぶようにすることもできました。
が、画像を翻訳したいとなったときに、**わざわざ母国語以外に翻訳するか？**という気持ちから、母国語に翻訳できるようにということで、ボタン一つで表示の言語に翻訳という形にしました。

また、もし表示の言語と母国語が違う（翻訳したい言語が違う）という場合は右上のボタンから違う言語に変換することもできます。

後はコピーした後の動きなどを少し工夫。

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">このレイアウトがな〜〜気に入らないんだよなあ〜〜〜〜〜 <a href="https://t.co/u80VW5N72z">https://t.co/u80VW5N72z</a> <a href="https://t.co/71b9T92YZt">pic.twitter.com/71b9T92YZt</a></p>&mdash; Yui🌒個人開発 (@yui_active) <a href="https://twitter.com/yui_active/status/1315715474135617542?ref_src=twsrc%5Etfw">October 12, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

これをこう。

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">すごい微妙に改善した<br>正直結局これで落ち着くならtootlipで組んだりalertで組んだりしてた時間がすべて無駄になったと思ったけど、まあシンプルなのが一番良い<br><br>後は文字起こしと翻訳のボタンのところにアイコンを追加したい<br>何かいいのあるかな <a href="https://t.co/eDIroyJtNw">https://t.co/eDIroyJtNw</a> <a href="https://t.co/DtQi0C5DAx">pic.twitter.com/DtQi0C5DAx</a></p>&mdash; Yui🌒個人開発 (@yui_active) <a href="https://twitter.com/yui_active/status/1315726989941186560?ref_src=twsrc%5Etfw">October 12, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

そして右上の言語のボタンが何を表すのかわかりにくかなと思い、tootlipをその部分に利用。
![スクリーンショット 2020-10-17 0.34.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670446/3fa2abcb-f0a7-a6a5-e629-13fd581b8d4a.png)

もちろんこの部分も多言語化対応済み。
例えば英語で見てるときは英語で表示されるようになっています。

# こだわりたかったけど時間の都合で省略した部分

今回どうしても省略した部分としては、**OGPの多言語化**です。
これは諸々の設定があまりにも面倒だったので、代わりに日本語と英語を両方表示するようにしました。

![スクリーンショット 2020-10-15 19.21.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670446/27a23085-26e3-2f61-ceca-87e6b2681598.png)


# 最後に

今回、作ったときはこんなに簡単なアプリを世の中に出してごめんなさい...という気持ちだったのですが、出してみると意外と好評で嬉しかったです。

これのLineBot版として**ほんやくこんにゃくん**も前に出したので、よかったら使ってみてください。

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">画像を送信するだけで、勝手に画像内の言語を認識して何でも日本語に変えてくれるLineBot作りました！<br>英語、中国語、ドイツ語、フランス語あたりは動作確認してます！（他の言語でもOK）<br>良いな〜と思ったら拡散してもらえると嬉しいです！<br><br>これからwebアプリ化もします！ <a href="https://t.co/PrAG1o1gHO">pic.twitter.com/PrAG1o1gHO</a></p>&mdash; Yui🌒個人開発 (@yui_active) <a href="https://twitter.com/yui_active/status/1313055726730792965?ref_src=twsrc%5Etfw">October 5, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


また、**Product Hunt**にも出してます！良ければvoteお願いします。

https://www.producthunt.com/posts/pic-translator