pub struct LangMs { /* private fields */ }Implementations§
Trait Implementations§
Source§impl Lang for LangMs
impl Lang for LangMs
Source§fn default_currency(&self) -> &str
fn default_currency(&self) -> &str
This language’s own to_currency(currency=...) default,
read from the live Python signature. Only 44 of 156 use EUR.
Source§fn to_ordinal_num(&self, value: &BigInt) -> Result<String>
fn to_ordinal_num(&self, value: &BigInt) -> Result<String>
Python: return "ke-" + str(n). No sign handling — see bug 3.
Source§fn to_year(&self, value: &BigInt) -> Result<String>
fn to_year(&self, value: &BigInt) -> Result<String>
Python’s to_year branches on n < 1000 / n < 2000 / else and returns
self._int_to_cardinal(n) in all three — see bug 4.
Source§fn ordinal_float_entry(&self, value: &FloatValue) -> Result<String>
fn ordinal_float_entry(&self, value: &FloatValue) -> Result<String>
to_ordinal(float/Decimal).
Python’s _int_to_ordinal(n) indexes self.ordinals (a list) with the
raw float/Decimal — TypeError — or reaches _int_to_word, which dies
the same way on any fractional residue; to_ordinal’s bare
except BaseException then retries as _int_to_ordinal(int(n)). The
only non-raising first passes (whole teens like 11.0, whole scale
counts like 1e6) produce the identical words the retry would — so the
observable result is always _int_to_ordinal(int(n)), truncation,
negative-index wraparound and all (-1.0 → “kesepuluh”,
-21.0 → IndexError).
Source§fn ordinal_num_float_entry(
&self,
_value: &FloatValue,
repr_str: &str,
) -> Result<String>
fn ordinal_num_float_entry( &self, _value: &FloatValue, repr_str: &str, ) -> Result<String>
to_ordinal_num(float/Decimal): "ke-" + str(n), purely lexical —
“ke-5.0”, “ke–17”, “ke-1E+2”.
Source§fn year_float_entry(&self, value: &FloatValue) -> Result<String>
fn year_float_entry(&self, value: &FloatValue) -> Result<String>
to_year(float/Decimal) — self._int_to_cardinal(n) on all three
branches, with no try/except: the list indexes inside
_int_to_word raise TypeError for most values (5.0, Decimal("5"),
-21.0, …) while dict hits and == 1 scale counts survive
(10.0 → “sepuluh”, 11.0 → “sebelas”, 100.0 → “seratus”,
1e+16 → “sepuluh ribu trilion”). All corpus-pinned.
Source§fn to_cardinal_float(
&self,
value: &FloatValue,
_precision_override: Option<u32>,
) -> Result<String>
fn to_cardinal_float( &self, value: &FloatValue, _precision_override: Option<u32>, ) -> Result<String>
The float/Decimal cardinal path — not Num2Word_Base’s.
MS overrides to_cardinal and never delegates to
Num2Word_Base.to_cardinal_float, so the inherited float path
(pointword + a word per fractional digit) is the wrong shape for MS. In
Python a non-integer flows straight into
to_cardinal(n) -> _int_to_cardinal(n) -> _int_to_word(n), which
indexes self.ones / self.tens (Python lists) or self.teens
(a dict) with the raw float/Decimal. A list index that is not an
int raises TypeError; a fractional value misses the teens dict
and raises KeyError. Either way MS’s bare except BaseException
retries as self._int_to_cardinal(int(n)), and that retry cannot raise
a second time — so the observable result is always
_int_to_cardinal(int(value))i.e. the integer part (truncated toward zero) spelled as a plain
cardinal, with no pointword and no fractional digits. This is
bug-for-bug the Python behaviour, verified against the live interpreter
over 40,000 random float/Decimal inputs (0 mismatches) and pinned by the
corpus: 0.5 -> “kosong”, 12.34 -> “dua belas”, -12.34 ->
“negatif dua belas”, Decimal("98746251323029.99") -> the full 14-digit
integer with the .99 dropped. Note int(-0.5) == 0, so the sign is
silently lost (-0.5 -> “kosong”), unlike the base path which would
re-prepend the negword.
precision_override (the precision= kwarg, issue #580) is ignored:
MS’s to_cardinal(self, n) takes no such parameter and never reads
self.precision, so num2words(v, lang="ms", precision=5) is
byte-for-byte num2words(v, lang="ms"). Confirmed against the live
interpreter.
Source§fn to_currency(
&self,
val: &CurrencyValue,
currency: &str,
_cents: bool,
_separator: Option<&str>,
_adjective: bool,
) -> Result<String>
fn to_currency( &self, val: &CurrencyValue, currency: &str, _cents: bool, _separator: Option<&str>, _adjective: bool, ) -> Result<String>
Python’s Num2Word_MS.to_currency(n, currency="MYR").
cents, separator and adjective do not exist on the Python
signature, so they are ignored (bug 8). has_decimal is ignored too:
the cents segment is gated on right > 0 alone (bug 7).
fn negword(&self) -> &str
fn pointword(&self) -> &str
fn to_cardinal(&self, value: &BigInt) -> Result<String>
fn to_ordinal(&self, value: &BigInt) -> Result<String>
Source§fn currency_forms(&self, code: &str) -> Option<&CurrencyForms>
fn currency_forms(&self, code: &str) -> Option<&CurrencyForms>
CURRENCY_FORMS[code]. None -> NotImplementedError, as in Python.fn cards(&self) -> &Cards
fn maxval(&self) -> &BigInt
fn is_title(&self) -> bool
fn exclude_title(&self) -> &[String]
Source§fn merge(&self, _l: (&str, &BigInt), _r: (&str, &BigInt)) -> (String, BigInt)
fn merge(&self, _l: (&str, &BigInt), _r: (&str, &BigInt)) -> (String, BigInt)
merge is abstract in Python (raise NotImplementedError).
Languages that override to_cardinal never reach it.fn title(&self, value: &str) -> String
Source§fn currency_precision(&self, _code: &str) -> i64
fn currency_precision(&self, _code: &str) -> i64
CURRENCY_PRECISION.get(code, 100) — subunits per unit. 1000 for
3-decimal currencies (BHD/KWD/…), 1 for no-subunit currencies.Source§fn pluralize(&self, _n: &BigInt, _forms: &[String]) -> Result<String>
fn pluralize(&self, _n: &BigInt, _forms: &[String]) -> Result<String>
pluralize(n, forms). Abstract in Python (raise NotImplementedError),
so the default raises rather than guessing a plural rule.fn money_verbose(&self, number: &BigInt, _currency: &str) -> Result<String>
fn cents_verbose(&self, number: &BigInt, _currency: &str) -> Result<String>
fn cents_terse(&self, number: &BigInt, currency: &str) -> Result<String>
Source§fn cardinal_from_decimal(&self, value: &BigDecimal) -> Result<String>
fn cardinal_from_decimal(&self, value: &BigDecimal) -> Result<String>
self.to_cardinal(float(right)), i.e. through the
float path, so the default routes there rather than raising.Source§fn default_separator(&self) -> &str
fn default_separator(&self) -> &str
separator= default. Base’s is “,”.Source§fn default_adjective(&self) -> bool
fn default_adjective(&self) -> bool
to_currency(adjective=...) default. Base’s is
False; only Mongolian defaults to True.fn to_cheque(&self, val: &BigDecimal, currency: &str) -> Result<String>
Source§fn to_fraction(
&self,
numerator: &BigInt,
denominator: &BigInt,
) -> Result<String>
fn to_fraction( &self, numerator: &BigInt, denominator: &BigInt, ) -> Result<String>
Num2Word_Base.to_fraction (issue #584). EN/DE/ES/FR/IT/PT and the
aero profiles override with idiomatic forms (half/quarter/Drittel).Source§fn cardinal_float_entry(
&self,
value: &FloatValue,
precision_override: Option<u32>,
) -> Result<String>
fn cardinal_float_entry( &self, value: &FloatValue, precision_override: Option<u32>, ) -> Result<String>
to_cardinal(float/Decimal) — the full entry, whole values included.Source§fn str_to_number(&self, s: &str) -> Result<ParsedNumber>
fn str_to_number(&self, s: &str) -> Result<ParsedNumber>
converter.str_to_number. Base is Decimal(value); ES (“1ro” ->
ordinal handshake), PT_BR (“1.50” -> ‘ponto’), DV (TypeError instead
of InvalidOperation), BN (abs()) and ID override.Source§fn cardinal_with_pointword(
&self,
_value: &FloatValue,
_pointword: &str,
_precision_override: Option<u32>,
) -> Result<String>
fn cardinal_with_pointword( &self, _value: &FloatValue, _pointword: &str, _precision_override: Option<u32>, ) -> Result<String>
to_cardinal(value) with the pointword
swapped for this one call. Only reachable through
ParsedNumber::DecPoint, so only PT_BR implements it.fn to_cardinal_kw(&self, value: &BigInt, kw: &Kwargs) -> Result<String>
fn to_ordinal_kw(&self, value: &BigInt, kw: &Kwargs) -> Result<String>
fn to_ordinal_num_kw(&self, value: &BigInt, kw: &Kwargs) -> Result<String>
fn to_year_kw(&self, value: &BigInt, kw: &Kwargs) -> Result<String>
fn to_currency_kw( &self, val: &CurrencyValue, currency: &str, cents: bool, separator: Option<&str>, adjective: bool, kw: &Kwargs, ) -> Result<String>
fn to_cardinal_float_kw( &self, value: &FloatValue, precision_override: Option<u32>, kw: &Kwargs, ) -> Result<String>
Source§fn es_currency_ordinal_fires(&self) -> bool
fn es_currency_ordinal_fires(&self) -> bool
Num2Word_ES
apocopates 1 → “un euro” in to_currency, bypassing to_cardinal, so
the stash never fires (false, the default). The regional es_XX
classes inherit Base.to_currency, whose _money_verbose calls
to_cardinal(1) → the stash fires → “primero córdoba” (true).Source§fn neg_zero_decimal(&self, _to: &str) -> Option<Result<String>>
fn neg_zero_decimal(&self, _to: &str) -> Option<Result<String>>
Decimal('-0.0') for mode to, which BigDecimal cannot
represent (it has no signed zero). None — the default — means the
value coincides with float -0.0, so the binding’s Float{-0.0}
demotion is exact. The ~10 languages that render the Decimal form
differently (ce/cy “dim”/“ноль” via the integer path, pl its float
grammar with the negword, rm a TypeError) override this to serve it
natively instead of leaning on a Python fallback.Source§fn inf_result(&self, _negative: bool, _to: &str) -> Result<String>
fn inf_result(&self, _negative: bool, _to: &str) -> Result<String>
str_to_number produced Decimal('Infinity') / -Infinity. Base’s
integer path does int(Decimal('Infinity')) → OverflowError. The many
self-contained converters that feed the raw token to int("Infinity")
get ValueError instead and override this. to is the requested mode.Source§fn nan_result(&self, _to: &str) -> Result<String>
fn nan_result(&self, _to: &str) -> Result<String>
str_to_number produced Decimal('NaN'). Base’s int(NaN) raises
ValueError (caught into the float path, which raises ValueError again).
Languages whose parse raises decimal.InvalidOperation first override.Source§fn python_maxval(&self) -> Option<BigInt>
fn python_maxval(&self) -> Option<BigInt>
getattr(converter, "MAXVAL", None) — the maxval() API.
Engine languages get it from their card table (Base sets
MAXVAL = 1000 * top_card); self-contained ones mostly lack the
attribute (None). The zero sentinel in maxval() means “unset”.