plural

package module
v2.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: BSD-3-Clause Imports: 2 Imported by: 0

README

plural - Simple Go API for Pluralisation.

GoDoc Go Report Card Build Coverage Issues

Package plural provides simple support for localising plurals in a flexible range of different styles.

There are considerable differences around the world in the way plurals are handled. This is a simple but useful API for catering with these differences when presenting to people formatted text with numbers.

This package is able to format countable things and continuous values. It can handle integers and floating point numbers equally and this allows you to decide to what extent each is appropriate.

For example, 2 cars might weigh 1.6 tonnes; both categories are covered.

Installation

    go get github.com/rickb777/plural/v2

Status

This library has been in reliable production use for some time. Versioning follows the well-known semantic version pattern.

More info

This API is deliberately simple; it doesn't address the full gamut of internationalisation. If that's what you need, you should consider other products instead, such as

Documentation

Overview

Package plural provides simple support for localising plurals in a flexible range of different styles.

There are considerable differences around the world in the way plurals are handled. This is a simple but competent API for catering with these differences when presenting formatted text with numbers to people.

This package is able to format countable things and continuous values. It can handle integers and floating point numbers equally and this allows you to decide to what extent each is appropriate.

For example, "2 cars" (countable) might weigh "1.6 tonnes" (continuous); both categories are covered.

This API is deliberately simple; it doesn't address the full gamut of internationalisation. If that's what you need, you might consider products such as https://pkg.go.dev/github.com/nicksnyder/go-i18n/v2/i18n instead.

This package is not intended to format negative quantities. Such values may be better handled as physical values, e.g. using https://pkg.go.dev/periph.io/x/conn/v3/physic.

Please see the examples and associated api documentation.

Index

Examples

Constants

This section is empty.

Variables

View Source
var AddS = func(noun string) string { return noun + "s" }

AddS is a pluggable function that appends "s" to a noun. This is used by Regular. Replace this with whatever your own language needs.

View Source
var Zero = func(noun string) string { return "no " + noun + "s" }

Zero is a pluggable function that prepends "no " and appends "s" to a noun. This is used by Regular. Replace this with whatever your own language needs.

Functions

This section is empty.

Types

type Cases

type Cases struct {
	// contains filtered or unexported fields
}

Cases provides a list of plural cases in the order they will be searched. The cases must be listed in ascending number order. They are contiguous (i.e. without gaps) and monotonic (i.e. always rising).

func ByOrdinal

func ByOrdinal(zeroth string, rest ...string) Cases

ByOrdinal is an alias for FromZero.

Example
package main

import (
	"fmt"

	"github.com/rickb777/plural/v2"
)

func main() {
	// ByOrdinal is easy to use for any collection of counting phrases, even with nouns that have irregular
	// plurals. In this case, "lolly" and "lollies" are used.
	//
	// ByOrdinal creates Cases that hold a sequence of cardinal cases where the
	// first matching case is used. Otherwise, if there's no match, the last one is used.

	var lollyPlurals = plural.ByOrdinal("no ice lollies", "1 ice lolly", "%v ice lollies")

	for d := 0; d < 4; d++ {
		s := lollyPlurals.Countable(d)
		fmt.Println(s)
	}

}
Output:
no ice lollies
1 ice lolly
2 ice lollies
3 ice lollies

func FromOne

func FromOne(first string, rest ...string) Cases

FromOne constructs a simple set of cases using small positive numbers (1, 2, 3 etc), which is a common requirement. The last case will be used for all subsequent numbers. Any cases may include a fmt.Sprintf number placeholder, Usually, this will be %v, which will support the countable and continuous cases effectively.

For example

plural.FromOne("%v cat", "%v cats")
plural.FromOne("one", "two", "many")

can then be used via Cases.Countable or Cases.Continuous to produce descriptive formatted values.

Note the behaviour of formatting when the count is zero. As a consequence of Cases.Countable evaluating its cases in ascending order, FromOne(...).Countable(0) will return a blank string. If this might arise, use FromZero instead.

Example
package main

import (
	"fmt"

	"github.com/rickb777/plural/v2"
)

func main() {
	// FromOne creates Cases that hold a sequence of cardinal cases where the
	// first matching case is used. Otherwise, if there's no match, the last one is used.
	//
	// Often, the last case will include a "%d", "%g" or "%v" placeholder for the number,
	// but placeholders are not mandatory in any of the cases.

	// mugPlurals and volumePlurals provide English formatted cases for some number of mugs and their volume.
	var mugPlurals = plural.FromOne("%d mug holds", "%d mugs hold")

	// Note %g, %f etc should be chosen appropriately
	var volumePlurals = plural.FromOne("%g litre", "%g litres")

	for d := 1; d < 6; d++ {
		s := mugPlurals.Countable(d)
		w := volumePlurals.Continuous(float64(d) * 0.25)
		fmt.Println(s, w)
	}

}
Output:
1 mug holds 0.25 litre
2 mugs hold 0.5 litre
3 mugs hold 0.75 litre
4 mugs hold 1 litre
5 mugs hold 1.25 litres

func FromZero

func FromZero(zeroth string, rest ...string) Cases

FromZero constructs a simple set of cases using small ordinals (0, 1, 2, 3 etc), which is a common requirement. The last case will be used for all subsequent numbers. Any cases may include a fmt.Sprintf number placeholder, Usually, this will be %v, which will support the countable and continuous cases effectively.

For example

plural.FromZero("nothing", "%v caddy", "%v caddies")
plural.FromZero("none", "one", "two", "many")

can then be used via Cases.Countable or Cases.Continuous to produce descriptive formatted values.

Example
package main

import (
	"fmt"

	"github.com/rickb777/plural/v2"
)

func main() {
	// FromZero creates Cases that hold a sequence of cardinal cases where the
	// first matching case is used. Otherwise, if there's no match, the last one is used.
	//
	// Often, the last case will include a "%d", "%g" or "%v" placeholder for the number,
	// but placeholders are not mandatory in any of the cases.
	//
	// ByOrdinal could be used instead of FromZero (they are aliases);
	// it builds simple common kinds of plurals using small ordinals (0, 1, 2, 3 etc).

	// bikePlurals and weightPlurals provide English formatted cases for some number of bikes and their weight.
	var bikePlurals = plural.FromZero("no bikes weigh", "%d bike weighs", "%d bikes weigh")

	var weightPlurals = plural.FromZero("nothing", "%1.1f tonne", "%1.1f tonnes")

	for d := 0; d < 5; d++ {
		s := bikePlurals.Countable(d)
		w := weightPlurals.Continuous(float64(d) * 0.5)
		fmt.Println(s, w)
	}

}
Output:
no bikes weigh nothing
1 bike weighs 0.5 tonne
2 bikes weigh 1.0 tonne
3 bikes weigh 1.5 tonnes
4 bikes weigh 2.0 tonnes

func Irregular added in v2.1.0

func Irregular(singular, plural string) Cases

Irregular returns plurals for irregular nouns typical in English such as words like "caddy" ("caddies"), for which noun has a singular and a plural form but the plural form is irregular.

It uses FromOne, passing the singular noun for the unit case, and the plural noun for all counts above one. This allows irregular nouns to be pluralised with little effort.

For example

plural.Irregular("caddy", "caddies")

can then be used via Cases.Countable or Cases.Continuous to produce descriptive formatted values.

Like Regular, Irregular is too simplistic for phrases instead of nouns and for any language that uses more than two variants; for these, FromZero or FromOne will be more appropriate.

Both Irregular(s, p).Countable(0) and FromOne(...).Countable(0) will return a blank string for zero. If this might arise, use FromZero instead.

Example
package main

import (
	"fmt"

	"github.com/rickb777/plural/v2"
)

func main() {
	// Irregular is similar to Regular, but differs by catering for the case of nouns that have different
	// forms in the singular and in the plural.

	var lollyPlurals = plural.Irregular("lolly", "lollies")

	for d := 1; d < 4; d++ {
		s := lollyPlurals.Countable(d)
		fmt.Println(s)
	}

}
Output:
1 lolly
2 lollies
3 lollies

func Regular

func Regular(noun string) Cases

Regular returns plurals for regular nouns typical in English such as words like "cat", "tree", for which the plural form is simply by adding letter 's'.

It uses FromZero, passing the noun with Zero for the zero case, the noun itself for the unit case, and with AddS for all counts above one. This allows the many easy regular nouns to be pluralised with little effort.

For example

plural.Regular("thing")

can then be used via Cases.Countable or Cases.Continuous to produce descriptive formatted values.

Irregular nouns such as "caddy" should not use this function (unless "caddys" really is the plural form you want). Instead, use Irregular, FromZero or FromOne.

Also, Regular is too simplistic for phrases instead of nouns; for these, FromZero or FromOne will be more appropriate.

Example
package main

import (
	"fmt"

	"github.com/rickb777/plural/v2"
)

func main() {
	// Regular caters for the common simple case of a noun that is easy to pluralise, e.g. by appending "s".
	// It uses the Zero and AddS functions, which can be altered if required.

	var catPlurals = plural.Regular("cat")

	for d := 0; d < 4; d++ {
		s := catPlurals.Countable(d)
		fmt.Println(s)
	}

}
Output:
no cats
1 cat
2 cats
3 cats

func (Cases) Continuous

func (plurals Cases) Continuous(value float64) string

Continuous expresses a continuous number in plural form. If no match is found, the last case will be used. It is recommended that any case placeholders should be the %v general value, but floating point placeholders such as %f or %g may be used instead.

Integer placeholders such as %d will render incorrectly and should not be used. Negative values are not supported.

func (Cases) Countable

func (plurals Cases) Countable(value int) string

Countable expresses a countable number in plural form. If no match is found, the last case will be used. It is recommended that any case placeholders should be the %v general value, but integer placeholders such as %d may be used instead.

Floating point placeholders such as %f or %g will render incorrectly and should not be used. Negative values are not supported.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL