QuiiBz / next-international

Type-safe internationalization (i18n) for Next.js
https://next-international.vercel.app
MIT License
1.26k stars 59 forks source link

Improve plural keys #199

Closed lindesvard closed 11 months ago

lindesvard commented 11 months ago

Is your feature request related to a problem? Please describe. Not sure if this is only me but I would assume the following rules would apply for the plural keys.

zero count = 0 one count = 1 two count = 2 other count = 3,4,5,6...

But if you have en-US as locale you will get the following (look code snippet).

[...new Array(30).fill(0)].forEach((_, count) => {
    console.log(`Count = ${count}`, new Intl.PluralRules('en-US').select(count))
})
Count = 0 other
Count = 1 one
Count = 2 other
Count = 3 other
Count = 4 other
Count = 5 other
Count = 6 other
...
...

Describe the solution you'd like This PR solves my problem https://github.com/QuiiBz/next-international/compare/main...lindesvard:next-international:improve-plurals?expand=1

Additional context For me coming from other translations libraries I feel like using Intl.PluralRules is somewhat wrong. Especially when it has quite different behavior between different locales.

For instance this is how i18n-next is doing https://www.i18next.com/translation-function/plurals

QuiiBz commented 11 months ago

Thanks for the suggestion. I'm not sure if this is something we want to do, because each language have its specifies and the Intl.PluralRules API handles them perfectly.

Otherwise, I agree that it might be confusing that key#zero isn't used with { count: 0 } in most languages. If we go further with this, what would be the difference between few, many and other? These are different based depending on the language.

Would love to get more insights from the users of next-international to make sure we're going in the right direction.

lindesvard commented 11 months ago

I think Intl.PluralRules is not the best way of handling plurals for this kind of lib. Best case scenario would be if Intl.MessageFormat would be a thing. There is also some good polyfills for this but I understand if you do not want to bloat the bundle with this.

The use case why I want this is because zero only works with some locales and I think its quite confusing reading the documentation. Since it implies that zero will match count: 0. But that depends if your locale support it.

t('selected', { count: 0 }) // No options selected
t('selected', { count: 1 }) // One option selected
t('selected', { count: 2 }) // 2 options selected
t('selected', { count: 5 }) // 5 options selected

This is the behavior I want for all locales and with the current documentation it looks like I can get that.

So either I think you should make it clear that zero and other plural words might not work for your locale. And link to this page for more information.

Or we just add the zero use case to be default when count is 0 for all locales. This should not be a breaking change either since we will fallback on #other if #zero is not defined.