【概要】
翻訳機能のAPI実装になります。
今回は、DeepL
での実装になりますので、Google翻訳API
でない点についてご留意ください。
併せて、今回はDeepLのGem
を使用しますので、詳細は、下記からご確認お願いします。
【環境】
・Rails:3.2.2
・Ruby :7.0.8
・DeepL
【導入背景】
自身のアプリでレシピを取得するために、EdamamsAPI
という海外のAPIを導入しました。
しかし、英語
でリクエストを送信しない場合は、取得時に失敗するという問題点がありました。
EdamamsAPI
については、下記になります。詳細が気になる方は下記の記事を参照してください。
【Google翻訳APIとの相違点】
以上から、翻訳機能の実装に至ったのですが、翻訳機能について調査を行った結果、GoogleAPI
とDeepL
が候補に上がりました。相違点は下記になります。
Google翻訳API | DeepL | |
---|---|---|
メリット | サポート言語が豊富・無料の文字数が多い | Google翻訳より翻訳精度が高い |
デメリット | 翻訳制度が悪い | 無料の文字数が少ない |
翻訳精度に関しては、下記のサイトが参考になるかと思います。
今回の実装では、リクエストの数を考えた時にDeepL
の無料枠で問題ない範囲でしたので、後者で実装することにいたしました。
【DeepL側での準備】
ここからは実装フェーズになります。
まずは、下記から、ログインして登録などを行なってください。また、不明点がある場合、下記の手順書を参考にしてください。
【手順書】
https://auto-worker.com/blog/?p=5030
以上が、DeepL側で実装する内容になります。ここからは、ソースを編集していきます。
【DeepLの実装_SRC編】
上記で取得した認証key
の情報を使用して、APIを実施塩ていきたいと思います。なお、今回の実装ではdotenv-rails
のgemを使用して実装しておりますが、credential
で実装していたただいても構いません。
【DeepLの実装_下準備】
1.dotenv-rails
のgrm取得
gem 'dotenv-rails'
bundle install
2.env
ファイルに認証KEY
の情報をセット
touch .env //.envファイルを作成
DEEPL_KEY='先ほど取得したDeepL-keyの内容'
3.deepl
のgemを取得
gem 'deepl-rb', require: 'deepl'
bundle install
4.httpclient
通信するためのgemを取得
gem 'httpclient'
bundle install
【DeepLの実装】
ここからが、実装になります。
class EdamamsController < ApplicationController
skip_before_action :require_login, only: %i[index]
require 'httpclient' # HTTP通信を行うためのライブラリ(API使用時に必要)
require 'cgi'
require 'deepl' # gemを使用するため、ここで読み込み処理をかける
def index
query = params[:search].blank? ? 'nodata' : params[:search]
translated_query = translate_to_english(query)
client = HTTPClient.new
res = client.get("https://api.edamam.com/api/recipes/v2?type=public&q=#{CGI.escape(translated_query)}&app_id=#{ENV.fetch('application_id', nil)}&app_key=#{ENV.fetch('application_keys', nil)}")
@foods = JSON.parse(res.body)
end
private
def translate_to_english(query)
api_key = ENV['DEEPL_KEY']
uri = ("https://api-free.deepl.com/v2/translate")
client = HTTPClient.new
client.ssl_config.clear_cert_store
client.ssl_config.set_trust_ca("/etc/ssl/certs")
params = {
auth_key: api_key,
text: query,
target_lang: "EN"
}
response = client.get(uri, query: params)
parsed_response = JSON.parse(response.body)
translation_text = parsed_response["translations"][0]["text"]
translation_text
end
end
<div class="container">
<div class="d-flex">
<h3 class="text-center">海外のレシピ検索</h3>
<div class="text-center"><%= render 'shared/how_to_edamams_api' %></div>
</div>
<%= form_with(url: edamams_path, method: :get, class: "search-form") do |f| %>
<%= f.text_field :search, placeholder: "食材で検索してください", class: 'form-control' %>
<%= f.submit '検索する', class: "btn-brown" %>
<% end %>
</div>
<% if @foods.present? && @foods["hits"].present? %>
<div class='m-3'>
<% @foods["hits"].first(12).each_slice(3) do |recipes| %>
<div class="row mb-3">
<% recipes.each do |recipe| %>
<div class='col-md-4'>
<div class="card" style="background-color: #FFEEC1">
<div class="card-body text-center">
<h4 class="card-title" style='color: #6B493D; font-size: 16px;'><%= translate_to_japanese(recipe["recipe"]["label"]) %></h4>
<%= image_tag recipe["recipe"]["image"], class: "card-img-bottom mx-auto", alt: "Card image", style: "width:70%; height: 70%; object-fit: contain;" %>
<div class="text-center mt-3">
<%= link_to '海外公式サイトへ', recipe["recipe"]["url"], class: "btn btn-warning", style: "color: #6B493D; font-size: 14px;" %>
</div>
</div>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
<% end %>
今回の実装方針としては、
1.入力された値を日本語化してEdamamsAPIとして渡す
2.EdamamsAPIから取得したjsonから英語を日本語に翻訳する
上記の2点がポイントになります。
【ポイント1】
require 'httpclient'
require 'deepl'
# 上記の記述でDeepL及びAPIを実行できるようにする。それぞれrequire対象の詳細についてはgithub参照。
def translate_to_english(query)
api_key = ENV['DEEPL_KEY']
uri = ("https://api-free.deepl.com/v2/translate")
client = HTTPClient.new
# 上記から、環境変数などのセットを行う。(有料プランの場合、uriが上記ではなくなります。)
client.ssl_config.clear_cert_store
client.ssl_config.set_trust_ca("/etc/ssl/certs")
# SSLなど証明書の情報をここで設定しておく。
params = {
auth_key: api_key,
text: query,
target_lang: "EN"
}
# 取得した日本語を英語に変換するので"EN"
response = client.get(uri, query: params)
parsed_response = JSON.parse(response.body)
translation_text = parsed_response["translations"][0]["text"]
translation_text
# json.parse後の中身に関して後述。
end
実際に、どのような挙動をしているのか確認しましょう。
def translate_to_english(query)
# 割愛
translation_text = parsed_response["translations"][0]["text"]
translation_text
Rails.logger.info(parsed_response["translations"])
# JSONの中身を検証。確認後に上記を削除します。
end
Parameters: {"search"=>"バナナ", "commit"=>"検索する"} # 検索値として、【バナナ】を確認
[{"detected_source_language"=>"JA", "text"=>"banana"}]# 一部抜粋。json形式内のtextがbananaに翻訳されたことを確認
以上、コントローラから日本語から英語に変換する作業を紹介しました。
今度は英語から日本語に変換する作業を紹介します。
【ポイント2】
今回は、viewの表示をhelper配下にmoduleで日本語表記になるように、設定したいと思います。
まずは、呼び出し元を下記のようにします。
<% @foods["hits"].first(12).each_slice(3) do |recipes| %>
<div class="row mb-3">
<% recipes.each do |recipe| %>
<h4 class="card-title" style='color: #6B493D; font-size: 16px;'><%= translate_to_japanese(recipe["recipe"]["label"]) %></h4> #ここで、moduleから呼び出せるように命名する。
(edamamsAPIの引数の詳細については本筋と逸れるので割愛します。確認したい場合、edamamsAPI取得後に、local環境を用意し、postmanなどで検証してください。)
module TranslationsHelper
def translate_to_japanese(query)
api_key = ENV['DEEPL_KEY']
uri = "https://api-free.deepl.com/v2/translate"
client = HTTPClient.new
# 上記で環境変数の設定
client.ssl_config.clear_cert_store
client.ssl_config.set_trust_ca("/etc/ssl/certs")
# SSLの設定
params = {
auth_key: api_key,
text: query,
target_lang: "JA"
}
# 英語から日本語に変換したいので、JAに設定。
response = client.get(uri, query: params)
parsed_response = JSON.parse(response.body)
translation_japanese = parsed_response["translations"][0]["text"]
translation_japanese
end
end
先ほどとの相違点としては、view側で表示したいので
1.helperに設定したこと
2.target_lang: "JA"
で日本語翻訳するように設定したこと
上記の2点になります。
ここまでで、今回の実装要件を満たすことができました!
完成系が下記になります。
【引用】