silvershop-suite / currency-format
Set the shop base currency in the CMS (Settings > Shop) and render prices locale-aware for it (ICU): correct symbol, placement, separators and decimals. A drop-in for single-currency shops that would otherwise configure currency via YAML.
Package info
github.com/silvershop-suite/silvershop-currency-format
Type:silverstripe-vendormodule
pkg:composer/silvershop-suite/currency-format
Requires
- php: ^8.3
- silvershop/core: ^6
- silverstripe/framework: ^6.0
- silverstripe/siteconfig: ^6.0
Requires (Dev)
- phpunit/phpunit: ^11.0
- silverstripe/sqlite3: ^4
- squizlabs/php_codesniffer: ^3.7
Suggests
- ext-intl: Recommended for locale-aware price formatting; without it the module falls back to a simple symbol + amount.
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-19 19:54:30 UTC
README
Set the shop base currency in the CMS (Settings → Shop) and render prices locale-aware for it, for SilverShop.
Out of the box, silvershop's base currency is YAML-only (ShopConfigExtension.base_currency, default NZD) and
ShopCurrency renders every price with a fixed $ symbol regardless of that currency. This module fills the gap for
the common single-currency shop: pick your currency in the CMS and prices format correctly for it — the right
symbol, placement, spacing, grouping and decimal separators, and the currency's own number of decimals.
What it adds
- A Currency selector in Settings → Shop (searchable, all 294 ISO 4217 currencies from
symfony/intl, shown asEUR - € (Euro); scoped toShopConfigExtension.supported_currencieswhen that is configured). - A Currency display setting —
Symbol(locale default, may disambiguate asUS$/JP¥),Narrow symbol(force the plain$/¥), orISO code(USD). Same vocabulary as JavaScript'sIntl.NumberFormatcurrencyDisplay. - Locale-aware price formatting via PHP
intl(ICU) — e.g. on annl_NLsite€ 1.234,50, onde_DE1.234,50 €, and¥1,234for JPY (no decimals). Formatting follows the site locale (i18n::get_locale()); the currency only decides the symbol and the number of decimals. - Pin the formatting locale independently of the UI language with
format_locale— useful for an English-language shop that still wants EU number format. The currency symbol and decimals are unchanged; only the digit grouping/placement follow this locale:SilverShop\CurrencyFormat\LocaleCurrency: format_locale: 'nl_NL' # e.g. "€ 28.999,99" with an English UI; null (default) follows i18n::get_locale()
- Prices render for the selected currency everywhere they appear — product listings, detail, price ranges, cart,
receipts, invoices — via an
Injectoroverride of silvershop's currency field.
Non-invasive by design
Leave the selector on System default and nothing changes: prices render exactly as stock silvershop/core does
(ShopCurrency::Nice()), and the base_currency YAML default is untouched. The module only alters behaviour once a
currency is explicitly chosen. Installs that already configure currency via YAML are unaffected.
Installation
composer require silvershop-suite/currency-format
Then run dev/build?flush=all. ext-intl is recommended (it powers the locale-aware formatting); without it the
module falls back to a simple symbol + amount.
How it works
LocaleCurrencyextends core'sShopCurrencyand is bound viaInjectorto both theCurrencyDBField cast and the concreteShopCurrencyservice — so every price uses it, including product price ranges, which core builds withShopCurrency::create(). When no currency is selected it defers toparent::Nice(), a transparent drop-in that renders exactly as stock silvershop/core. The per-localeNumberFormatteris cached per request, so formatting adds negligible overhead versus core.- The selection is made authoritative through core's
updateSiteCurrencyextension hook:CurrencyConfigExtension::updateSiteCurrency()feedsSiteConfig.BaseCurrencyintoShopConfigExtension::get_site_currency(), so orders, conversion and display all agree — no config is mutated at runtime. A blank selection leaves core'sbase_currencydefault untouched. On a silvershop/core without the hook the module still formats prices (display follows the field); only the logical base currency then stays with the YAML config.
Notes
- The comma / space / symbol placement come from the locale, not the currency: to display
€ 1.234,50the site must run thenl_NLlocale. A currency picked underen_USrenders the US way (€1,234.50). - This is the single-currency stepping-stone; a full multi-currency solution (storefront switcher, live exchange rates, per-currency price overrides) is a separate, larger concern.
Licence
BSD-3-Clause.
Credits
Built and maintained by Remy Vaartjes (remy@xd.nl) — part of the SilverShop-Suite.