Search code examples
reactjstranslationi18nextreact-i18next

Understanding plural keys for i18next?


I am working on integrating i18next in a react project, using react-18next, and using i18next-parser to generate the JSON files with the current translation strings, and using natural language keys.

In my source code, I have something like:

<p>{t('{{count}} Sensors', { count: getSensorCount() })}</p>

where getSensorCount() returns a number.

My i18next-parser config is as follows:

{
  locales: ['en', 'fr', 'es'],
  output: 'src/locales/$LOCALE/$NAMESPACE.json',
  defaultValue: (locale, namespace, key, value) => value || key,
  keySeparator: false,
  namespaceSeparator: false,
  verbose: true,
  createOldCatalogs: false
}

Running the parser generates a JSON file with the keys like:

{
...
  "{{count}} Sensors_one": "{{count}} Sensors",
  "{{count}} Sensors_other": "{{count}} Sensors",
...
}

which I then change the value for Sensors_one to be {{count}} Sensor.

I expect this to return "1 Sensor" when count is 1. This is also how the i18next documentation describes plurals to work.

However, it just returns the key, and it seems like it is unable to find the translation in the JSON file.

The only way I can get it to return the proper value is if I change the keys like this:

  "{{count}} Sensors": "{{count}} Sensor",
  "{{count}} Sensors_plural": "{{count}} Sensors",

I would like to know what the proper syntax for plural keys is, and

if it is key_one and key_other, how I can get my project to recognize that

if it is key and key_plural, how I can get my i18next-parser config to generate the JSON files with the proper keys.

My package versions are as follows:

"i18next": "^20.6.1",
"i18next-parser": "^8.0.0",
"react-i18next": "^13.0.0",
"react": "^18.2.0",

Thank you.

EDIT: Codesandbox example: https://codesandbox.io/s/react-i18next-forked-l5t9ws?file=/src/app.js


Solution

  • In version 21.0.0 of i18next they changed the way that plurals are supposed to be written in the json file. Before 21, as in your sandbox, the correct way is "foo_plural". After 21, it's "foo_other". This change was done in order to use the same terms as the Intl feature of javascript uses.

    So apparently you're using a new version of i18next-parser, but an old version of i18next. Possible solutions include:

    1. Switch to a new version of i18next
    2. Switch to an old version of i18next-parser (i'm not sure exactly what version that would be)
    3. Pass an option into i18next-parser telling it to parse plurals in the old way:
    {
      i18nextOptions: {
        compatibilityJSON: 'v3'
      }
    }