gilbsgilbs/babel-plugin-i18next-extract

ICU extraction of plural in multiple languages produces invalid result

jakubriedl opened this issue · 0 comments

Describe the bug
When extracting multiple languages from Trans component with ICU, it produces invalid result for 2nd and latter language. See examples below.

How to reproduce
Run script yarn run babel 'src/**/*.tsx' with babel below and React component above

Babel configuration:

module.exports = {
  presets: ["@babel/preset-typescript"],
  plugins: [
    [
      "i18next-extract",
      {
        locales: ["en", "cs"],
        enableExperimentalIcu: true,
        outputPath: "locales/{{locale}}/{{ns}}.json",
        defaultNS: require(`${process.cwd()}/package.json`).name,
        useI18nextDefaultValue: true,
        discardOldKeys: true,
        customTransComponents: [
          ["react-i18next", "Trans"],
          ["react-i18next/icu.macro", "Trans"],
        ],
      },
    ],
  ],
}

Reproduction:

import { Trans } from "react-i18next/icu.macro"

export const Demo = () => {
  return (<Trans i18nKey="count-things" count={count}>{{count}} Thing</Trans>)
}

Expected behavior

{
  "count-things": "{count, plural, one {{count} Thing} other {{count} Thing}"
}

What actually happens

On second and latter language produces invalid result

{
  "count-things": "{count, plural, one {{count, plural, one {count} Thing} other {count} Thing}} other {{count, plural, one {count} Thing} other {count} Thing}}"
}

Your environment

  • OS (e.g. ArchLinux): OSX
  • Plugin version (e.g. 0.3.0): 0.8.2
  • Node version (e.g. 12.13.0): 14.15.4

Additional context

Why it happens: I tracked things down in the code and it is caused by the code in

const icuPlurals = pluralNumbersAsText
.map(
(numAsText: string) =>
`${numAsText} {${icuPluralValue(
extractedKey.parsedOptions.defaultValue,
)}}`,
)
.join(' ');
extractedKey.parsedOptions.defaultValue = `{count, plural, ${icuPlurals}`;
The reason is that the first run (language) sets the extractedKey.parsedOptions.defaultValue to the ICU formatted and the second run wrap that again and another again and so on. The fix can be to run this default value set only once and then use it for all languages.