ethers-i18n GitHub Repository

The Problem

When building dApps with ethers.js, error messages are always in English:

Error: insufficient funds for intrinsic transaction cost

While developers understand these messages, they aren’t user-friendly — especially for non-English-speaking end users. Translating ethers.js error messages manually in every project leads to duplicated effort and inconsistent quality.

ethers-i18n solves this by providing a lightweight i18n plugin for ethers.js error messages.

https://github.com/nakamura196/ethers-i18n

What is ethers-i18n?

ethers-i18n provides localized translations for ethers.js v6 error codes. It currently supports 4 languages: English, Japanese, Korean, and Chinese.

Key features:

  • Simple API — Just setLocale("ja") and t("ERROR_CODE")
  • Non-breaking — Works alongside existing ethers.js code without modifications
  • Type-safe — Full TypeScript support with strict error code typing
  • 4 languages — English, Japanese, Korean, and Chinese
  • Lightweight — Only ethers.js as a peer dependency

Installation

npm install @nakamura196/ethers-i18n

Requires ethers.js v6 as a peer dependency.

Basic Usage

Setting Locale and Translating

import { setLocale, t, getSupportedLocales } from "@nakamura196/ethers-i18n";

// Check available locales
console.log(getSupportedLocales()); // ["en", "ja", "ko", "zh"]

// Set to Japanese
setLocale("ja");

// Translate error codes
console.log(t("INVALID_ARGUMENT"));    // "無効な引数です"
console.log(t("INSUFFICIENT_FUNDS"));  // "トランザクションに必要な残高が不足しています"
console.log(t("NETWORK_ERROR"));       // "ネットワークエラーが発生しました"

Translating Error Objects

Translate ethers.js error objects directly:

import { setLocale } from "@nakamura196/ethers-i18n";
import { translateError } from "@nakamura196/ethers-i18n/wrapper";

setLocale("ja");

try {
  await provider.getBalance("invalid-address");
} catch (error) {
  // Automatically detects the ethers.js error code and translates
  const message = translateError(error);
  console.log(message); // "無効な引数です"
}

The withI18n Wrapper

Wrap async functions to automatically translate errors:

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 is already translated
  console.log(error.message); // "無効な引数です"

  // Original message is preserved
  console.log(error.originalMessage); // "invalid argument"
}

The advantage of withI18n is that it throws translated errors, so upstream error handlers can use the localized messages directly.

Supported Error Codes

ethers-i18n covers 17 major ethers.js v6 error codes:

Error CodeEnglishJapanese
INVALID_ARGUMENTinvalid argument無効な引数です
MISSING_ARGUMENTmissing argument引数が不足しています
UNEXPECTED_ARGUMENTunexpected argument予期しない引数です
CALL_EXCEPTIONcall exceptionコントラクト呼び出しに失敗しました
INSUFFICIENT_FUNDSinsufficient fundsトランザクションに必要な残高が不足しています
NETWORK_ERRORnetwork errorネットワークエラーが発生しました
SERVER_ERRORserver errorサーバーエラーが発生しました
TIMEOUTtimeoutタイムアウトしました
BUFFER_OVERRUNbuffer overrunバッファオーバーランが発生しました
NUMERIC_FAULTnumeric fault数値演算エラーが発生しました
ACTION_REJECTEDaction rejectedユーザーによって操作が拒否されました
NONCE_EXPIREDnonce expiredノンスは既に使用されています
REPLACEMENT_UNDERPRICEDreplacement fee too low置換手数料が低すぎます
TRANSACTION_REPLACEDtransaction replacedトランザクションが置換されました
UNPREDICTABLE_GAS_LIMITcannot estimate gasガスリミットを推定できません
UNSUPPORTED_OPERATIONunsupported operationサポートされていない操作です
UNKNOWN_ERRORunknown error不明なエラーが発生しました

Design Decisions

Why a Separate Library?

In dApp projects, error message translation is typically handled on a per-project basis. However, since ethers.js error codes are part of a fixed specification, translations can be shared.

By providing this as a library:

  1. No reinventing the wheel — Avoid writing the same translations in every project
  2. Better translation quality — Community review and improvement
  3. Type safety — Catch error code typos at compile time

Simple API

// Configure in one line
setLocale("ja");

// Translate in one line
const msg = t("INVALID_ARGUMENT");

No complex configuration needed. By focusing on the narrow scope of ethers.js error codes, the API stays minimal and intuitive.

Fallback Mechanism

When a translation is missing, the fallback locale (default: English) is used:

import { configure } from "@nakamura196/ethers-i18n";

configure({
  locale: "ja",
  fallback: "en", // Falls back to English when Japanese translation is missing
});

Adding a New Language

Adding a new language is straightforward — just create one locale file:

// 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",
  // ... define all error codes
};

The LocaleMessages type ensures all error codes must be defined, preventing missed translations at compile time.

Use Cases

1. dApp Error Display

// React example
import { setLocale } from "@nakamura196/ethers-i18n";
import { translateError } from "@nakamura196/ethers-i18n/wrapper";

function App() {
  // Set locale based on browser language
  useEffect(() => {
    const lang = navigator.language.startsWith("ja") ? "ja" : "en";
    setLocale(lang);
  }, []);

  const handleTransaction = async () => {
    try {
      await contract.transfer(to, amount);
    } catch (error) {
      // Show user-friendly localized message
      toast.error(translateError(error));
    }
  };
}

2. CLI Tool Error Messages

import { setLocale } from "@nakamura196/ethers-i18n";
import { withI18n } from "@nakamura196/ethers-i18n/wrapper";

// Control locale via environment variable
setLocale(process.env.LANG?.startsWith("ja") ? "ja" : "en");

const balance = await withI18n(() => provider.getBalance(address));

Future Plans

  • More languages — French, Spanish, German, and more
  • Custom message overrides — Allow projects to override translations
  • viem support — Extend beyond ethers.js to support viem error messages

Contributions are welcome! We especially appreciate PRs for new language translations.

Conclusion

ethers-i18n is a lightweight plugin that brings multilingual support to ethers.js error messages. With a simple API and TypeScript type safety, it integrates easily into existing projects and helps prevent translation gaps.

Give it a try to improve your dApp’s UX for a global audience.

https://github.com/nakamura196/ethers-i18n