Template function for plural-sensitive formatting.
yarn add templural
or
npm install templural
import { templural } from 'templural'
or
const { templural } = require('templural')
templural uses Intl.PluralRules to know which plural rule to apply for a given number, and plural rules vary depending on the language.
This means you have to set the locale used by templural in order to format correct sentences.
Either set the default locale:
templural.setLocales('fr_BE') // French (Belgium)
or get a new template function for a specific locale:
import { forLocales } from 'templural'
const templuralDeCH = forLocales('de_CH') // German (Switzerland)
For more information about the values accepted by templural.setLocales()
and forLocales()
see locales argument.
The following examples are specific to the English language, see Internationalization for information about other languages.
templural`Yoann and Valentin had ${numberOfIdeas} interesting idea{s}`
// numberOfIdeas = 1 ➔ "Yoann and Valentin had 1 interesting idea"
// numberOfIdeas = 2 ➔ "Yoann and Valentin had 2 interesting ideas"
// numberOfIdeas = 42 ➔ "Yoann and Valentin had 42 interesting ideas"
// numberOfIdeas = 0 ➔ "Yoann and Valentin had 0 interesting ideas"
templural`${userName} has ${nbPoints} point{s}`
// userName = "Joe", nbPoints = 1 ➔ "Joe has 1 point"
// userName = "Mario", nbPoints = 1000 ➔ "Mario has 1000 points"
templural`I just had ${nbPints} beer{s} darling{s}, I swear{s}`
// nbPints = 1 ➔ "I just had 1 beer darling, I swear"
// nbPints = 2 ➔ "I just had 2 beers darlings, I swears"
// nbPints = 6 ➔ "I just had 6 beers darlings, I swears"
templural`I bought ${nbCarrots} carrot{s} and ${nbPotatoes} potato{es}`
// nbCarrots = 1, nbPotatoes = 1 ➔ "I bought 1 carrot and 1 potato"
// nbCarrots = 1, nbPotatoes = 3 ➔ "I bought 1 carrot and 3 potatoes"
// nbCarrots = 2, nbPotatoes = 1 ➔ "I bought 2 carrots and 1 potato"
// nbCarrots = 2, nbPotatoes = 3 ➔ "I bought 2 carrots and 3 potatoes"
templural`${nbConnected} {person;people} {is;are} connected`
// nbConnected = 1 ➔ "1 person is connected"
// nbConnected = 2 ➔ "2 people are connected"
// nbConnected = 666 ➔ "666 people are connected"
templural`${nbDogs} dog{s} bark{s;} and ${nbCats} cat{s} meow{s;}`
// nbDogs = 1, nbCats = 1 ➔ "1 dog barks and 1 cat meows"
// nbDogs = 2, nbCats = 1 ➔ "2 dogs bark and 1 cat meows"
// nbDogs = 1, nbCats = 2 ➔ "1 dog barks and 2 cats meow"
// nbDogs = 2, nbCats = 2 ➔ "2 dogs bark and 2 cats meow"
templural`There {1$is;are} ${nbWhales} flying whale{s}`
// nbWhales = 1 ➔ "There is 1 flying whale"
// nbWhales = 2 ➔ "There are 2 flying whales"
1$
references the first interpolated expression.
Use 2$
, 3$
or n$
to reference the second, the third or the nth interpolated expression.
In some cases, associative syntax may be used to avoid empty values:
templural`${nbDogs} dog{s} bark{s;} and ${nbCats} cat{s} meow{s;}`
// may be replaced by
templural`${nbDogs} dog{s} bark{one:s} and ${nbCats} cat{s} meow{one:s}`
// this is OK:
templural`${nbConnected} {one:person;other:people} connected`
// this is NOT OK:
templural`${nbConnected} {one:person;people} connected`
templural is built on top of Intl.PluralRules and may be used to format sentences in any language.
This README is available in the following other languages:
Each language has different plural rules.
For example English has two plural categories, "one"
for singular, and "other"
for plural:
templural.setLocales('en')
templural`${n} is in the {one;other} category`
// n = 1 ➔ "1 is in the one category"
// n = 2 ➔ "2 is in the other category"
// n = 1000000 ➔ "1000000 is in the other category"
// n = 0 ➔ "0 is in the other category"
French is a little different from English, it has a third category "many"
for some large numbers, and 0 is singular:
templural.setLocales('fr')
templural`${n} is in the {one;other;many} category`
// n = 1 ➔ "1 is in the one category"
// n = 2 ➔ "2 is in the other category"
// n = 1000000 ➔ "1000000 is in the many category"
// n = 0 ➔ "0 is in the one category"
See Language Plural Rules for information about plural rules in any language.
templural's behavior may be customized using three mechanisms:
templural.setLocales()
and forLocales()
accept LocalesOptions
as second parameter, see locales.ts.
Category priority defines which categories are valued when not giving values for all categories.
If priority is:
many
other
one
Then:
// giving only one value is for category many
templural`${n} is {many}`
// giving two values is for categories other and many
templural`${n} is {other;many}`
// giving three values is for categories one, other and many
templural`${n} is {one;other;many}`
The default priority (regardless of locale) is:
other
one
two
few
many
zero
This default priority is filtered to include only categories of the selected locale, for example in English:
other
one
Some languages may have a different default priority, see locales.ts.
Category order defines the order in which categories are valued (regardless of their priority).
If order is:
many
other
one
Then:
// giving two values is other then one (many has a lower priority)
templural`${n} is {other;one}`
// giving three values is many then other then one
templural`${n} is {many;other;one}`
The default order (regardless of locale) is:
zero
one
two
few
many
other
This default order is filtered to include only categories of the locale, for example in English:
one
other
Some languages may have a different default order, see locales.ts.
Certain languages may need a category to fallback to another category.
For example in French, many
behaves like a sub-category of other
, which means many
needs to fallback to other
:
templural`${1000000} is {one;other;many} and falls back to {one;other}`
// ➔ "1000000 is many and falls back to other"
Some languages may have default fallbacks, see locales.ts.
templural doesn't care, it relies on Intl.PluralRules.
Not for the moment.
templural is simple and dumb, and it will probably stay like this.
Use the Discussions tab.
Nicolas Lepage ✍️ |
Thanks goes to these wonderful people (emoji key):
Valentin Cocaud 🤔 |
Yoann Prot 🤔 |
Svetlana A. 📖 🌍 |
Marie Viley 📖 🌍 |
Patrice De Saint Steban 📖 |
This project follows the all-contributors specification. Contributions of any kind welcome!
Contributions, issues and feature requests are welcome! Check out our Contributing guide for more information.
In the interest of fostering an open and welcoming environment, we have adopted a Code of Conduct that we expect project participants to commit to. Please read the full text so that you can understand what behavior will and will not be tolerated.
Give a ⭐️ and/or sponsor if this project helped you!
Copyright © 2021 Nicolas Lepage.
This project is Apache-2.0 licensed.