1日目のゴールと今日やること
LibreTranslate API 中級編 1 日目のテーマは
「テキストを入力 → API に送信 → 翻訳結果を表示する“翻訳アプリの基礎”を作る」
ことです。
扱う技術はこの 3 つ。
- fetch
- Promise / async-await
- エラーハンドリング
そして実装としては、まずこのレベルを目指します。
- 入力欄に文章を入れる
- 翻訳元言語・翻訳先言語を選ぶ
- 「翻訳する」ボタンを押す
- LibreTranslate API から翻訳結果を取得
- ローディング表示を出す
- 通信失敗時にわかりやすいエラーメッセージを出す
翻訳アプリは「入力 → API → 出力」という流れがとても明確なので、
fetch・async/await の練習に最適です。
LibreTranslate API の基本を理解する
どんな API なのか
LibreTranslate は、無料で使える翻訳 API です。
Google 翻訳のように、テキストを送ると翻訳結果を返してくれます。
翻訳用のエンドポイントはこれです。
POST https://libretranslate.com/translate
送るデータは JSON 形式で、
{
"q": "Hello",
"source": "en",
"target": "ja",
"format": "text"
}
返ってくる JSON はこうです。
{
"translatedText": "こんにちは"
}
つまり、
「テキストを送る → translatedText を受け取る」
というシンプルな構造です。
今日作るミニ翻訳アプリのイメージ
必要な UI
まずは最低限の UI を考えます。
- 翻訳元テキスト入力欄
- 翻訳元言語選択
- 翻訳先言語選択
- 翻訳ボタン
- ステータス表示(ローディング・成功・エラー)
- 翻訳結果表示欄
HTML のイメージはこんな感じです。
<textarea id="inputText" placeholder="翻訳したい文章を入力"></textarea>
<select id="sourceLang">
<option value="en">英語</option>
<option value="ja">日本語</option>
<option value="es">スペイン語</option>
</select>
<select id="targetLang">
<option value="ja">日本語</option>
<option value="en">英語</option>
<option value="es">スペイン語</option>
</select>
<button id="translateButton">翻訳する</button>
<div id="status"></div>
<div id="result"></div>
fetch を「API にお願いしに行く関数」として理解する
fetch の基本形
fetch は、
「この URL にアクセスして、結果をちょうだい」
とブラウザに頼む関数です。
LibreTranslate は POST リクエストなので、
fetch の書き方はこうなります。
fetch("https://libretranslate.com/translate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
q: "Hello",
source: "en",
target: "ja",
format: "text"
})
});
JavaScriptここで大事なのは、
- method: “POST”
- headers で JSON を送ることを宣言
- body に JSON.stringify したデータを入れる
という 3 点です。
Promise と async/await をかみ砕いて理解する
Promise は「未来の結果の箱」
fetch はすぐに結果を返しません。
「あとで結果がわかるよ」という Promise を返します。
const promise = fetch(url);
JavaScriptthen を使うと、
promise.then((response) => {
console.log("終わったよ", response);
});
JavaScriptasync/await は「同期っぽく書ける魔法」
Promise を then でつなぐと読みにくいので、
async/await を使うとスッキリします。
async function translate() {
const response = await fetch(url);
const data = await response.json();
}
JavaScript- await は「Promise が終わるまで待つ」
- async は「この関数の中で await を使いますよ」という宣言
この 2 つはセットです。
エラーハンドリングの基本を理解する
エラーは 3 段階で考える
API 通信のエラーは、ざっくり 3 種類あります。
- fetch 自体の失敗(ネットワークエラー)
- HTTP エラー(ステータスコードが 200 以外)
- API が返した JSON の中身が想定外
これを全部 try-catch で扱います。
ローディング表示を入れる理由
翻訳は数百ミリ秒〜数秒かかることがあります。
その間、ユーザーは「押したのに何も起きない」と不安になります。
だから、
- 「翻訳中です…」と表示
- ボタンを無効化して連打を防ぐ
という UI が必要です。
中心となる async 関数を作る
DOM 要素を取得する
const inputText = document.getElementById("inputText");
const sourceLang = document.getElementById("sourceLang");
const targetLang = document.getElementById("targetLang");
const translateButton = document.getElementById("translateButton");
const statusDiv = document.getElementById("status");
const resultDiv = document.getElementById("result");
JavaScriptローディング開始・終了の関数
function startLoading() {
statusDiv.textContent = "翻訳中です…";
translateButton.disabled = true;
}
function endLoading() {
translateButton.disabled = false;
}
JavaScript翻訳処理の本体(重要)
async function translateText() {
const text = inputText.value.trim();
const source = sourceLang.value;
const target = targetLang.value;
if (!text) {
statusDiv.textContent = "翻訳する文章を入力してください。";
resultDiv.textContent = "";
return;
}
startLoading();
resultDiv.textContent = "";
try {
const response = await fetch("https://libretranslate.com/translate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
q: text,
source: source,
target: target,
format: "text"
})
});
if (!response.ok) {
statusDiv.textContent = `サーバーエラーが発生しました。(${response.status})`;
return;
}
const data = await response.json();
if (!data.translatedText) {
statusDiv.textContent = "翻訳結果が取得できませんでした。";
return;
}
statusDiv.textContent = "翻訳に成功しました。";
resultDiv.textContent = data.translatedText;
} catch (error) {
statusDiv.textContent = "通信に失敗しました。ネットワークを確認してください。";
console.error(error);
} finally {
endLoading();
}
}
JavaScriptボタンにイベントを付ける
translateButton.addEventListener("click", translateText);
JavaScript通信失敗時の分岐を“ユーザー目線”で設計する
失敗パターンごとにメッセージを変える
- ネットワークエラー
→ 「通信に失敗しました。ネットワークを確認してください。」 - HTTP エラー
→ 「サーバーエラーが発生しました。(ステータスコード)」 - JSON の中身が想定外
→ 「翻訳結果が取得できませんでした。」
これだけで、ユーザーの安心感が大きく変わります。
1日目のまとめ
今日やったことは、翻訳アプリの“基礎の基礎”です。
- fetch で API にデータを送る
- async/await で読みやすく書く
- try-catch で通信エラーを扱う
- ローディング表示でユーザーを安心させる
- HTTP エラーと「該当なし」を分ける
そして何より大事なのは、
「API が返す JSON の形を理解してからコードを書く」
という姿勢です。
LibreTranslate は translatedText を返す。
Datamuse は配列を返す。
NewsAPI は articles を返す。
API ごとに形は違うけれど、
fetch・async/await・エラーハンドリングの“型”は同じです。
次のステップ(2日目の予告)
2日目では、今日作った翻訳アプリに
- 言語一覧を API から取得して自動生成
- ローディング表示の改善
- エラー表示のパターン化
- 翻訳履歴の追加
などを加えて、
「毎日使える翻訳ツール」に育てていきます。
続きも一緒に作っていこう。

