> ## Documentation Index
> Fetch the complete documentation index at: https://sonamu.cartanova.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Helper Functions

> i18n utilities: josa, plural, format, and more

Sonamu provides helper functions to assist with writing multilingual messages.

## josa - Korean Particle Handling

The `josa()` function selects the appropriate Korean particle based on whether the preceding word ends with a consonant (batchim):

```typescript theme={null}
import { josa } from "sonamu/dict";

josa("사람", "은는"); // "사람은"
josa("나", "은는"); // "나는"

josa("물", "이가"); // "물이"
josa("바다", "이가"); // "바다가"

josa("밥", "을를"); // "밥을"
josa("커피", "을를"); // "커피를"

josa("빵", "과와"); // "빵과"
josa("우유", "과와"); // "우유와"

josa("집", "으로"); // "집으로"
josa("학교", "으로"); // "학교로"
```

### Supported Particles

| Particle | With final consonant | Without final consonant |
| -------- | -------------------- | ----------------------- |
| `은는`     | 은                    | 는                       |
| `이가`     | 이                    | 가                       |
| `을를`     | 을                    | 를                       |
| `과와`     | 과                    | 와                       |
| `으로`     | 으로                   | 로                       |

### Using in Dictionary

```typescript theme={null}
// ko.ts
import { josa } from "sonamu/dict";

export default {
  "validation.required": (field: string) => `${josa(field, "은는")} 필수입니다`,
  "validation.duplicate": (field: string) => `이미 사용중인 ${josa(field, "이가")} 있습니다`,
  "error.notFound": (name: string) => `${josa(name, "을를")} 찾을 수 없습니다`,
} as const;

// Usage
SD("validation.required")("이메일"); // "이메일은 필수입니다"
SD("validation.required")("이름"); // "이름은 필수입니다"
```

## plural - Pluralization Handling

The `plural()` function returns different text based on the number:

```typescript theme={null}
import { plural } from "sonamu/dict";

plural(0, { zero: "none", one: "1 item", other: "multiple items" }); // "none"
plural(1, { zero: "none", one: "1 item", other: "multiple items" }); // "1 item"
plural(5, { zero: "none", one: "1 item", other: "multiple items" }); // "multiple items"

// Using a function for other
plural(5, { other: (n) => `${n} items` }); // "5 items"

// Falls back to other if zero or one is not defined
plural(0, { other: "default" }); // "default"
plural(1, { other: "default" }); // "default"
```

### Options

| Option  | Condition | Description             |
| ------- | --------- | ----------------------- |
| `zero`  | n === 0   | Text when count is 0    |
| `one`   | n === 1   | Text when count is 1    |
| `other` | otherwise | Default text (required) |

### Using in Dictionary

```typescript theme={null}
// ko.ts
import { plural } from "sonamu/dict";

export default {
  "items.count": (count: number) =>
    plural(count, {
      zero: "항목이 없습니다",
      one: "1개 항목",
      other: (n) => `${n}개 항목`,
    }),

  "cart.items": (count: number) =>
    plural(count, {
      zero: "장바구니가 비어있습니다",
      other: (n) => `장바구니에 ${n}개 상품`,
    }),
} as const;
```

## createFormat - Number/Date Formatting

The `createFormat()` function creates number and date formatters for a specific locale:

```typescript theme={null}
import { createFormat } from "sonamu/dict";

const format = createFormat("ko");

format.number(1234567); // "1,234,567"
format.date(new Date("2024-01-15")); // "2024. 1. 15."

const enFormat = createFormat("en");
enFormat.number(1234567); // "1,234,567"
enFormat.date(new Date("2024-01-15")); // "1/15/2024"
```

### Using in Dictionary

```typescript theme={null}
// ko.ts
import { createFormat } from "sonamu/dict";

const format = createFormat("ko");

export default {
  "price.display": (price: number) => `${format.number(price)}원`,
  "date.created": (date: Date) => `${format.date(date)} 등록`,
  "validation.range": (field: string, min: number, max: number) =>
    `${field}은(는) ${format.number(min)}~${format.number(max)} 사이여야 합니다`,
} as const;
```

## Combining Multiple Helpers

Complex messages can be written by combining multiple helpers:

```typescript theme={null}
// ko.ts
import { createFormat, josa, plural } from "sonamu/dict";

const format = createFormat("ko");

export default {
  // josa + plural
  "search.results": (keyword: string, count: number) =>
    `'${keyword}'${josa(keyword, "으로")} 검색한 결과 ` +
    plural(count, {
      zero: "없음",
      other: (n) => `${format.number(n)}건`,
    }),

  // format + josa
  "order.total": (itemCount: number, total: number) =>
    `${itemCount}개 상품, 총 ${format.number(total)}원`,

  // Complex message
  "dashboard.summary": (userName: string, taskCount: number, date: Date) =>
    `${userName}님, ${format.date(date)} 기준 ` +
    plural(taskCount, {
      zero: "처리할 작업이 없습니다",
      one: "1개의 작업이 대기 중입니다",
      other: (n) => `${n}개의 작업이 대기 중입니다`,
    }),
} as const;
```

<CardGroup cols={2}>
  <Card title="Using the SD Function" icon="code" href="/en/advanced-features/i18n/dictionary">
    Writing and using dictionaries
  </Card>

  <Card title="Localized Columns" icon="database" href="/en/advanced-features/i18n/localized-columns">
    Multilingual DB column support
  </Card>
</CardGroup>
