Usage
Basic operations for defining error classes, registering messages, switching languages, prefixes, and fallback.
Basic flow
Define an error class
Extend I18nErrorBase<TMeta> and define info for message generation in TMeta.
Register per-language messages
Register the message for each class and language with setErrorMessage.
Switch languages and read message
Switch with setGlobalConfig({ lang }) and read error.message.
import { setGlobalConfig } from "valibot";
import { I18nErrorBase, setErrorMessage } from "i18n-error-base";
class BusinessRuleError extends I18nErrorBase<{ code: string; limit: number }> {
public constructor(meta: { code: string; limit: number }) {
super(meta, ({ code, limit }) => `Code: ${code}, Limit: ${limit}`);
}
}
setErrorMessage(
BusinessRuleError,
({ code, limit }) => `コード: ${code}、制限: ${limit}`,
"ja",
);
const error = new BusinessRuleError({ code: "ERR", limit: 50 });
setGlobalConfig({ lang: "ja" });
console.log(error.message); // コード: ERR、制限: 50
setGlobalConfig({ lang: "en" });
console.log(error.message); // Code: ERR, Limit: 50
Define an error class
TMeta is auxiliary info for message generation. It is kept in error.meta and passed to registered functions.
import { I18nErrorBase } from "i18n-error-base";
class NotFoundError extends I18nErrorBase<{ resource: string }> {}
const error = new NotFoundError({ resource: "user" }, "fallback message");
console.log(error.meta); // { resource: "user" }
The second argument is a string or a (meta) => string function. The third is { cause } and other Error options.
class TestError extends I18nErrorBase<{ code: string }> {}
const cause = new Error("original");
const error = new TestError({ code: "ERR" }, "something went wrong", { cause });
console.log(error.cause === cause); // true
Setting TMeta to undefined lets you omit meta.
class NoMetaError extends I18nErrorBase<undefined> {}
const a = new NoMetaError("no meta");
const b = new NoMetaError(undefined, "no meta");
console.log(a.meta); // undefined
Register messages
setErrorMessage registers per-class, per-language factory functions.
import { I18nErrorBase, setErrorMessage } from "i18n-error-base";
class TestError extends I18nErrorBase<{ code: string }> {}
setErrorMessage(TestError, ({ code }) => `エラーコード: ${code}`, "ja");
setErrorMessage(TestError, "something went wrong", "en");
Strings are also allowed. Languages can be specified as arrays.
const message = ({ code }: { code: string }) => `エラーコード: ${code}`;
setErrorMessage(TestError, message, ["ja", "ko", "zh"]);
Re-registering the same class and language overwrites. It applies only when the constructors at registration and lookup match, not via instanceof.
Switch languages
Switch with Valibot’s global config. message refers to the current lang on each read.
import { setGlobalConfig } from "valibot";
setGlobalConfig({ lang: "ja" });
console.log(error.message); // 日本語の登録メッセージ
setGlobalConfig({ lang: "en" });
console.log(error.message); // 英語の登録メッセージ or 既定メッセージ
Unset lang is "en". Unregistered languages use the constructor’s default message.
setErrorMessage(BusinessRuleError, () => "日本語メッセージ", "ja");
setGlobalConfig({ lang: "fr" });
console.log(error.message); // "Code: ERR, Limit: 50"(既定メッセージ)
Add a prefix
static prefix is prepended to the resolved message. It applies to both translated and default messages.
class PrefixedError extends I18nErrorBase<{ code: string }> {
static {
this.prefix = "[ERROR] ";
}
}
setErrorMessage(PrefixedError, ({ code }) => `code is ${code}`, "ja");
const error = new PrefixedError({ code: "ERR" }, "fallback");
setGlobalConfig({ lang: "ja" });
console.log(error.message); // "[ERROR] code is ERR"
setGlobalConfig({ lang: "en" });
console.log(error.message); // "[ERROR] fallback"
When unset, it is returned as is.
Behavior as an Error
error instanceof Error,instanceof I18nErrorBase, andinstanceof <concrete class>are alltrueString(error)/error.toString()include the resolved message (e.g."Error: ...")causeis kept via{ cause }
Common patterns
Fix the default message in the constructor
class BusinessRuleError extends I18nErrorBase<{ code: string; limit: number }> {
public constructor(meta: { code: string; limit: number }, options?: ErrorOptions) {
super(meta, ({ code, limit }) => `Code: ${code}, Limit: ${limit}`, options);
}
}
Callers only pass meta, avoiding duplication of the default text.
Register multiple languages at once
setErrorMessage(MyError, "エラーが発生しました", ["ja"]);
setErrorMessage(MyError, "An error occurred", ["en", "en-US"]);
Language codes are not normalized. "en" and "en-US" are separate keys, so register needed codes explicitly.