From f7fdb2b8234cae296a75bebb308e840fd89f30a6 Mon Sep 17 00:00:00 2001 From: Terry Yiu Date: Thu, 10 Sep 2026 14:15:15 +0300 Subject: [PATCH] Use the browser's own locale for web currency display names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit jsCurrencyDisplayName() was hardcoding 'en' for Intl.DisplayNames, so every currency name shown on web (USD, JPY, ...) stayed English regardless of the user's locale — same class of bug as the "EU" string, just for every currency rather than one region. Switched to undefined, matching regionDisplayName()'s fix; verified with Node that this actually produces locale-appropriate names (e.g. "US Dollar" / "dollar des États-Unis" / "米ドル"). Left jsCurrencyFractionDigits()'s 'en' alone and documented why: verified with Node that a currency's decimal-digit count doesn't vary by locale, so locale there is just a required constructor argument, not something the result depends on. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01FXcrACM5sok3M1KQJ8kByy --- .../kotlin/xyz/tyiu/satsprice/SystemCurrencies.web.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/shared/src/webMain/kotlin/xyz/tyiu/satsprice/SystemCurrencies.web.kt b/shared/src/webMain/kotlin/xyz/tyiu/satsprice/SystemCurrencies.web.kt index a3cdcce..6e11b44 100644 --- a/shared/src/webMain/kotlin/xyz/tyiu/satsprice/SystemCurrencies.web.kt +++ b/shared/src/webMain/kotlin/xyz/tyiu/satsprice/SystemCurrencies.web.kt @@ -6,8 +6,10 @@ private fun jsSupportedCurrencyCodes(): JsArray = js("Intl.supportedVa // A chained `new Foo(x).bar()` inside js() can misparse (`new` binding to the whole chain rather // than just the constructor call), so the constructor result is bound to a variable first. +// `undefined` (rather than a fixed locale like 'en') uses the browser's own locale — code always +// comes from jsSupportedCurrencyCodes() itself, so .of(code) is guaranteed to resolve. private fun jsCurrencyDisplayName(code: String): String = js( - "(function() { var names = new Intl.DisplayNames(['en'], { type: 'currency' }); return names.of(code); })()", + "(function() { var names = new Intl.DisplayNames(undefined, { type: 'currency' }); return names.of(code); })()", ) actual fun systemCurrencies(): List = @@ -27,6 +29,10 @@ actual fun systemCurrencies(): List = */ actual fun localeCurrencyCode(): String? = null +// A currency's decimal-digit count is a property of the currency, not the locale (e.g. JPY's is +// always 0), so — unlike jsCurrencyDisplayName/jsRegionDisplayName above — locale is only a +// required constructor argument here, not something the result actually depends on; 'en' is as +// good as any other. private fun jsCurrencyFractionDigits(code: String): Int = js( """(function() { var fmt = new Intl.NumberFormat('en', { style: 'currency', currency: code }); return fmt.resolvedOptions().maximumFractionDigits; })()""", )