Compile-time overrides for domain-specific inflection.
Use this module to create a custom inflection module that adds your own
irregulars and uncountables on top of Plurality's built-in data. Custom
entries are checked first and take priority; unknown words fall through
to the default Plurality module.
Usage
defmodule MyApp.Inflection do
use Plurality.Custom,
irregulars: [
{"regex", "regexen"},
{"pokemon", "pokemon"},
{"elasticsearch", "elasticsearch"}
],
uncountables: [
"kubernetes",
"graphql",
"redis"
]
endThen call your module directly:
MyApp.Inflection.pluralize("regex") #=> "regexen"
MyApp.Inflection.pluralize("kubernetes") #=> "kubernetes"
MyApp.Inflection.pluralize("leaf") #=> "leaves"
MyApp.Inflection.singularize("regexen") #=> "regex"
MyApp.Inflection.plural?("kubernetes") #=> true
MyApp.Inflection.singular?("kubernetes") #=> trueHow it works
use Plurality.Custom generates five functions in your module at compile
time:
pluralize/2— checks custom uncountables, then custom irregulars, then delegates toPlurality.pluralize/2singularize/1— checks custom uncountables, then custom reverse irregulars, then delegates toPlurality.singularize/1plural?/1— checks custom data, then delegates toPlurality.plural?/1singular?/1— checks custom data, then delegates toPlurality.singular?/1inflect/2— count-based delegation tosingularize/1orpluralize/1
Custom irregulars and uncountables are stored as module attributes
(@custom_irregulars_s2p, @custom_irregulars_p2s, @custom_uncountables)
and compiled into the module's bytecode. There is no runtime overhead
beyond a Map/MapSet lookup.
Options
:irregulars— a list of{singular, plural}tuples. Each pair is stored in both a forward map (singular → plural) and a reverse map (plural → singular). Identity pairs like{"pokemon", "pokemon"}work correctly — the word is returned unchanged in both directions.:uncountables— a list of strings. These words are returned unchanged by bothpluralize/2andsingularize/1, and returntruefor bothplural?/1andsingular?/1.
Design rationale
Custom modules are called directly rather than being registered globally. This is intentional:
- Explicit — no hidden app-wide config or implicit delegation
- Composable — different parts of your app can use different custom modules
- Zero overhead — no ETS lookups or runtime configuration reads
- Compile-time verified — typos in irregular pairs are caught at compile time, not at runtime
Summary
Types
@type custom_opts() :: [irregulars: [irregular_pair()], uncountables: [String.t()]]
Options accepted by use Plurality.Custom.
:irregulars— list ofirregular_pair/0:uncountables— list ofString.t/0
A singular/plural pair for custom irregular words.
The first element is the singular form, the second is the plural form. Identity pairs (where both are the same) are valid and indicate that the word should be returned unchanged in both directions.