LoginSignup
27
35

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-10-16

こんにちは、Yuiです。

この度、ボタン一つで画像から文字起こし&翻訳できるアプリを作りました!

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

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

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

使った技術スタック

今回、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の文字を多言語化するにあたって、どういう風にかけば良いか悩みました。

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

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

//ファイルアップロード部分
<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に以下を追加

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で怒られたので上記のように書き直しました。

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

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

工夫した点

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

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

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

スクリーンショット 2020-10-17 0.26.45.png

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

スクリーンショット 2020-10-17 0.27.55.png

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

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

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

これをこう。

そして右上の言語のボタンが何を表すのかわかりにくかなと思い、tootlipをその部分に利用。
スクリーンショット 2020-10-17 0.34.08.png

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

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

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

スクリーンショット 2020-10-15 19.21.55.png

最後に

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

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

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

27
35
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
35