
はじめに
ethers.jsを使ったdApp開発で、こんな経験はありませんか?
Error: insufficient funds for intrinsic transaction cost
エラーの意味は分かるけれど、このメッセージをそのままエンドユーザーに見せるわけにはいきません。特に日本語圏のユーザー向けサービスでは、エラーメッセージの日本語化は避けて通れない課題です。
そこで、ethers.jsのエラーメッセージを多言語化するライブラリ ethers-i18n を作りました。
https://github.com/nakamura196/ethers-i18n
ethers-i18nとは
ethers-i18nは、ethers.js v6のエラーコードに対応した翻訳メッセージを提供するi18nプラグインです。
主な特徴:
- シンプルなAPI —
setLocale("ja")とt("ERROR_CODE")だけで使える - 非破壊的 — 既存のethers.jsコードに影響を与えない
- 型安全 — TypeScriptの型定義を完備
- 4言語対応 — 英語・日本語・韓国語・中国語をサポート
- 軽量 — 依存関係はethers.jsのみ(peerDependency)
インストール
npm install @nakamura196/ethers-i18n
ethers.js v6がpeerDependencyとして必要です。
基本的な使い方
ロケールの設定と翻訳
import { setLocale, t, getLocale, getSupportedLocales } from "@nakamura196/ethers-i18n";
// サポートされているロケール一覧
console.log(getSupportedLocales()); // ["en", "ja", "ko", "zh"]
// 日本語に設定
setLocale("ja");
console.log(getLocale()); // "ja"
// エラーコードを翻訳
console.log(t("INVALID_ARGUMENT")); // "無効な引数です"
console.log(t("INSUFFICIENT_FUNDS")); // "トランザクションに必要な残高が不足しています"
console.log(t("NETWORK_ERROR")); // "ネットワークエラーが発生しました"
エラーオブジェクトの翻訳
ethers.jsが投げるエラーオブジェクトをそのまま翻訳できます。
import { setLocale } from "@nakamura196/ethers-i18n";
import { translateError } from "@nakamura196/ethers-i18n/wrapper";
setLocale("ja");
try {
// ethers.jsの操作(例:不正なアドレスでの送金)
await provider.getBalance("invalid-address");
} catch (error) {
// ethers.jsのエラーコードを自動検出して翻訳
const message = translateError(error);
console.log(message); // "無効な引数です"
}
withI18nラッパー
非同期関数をラップして、エラーメッセージを自動的に翻訳することもできます。
import { setLocale } from "@nakamura196/ethers-i18n";
import { withI18n } from "@nakamura196/ethers-i18n/wrapper";
setLocale("ja");
try {
const balance = await withI18n(() => provider.getBalance("invalid-address"));
} catch (error) {
// error.message は翻訳済み
console.log(error.message); // "無効な引数です"
// 元のメッセージも保持されている
console.log(error.originalMessage); // "invalid argument"
}
withI18nの利点は、翻訳されたエラーをthrowしてくれるため、上位のエラーハンドリングでそのまま多言語メッセージを利用できることです。
対応エラーコード一覧
ethers.js v6の主要なエラーコード17種に対応しています。
| エラーコード | 英語 | 日本語 |
|---|---|---|
INVALID_ARGUMENT | invalid argument | 無効な引数です |
MISSING_ARGUMENT | missing argument | 引数が不足しています |
UNEXPECTED_ARGUMENT | unexpected argument | 予期しない引数です |
CALL_EXCEPTION | call exception | コントラクト呼び出しに失敗しました |
INSUFFICIENT_FUNDS | insufficient funds | トランザクションに必要な残高が不足しています |
NETWORK_ERROR | network error | ネットワークエラーが発生しました |
SERVER_ERROR | server error | サーバーエラーが発生しました |
TIMEOUT | timeout | タイムアウトしました |
BUFFER_OVERRUN | buffer overrun | バッファオーバーランが発生しました |
NUMERIC_FAULT | numeric fault | 数値演算エラーが発生しました |
ACTION_REJECTED | action rejected | ユーザーによって操作が拒否されました |
NONCE_EXPIRED | nonce expired | ノンスは既に使用されています |
REPLACEMENT_UNDERPRICED | replacement fee too low | 置換手数料が低すぎます |
TRANSACTION_REPLACED | transaction replaced | トランザクションが置換されました |
UNPREDICTABLE_GAS_LIMIT | cannot estimate gas | ガスリミットを推定できません |
UNSUPPORTED_OPERATION | unsupported operation | サポートされていない操作です |
UNKNOWN_ERROR | unknown error | 不明なエラーが発生しました |
設計思想
なぜライブラリとして切り出したのか
dApp開発ではエラーメッセージの翻訳は各プロジェクトで個別に対応しがちです。しかし、ethers.jsのエラーコードは仕様として固定されているため、翻訳を共通化できます。
ライブラリとして提供することで:
- 車輪の再発明を防ぐ — 各プロジェクトで同じ翻訳を書く必要がない
- 翻訳品質の向上 — コミュニティで翻訳をレビュー・改善できる
- 型安全性 — エラーコードのtypoをコンパイル時に検出できる
シンプルなAPI設計
// 設定は1行
setLocale("ja");
// 翻訳も1行
const msg = t("INVALID_ARGUMENT");
i18nライブラリにありがちな複雑な設定は不要です。ethers.jsのエラーコードという限定されたスコープに特化することで、APIをシンプルに保っています。
フォールバック機構
翻訳が見つからない場合は、フォールバックロケール(デフォルト: 英語)が使われます。
import { configure } from "@nakamura196/ethers-i18n";
configure({
locale: "ja",
fallback: "en", // 日本語訳がない場合は英語にフォールバック
});
新しい言語を追加する
新しい言語の追加は非常に簡単です。ロケールファイルを1つ作成するだけです。
// src/locales/fr.ts
import { LocaleMessages } from "../types";
export const fr: LocaleMessages = {
INVALID_ARGUMENT: "argument invalide",
MISSING_ARGUMENT: "argument manquant",
UNEXPECTED_ARGUMENT: "argument inattendu",
CALL_EXCEPTION: "exception d'appel de contrat",
INSUFFICIENT_FUNDS: "fonds insuffisants pour la transaction",
// ... 残りのエラーコードも定義
};
LocaleMessages型により、すべてのエラーコードを漏れなく定義する必要があるため、翻訳の抜け漏れを防げます。
ユースケース
1. dAppのエラー表示
// React での使用例
import { setLocale } from "@nakamura196/ethers-i18n";
import { translateError } from "@nakamura196/ethers-i18n/wrapper";
function App() {
// ブラウザの言語設定に応じてロケールを切り替え
useEffect(() => {
const lang = navigator.language.startsWith("ja") ? "ja" : "en";
setLocale(lang);
}, []);
const handleTransaction = async () => {
try {
await contract.transfer(to, amount);
} catch (error) {
// ユーザーに分かりやすいメッセージを表示
toast.error(translateError(error));
}
};
}
2. CLIツールのエラーメッセージ
import { setLocale } from "@nakamura196/ethers-i18n";
import { withI18n } from "@nakamura196/ethers-i18n/wrapper";
// 環境変数でロケールを制御
setLocale(process.env.LANG?.startsWith("ja") ? "ja" : "en");
const balance = await withI18n(() => provider.getBalance(address));
今後の展望
- 対応言語の拡充 — フランス語、スペイン語、ドイツ語などの追加
- エラーメッセージのカスタマイズ — プロジェクト固有のメッセージで上書きする機能
- viem対応 — ethers.jsだけでなくviemのエラーメッセージにも対応
コントリビューションは大歓迎です!特に各言語の翻訳についてPRをお待ちしています。
まとめ
ethers-i18nは、ethers.jsのエラーメッセージを多言語化するための軽量なプラグインです。シンプルなAPIで既存のコードに簡単に組み込め、TypeScriptの型安全性により翻訳の抜け漏れも防げます。
dAppのUX向上に、ぜひお試しください。