初心者がNext.jsでTypescriptを使ってDeepL APIによる翻訳機能を実装する。
はじめに
DeepL APIの実装方法についてまとめている記事が少なかったので、Next.jsでDeepL APIを使い、日本語の文章を英語に自動翻訳する機能の実装方法について自分なりにまとめました。
Next.jsを触り始めて3日目なので、私と同じ初学者との情報共有を目的とした記事です。
Next.jsに詳しい方で、気になるところがあれば気軽に指摘していただけると幸いです。
Next.jsアプリケーションを開始
まずはNext.jsのアプリケーションを開始します。開始の仕方は公式のドキュメントを参照してください。今回のプロジェクトではyarnを使用し、TypescriptとESLintをONにしました。
アプリケーションの立ち上げが終わったら、code .
でVSCodeを開きます。
アプリケーションが正常に開始されていることが確認できたら、pages/index.tsx
ファイルを開き、<main></main>
タグの中身を空にします。そして、styles/Home.modules.css
ファイルを開き、.main
セレクターの中身を
.main {
min-height: 100vh;
background-color: white;
color: black;
}
に書き換えてください。それ以外のセレクターは削除してしまって大丈夫です。
ターミナルでyarn dev
またはnpm run dev
と叩き、localhostを立ち上げてブラウザ上で確認してみると、真っ白なページが表示されると思います。
次にpages/index.tsx
ファイルに戻り、<main></main>
タグの中に以下を追加してみてください。
<main>
{/* 以下を追加 */}
<div className={styles.content}>
<button >英語に翻訳</button><br/><br/>
<p>ここにテキストが入る</p>
</div>
</main>
見やすいようにcssを追加します。
.content {
margin: 0 auto;
width: 60%;
padding-top: 100px;
}
ブラウザで確認すると以下のようになってると思います。
これでNext.jsの準備は終わりです。今回はコンポーネントなどは使わず、pages/index.tsx
ページのみで実装します。
DeepL APIの登録と準備
まず、DeepL APIのサイトを開きます。
「無料で登録する」ボタンをクリックと、DeepL API Free か DeepL API Pro を選ぶセクションにスクロールします。今回は DeepL API Free を使うので DeepL API Free の「無料で登録する」をクリックしてください。
DeepL API Pro を選択すると、多少コストが増えますが、翻訳機能を無制限に使うことができます。対して、DeepL API Freeは月々500,000文字までという制限がつきます。
「無料で登録する」ボタンをクリックすると、アカウント情報を入力するページに遷移するので案内に従って情報を入力してください。途中でカード情報を聞かれますが、セキュリティのための登録で、支払い請求が来ることはありません。
DeepL API の登録はこれで終了です。
DeepL API の使用状況やDeepL APIを使う上で大事な「認証キー」はアカウントページからみることができます。今後使うので開いておいてください。
DeepL ライブラリのインストール
今回はより簡単に実装するためにdeeplライブラリを使用しました。
VSCodeでターミナルを開きctrl+c
で一旦localhostを中断し、yarn add deepl --save
またはnpm i deepl --save
と叩き、deeplライブラリをインストールします。
※他にもdeepl-nodeというライブラリがありますが、サーバーサイドでの実装は上手く行ったものの、なぜかクライアントサイドでの実装でエラーが出るので、やり方わかる人いたらコメントください😭
DeepL APIによる自動翻訳関数の実装
それではDeepL API による日本語→英語の自動翻訳機能を実装します。
まず、プロジェクトのルートにlibs
というフォルダーを作成し、libs
の中に、Translation.tsx
ファイルを作成します。
Translation.tsx
ファイルを開き、deeplライブラリをインポートします。
ここでdeeplライブラリのドキュメントを確認してみると、
translate({
text: 'I am a text',
target_lang: 'FR',
auth_key: 'authkey',
// All optional parameters available in the official documentation can be defined here as well.
})
.then(result => {
console.log(result.data);
})
.catch(error => {
console.error(error)
});
translate()
という関数があることがわかります。まず、それをインポートしましょう。
import translate from 'deepl'
そして、translate()
関数を使うにはtext
、target_lang
、auth_key
の3つの引数が最低限必要であることが記されています。今回はTypescriptでの実装なのでそれぞれのtypeを見てみると、text: string
、target_lang:DeeplLanguages
、auth_key:string
になっています。target_lang
のtypeがDeeplLanguages
になっている理由は、サポートしている言語コード以外の言語コードが入力された場合にエラーを返すためだと考えられます。
このtype DeeplLanguages
もdeeplライブラリからインポートすることができます。translate
のインポートに{ DeeplLanguages }
を追加してください。
import translate, { DeeplLanguages } from 'deepl'
次にdeeplライブラリの引数であるauth_keyを設定します。このauth_keyはDeepL APIから情報を取得するときに必要な認証キーで、外部に漏れてはいきません。このような情報は環境変数として.env.local
ファイルに書いておく必要があります。
プロジェクトのルートに.env.local
ファイルを新しく作成してください。
続いて、DeepL APIのアカウントページにいきアカウントタブをクリックしてください。
下にスクロールすると「DeepL APIで使用する認証キー」というセクションがあるので、認証キーをコピーしてください。
.env.local
ファイルに戻り、以下の通りに書いてください。
NEXT_PUBLIC_DEEPL_AUTH_KEY=認証キー
※頭にNEXT_PUBLIC_
がないと上手くアクセスできませんでした。
認証キーにクオテーションマークや()などは必要ありません。
process.env.NEXT_PUBLIC_DEEPL_AUTH_KEY
でこの認証キーにアクセスすることができます。libs/Translation.tsx
で変数として呼んでみましょう。
const auth_key:string = (process.env.NEXT_PUBLIC_DEEPL_AUTH_KEY === undefined)? "":process.env.NEXT_PUBLIC_DEEPL_AUTH_KEY;
ここで、auth_key
のtypeがstring
なのに対し、process.env.NEXT_PUBLIC_DEEPL_AUTH_KEY
のtypeがstring | undefined
なので、process.env.NEXT_PUBLIC_DEEPL_AUTH_KEY
がundefinedの場合は空文字を返すような実装にしました。
※もっといい方法あったらコメントで教えてください
次に、DeepL APIと通信をして翻訳したテキストを返す関数を非同期処理、async function
で実装します。今回の関数は引数としてmy_text: string
my_target_lang: DeeplLanguages
を取ります。また、今回は DeepL API Free での実装なのでtranslate()
関数のoptional引数であるfree_api
をtrue
に設定する必要があります。
deeplライブラリのドキュメントを確認すると、translate()
関数の返り値の例は以下のようになります。
{
"translations": [
{
"detected_source_language": "EN",
"text": "Je suis un texte"
}
]
}
今回の関数を呼ぶと
{
"detected_source_language": DeeplLanguages,
"text": string,
}
という値にアクセスできるように実装します。以下が実装した関数です。
export async function Translator(text:string, target:DeeplLanguages) {
const res = await translate({free_api:true, text: text, target_lang:target, auth_key:auth_key!})
const result = res.data.translations
return result[0]
}
このTranslator
関数をpages/index.tsx
にインポートすれば自動翻訳を実装することができます。
自動翻訳関数を使ってみる
pages/index.tsx
に移動してください。
まず、Translator
関数をインポートします。また、type DeeplLanguages
も使いたいので、pages/index.tsx
の方でもインポートします。
import { Translator } from '@/libs/Translation'
import { DeeplLanguages } from 'deepl'
続いて、Home()
内にuseState()を使って値と更新のための関数を宣言します。useStateのインポートは自動でされると思いますが、されない場合は忘れずに行なってください。
import Head from 'next/head'
import styles from '@/styles/Home.module.css'
import { Translator } from '@/libs/Translation'
import { useState } from 'react'
export default function Home() {
const [myText, setMyText] = useState('')
return (
<>
...
</>
)
}
次に、ボタンを押した時のクリック関数を作り、その中でTranslator
関数と、その返り値でsetMyText
関数を実行します。
ここで注意しなければいけないことがあります。Translator()
関数の返り値のtypeは
{
"detected_source_language": DeeplLanguages,
"text": string,
}
だと思われがちなのですが、async function
で非同期処理を行う場合の返り値はPromise<>
オブジェクトで囲われてしまいます。このPromise<>
オブジェクトから欲しい情報を取り出すには、ライブラリのドキュメントにある通り、.then()
関数の中で処理を行う必要があります。
translate({
text: 'I am a text',
target_lang: 'FR',
auth_key: 'authkey',
// All optional parameters available in the official documentation can be defined here as well.
})
.then(result => {
console.log(result.data);
})
.catch(error => {
console.error(error)
});
それでは、クリック関数を実装していきます。
import Head from 'next/head'
import styles from '@/styles/Home.module.css'
import { Translator } from '@/libs/Translation'
import { DeeplLanguages } from 'deepl'
import { useState } from 'react'
export default function Home() {
const [myText, setMyText] = useState('')
function clickTranslate(my_text:string, my_target_lang:DeeplLanguages) {
const translations = Translator(my_text, my_target_lang)
translations.then((result) => setMyText(result.text))
}
return (
<>
...
</>
)
}
前述した通り、then()
関数の中で
{
"detected_source_language": DeeplLanguages,
"text": string,
}
をresult
としてを受け取り、result.text
をsetMyText()
関数の引数に代入しています。
このクリック関数を<button></button>
タグの中のonClick
アトリビュートで呼びます。引数に代入する値はmyText
と、今回は日本語→英語の翻訳なので、言語コードとして設定されている'EN-US'
にします。
<main className={styles.main}>
{/* ここを追加 */}
<div className={styles.content}>
<button onClick={() => clickTranslate(myText, 'EN-US')}>英語に翻訳</button><br/><br />
<p>ここにテキストが入る</p>
</div>
</main>
最後にmyTextの初期値を適当に設定して翻訳されるか確かめたいと思います。<p></p>
タグの中身も忘れずに{myText}
に変えておいてください。
import Head from 'next/head'
import styles from '@/styles/Home.module.css'
import { Translator } from '@/libs/Translation'
import { DeeplLanguages } from 'deepl'
import { useState } from 'react'
export default function Home() {
// ここを追加
const templeteText = "翻訳とは、ある形で表現されている対象を、異なる形で改めて表現する行為である。\
特に、自然言語において、起点言語による文章を、別の目標言語による文章に変換する行為をさす。例えば、\
英語文から日本語文へ翻訳された場合は、起点言語が英語であり、目標言語が日本語である。起点言語による文を原文といい、\
目標言語による文を訳文・翻訳文と言う。一方で、プログラミング用語としては形式言語の変換という意味でも用いられる。なお、\
文ではなく発話を翻訳する行為は、通訳とも呼ばれる。"
// useState()の中にtempleteTextを入れる。
const [myText, setMyText] = useState(templeteText)
function clickTranslate(my_text:string, my_target_lang:DeeplLanguages) {
const translations = Translator(my_text, my_target_lang)
translations.then((result) => setMyText(result.text))
}
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<div className={styles.content}>
<button onClick={() => clickTranslate(myText, 'EN-US')}>英語に翻訳</button><br/><br />
{/* ここを変更 */}
<p>{myText}</p>
</div>
</main>
</>
)
}
yarn dev
またはnpm run dev
で実行し、ブラウザで確認してみましょう。最初は日本語の文章が表示されているはずです。
ボタンを押して翻訳されるか確認してみましょう。
無事翻訳されました。
以上でDeepL APIによる日本語→英語の自動翻訳機能の実装方法の紹介を終わります。
全コード↓
import translate, { DeeplLanguages } from 'deepl'
const auth_key:string = (process.env.NEXT_PUBLIC_DEEPL_AUTH_KEY === undefined)? "":process.env.NEXT_PUBLIC_DEEPL_AUTH_KEY;
export async function Translator(my_text:string, my_target_lang:DeeplLanguages) {
const res = await translate({free_api:true, text: my_text, target_lang:my_target_lang, auth_key:auth_key})
const result = res.data.translations
return result[0]
}
NEXT_PUBLIC_DEEPL_AUTH_KEY=認証キー
import Head from 'next/head'
import styles from '@/styles/Home.module.css'
import { Translator } from '@/libs/Translation'
import { DeeplLanguages } from 'deepl'
import { useState } from 'react'
export default function Home() {
const templeteText = "翻訳とは、ある形で表現されている対象を、異なる形で改めて表現する行為である。\
特に、自然言語において、起点言語による文章を、別の目標言語による文章に変換する行為をさす。例えば、\
英語文から日本語文へ翻訳された場合は、起点言語が英語であり、目標言語が日本語である。起点言語による文を原文といい、\
目標言語による文を訳文・翻訳文と言う。一方で、プログラミング用語としては形式言語の変換という意味でも用いられる。なお、\
文ではなく発話を翻訳する行為は、通訳とも呼ばれる。"
const [myText, setMyText] = useState(templeteText)
function clickTranslate(my_text:string, my_target_lang:DeeplLanguages) {
const translations = Translator(my_text, my_target_lang)
translations.then((result) => setMyText(result.text))
}
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<div className={styles.content}>
<button onClick={() => clickTranslate(myText, 'EN-US')}>英語に翻訳</button><br/><br />
<p>{myText}</p>
</div>
</main>
</>
)
}
最後に
初めてZennで記事を書いてみたのですが、いかがだったでしょうか。
このやり方を使って、microCMSのブログを自動翻訳する機能も実装したので、需要があったら記事にします。
もっともっと成長していきたいので、ぜひコメントで厳しいご指摘をください。
最後まで読んでいただきありがとうございました。
Discussion