pub struct LangCe { /* private fields */ }Implementations§
Trait Implementations§
Source§impl Lang for LangCe
impl Lang for LangCe
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 default_separator(&self) -> &str
fn default_separator(&self) -> &str
This language’s own to_currency(separator=...) default,
read from the live Python signature. Base’s is “,”, but only
36 of 149 languages actually use it — most default to “ “ or a
conjunction, so inheriting Base’s comma silently corrupts them.
Source§fn pointword(&self) -> &str
fn pointword(&self) -> &str
What setup() assigns — reported for fidelity, never used. CE’s float
path joins on [DECIMALPOINT] instead (see [POINTWORD]).
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>
CE does not inherit Num2Word_Base.to_cardinal_float — it overrides
to_cardinal and dispatches on isinstance(number, float) inline, so
this hook routes to whichever arm Python’s type test would pick.
precision_override is discarded on purpose: the dispatcher’s
precision= kwarg assigns self.precision, and no CE code path reads it
(module docs, bug 10). Honouring it here would invent behaviour Python
does not have.
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), full routing.
The base default short-circuits a whole value to the integer path —
which is exactly what CE does not do. Python’s to_cardinal tests
isinstance(number, float) before anything else, so 1.0 takes the
float branch and renders its repr’s fractional digit: “цхьаъ а ноль”,
never plain “цхьаъ”. A whole Decimal conversely never sees the float
branch and resolves through the integer branches’ dict lookups. Both
arms already live in Lang::to_cardinal_float above; this override
only removes the whole-value shortcut in front of them.
Source§fn ordinal_float_entry(&self, value: &FloatValue) -> Result<String>
fn ordinal_float_entry(&self, value: &FloatValue) -> Result<String>
to_ordinal(float/Decimal) — to_cardinal(number, clazz, case="ORD").
For a float the case dies in the float branch (module docs, bug 9),
so to_ordinal(5.0) is the plain cardinal “пхиъ а ноль”. A Decimal
carries “ORD” through the integer branches, so to_ordinal(Decimal ("5.0")) really is “пхоьалгӀа” — same call, opposite outcome, decided
solely by isinstance. No verify_ordinal anywhere (bug 6), so
negatives render with the minus word and 1e16 still IndexErrors out
of the repr slice.
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) — verify_ordinal(number), then
str(number) + "-й".
This is the one CE entry point that does call verify_ordinal, and
Base’s runs both checks on the original value:
if not value == int(value):
raise TypeError(self.errmsg_floatord % value) # 0.5, Decimal("1.5")
if not abs(value) == value:
raise TypeError(self.errmsg_negord % value) # -3.0Both comparisons are numeric, so -0.0 (and Decimal("-0.0")) pass —
abs(-0.0) == -0.0 is True — and come out as “-0.0-й”, sign intact,
because the suffix is glued onto str(number), which is repr_str
here. A whole huge float sails through too: int(1e20) is exact, so
“1e+20-й” with the exponent form verbatim. %s renders the value the
same way, hence repr_str in both messages.
Source§fn year_float_entry(&self, value: &FloatValue) -> Result<String>
fn year_float_entry(&self, value: &FloatValue) -> Result<String>
to_year(float/Decimal) — to_cardinal(year, case="abs"), i.e. the
exact cardinal routing: floats through the float branch (whole values
included), Decimals through the integer branches.
Source§fn str_to_number(&self, s: &str) -> Result<ParsedNumber>
fn str_to_number(&self, s: &str) -> Result<ParsedNumber>
converter.str_to_number is Base’s plain Decimal(value) — CE does
not override it. The parse itself is therefore the default, but the
outcomes for the two non-finite specials diverge from what the
binding’s generic Inf/NaN mapping assumes, because CE’s to_cardinal
never calls int():
Decimal("Infinity")falls through every<comparison to the literalreturn "NOT IMPLEMENTED"(and “-Infinity” to “минус NOT IMPLEMENTED” via the negative branch) — a string, not the OverflowError other languages raise.Decimal("NaN")dies on the very first comparison,number < 0, withdecimal.InvalidOperation— not the ValueError fromint().
Neither is expressible through ParsedNumber (a BigDecimal cannot
hold Inf/NaN), so the parse itself is the plain default and the two
specials are served natively by the Lang::inf_result /
Lang::nan_result hooks below — no Python fallback.
Source§fn inf_result(&self, negative: bool, _to: &str) -> Result<String>
fn inf_result(&self, negative: bool, _to: &str) -> Result<String>
Decimal("Infinity") / -Infinity. CE’s to_cardinal never calls
int(): the value falls through every < comparison to the literal
return "NOT IMPLEMENTED", and the negative branch prepends
self.negword + " " — a string, not the OverflowError the base path
raises. Every mode routes through to_cardinal (to_ordinal/to_year
forward to it, and the fall-through ignores case), so to is unread.
Source§fn nan_result(&self, _to: &str) -> Result<String>
fn nan_result(&self, _to: &str) -> Result<String>
Decimal("NaN"). CE’s to_cardinal dies on its very first branch,
number < 0, because Decimal("NaN") < 0 raises
decimal.InvalidOperation — not the ValueError of int(NaN). No digit
is present in “NaN”, so the dispatcher propagates it natively.
Source§fn neg_zero_decimal(&self, to: &str) -> Option<Result<String>>
fn neg_zero_decimal(&self, to: &str) -> Option<Result<String>>
Decimal("-0.0"). BigDecimal cannot carry the sign, so the binding
would demote it to Float{-0.0} and CE’s float branch would render
“ноль а ноль”. But Decimal("-0.0") is not a float in Python: it
falls through the integer branches, number < 20 is true, and the
CARDINALS lookup hashes it to the integer key 0 — so it renders as
plain zero. cardinal/year run at case="abs" (“ноль”), ordinal at
case="ORD" (“нольалгӀа”). ordinal_num is left to the demoted float
path (returns None): it echoes str(number) == “-0.0” as “-0.0-й”,
which the repr-carrying float hook reproduces and this one cannot.
Source§fn to_cardinal_kw(&self, value: &BigInt, kw: &Kwargs) -> Result<String>
fn to_cardinal_kw(&self, value: &BigInt, kw: &Kwargs) -> Result<String>
to_cardinal(number, clazz=..., case=...).
Source§fn to_ordinal_kw(&self, value: &BigInt, kw: &Kwargs) -> Result<String>
fn to_ordinal_kw(&self, value: &BigInt, kw: &Kwargs) -> Result<String>
to_ordinal(number, clazz=...) — no case in this signature; it is
pinned to “ORD” by the forwarding call.
Source§fn to_year_kw(&self, value: &BigInt, kw: &Kwargs) -> Result<String>
fn to_year_kw(&self, value: &BigInt, kw: &Kwargs) -> Result<String>
to_year(year, case=...) — no clazz in this signature; the
forwarding call leaves it at the default.
Source§fn to_cardinal_float_kw(
&self,
value: &FloatValue,
_precision_override: Option<u32>,
kw: &Kwargs,
) -> Result<String>
fn to_cardinal_float_kw( &self, value: &FloatValue, _precision_override: Option<u32>, kw: &Kwargs, ) -> Result<String>
to_cardinal(float/Decimal, clazz=..., case=...). The float branch
drops both kwargs on the floor (module docs, bug 9) but accepts
them; only a Decimal actually feels them, riding the integer branches.
Source§fn to_ordinal(&self, value: &BigInt) -> Result<String>
fn to_ordinal(&self, value: &BigInt) -> Result<String>
to_ordinal(number, clazz="д") → to_cardinal(number, clazz, case="ORD").
Deliberately not guarded by verify_ordinal — negatives are accepted
and rendered with the minus word (module docs, bug 6).
Source§fn to_year(&self, value: &BigInt) -> Result<String>
fn to_year(&self, value: &BigInt) -> Result<String>
to_year(year, case="abs") → to_cardinal(year, case=case). No
era/century handling at all; identical to to_cardinal by default.
Source§fn currency_adjective(&self, code: &str) -> Option<&str>
fn currency_adjective(&self, code: &str) -> Option<&str>
Inherited from Num2Word_EUR and unreachable — see
[build_currency_adjectives].
Source§fn pluralize(&self, n: &BigInt, forms: &[String]) -> Result<String>
fn pluralize(&self, n: &BigInt, forms: &[String]) -> Result<String>
Num2Word_EUR.pluralize: forms[0 if n == 1 else 1].
Inherited, and non-default (Base’s raises NotImplementedError), so it is
ported — but no CE path reaches it. to_currency takes cr1[0]/cr2[0]
directly and to_cheque takes cr1[-1]; only default_to_currency
calls pluralize, and CE overrides to_currency wholesale.
Python indexes the tuple, so a one-form entry with n != 1 would raise
IndexError. All four CE entries carry two forms, so that cannot fire —
mapped to Index rather than a panic so the exception type survives if
the table ever changes.
Source§fn money_verbose(&self, _number: &BigInt, _currency: &str) -> Result<String>
fn money_verbose(&self, _number: &BigInt, _currency: &str) -> Result<String>
Num2Word_CE._money_verbose(self, number, currency, case) — three
positional parameters, where Num2Word_Base’s (and every other
language’s) takes two. CE is the only class in the library that widens
this signature.
This trait hook is the two-argument call, and CE has no two-argument
_money_verbose, so reaching it is precisely Python’s TypeError. The
sole live call site is the one to_cheque inherits from Base:
words = self._money_verbose(whole, currency) # boom, every timeSo to_cheque is unconditionally broken for CE on every currency it
implements, and the corpus records exactly that split:
cheque:EUR/USD/GBP -> TypeError (arity, raised here)
cheque:JPY/KWD/... -> NotImplementedError (code lookup, raised first)Leaving to_cheque at its default reproduces both and keeps the raise
at the call site Python raises from: default_to_cheque looks the
currency up before calling money_verbose, matching Base’s order.
to_currency never lands here — it calls cardinal(.., MONEY_CASE)
directly, which is what _money_verbose resolves to under case="abs".
Source§fn cardinal_from_decimal(&self, value: &BigDecimal) -> Result<String>
fn cardinal_from_decimal(&self, value: &BigDecimal) -> Result<String>
The fractional-cents hook: Python’s self.to_cardinal(float(right)).
The trait default routes to floatpath::cardinal_from_bigdecimal, which
ends in Num2Word_Base.to_cardinal_float — the wrong method for CE,
which overrides to_cardinal and never inherits that path. The default
would print lang.pointword() (“запятая”) where CE prints
[DECIMALPOINT] (“а”), and would run float2tuple’s scaling and
zero-padding where CE just slices the repr.
The float(right) cast is reproduced rather than staying in arbitrary
precision, because it is what Python does and it is lossy: right is a
Decimal like 1.100, and the f64 it becomes is what str() then sees.
Source§fn cents_verbose(&self, _number: &BigInt, _currency: &str) -> Result<String>
fn cents_verbose(&self, _number: &BigInt, _currency: &str) -> Result<String>
Num2Word_CE._cents_verbose(self, number, currency, case) — the same
three-parameter widening as money_verbose, and
the same TypeError on a two-argument call.
Unreachable in practice: the only caller is default_to_currency, which
CE’s to_currency override displaces. Ported for symmetry, so that the
pair cannot drift apart and a future refactor that routes CE back
through the default path fails loudly instead of silently inventing a
two-argument method Python does not have.
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>
Num2Word_CE.to_currency at its case="abs" default. The full body,
case= included, lives in LangCe::currency_with_case;
Lang::to_currency_kw below reaches it with the caller’s case.
Source§fn to_currency_kw(
&self,
val: &CurrencyValue,
currency: &str,
cents: bool,
separator: Option<&str>,
adjective: bool,
kw: &Kwargs,
) -> Result<String>
fn to_currency_kw( &self, val: &CurrencyValue, currency: &str, cents: bool, separator: Option<&str>, adjective: bool, kw: &Kwargs, ) -> Result<String>
to_currency(..., case=...) — the one extra kwarg CE’s signature
carries beyond the trait hook.
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”.fn negword(&self) -> &str
fn to_cardinal(&self, value: &BigInt) -> Result<String>
fn to_ordinal_num(&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.fn cents_terse(&self, number: &BigInt, currency: &str) -> Result<String>
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_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_ordinal_num_kw(&self, value: &BigInt, 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).