gilbsgilbs / babel-plugin-i18next-extract

Babel plugin that statically extracts i18next and react-i18next translation keys.
https://i18next-extract.netlify.com
MIT License
161 stars 37 forks source link

Plurals with "discardOldKeys" true / general plural syntax #167

Open aaronfg opened 4 years ago

aaronfg commented 4 years ago

Describe the bug

There seems to be no way to have the extraction accept a default value for the plural of a word.

How to reproduce

Trying to see how pluralization works with the extraction and also providing a defaultValue.

Based on the i18next docs, passing in "{count: x}" to the options object will let i18next look for the "key_plural" key, yes?

so given this code:

const test = t('TestKey', { count: 1, defaultValue: 'Test' });

the extracted string looks like this:

{
 "TestKey": "Test",
 "TestKey_plural": ""
}

How am I supposed to pass in what the default plural is?

I tried this to see what would happen:

const test = t('TestKey', { count: 1, defaultValue: 'Test' });
const tests = t('TestKey', { count: 2, defaultValue: 'Tests' });

But the extracted strings just overwrote the initial one and the extracted strings end up like this:

{
 "TestKey": "Tests",
 "TestKey_plural": ""
}

If I had the "TestKey" and "TestKey_plural" already in the file, then the code should work. But this plugin is for extracting/generating those keys/values in the file for me automatically. I'm just trying to figure out what the syntax is for what I'm describing.

What am I missing?

Babel configuration:

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  "plugins": [
    ["i18next-extract", {
        "defaultNS" : "strings",
        "outputPath" : "lang/{{locale}}/{{ns}}.json",
        "discardOldKeys" : true,
      },
    ],
  ]
};

Expected behavior

Have the extraction generate the key and key_plural entries with proper default values.

{
 "TestKey": "Test",
 "TestKey_plural": "Tests"
}

What actually happens

Your environment

hazem3500 commented 4 years ago

I've also struggled with handling extraction with pluralization. You could use i18next-intervalplural-postprocessor then you would write something like this

t('TestKey_interval', { count: count, defaultValue: '(1){test};(2-inf)}{tests};' })

that way you could extract the pluralization, But I don't know if that's the best way

aaronfg commented 4 years ago

Interesting.

I have not seen that syntax with the semicolons inside the default value string to separate the defaults.

I'll take a look at the postprocessor and see how that works.

thanks for this!

hazem3500 commented 4 years ago

You can also consider using ICU format You can write the plural like this

<Plural
  i18nKey="TestKey"
  count={count}
  one="test"
  other="tests"
/>
kamil7x commented 2 years ago

This would be very useful. Any chances for making it work?

gilbsgilbs commented 2 years ago

Is this issue actually related to discardOldKeys in any way, as the title suggests? It may be, but I do not understand how.

Also, I'm not sure which default value you would expect to be used. I feel like having a comment hint for that purpose would be slightly "too much" and using the singular default value as default value for plurals doesn't seem correct either (because it will be considered as translated when it should be reworked). Especially with intervalplural-preprocessor, I'm not sure how all this should work together.

I'm under the impression that this is rather an issue for the translation tool: it should display singular and plurals "together", so that they can be translated in a batch. But I definitely don't have a strong opinion.

kamil7x commented 2 years ago

@gilbsgilbs i18next allows to pass multiple default values, eg

function totalItems(count: number) {
  return t('total_count', {
    count,
    defaultValue_one: 'Total {{count}} item',
    defaultValue_other: 'Total {{count}} items',
  });
}

and then:

console.log(totalItems(0));     // Total 0 items
console.log(totalItems(1));     // Total 1 item
console.log(totalItems(4));     // Total 4 items
console.log(totalItems(127));   // Total 127 items

Same for other suffixes used in different languages like _few and _many

gilbsgilbs commented 2 years ago

I didn't know that. This is a nice feature request. I'll happily accept PRs for it.

felicoz commented 1 year ago

bump..