pub struct LangCs { /* private fields */ }Implementations§
Trait Implementations§
Source§impl Lang for LangCs
impl Lang for LangCs
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 to_cardinal(&self, value: &BigInt) -> Result<String>
fn to_cardinal(&self, value: &BigInt) -> Result<String>
Port of Num2Word_CS.to_cardinal, integer path only.
Python builds n = str(number).replace(",", ".") and branches on
"." in n. For integer input there is never a . or ,, so only the
else arm is reachable: strip a leading "-", convert the magnitude,
and prefix negword + " ".
Note the negword is used unstripped (self.negword + " " + result),
not via Num2Word_Base’s "%s " % self.negword.strip(). “mínus” has no
surrounding whitespace, so both spell “mínus jedna” — but the override
means the base’s parse_minus spacing convention does not apply here.
Source§fn to_ordinal(&self, value: &BigInt) -> Result<String>
fn to_ordinal(&self, value: &BigInt) -> Result<String>
Port of Num2Word_CS.to_ordinal.
int(number) inside Python’s try always succeeds for integer input,
so the except (ValueError, TypeError): return str(number) fallback is
unreachable and is not modelled.
The table covers 1..=20, the round tens 30..=90, 100 and 1000. Every
other input — including 0 and all negatives — takes the
to_cardinal(num) + "ý" path, producing the malformed-but-correct
outputs documented in the module header (“nulaý”, “dvě stěý”,
“mínus jednaý”, …). Reproduced verbatim; see PORTING.md fidelity rules.
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 first line is num = int(number) — truncation toward zero — so 2.5 → “druhý”,
-1.5 → “mínus jednaý”, Decimal("1E+2") → “stý”, and the huge
e-form floats that make the cardinal path raise ValueError
(1e+16) convert cleanly here (“deset biliardý”). The
except (ValueError, TypeError) rescue is unreachable for a
finite float/Decimal; int(inf)’s OverflowError and int(nan)’s
ValueError are modelled for completeness.
Source§fn str_to_number(&self, s: &str) -> Result<ParsedNumber>
fn str_to_number(&self, s: &str) -> Result<ParsedNumber>
str_to_number stays Base’s Decimal(value), but CS’s to_cardinal
then runs int() over the dot-free str() form, so "Infinity"
raises ValueError (int('Infinity')) rather than the shared Inf
sentinel’s OverflowError.
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>
Port of the non-integer path of Num2Word_CS.to_cardinal.
CS overrides to_cardinal outright and handles floats/Decimals inline
off the string form, never through Num2Word_Base.to_cardinal_float
and never through float2tuple. So this override does NOT call the
shared floatpath code: it rebuilds n = str(number) exactly
(python_repr_f64 for a float, python_str_decimal for a Decimal — the
same two reconstructors the currency notes describe) and then runs the
Python algorithm character by character:
n = str(number).replace(",", ".")
if "." in n:
is_negative = n.startswith("-")
abs_n = n[1:] if is_negative else n
left, right = abs_n.split(".")
right = right.rstrip("0") or "0" # '1.50' and 1.50 → 'pět'; '1.00' → 'nula'
decimal_part = " ".join(ZERO[0] if d == "0" else ONES[int(d)][0] for d in right)
result = "%s %s %s" % (self._int2word(int(left)), self.pointword, decimal_part)
if is_negative: result = self.negword + " " + result
return result
else:
is_negative = n.startswith("-")
if is_negative: return self.negword + " " + self._int2word(int(n[1:]))
else: return self._int2word(int(n))Consequences reproduced verbatim:
- The f64-artefact trap does not apply here: CS reads the shortest-
round-trip repr string, not
abs(value-pre)*10**precision.2.675reads its digits straight off"2.675"→ “dva čárka šest sedm pět”;1.005off"1.005"→ “jedna čárka nula nula pět”. precision/precision_overrideare ignored. CS’s Pythonto_cardinaltakes noprecisionkwarg and never readsself.precision, so theprecision=override the dispatcher stashes on the converter is dead for CS. The parameter is accepted and dropped.- Trailing zeros are stripped from the fraction (issue #75), an all-
zero fraction collapses to a single “nula”:
Decimal('1.10')→ “jedna čárka jedna”,1.0→ “jedna čárka nula”. - A repr/str with no “.” (scientific notation,
inf,nan) takes theelsearm and feeds a non-decimal token toint(), which raises ValueError — reproduced via [parse_int_token].1e-05,1e+16,Decimal('1E-7'),inf,nanall raise, matching the interpreter. An integral Decimal likeDecimal('5')prints"5"and the else arm returns “pět”;Decimal('-3')returns “mínus tři”. - A “.” repr that also carries an
'e'(e.g.1.5e-05→"1.5e-05") enters the decimal arm and hits the'e'while spelling the fractional digits →int('e')ValueError, same as Python.
negword is used unstripped (self.negword + " " + result), exactly
as the Python source does; “mínus” has no surrounding whitespace so the
bytes are identical.
Source§fn pluralize(&self, n: &BigInt, forms: &[String]) -> Result<String>
fn pluralize(&self, n: &BigInt, forms: &[String]) -> Result<String>
Port of Num2Word_CS.pluralize(n, forms).
Python indexes the tuple directly, so a form list shorter than the
selected index raises IndexError. Every CS entry has three forms, so
that is unreachable — but it is mapped to Index rather than panicking
so the exception type survives if the table ever changes.
Reached only from Num2Word_Base.to_currency’s float path; CS’s own
int path pointedly does not call this (see to_currency).
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>
Port of Num2Word_CS.to_currency.
CS intercepts isinstance(val, int) — a true Python int, never a
whole float — and hands everything else to Num2Word_Base.to_currency.
The split is why currency:USD of 1 is “jedna dolar” (no cents) while
1.0 is “jedna dolar, nula centů”.
§The int path’s plural bug, reproduced
Python picks the currency word by hand here instead of calling
self.pluralize:
if abs_val == 1:
currency_str = cr1[0]
else:
currency_str = cr1[1] if len(cr1) > 1 else cr1[0]So every count other than 1 takes cr1[1], the paucal (2-4) form,
including 0, 5+ and the teens — where pluralize would correctly pick
cr1[2]. The corpus locks the wrong answers in: currency:USD of 0
is “nula dolary”, of 100 is “sto dolary”, of 1000000 is
“milion dolary” — all should be “dolarů”, and the float path one line
below does say “dolarů” for the same magnitudes (“nula dolarů,
padesát centů” at 0.5). EUR hides the bug entirely because its three
forms are identical. Do not “fix” this into a pluralize call.
abs(val) is taken before the comparison, so -1 is singular too:
“mínus jedna dolar”.
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.fn negword(&self) -> &str
fn pointword(&self) -> &str
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
fn to_ordinal_num(&self, value: &BigInt) -> Result<String>
fn to_year(&self, value: &BigInt) -> Result<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 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_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 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). Base returns the value unchanged and
the dispatcher str()s it, so the default echoes the Python repr the
binding computed.Source§fn year_float_entry(&self, value: &FloatValue) -> Result<String>
fn year_float_entry(&self, value: &FloatValue) -> Result<String>
to_year(float/Decimal). Base’s to_year is to_cardinal.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”.