pub struct LangFa { /* private fields */ }Implementations§
Trait Implementations§
Source§impl Lang for LangFa
impl Lang for LangFa
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_FA.to_cardinal.
The float2tuple call in Python collapses to (value, 0, 0) for every
integer, so the fractional branches are dead here — see module docs.
Source§fn to_ordinal(&self, value: &BigInt) -> Result<String>
fn to_ordinal(&self, value: &BigInt) -> Result<String>
Port of Num2Word_FA.to_ordinal.
r = self.to_cardinal(number)
if r[-1] == "ه" and r[-2] == "س":
return r[:-1] + "وم"
return r + "م"Source§fn to_ordinal_num(&self, value: &BigInt) -> Result<String>
fn to_ordinal_num(&self, value: &BigInt) -> Result<String>
Port of Num2Word_FA.to_ordinal_num (a @staticmethod):
str(value) + "م". Purely lexical — the minus sign survives verbatim,
so -5 gives “-5م”, and the 10^18 ceiling does not apply because
to_cardinal is never called.
Source§fn to_year(&self, value: &BigInt) -> Result<String>
fn to_year(&self, value: &BigInt) -> Result<String>
Port of Num2Word_FA.to_year: return self.to_cardinal(value).
No era suffix, no two-digit-pair splitting — years are plain cardinals.
Source§fn ordinal_float_entry(&self, value: &FloatValue) -> Result<String>
fn ordinal_float_entry(&self, value: &FloatValue) -> Result<String>
to_ordinal(float/Decimal): FA’s to_ordinal is
self.to_cardinal(number) + the “م”/“سوم” suffix rule, and its
to_cardinal handles floats/Decimals itself — so the ordinal float
path is just the cardinal float path re-suffixed: 0.5 → “نیمم”,
3.25 → “سه و بیست و پنج صدمم”, -1000000.0 → “منفی یک میلیونم”.
The r[-1] probe on the empty cardinal that values >= 10^18 produce
raises IndexError (1e+20), exactly as the int path does.
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): str(value) + "م", purely lexical —
“5.0م”, “-17م”, “1E+2م”.
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 as it actually behaves on
Num2Word_FA — whose __init__ never chains to Base’s, so
self.negword does not exist (bug 3): a negative fraction dies on
the attribute lookup with AttributeError before any words are built.
Positive fractions keep Base’s port, bare “s” plural included
(“دو پنجمs”).
Source§fn str_to_number(&self, s: &str) -> Result<ParsedNumber>
fn str_to_number(&self, s: &str) -> Result<ParsedNumber>
converter.str_to_number — Base’s Decimal(value). Decimal("NaN")
parses fine; FA’s to_cardinal then dies on the very first comparison
(number < 0) with decimal.InvalidOperation. The binding otherwise
maps ParsedNumber::NaN to int(NaN)’s ValueError, so the
InvalidOperation must be raised here. Infinity keeps the default
routing (int(Decimal("Infinity")) → OverflowError inside
float2tuple), which the binding already produces.
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>
Float/Decimal cardinal. FA overrides to_cardinal (not
to_cardinal_float) in Python and renders the fraction with its own
fractional/farsiFrac/“نیم” machinery, never Base’s “(.)” pointword —
so this must NOT fall through to default_to_cardinal_float. See
[fa_cardinal_float] and the module docs.
precision_override is ignored: FA’s float2tuple recomputes
self.precision from the value every call, clobbering it. Verified
against the interpreter (precision=1 and precision=4 agree).
Source§fn cardinal_from_decimal(&self, value: &BigDecimal) -> Result<String>
fn cardinal_from_decimal(&self, value: &BigDecimal) -> Result<String>
Fractional-cents bridge. Python’s currency path does
cents_str = self.to_cardinal(float(right)), so the Decimal is
float-cast (reproducing any repr rounding) and run through FA’s own
float cardinal — the same rendering as [fa_cardinal_float], with the
“نیم” quirk and no pointword. The precision is derived from the cast
f64’s repr exactly as FA’s float2tuple does.
Source§fn pluralize(&self, _n: &BigInt, forms: &[String]) -> Result<String>
fn pluralize(&self, _n: &BigInt, forms: &[String]) -> Result<String>
Port of Num2Word_FA.pluralize:
if isinstance(forms, tuple):
return forms[0]
return formsPersian does not inflect a counted noun, so the first form comes back
for every n. Ignoring n is the whole point, not an oversight — and
both members of each pair are identical anyway, so even a Base-style
forms[0 if n == 1 else 1] would agree on this table.
The isinstance test can only go one way in practice: the sole caller
(Num2Word_Base.to_currency) passes a CURRENCY_FORMS tuple, and
prefix_currency — the one thing that could substitute something else —
returns a tuple too and is dead here regardless, since
CURRENCY_ADJECTIVES is empty. Python’s forms[0] on an empty tuple
would be IndexError, so the miss maps to Index rather than panicking.
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_FA.to_currency, which is a pass-through:
def to_currency(self, val, currency="IRT", cents=True,
separator=" و ", adjective=False):
return super(Num2Word_FA, self).to_currency(...)The kwarg defaults are already carried by Self::default_currency and
Self::default_separator, so the body would be Base’s verbatim — were
it not for bug 3. Base formats its minus sign from self.negword, an
attribute this class does not have, so every negative amount raises
AttributeError instead of returning a string.
Ordering is load-bearing and verified against the interpreter: Base
looks the currency up — raising NotImplementedError on a miss — before
it touches negword, on the int branch and the float branch alike. So
an unknown code beats a negative value: to_currency(-12.34, "GBP") is
NotImplementedError, to_currency(-12.34, "USD") is AttributeError.
Both appear in the corpus.
to_cardinal is untouched by any of this — FA’s own override inlines
the literal “منفی “ rather than reading the attribute, which is why
negative cardinals work while negative currency does not.
fn negword(&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 pointword(&self) -> &str
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 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 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 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 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”.