GlobalWebIndex / elm-plural-rules / PluralRules

Abstraction for working with pluralization rules.

Check Unicode Language Plural Rules for more information and examples for various languages.

Screenshot of English
rules

Screenshot of Czech
rules

Rules


type Rules

Rules are a dictionary with various plural forms of words in your given language.

Elsewhere you can supply a function giving the default pluralization (in English that's adding a -s suffix), but here in Rules you'll have to supply the "exceptions" (like words that add an -es suffix instead).

For an example see fromList.

Note Rules don't do anything about case at all! If they contain "query" but you then try to pluralize 5 "Query", the query rule won't get used!

empty : Rules

Initialize empty Rules.

fromList : List ( String, List ( Cardinal, String ) ) -> Rules

Create Rules from a list of given exceptions to the general rule.

fromList
    [ ( "Query"
      , [ ( One, "Query" )
        , ( Other, "Queries" )
        ]
      )
    ]

You can imagine more complicated rules in other languages:

-- Czech rules
fromList
    [ ( "muž"
      , [ ( One, "muž" ) -- 1, no decimal digits
        , ( Few, "muži" ) -- 2..4, no decimal digits
        , ( Many, "muže" ) -- with decimal digits
        , ( Other, "mužů" ) -- the rest
        ]
      )
    ]

add : String -> List ( Cardinal, String ) -> Rules -> Rules

Add rules for a new word.

Behaves like Dict.insert in case of collisions: replaces the previous value in Rules with the new value.

Cardinals


type Cardinal
    = Zero
    | One
    | Two
    | Few
    | Many
    | Other

Each language will have its own rules for when to use which cardinal.

Check Unicode Language Plural Rules for more information and examples for various languages.

Pluralization

fromInt : { toCardinal : Basics.Float -> Cardinal, defaultPluralize : String -> String } -> Rules -> Basics.Int -> String -> String

Integer-specialized pluralization function. For more info see fromFloat.

fromFloat : { toCardinal : Basics.Float -> Cardinal, defaultPluralize : String -> String } -> Rules -> Basics.Float -> String -> String

Pluralize a single word.

This is the most general case; the goal is to define and use a partially applied "homegrown" variant that will apply the configuration and rules and end up with a function of signature pluralize : Int -> String -> String:

pluralize 5 "word"
--> "words"

pluralize 5 "query"
--> "queries" if you supplied the cases for "query" in the Rules dictionary
--> "querys" otherwise, as the default rule would fire!

The defaultPluralize function is a helper for minimizing the amount of Rules you'll have to write -- it is used when a word or its cardinal isn't found in Rules.

The toCardinal function implements the rules from Unicode Language Plural Rules for which quantities result in which cardinal. Your Rules dictionary can then just supply a word for each relevant cardinal, for cases where defaultPluralize isn't enough.

Plural Operands

When implementing the toCardinal function you'll likely reference the table of Plural Rules for your language.

The rules have conditions like i = 2..4 and v = 0. See the Plural Operand Meanings table or below for description of these.


type alias Operands =
{ absoluteValue : Basics.Float
, integerDigits : Basics.Int
, hasFractionDigits : Basics.Bool 
}

Taken from Plural Operand Meanings.

Note that v,w,f,t are quite problematic because of Float behaviour, at least when not dealing with simple != 0. As we didn't need to deal with those problematic rules, we're currently keeping only what we can guarantee: notably hasFractionDigits == v != 0.

If you, when implementing toCardinal for your language, need those v,w,f,t operands, shoot us a GitHub issue, we can likely create something working on Strings which be able to work with trailing zeros etc.

operands : Basics.Float -> Operands

Compute Operands from a Float number.