# General Translation Knowledge Base: How do I handle plurals in React?
URL: https://generaltranslation.com/en-GB/kb/how-to-handle-plurals-in-react.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Don't hard-code plural logic with checks such as n === 1. A small helper is enough for English-only apps, but multilingual apps need locale-aware plural rules, which an i18n component such as `<Plural>` from gt-react or gt-next handles for every language.
Category: Locale Formatting
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 secs)

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.

## Why pluralisation matters in React

We often come across apps that display awkward messages such as:

```text
You have 1 new message(s)
```

This is a telltale sign of a developer who hasn&#39;t thought carefully about user experience.

React apps often need to handle pluralisation — for notification counts, list lengths, or search results.
**And it&#39;s not that hard to get pluralisation right, especially if you only need your app in English.**
But there are plenty of bad practices that new developers fall into, especially when building multilingual interfaces.

This guide covers how to handle English plurals cleanly, format numbers for different locales, and build a fully multilingual plural system in React and Next.js.

### The problem with hard-coded plurals

Many projects — including surprisingly large and important ones — hard-code plural logic.

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

But pluralisation is often more complex than just adding an &quot;s&quot; to the end of a word.
Some nouns have irregular plural forms, like &quot;child&quot; and &quot;children&quot;.
Sometimes, other parts of the sentence also need to change to reflect the noun, like
&quot;is&quot; and &quot;are&quot; depending on the count.

The table below illustrates some common scenarios:

| Scenario       | Examples                                                                                    | Notes                                                                                   |
| -------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| Viewer count   | &quot;1 person is watching&quot; <br /> &quot;2 people are watching&quot;                   | Irregular noun (&quot;person&quot; → &quot;people&quot;) and verb changes needed.       |
| Item deletion  | &quot;Delete this message?&quot; <br /> &quot;Delete these 2 messages?&quot;                | Demonstrative changes (&quot;this&quot; vs. &quot;these&quot;) plus noun pluralisation. |
| Search results | &quot;No results&quot; <br /> &quot;1 result found&quot; <br /> &quot;2 results found&quot; | Different phrasing for zero, one and multiple results.                                  |

Using conditional expressions quickly becomes unwieldy.

And it becomes a nightmare when you need to ship your app in other languages.
What works for English often breaks completely in languages like Polish or Arabic, which have entirely different rules for handling quantities.
**Companies we work with often put off internationalisation
because of the pain of refactoring hard-coded UI like this.**

***

## How to handle plurals in English

In English, using the right plurals in your app is usually straightforward.

For simple noun pluralisation, write a utility function:

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

Now there is a single function for handling all your plural logic,
and it works for irregular plurals too:

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

But what if you need more complex logic, such as:

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

At this stage, you should think seriously about a low-maintenance internationalisation (&quot;i18n&quot;) library.

Although developers often think that i18n libraries are only for multilingual interfaces,
they can be very useful for plural and variable formatting even in single-language applications.
Under the hood, most i18n libraries use JavaScript&#39;s built-in `Intl.PluralRules` API to determine the correct plural form for any language.

There are plenty of React i18n libraries, including ours, [`gt-react`](/docs/react/overview) (or [`gt-next`](/docs/react/nextjs-quickstart) if you&#39;re using Next.js).
Displaying an English plural with gt-react is simple:

```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 is conditionally rendered based on the value of `n`.

Most libraries use JavaScript&#39;s [`Intl.PluralRules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules) API to decide which plural form to display.
This means that in English, you would use the name `"one"` to refer to a singular and `"other"` to refer to a plural.
Our [`<Plural>`](/docs/react/reference/components/plural) component checks the exact plural category first, then the generic `plural` and `other` props. It falls back to its children only when none of those props are available.

Using a library here is best practice even for English-only applications, and makes future internationalisation much easier.

***

## Pluralisation in multilingual React apps (i18n)

If your app only serves English-speaking users, the approach above may be all you need — but most production apps eventually need to support multiple languages. That&#39;s where things get interesting.

* In Arabic, nouns have different forms depending on whether there are zero, one, two or many of them
* In locales such as `de-DE`, `es-ES` and `it-IT`, large numbers use full stops instead of commas, so 1,000,000 becomes 1.000.000
* In Hindi, digits are grouped in pairs, so 1,000,000 would become 10,00,000

**For an internationalised app, you should use a dedicated i18n library**, which will have its own documentation on how to handle plurals and number formatting.

### Formatting numbers for different locales

You can use the `Intl` object to [format numbers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) for any locale.
The easiest way to do this is with the built-in `toLocaleString()` method.

By default, this will use the runtime&#39;s current locale:

```javascript
const n = 1000000
n.toLocaleString() // displays 1,000,000 when the runtime locale is "en-US" (American English)
n.toLocaleString('de') // 1.000.000 because the locale has been specified as "de" (German)
```

gt-react also offers a [`<Num>`](/docs/react/reference/components/num) component, which relies on `Intl.NumberFormat` under the hood.

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

// displays 1,000,000 when the language is "en-US"
// displays 1.000.000 when the language is "de"
// displays 10,00,000 when the language is "hi"
export default function Example() {
  return <Num>1000000</Num>
}
```

### Understanding plural forms across languages

The six plural forms supported by JavaScript&#39;s `Intl.PluralRules` API are: `zero`, `one`, `two`, `few`, `many`, `other`.
Although English uses only `one` (&quot;singular&quot;) and `other` (&quot;plural&quot;),
languages such as Arabic and Polish have more than just these two forms.

For example, an English-speaking user might expect:

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

Whereas an Arabic-speaking user might expect different expressions for singular,
dual (when the count is exactly two things), and small and large plural forms:

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

This is where an internationalisation library becomes essential.
Every language has its own logic for when and how to display plurals,
so it&#39;s better to rely on a dedicated library to get it right.

A good i18n library will do two things:

1. Decide which plural form (`one`, `many`, `other`, etc.) to use based on the locale
2. Locate the translation in the right language that corresponds to that form

**If you already have an internationalisation library,
check its docs for information on plural formatting.**
Almost all libraries have dedicated documentation on rendering plurals.

### Full example: plurals in a multilingual React app

If you don&#39;t already have an internationalisation library, consider [`gt-react`](/docs/react/react-quickstart)!

gt-react&#39;s [`<Plural>`](/docs/react/reference/components/plural) component:

* Is a simple, declarative way to render plurals correctly in React
* Works natively with the [`<Num>`](/docs/react/reference/components/num) formatting component
* Works natively with the [`<T>`](/docs/react/reference/components/t) translation component, which integrates with our [translation service](https://generaltranslation.com) to generate plural forms automatically

Putting all the building blocks together, here&#39;s a complete multilingual component:

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

// Works out of the box in 100+ languages
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>
  )
}
```

***

Set up pluralisation with the [`gt-react` Quickstart](/docs/react/react-quickstart) for React apps or the [`gt-next` Quickstart](/docs/react/nextjs-quickstart) for Next.js apps. See the [`<Plural>` API reference](/docs/react/reference/components/plural) for the full component API.

Pluralisation is one of the most common i18n challenges in React — getting it right from the start saves significant refactoring later on.

## Related questions

- [How do I translate conditional text in JSX?](https://generaltranslation.com/en-GB/kb/translate-conditional-jsx.mdx): Rather than translating each side of a ternary separately, wrap the whole sentence in a `<T>` component and express the condition with `<Branch>`, so that the translator sees the full context and can reorder the sentence for each language.
- [Can I do i18n without translation files?](https://generaltranslation.com/en-GB/kb/i18n-without-translation-files.mdx): Yes. With gt-react or gt-next, content stays inline in your components inside a `<T>` component, and translations are generated at build time as output, so there are no keys or per-locale JSON files to write and keep in sync.
- [Why use General Translation instead of a TMS (Smartling, Lokalise, Phrase, Crowdin, or Transifex)?](https://generaltranslation.com/en-GB/kb/general-translation-vs-tms.mdx): A translation management system (TMS) such as Smartling, Lokalise, Phrase, Crowdin, or Transifex coordinates translators, but engineers still extract strings, send them out, wait for translations, and wire them back into the product. General Translation translates content in your code with its context, ships every language with each release, and runs on open-source libraries with no lock-in.

## Previous and next questions

- Next question: [How do I translate conditional text in JSX?](https://generaltranslation.com/en-GB/kb/translate-conditional-jsx.mdx)

## Sitemap

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