# General Translation Knowledge Base: Как работать с формами множественного числа в React?
URL: https://generaltranslation.com/ru/kb/how-to-handle-plurals-in-react.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Не зашивайте логику выбора формы множественного числа в код с помощью проверок вроде n === 1. Для приложений только на английском хватит небольшой вспомогательной функции, но многоязычным приложениям нужны locale-aware правила множественного числа. С ними для любого языка справляется i18n-компонент, например `<Plural>` из gt-react или gt-next.
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» в конец слова.
У некоторых существительных неправильные формы множественного числа, например &quot;child&quot; и &quot;children&quot;.
Иногда вслед за существительным должны меняться и другие части предложения — например,
&quot;is&quot; и &quot;are&quot; в зависимости от количества.

В таблице ниже приведены несколько типичных сценариев:

| Сценарий           | Примеры                                                                                     | Заметка                                                                                                                      |
| ------------------ | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Число зрителей     | &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; | Разные формулировки для нуля, одного и нескольких результатов.                                                               |

Условные выражения быстро становятся громоздкими.

А когда приложение нужно выпустить на других языках, всё превращается в настоящий кошмар.
То, что работает в английском, часто полностью ломается в таких языках, как польский или арабский, где количество выражается по совершенно другим правилам.
**Компании, с которыми мы работаем, часто откладывают интернационализацию,
потому что рефакторить подобный жёстко закодированный UI слишком болезненно.**

***

## Как работать с формами множественного числа в английском языке

В английском языке правильно использовать формы множественного числа в приложении обычно несложно.

Для простой обработки форм множественного числа существительных достаточно написать вспомогательную функцию:

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

Теперь для всей логики выбора формы множественного числа достаточно одной функции,
и она справляется даже с неправильными формами множественного числа:

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

На этом этапе стоит всерьёз задуматься о библиотеке интернационализации («i18n»), которая не требует больших усилий на поддержку.

Хотя разработчики часто считают, что библиотеки интернационализации нужны только для многоязычных интерфейсов,
они очень полезны для форматирования множественного числа и переменных даже в одноязычных приложениях.
Под капотом большинство библиотек интернационализации используют встроенный в JavaScript API `Intl.PluralRules`, чтобы определить правильную форму множественного числа для любого языка.

Для React существует множество библиотек интернационализации, в том числе и наша — [`gt-react`](/docs/react/overview) (или [`gt-next`](/docs/react/nextjs-quickstart), если вы используете Next.js).
Вывести английское множественное число с помощью 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`.

Большинство библиотек используют API JavaScript [`Intl.PluralRules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules), чтобы определить, какую форму множественного числа отобразить.
Это значит, что в английском языке для единственного числа используется имя `"one"`, а для множественного — `"other"`.
Наш компонент [`<Plural>`](/docs/react/reference/components/plural) сначала проверяет точную категорию множественного числа, а затем — общие пропсы `plural` и `other`. К дочерним элементам он обращается, только если ни один из этих пропсов не задан.

Использовать здесь библиотеку рекомендуется даже в приложениях, работающих только на английском: это значительно упростит интернационализацию в будущем.

***

## Обработка форм множественного числа в многоязычных React-приложениях (i18n)

Если ваше приложение рассчитано только на англоязычных пользователей, описанного выше подхода может быть вполне достаточно. Однако большинству приложений в рабочей среде рано или поздно требуется поддержка нескольких языков. Вот тут-то и начинается самое интересное.

* В арабском языке форма существительного зависит от количества предметов: ноль, один, два или много
* В таких локалях, как `de-DE`, `es-ES` и `it-IT`, разряды больших чисел разделяются точками, а не запятыми, поэтому 1,000,000 превращается в 1.000.000
* В хинди цифры группируются парами, поэтому 1,000,000 записывается как 10,00,000

**Для интернационализированного приложения следует использовать специализированную библиотеку интернационализации**: в её документации описано, как работать с формами множественного числа и форматированием чисел.

### Форматирование чисел для разных локалей

С помощью объекта `Intl` можно [форматировать числа](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) для любой локали.
Проще всего это сделать встроенным методом `toLocaleString()`.

По умолчанию он использует текущую локаль среды выполнения:

```javascript
const n = 1000000
n.toLocaleString() // выводит 1,000,000, если локаль среды выполнения — "en-US" (американский английский)
n.toLocaleString('de') // 1.000.000, поскольку явно указана локаль "de" (немецкий)
```

gt-react также предоставляет компонент [`<Num>`](/docs/react/reference/components/num), который под капотом использует `Intl.NumberFormat`.

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

// отображает 1,000,000, если выбран язык "en-US"
// отображает 1.000.000, если выбран язык "de"
// отображает 10,00,000, если выбран язык "hi"
export default function Example() {
  return <Num>1000000</Num>
}
```

### Формы множественного числа в разных языках

API `Intl.PluralRules` в JavaScript поддерживает шесть форм множественного числа: `zero`, `one`, `two`, `few`, `many`, `other`.
В английском используются только `one` («единственное число») и `other` («множественное число»),
но в таких языках, как арабский и польский, форм больше двух.

Например, англоязычный пользователь ожидает увидеть:

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

А вот арабоязычный пользователь может ожидать разных формулировок для единственного числа,
двойственного числа (когда предметов ровно два), а также для малой и большой форм множественного числа:

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

Именно здесь без библиотеки интернационализации не обойтись.
В каждом языке свои правила того, когда и как использовать формы множественного числа,
поэтому лучше доверить эту задачу специализированной библиотеке.

Хорошая библиотека интернационализации решает две задачи:

1. Определяет, какую форму множественного числа (`one`, `many`, `other` и т. д.) использовать в зависимости от локали
2. Находит перевод на нужном языке, соответствующий этой форме

**Если вы уже используете библиотеку интернационализации,
загляните в её документацию: там должен быть раздел о форматировании форм множественного числа.**
Почти у всех библиотек есть отдельная документация по рендерингу форм множественного числа.

### Полный пример: формы множественного числа в многоязычном React-приложении

Если у вас ещё нет библиотеки интернационализации, обратите внимание на [`gt-react`](/docs/react/react-quickstart)!

Компонент [`<Plural>`](/docs/react/reference/components/plural) из gt-react:

* Позволяет просто и декларативно выполнять корректный рендеринг форм множественного числа в React
* Нативно работает с компонентом форматирования [`<Num>`](/docs/react/reference/components/num)
* Нативно работает с компонентом перевода [`<T>`](/docs/react/reference/components/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>
  )
}
```

***

Настройте обработку форм множественного числа по руководству [«Быстрый старт» для `gt-react`](/docs/react/react-quickstart) для приложений React или [«Быстрый старт» для `gt-next`](/docs/react/nextjs-quickstart) для приложений Next.js. Полное описание API компонента см. в [справочнике API `<Plural>`](/docs/react/reference/components/plural).

Обработка форм множественного числа — одна из самых распространённых задач i18n в React. Если реализовать её правильно с самого начала, в дальнейшем вы избежите масштабного рефакторинга.

## Related questions

- [Как перевести условный текст в JSX?](https://generaltranslation.com/ru/kb/translate-conditional-jsx.mdx): Не переводите каждую ветвь тернарного оператора по отдельности — оберните всё предложение в компонент `<T>` и задайте условие с помощью `<Branch>`. Так переводчик увидит полный контекст и сможет перестроить предложение для каждого языка.
- [Можно ли реализовать i18n без файлов перевода?](https://generaltranslation.com/ru/kb/i18n-without-translation-files.mdx): Да. С gt-react или gt-next контент остаётся встроенным прямо в ваши компоненты внутри компонента `<T>`, а переводы генерируются во время сборки, поэтому не нужно писать ключи и JSON-файлы для каждой локали и следить за их синхронизацией.
- [Что проверить перед запуском многоязычного приложения?](https://generaltranslation.com/ru/kb/multilingual-app-launch-checklist.mdx): Перед запуском многоязычного приложения проверьте девять аспектов в каждой поддерживаемой локали: пользовательские сценарии целиком, включая ошибки; определение и переключение языка; переменные и формы множественного числа; валюту и часовые пояса; увеличение длины текста; вёрстку для языков с письмом справа налево; доступность; доставку переводов в рабочей среде; индексируемые языковые URL для SEO. Для каждой проверки нужен явный критерий успешного прохождения.

## Previous and next questions

- Next question: [Как перевести условный текст в JSX?](https://generaltranslation.com/ru/kb/translate-conditional-jsx.mdx)

## Sitemap

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