# General Translation Knowledge Base: React で複数形を扱うには？
URL: https://generaltranslation.com/ja/kb/how-to-handle-plurals-in-react.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: n === 1 のような条件分岐で複数形の選択ロジックをハードコードするのは避けましょう。英語のみのアプリなら小さなヘルパーで十分ですが、多言語アプリではロケール対応の複数形規則が必要になります。gt-react や gt-next の `<Plural>` のような i18n コンポーネントを使えば、あらゆる言語の複数形に対応できます。
Category: ロケール別フォーマット
Last updated: 2025-02-17
Authors: Archie McKenzie
Published: 2025-02-17

## Video

The video is narrated in English, with English captions.

[How do I handle plurals in React?](https://caxecubb9c64cezv.public.blob.vercel-storage.com/films/kb-how-to-handle-plurals-in-react.mp4) (48 秒)

General Translation handles plurals in React with the `Plural` component. Run `npx gt init` and sign in, give `Plural` the count and an English sentence for each form, wrap it in a `T` component with the count in `Num`, then run `npx gt translate` to write the forms each language needs.

## React で複数形処理が重要な理由

次のような不自然なメッセージを表示するアプリをよく見かけます：

```text
1件の新しいメッセージ（複数）があります
```

これは、ユーザー体験を十分に考えていない開発者にありがちな、典型的な兆候です。

React アプリでは、通知件数やリストの長さ、検索結果などで複数形処理が必要になることがよくあります。
**とはいえ、複数形処理を正しく行うのはそれほど難しくありません。アプリが英語だけで済むなら、なおさらです。**
しかし、経験の浅い開発者が陥りがちな悪いやり方も数多くあり、多言語インターフェースを構築する場合は特にその傾向が強くなります。

このガイドでは、英語の複数形をすっきりと扱う方法、ロケールごとに数値を書式設定する方法、そして React と Next.js で完全な多言語対応の複数形処理の仕組みを構築する方法を解説します。

### 複数形をハードコードすることの問題点

驚くほど大規模で重要なものも含め、多くのプロジェクトが複数形の選択ロジックをハードコードしています。

```jsx
export default function Example({ n }) {
  return (
    <p>
      Displaying {n} item{n === 1 ? '' : 's'}
    </p>
  )
}
```

しかし、複数形処理は単語の末尾に「s」を付けるだけで済むほど単純でないことが多々あります。
「child」と「children」のように、不規則な複数形を持つ名詞もあります。
また、名詞に合わせて文の他の部分も変える必要がある場合もあります。たとえば、
数に応じて「is」と「are」を使い分けるといったケースです。

以下の表は、よくあるシナリオの例です。

| シナリオ    | 例                                                                                           | メモ                                                              |
| ------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| 視聴者数    | &quot;1 person is watching&quot; <br /> &quot;2 people are watching&quot;                   | 不規則名詞 (&quot;person&quot; → &quot;people&quot;) と動詞の変化が必要です。    |
| アイテムの削除 | &quot;Delete this message?&quot; <br /> &quot;Delete these 2 messages?&quot;                | 指示詞の変化 (&quot;this&quot; と &quot;these&quot;) に加えて名詞の複数形処理が必要です。 |
| 検索結果    | &quot;No results&quot; <br /> &quot;1 result found&quot; <br /> &quot;2 results found&quot; | 0件、1件、複数件でそれぞれ異なる表現になります。                                       |

条件式で対応しようとすると、すぐに手に負えなくなります。

さらに、アプリを他の言語でもリリースするとなると、まさに悪夢です。
英語ではうまくいく方法も、数量の扱いにまったく異なるルールを持つポーランド語やアラビア語などでは、完全に破綻してしまうことがよくあります。
**私たちが支援している企業の多くは、このようなハードコードされた UI をリファクタリングする負担から、
国際化を後回しにしがちです。**

***

## 英語で複数形を扱う方法

英語の場合、アプリで複数形を正しく使い分けるのは、たいていそれほど難しくありません。

単純な名詞の複数形処理であれば、次のようなユーティリティ関数を作成します:

```jsx
export function pluralize(
  count: number,
  singular: string,
  plural: string = singular + 's'
) {
  return `${count === 1 ? singular : plural}`;
}
```

これで、複数形の選択ロジックをすべて1つの関数で処理できるようになりました。
不規則な複数形にも対応しています。

```js
pluralize(2, 'user') // "users"
pluralize(2, 'person', 'people') // "people"
pluralize(2, 'child', 'children') // "children"
```

では、次のような、より複雑なロジックが必要な場合はどうすればよいでしょうか。

```text
"No one is watching"
"1 person is watching"
"2 people are watching"
```

この段階で、メンテナンスの手間が少ない国際化 (&quot;i18n&quot;) ライブラリの導入を真剣に検討すべきです。

i18nライブラリは多言語インターフェース専用のものだと考える開発者は多いですが、
単一言語のアプリケーションでも、複数形や変数のフォーマットに大いに役立ちます。
ほとんどのi18nライブラリは、内部でJavaScript組み込みの `Intl.PluralRules` APIを使用し、あらゆる言語で正しい複数形を判定しています。

React向けのi18nライブラリは数多くあり、私たちの [`gt-react`](/docs/react/overview) (Next.jsを使用している場合は [`gt-next`](/docs/react/nextjs-quickstart)) もその一つです。
gt-reactを使えば、英語の複数形を簡単に表示できます。

```jsx
import { Plural } from 'gt-react'

function Example({ count }) {
  return (
    <Plural n={count} zero={'No one is watching'} one={`${count} person is watching`}>
      {count} people are watching
    </Plural>
  )
}
```

UI は `n` の値に応じて条件付きでレンダリングされます。

ほとんどのライブラリは、JavaScript の [`Intl.PluralRules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules) API を使って、どの複数形を表示するかを決定します。
つまり英語の場合、単数には `"one"`、複数には `"other"` という名前を使います。
GT の [`<Plural>`](/docs/react/reference/components/plural) コンポーネントは、まず該当する複数形カテゴリを厳密に確認し、次に汎用の `plural` および `other` props を確認します。これらの props がいずれも指定されていない場合にのみ、子要素にフォールバックします。

英語のみのアプリケーションであっても、ここではライブラリを使うのがベストプラクティスです。そうしておけば、将来の国際化対応もずっと容易になります。

***

## 多言語Reactアプリ (i18n) における複数形処理

アプリが英語圏のユーザーだけを対象としているなら、上記のアプローチで十分かもしれません。しかし、本番環境で運用されるアプリの多くは、いずれ複数の言語に対応する必要が出てきます。ここからが本題です。

* アラビア語では、名詞の形が0個、1個、2個、それ以上のいずれであるかによって変化します
* `de-DE`、`es-ES`、`it-IT` などのロケールでは、大きな数値の桁区切りにカンマではなくピリオドを使うため、1,000,000は1.000.000になります
* ヒンディー語では数字が2桁ずつ区切られるため、1,000,000は10,00,000になります

**国際化対応のアプリでは、専用のi18nライブラリを使用してください。** 複数形や数値フォーマットの扱い方については、各ライブラリのドキュメントを参照してください。

### ロケールに応じた数値のフォーマット

`Intl` オブジェクトを使うと、任意のロケールに合わせて[数値を書式設定](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat)できます。
最も簡単なのは、組み込みの `toLocaleString()` メソッドを使う方法です。

デフォルトでは、ランタイムの現在のロケールが使用されます。

```javascript
const n = 1000000
n.toLocaleString() // ランタイムのロケールが "en-US"（アメリカ英語）の場合、1,000,000 と表示されます
n.toLocaleString('de') // ロケールに "de"（ドイツ語）が指定されているため、1.000.000 と表示されます
```

gt-react には、内部で `Intl.NumberFormat` を利用する [`<Num>`](/docs/react/reference/components/num) コンポーネントも用意されています。

```jsx
import { Num } from 'gt-react'

// 言語が "en-US" の場合は 1,000,000 と表示される
// 言語が "de" の場合は 1.000.000 と表示される
// 言語が "hi" の場合は 10,00,000 と表示される
export default function Example() {
  return <Num>1000000</Num>
}
```

### 言語による複数形の違いを理解する

JavaScript の `Intl.PluralRules` API がサポートする複数形は、`zero`、`one`、`two`、`few`、`many`、`other` の6つです。
英語で使われるのは `one` (「単数」) と `other` (「複数」) だけですが、
アラビア語やポーランド語などの言語には、この2つ以外の形もあります。

たとえば、英語を話すユーザーは次のような表示を想定しているでしょう。

```text
"No one is watching"
"1 person is watching"
"2 people are watching"
```

一方、アラビア語を話すユーザーは、単数形、
双数形 (数がちょうど2の場合) 、さらに少数用と多数用の複数形で、それぞれ異なる表現が使われることを期待するでしょう。

```text
"لا أحد يشاهد"
"1 شخص يشاهد"
"2 شخصان يشاهدان"
"3 أشخاص يشاهدون"
"11 شخصاً يشاهدون"
```

そこで欠かせないのが国際化ライブラリです。
複数形をいつ、どのように表示するかのロジックは言語ごとに異なるため、
正しく処理するには専用のライブラリに任せるのが得策です。

優れたi18nライブラリは、次の2つを行います。

1. ロケールに応じて、使用する複数形 (`one`、`many`、`other` など) を判定する
2. その形に対応する、適切な言語の翻訳を取得する

**すでに国際化ライブラリを使用している場合は、
複数形のフォーマットについてそのライブラリのドキュメントを確認してください。**
ほぼすべてのライブラリに、複数形のレンダリングに関する専用のドキュメントが用意されています。

### 完全な例: 多言語 React アプリでの複数形

まだ国際化ライブラリを導入していない場合は、[`gt-react`](/docs/react/react-quickstart) をぜひご検討ください！

gt-react の [`<Plural>`](/docs/react/reference/components/plural) コンポーネントには、次のような特長があります。

* React で複数形を正しくレンダリングできる、シンプルで宣言的な手段です
* [`<Num>`](/docs/react/reference/components/num) フォーマットコンポーネントとネイティブに連携します
* [`<T>`](/docs/react/reference/components/t) 翻訳コンポーネントともネイティブに連携します。`<T>` は当社の[翻訳サービス](https://generaltranslation.com)と統合されており、複数形を自動生成します

これらの要素をすべて組み合わせると、多言語対応のコンポーネントは次のようになります。

```jsx
import { T, Plural, Num } from 'gt-react'

// 追加設定なしで100以上の言語に対応
function Example({ count }) {
  return (
    <T>
      <Plural
        n={count}
        zero={'No one is watching'}
        one={
          <>
            <Num>{count}</Num> person is watching
          </>
        }
      >
        <Num>{count}</Num> people are watching
      </Plural>
    </T>
  )
}
```

***

複数形処理のセットアップについては、React アプリの場合は [`gt-react` クイックスタート](/docs/react/react-quickstart)、Next.js アプリの場合は [`gt-next` クイックスタート](/docs/react/nextjs-quickstart) を参照してください。コンポーネント API の全容は [`<Plural>` API リファレンス](/docs/react/reference/components/plural) をご覧ください。

複数形処理は、React の i18n で特によく直面する課題の一つです。最初から正しく実装しておけば、後になって大がかりなリファクタリングをせずに済みます。

## Related questions

- [JSX 内の条件付きテキストはどう翻訳すればよいですか？](https://generaltranslation.com/ja/kb/translate-conditional-jsx.mdx): 三項演算子の各分岐を個別に翻訳するのではなく、文全体を `<T>` コンポーネントでラップし、条件を `<Branch>` で表現しましょう。こうすることで翻訳者が文脈全体を把握でき、言語ごとに語順を組み替えられます。
- [翻訳ファイルなしで i18n はできますか？](https://generaltranslation.com/ja/kb/i18n-without-translation-files.mdx): はい。gt-react または gt-next を使えば、コンテンツは `<T>` コンポーネントで囲んだままコンポーネント内にインラインで記述でき、翻訳はビルド時に出力として生成されます。そのため、キーやロケールごとの JSON ファイルを作成したり、同期を保ったりする必要はありません。
- [多言語アプリをローンチする前に何を確認すべきか？](https://generaltranslation.com/ja/kb/multilingual-app-launch-checklist.mdx): 多言語アプリをローンチする前に、サポート対象のすべてのロケールで次の9項目をテストしてください：エラー時を含むユーザージャーニー全体、言語検出と言語の切り替え、変数と複数形、通貨とタイムゾーン、テキストの伸長、右から左のレイアウト、アクセシビリティ、本番環境での翻訳の配信、SEOのためのクロール可能な言語別URL。各項目には明確な合格条件が必要です。

## Previous and next questions

- Next question: [JSX 内の条件付きテキストはどう翻訳すればよいですか？](https://generaltranslation.com/ja/kb/translate-conditional-jsx.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/ja/kb/sitemap.md) for every article.
