n2words/lib.rs
1//! Numbers to words in 50 languages (72 regional variants).
2//!
3//! A Rust port of the [n2words](https://github.com/forzagreen/n2words)
4//! JavaScript library. Each language is a module named after its BCP 47 code
5//! in snake_case, exposing up to three **forms**:
6//!
7//! | Form | Function | Example |
8//! |----------|----------------------------------|-------------------------------------|
9//! | Cardinal | [`en::to_cardinal`] | "forty-two" |
10//! | Ordinal | [`en::to_ordinal`] | "forty-second" |
11//! | Currency | [`en_us::to_currency`] | "forty-two dollars and fifty cents" |
12//!
13//! ```
14//! use n2words::{en, en_us, es, fr, Currency};
15//!
16//! assert_eq!(en::to_cardinal(42)?, "forty-two");
17//! assert_eq!(en::to_ordinal(42)?, "forty-second");
18//! assert_eq!(es::to_cardinal(42)?, "cuarenta y dos");
19//! assert_eq!(fr::to_cardinal("1234.5")?, "mille deux cent trente-quatre virgule cinq");
20//!
21//! // A region-qualified code carries a default currency ...
22//! assert_eq!(en_us::to_currency(42.5)?, "forty-two dollars and fifty cents");
23//! // ... while a bare language tag has no country to take one from, so it is explicit.
24//! assert_eq!(en::to_currency(42.5, Currency::GBP)?, "forty-two pounds and fifty pence");
25//! # Ok::<(), n2words::Error>(())
26//! ```
27//!
28//! # Input
29//!
30//! Every function takes `impl Into<`[`Number`]`>`: any primitive integer, an
31//! `f64`/`f32`, a numeric `&str`/`String` (arbitrary precision, scientific
32//! notation accepted) or a [`num_bigint::BigInt`]/`BigUint`. Cardinal and
33//! currency accept negatives and decimals; ordinal takes positive integers.
34//!
35//! # Options
36//!
37//! A form that has options comes in two flavours: `to_cardinal(value)` with
38//! the language's defaults, and `to_cardinal_with(value, &options)` taking a
39//! per-language options struct whose `Default` *is* those defaults:
40//!
41//! ```
42//! use n2words::en_us::{self, CardinalOptions};
43//!
44//! assert_eq!(en_us::to_cardinal(1501)?, "one thousand five hundred one");
45//! let informal = CardinalOptions { and: true, hundred_pairing: true, ..Default::default() };
46//! assert_eq!(en_us::to_cardinal_with(1501, &informal)?, "fifteen hundred and one");
47//! # Ok::<(), n2words::Error>(())
48//! ```
49//!
50//! # Range
51//!
52//! Each form spells values up to the largest scale word it knows, declared as
53//! a [`Max`] constant (`en_us::CARDINAL_MAX` is `10^66`), and returns
54//! [`Error::OutOfRange`] past it rather than inventing vocabulary.
55//!
56//! # Picking a language at runtime
57//!
58//! [`language()`] looks an entry point up by code and gives access to the same
59//! conversions through string-keyed options, which is what the `n2words`
60//! command-line tool is built on:
61//!
62//! ```
63//! use n2words::{language, FormKind};
64//!
65//! let de = language("de").expect("German is supported");
66//! assert_eq!(de.convert(FormKind::Cardinal, 42, &[])?, "zweiundvierzig");
67//! assert_eq!(de.convert(FormKind::Currency, "42.50", &[("currency", "EUR")])?, "zweiundvierzig Euro und fünfzig Cent");
68//! # Ok::<(), n2words::Error>(())
69//! ```
70//!
71//! # Languages
72//!
73//! Most languages are reachable through a bare primary subtag (`de`, `en`,
74//! `fr`, ...), a documented alias of one specific regional variant; the
75//! region- or script-qualified module always exists too (`en_gb`, `fr_be`),
76//! and is the only entry point for the few languages whose variants differ in
77//! script or core numbering (`zh_hans_cn`/`zh_hant_tw`, `pt_br`/`pt_pt`,
78//! `sr_cyrl_rs`/`sr_latn_rs`, `am_et`/`am_latn_et`). See `LANGUAGES.md` in
79//! the repository for the full table, per-language options and ceilings.
80
81#![forbid(unsafe_code)]
82#![doc(html_root_url = "https://docs.rs/n2words/0.1.1")]
83
84pub use num_bigint;
85
86pub mod currency;
87mod error;
88mod lang;
89pub mod language;
90mod max;
91mod number;
92pub mod options;
93
94pub use currency::Currency;
95pub use error::{Error, Result};
96pub use lang::*;
97pub use language::{ConvertFn, Form, FormKind, Kind, Language, language, languages};
98pub use max::Max;
99pub use number::Number;
100pub use options::Gender;
101
102/// The crate version, as published.
103pub const VERSION: &str = env!("CARGO_PKG_VERSION");