Plurality.Custom (Plurality v0.2.3)

Copy Markdown View Source

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"
    ]
end

Then 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")       #=> true

How it works

use Plurality.Custom generates five functions in your module at compile time:

  • pluralize/2 — checks custom uncountables, then custom irregulars, then delegates to Plurality.pluralize/2
  • singularize/1 — checks custom uncountables, then custom reverse irregulars, then delegates to Plurality.singularize/1
  • plural?/1 — checks custom data, then delegates to Plurality.plural?/1
  • singular?/1 — checks custom data, then delegates to Plurality.singular?/1
  • inflect/2 — count-based delegation to singularize/1 or pluralize/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 both pluralize/2 and singularize/1, and return true for both plural?/1 and singular?/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

Options accepted by use Plurality.Custom.

A singular/plural pair for custom irregular words.

Types

custom_opts()

@type custom_opts() :: [irregulars: [irregular_pair()], uncountables: [String.t()]]

Options accepted by use Plurality.Custom.

irregular_pair()

@type irregular_pair() :: {singular :: String.t(), plural :: String.t()}

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.