aralroca / next-translate

Next.js plugin + i18n API for Next.js 🌍 - Load page translations and use them in an easy way!
MIT License
2.66k stars 206 forks source link

Plural formats #365

Closed josephfarina closed 3 years ago

josephfarina commented 3 years ago

Hey again,

Can different plural formats be used? The translating service we use doesn't support the current _plural style syntax. The current way is:

{
  "plural-example": "This is singular because the value is {{count}}",
  "plural-example_0": "Is zero because the value is {{count}}",
  "plural-example_2": "Is two because the value is {{count}}",
  "plural-example_plural": "Is in plural because the value is {{count}}"
}

Is there a way to use the ICU format:

plural-example: "{count, plural, one {This is singular because the value is {count}} other {Is in plural because the value is {count}}}"

Or the Rails style of:

{
  "plural-example: {
    "one": "This is singular because the value is {{count}}",
    "other": "Is in plural because the value is {{count}}"
  }
}

Thanks!

aralroca commented 3 years ago

@josephfarina On version 0.x the support of plurals is quite simple. In version 1.0 we support 6 plural forms (taken from CLDR Plurals page) by adding to the key this suffix:

_See more info about plurals here_.

Only the last one, _other, is required because it’s the only common plural form used in all locales. This is the equivalent of _plural on 0.x version.

All other plural forms depends on locale. For example English has only two: _one and _other (1 cat vs. 2 cats). Some languages have more, like Russian and Arabic.

In addition, we also support an exact match by specifying the number (_0, _999) and this works for all locales. Here is an example:

Code:

// Note: Only works if the name of the variable is {{count}}.
t('cart-message', { count })

Namespace:

{
  "cart-message_0": "The cart is empty", // when count === 0
  "cart-message_one": "The cart has only {{count}} product", // singular
  "cart-message_other": "The cart has {{count}} products", // plural
  "cart-message_999": "The cart is full", // when count === 999
}

The version 1.0 right now is under prerelease 1.0.0-canary.2, if you want you can start using it, I suppose that the final version will be released in a few days.

Useful links:

josephfarina commented 3 years ago

This is great information. Thank you @aralroca! Just one follow up question. Is it possible to define the one/other keys as children of the key?

Something like this:

{
  "cart-message": {
    "one": "The cart has only {{count}} product", // singular
    "other": "The cart has {{count}} products", // plural
  }
}
aralroca commented 3 years ago

@josephfarina No... You could do it with a workaround but it would not be directly supported...

const pluralForm = new Intl.PluralRules(lang).select(count)
const plural = t('cart-message', { count }, { returnObjects: true })[pluralForm]

Why? Does your translating service require this structure? If it's something strictly necessary we could look at implementing it. Which is the translation service?

josephfarina commented 3 years ago

Hey @aralroca so I just confirmed that the translating service we use, Smartling, does in fact require it to be nested. Or use the ICU format ("{people_count, plural, one {{people_count} person here.} other {{people_count} people here.}}").

Do you think this is something that is relatively easy to implement? I could take a look, but wouldn't know where to start...

aralroca commented 3 years ago

@josephfarina If you want to implement it, the first point to start would be to add the tests of these cases:

And once you have the failed tests, then you must surely touch this part of the code to make the tests work:

You can run the test with yarn test, and you can also test against the repo examples with yarn example. And your PR should be done to the canary branch. 😊

josephfarina commented 3 years ago

@aralroca I think I figured it out 😄 Let me know if this is what you imagined! https://github.com/vinissimus/next-translate/pull/368

aralroca commented 3 years ago

It is admirable how fast you have been. The PR looks good, I did a couple of comments, but I see it well. Good job and welcome as a first-time contributor!

aralroca commented 3 years ago

@josephfarina I prereleased 1.0.0-canary.5 with your change