7日目のゴールと今日やること
7日目のテーマは
「LibreTranslate API 翻訳アプリを“中級編の完成形”としてまとめる」
ことです。
ここまで 6 日間であなたは、
- fetch の基本と POST リクエスト
- async/await による読みやすい非同期処理
- try-catch によるエラーハンドリング
- 言語一覧の取得
- 翻訳処理の共通化
- 自動翻訳(デバウンス)
- 履歴・お気に入り・コピー機能
- ローディング表示の改善
- localStorage による保存
をすべて経験してきました。
7日目は、これらを 「ひとつの完成したアプリ」 として整理し、
fetch / async-await / エラーハンドリングの“型”を自分のものにします。
翻訳アプリの全体構造を理解する
アプリは 4 つの層でできている
翻訳アプリは、次の 4 層で構成されています。
状態管理(state)
アプリの「現在の状態」をひとまとめにする場所。
const state = {
isLoading: false,
history: [],
favorites: [],
languages: []
};
JavaScriptAPI 通信(fetch / async-await)
LibreTranslate API にアクセスしてデータを取得する部分。
UI 更新(render 系)
翻訳結果・履歴・お気に入りなどを画面に表示する部分。
イベント処理(クリック・入力)
ユーザーの操作を受け取って処理を呼び出す部分。
この 4 層を意識すると、
アプリが「どこで何をしているか」が一気に理解しやすくなります。
fetch / async-await / エラーハンドリングの“完成形”を作る
共通 fetch 関数を作る理由
fetch を使う場面は多いので、
毎回 try-catch を書くとコードが散らかります。
そこで、
fetch のエラー処理をひとつにまとめた関数
を作ります。
共通の JSON リクエスト関数
async function requestJson(url, options = {}) {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTPエラー(${response.status})`);
}
const data = await response.json();
return data;
} catch (error) {
throw new Error(error.message);
}
}
JavaScript深掘りポイント
この関数は、
- fetch の失敗
- HTTP エラー
- JSON パースエラー
をすべて Error として上に投げる 役割を持っています。
これにより、
上位の関数は「何をしたいか」だけに集中できます。
翻訳専用の関数を“API の仕様を知っている唯一の場所”にする
翻訳リクエストを共通化する
async function requestTranslate(text, source, target, format) {
const body = {
q: text,
source: source,
target: target,
format: format
};
const data = await requestJson("https://libretranslate.com/translate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body)
});
if (!data.translatedText) {
throw new Error("翻訳結果が取得できませんでした。");
}
return data.translatedText;
}
JavaScript深掘りポイント
requestTranslate は
「LibreTranslate API の仕様を知っている唯一の関数」
です。
他の関数は API の細かい仕様を知らなくてよくなり、
アプリ全体が読みやすくなります。
ローディング表示を「状態と UI の両方」で管理する
ローディング開始・終了の関数
function startLoading(message) {
updateState({ isLoading: true });
statusDiv.textContent = message || "処理中です…";
translateButton.disabled = true;
}
function endLoading() {
updateState({ isLoading: false });
translateButton.disabled = false;
}
JavaScript深掘りポイント
ローディング表示は、
「アプリが固まっていない」ことを伝える重要な UI
です。
状態(state)と UI を連動させることで、
アプリ全体の動きが統一されます。
翻訳処理を「ストーリーとして読める」形にする
translateText の完成形
async function translateText() {
const text = inputText.value.trim();
const source = sourceLang.value;
const target = targetLang.value;
const format = formatMode.value;
if (!text) {
statusDiv.textContent = "翻訳する文章を入力してください。";
resultDiv.textContent = "";
return;
}
if (source === target) {
statusDiv.textContent = "翻訳元と翻訳先が同じです。別の言語を選んでください。";
return;
}
startLoading("翻訳中です…");
resultDiv.textContent = "";
try {
const translated = await requestTranslate(text, source, target, format);
statusDiv.textContent = "翻訳に成功しました。";
resultDiv.textContent = translated;
addHistory(text, translated, source, target);
} catch (error) {
statusDiv.textContent = `翻訳中にエラーが発生しました:${error.message}`;
console.error(error);
} finally {
endLoading();
}
}
JavaScript深掘りポイント
この関数は、
「翻訳の流れをそのまま読める」
という設計になっています。
- 入力チェック
- ローディング開始
- 翻訳
- 成功時の処理
- 失敗時の処理
- ローディング終了
fetch の細かい処理はrequestTranslate に隠れているため、
とても読みやすくなっています。
通信失敗時の分岐を「ユーザー目線」で整理する
エラーの種類を分類する
翻訳アプリでは、次のようなエラーが起きます。
- ネットワークエラー
- HTTP エラー
- JSON パースエラー
- API の中身が想定外
- 入力が空
- 言語が同じ
これらをすべて
「ユーザーが理解できる言葉」
に変換します。
例:429(リクエスト過多)
if (response.status === 429) {
throw new Error("リクエストが多すぎます。少し待ってから再試行してください。");
}
JavaScript深掘りポイント
エラーメッセージは、
「技術的に正しい」より「ユーザーに伝わる」ことが大事
です。
翻訳アプリの“完成形”をまとめる
7日目で完成したアプリの特徴
- 言語一覧を API から取得
- 翻訳処理は requestTranslate に一本化
- fetch のエラー処理は requestJson に集約
- ローディング表示は startLoading / endLoading に統一
- 履歴・お気に入りは localStorage に保存
- 自動翻訳(デバウンス)にも対応
- コピー機能で翻訳結果を簡単に利用できる
- UI が読みやすく、コードも読みやすい
これはもう、
「実用的な翻訳アプリ」
です。
今日いちばん深く理解してほしいこと
7日目の本質は、
「API 通信アプリは、fetch・async/await・エラーハンドリングの“型”を作れば、あとは機能を積み上げるだけ」
ということです。
あなたはすでに、
- Datamuse API
- NewsAPI
- LibreTranslate API
という 3 種類の API を扱えるようになりました。
これはつまり、
どんな API でも扱える基礎力が身についた
ということです。
ここから先は、
あなたが作りたいアプリに合わせて、
機能を自由に組み合わせていくだけです。

