---
title: 使用方式
description: 定義錯誤類別、註冊訊息、切換語言、前綴、退回的基本操作。
---

## 基本流程 [#basic-flow]

1. **定義錯誤類別**

    繼承 `I18nErrorBase<TMeta>`，並將用於訊息產生的資訊定義為 `TMeta`。

2. **註冊各語言的訊息**

    使用 `setErrorMessage` 註冊類別與語言對應的訊息。

3. **切換語言並讀取 message**

    透過 `setGlobalConfig({ lang })` 切換，並讀取 `error.message`。

```ts
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-error-class]

`TMeta` 是用於訊息產生的附加資訊。保留於 `error.meta`，並傳遞給註冊函式。

```ts
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" }
```

第二個參數是字串或 `(meta) => string`。第三個參數是與 `Error` 相同的 `{ cause }` 等選項。

```ts
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
```

將 `TMeta` 設為 `undefined` 時可以省略 `meta`。

```ts
class NoMetaError extends I18nErrorBase<undefined> {}

const a = new NoMetaError("no meta");
const b = new NoMetaError(undefined, "no meta");
console.log(a.meta); // undefined
```

:::note
請勿直接 `new`，務必繼承後使用。註冊按類別區分，父類別的註冊不會繼承給子類別。
:::

## 註冊訊息 [#register-message]

`setErrorMessage` 註冊按類別、按語言的產生函式。

```ts
import { I18nErrorBase, setErrorMessage } from "i18n-error-base";

class TestError extends I18nErrorBase<{ code: string }> {}

setErrorMessage(TestError, ({ code }) => `エラーコード: ${code}`, "ja");
setErrorMessage(TestError, "something went wrong", "en");
```

亦可指定字串。語言亦可用陣列指定。

```ts
const message = ({ code }: { code: string }) => `エラーコード: ${code}`;
setErrorMessage(TestError, message, ["ja", "ko", "zh"]);
```

同一類別與同一語言的重新註冊會覆寫。僅在註冊時與參照時的建構函式相同時使用，與 `instanceof` 無關。

:::warning[注意在註冊前存取]
先讀取 `message` 會固定預設值。請在建立執行個體之前完成註冊。
:::

## 切換語言 [#switch-language]

透過 Valibot 的全域設定切換。`message` 在每次讀取時參照目前的 `lang`。

```ts
import { setGlobalConfig } from "valibot";

setGlobalConfig({ lang: "ja" });
console.log(error.message); // 日本語の登録メッセージ

setGlobalConfig({ lang: "en" });
console.log(error.message); // 英語の登録メッセージ or 既定メッセージ
```

未設定 `lang` 時為 `"en"`。未註冊的語言使用建構函式的預設訊息。

```ts
setErrorMessage(BusinessRuleError, () => "日本語メッセージ", "ja");

setGlobalConfig({ lang: "fr" });
console.log(error.message); // "Code: ERR, Limit: 50"（既定メッセージ）
```

## 加上前綴 [#prefix]

`static prefix` 會串接至解析後訊息的開頭。對翻譯訊息與預設訊息皆會生效。

```ts
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"
```

未設定時按原樣回傳。

## 作為 Error 的行為 [#error-behavior]

- `error instanceof Error`、`instanceof I18nErrorBase`、`instanceof 具體類別` 皆為 `true`
- `String(error)` / `error.toString()` 包含解析後的訊息（例如 `"Error: ..."`）
- `cause` 透過 `{ cause }` 保留

## 常見模式 [#common-patterns]

### 在建構函式中固定預設訊息 [#fix-default-message-in-constructor]

```ts
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);
  }
}
```

呼叫端只需傳遞 `meta`，可避免預設文字的重複。

### 批次註冊多種語言 [#register-multiple-languages]

```ts
setErrorMessage(MyError, "エラーが発生しました", ["ja"]);
setErrorMessage(MyError, "An error occurred", ["en", "en-US"]);
```

語言代碼不會正規化。`"en"` 與 `"en-US"` 是不同的鍵，請明確註冊所需的代碼。
