A thoughtful collection of libraries for how humans actually speak.
Sayable is a family of zero-dependency formatting libraries. Each library tackles a different aspect of human-friendly output — the kind of phrasing people use in conversation, not the kind machines produce.
| age | date | duration | time | |
|---|---|---|---|---|
| What it does | Formats ages the way parents talk | Formats dates the way people reference them | Formats durations and relative time | Formats clock time conversationally |
| Example | "14 months" · "4½ years" | "last Tuesday" · "3 days ago" | "about 2 hours" | "quarter past 3" |
| Languages | 51 | 51 | 51 | 51 |
| Locales | 168 | 168 | 168 | 168 |
All 51 languages have identical implementations across all 4 libraries:
Ada, Bash, C, C#, C++, Clojure, COBOL, Common Lisp, Crystal, D, Dart, Elixir, Elm, Erlang, F#, Fortran, Gleam, Go, Goose, Groovy, Haskell, Janet, Java, Julia, Kotlin, Lua, Mojo, Nim, OCaml, Octave, Odin, Pascal, Perl, Pharo, PHP, PowerShell, Prolog, Python, R, Racket, Raku, Ruby, Rust, Scala, Swift, Tcl, TypeScript, V, VB.NET, Wren, Zig
See the full compatibility matrix.
See the locale coverage maps for a visual breakdown of how well Sayable's locales cover each country's languages.
- Zero dependencies. Pure standard-library code in every language.
- Polyglot. Identical implementations across languages, sharing canonical test cases and locale data.
- Localization-first. Culture-aware output with CLDR-compliant plural rules.
- Deterministic. All tests use explicit inputs — no flaky tests from system state.
Develop and test natively on macOS/Linux or inside a Docker container. Either
way you need just and
hecatron, the separate tool that installs,
checks and repairs each language's toolchain and runs the per-language
commands. Sayable's side of it is .hecatron/: the project
config and each language's test, lint, build and clean hooks. Until hecatron
has a Homebrew formula, use a checkout:
brew install just # or your package manager's just
git clone https://github.com/dnf/hecatron ~/hecatron
export PATH="${HOME}/hecatron/bin:${PATH}" # add to your shell profilehecatron bootstrap # base packages + every language toolchain (macOS or Ubuntu/Debian)
hecatron doctor # check every toolchain works; --fix repairs./tools/docker-test.sh # build the image (age/Dockerfile) and run every test suite
./tools/docker-test.sh bash # interactive shell inside the containerInstall or uninstall individual languages:
just install go # single language
just install ts py rb # multiple (aliases work)
just install # all languages
just uninstall go # remove a languageA top-level justfile provides a single entry point:
just test # run all test suites + codegen check
just test go # one language's tests, all four libraries
just test go -c age # one language, one library
just test cli # canonical tests through every language's CLI
just build # build all compiled languages
just lint # run all linters
just doctor # check every toolchain works (--fix repairs)
just generate locales # regenerate locale files from canonical JSON
just check # verify generated files are up-to-date
just --list # see all available commandsSee CONTRIBUTING.md for guidelines. All implementations share identical test cases — changes to formatting logic must be applied to all languages.
