""" Locale / formatting settings for the Palladium Streamlit app. All settings are read from environment variables (via .env) so the same codebase can be deployed for different regions without code changes. Environment variables --------------------- PALLADIUM_CURRENCY_SYMBOL Default: "$" Prefix shown before monetary values (e.g. "$", "€", "£", "CAD "). PALLADIUM_THOUSANDS_SEP Default: "," Thousands separator used in number display (e.g. "," for Americas, "." for continental Europe, " " for some locales). PALLADIUM_DECIMAL_SEP Default: "." Decimal separator (e.g. "." for Americas/UK, "," for continental Europe). Note: Streamlit's NumberColumn ``format`` uses printf-style strings. The ``%,`` flag (thousands separator) is supported in Streamlit ≥ 1.31. For non-standard separators (e.g. European "." thousands / "," decimal) the values are pre-formatted as strings and displayed in TextColumns. """ from __future__ import annotations import os def _env(key: str, default: str) -> str: return os.environ.get(key, default).strip() # --------------------------------------------------------------------------- # Resolved settings (read once at import time; restart app to pick up changes) # --------------------------------------------------------------------------- CURRENCY_SYMBOL: str = _env("PALLADIUM_CURRENCY_SYMBOL", "$") THOUSANDS_SEP: str = _env("PALLADIUM_THOUSANDS_SEP", ",") DECIMAL_SEP: str = _env("PALLADIUM_DECIMAL_SEP", ".") # True when the locale uses standard printf-compatible separators # (i.e. "," thousands + "." decimal — the C/POSIX default). # When False, we pre-format values as strings instead of relying on printf. _STANDARD_LOCALE: bool = THOUSANDS_SEP == "," and DECIMAL_SEP == "." def currency_fmt() -> str: """Return a Streamlit NumberColumn ``format`` string for currency. For standard locales returns e.g. ``"$%,.0f"`` (thousands-separated, no decimal places). For non-standard locales returns ``"%s"`` and callers should use :func:`fmt_currency` to pre-format the value. """ if _STANDARD_LOCALE: return f"{CURRENCY_SYMBOL}%,.0f" return "%s" def pct_fmt() -> str: """Return a Streamlit NumberColumn ``format`` string for percentages. Stores the value as a fraction (0–1) and displays as e.g. ``"20.00%"``. Streamlit's ``%%`` in format strings renders a literal ``%``. """ if _STANDARD_LOCALE: return "%.2f%%" return "%s" def fmt_currency(value: float) -> str: """Format *value* as a currency string using the configured locale.""" if _STANDARD_LOCALE: return f"{CURRENCY_SYMBOL}{value:,.0f}" # Non-standard: build manually integer_part = f"{int(abs(value)):,}".replace(",", THOUSANDS_SEP) sign = "-" if value < 0 else "" return f"{sign}{CURRENCY_SYMBOL}{integer_part}" def fmt_pct(value: float) -> str: """Format *value* (0–1 fraction) as a percentage string.""" pct = value * 100 if _STANDARD_LOCALE: return f"{pct:.2f}%" integer_part = f"{int(pct)}" decimal_part = f"{abs(pct) % 1:.2f}"[1:] # ".xx" return f"{integer_part}{DECIMAL_SEP}{decimal_part[1:]}%"