Intl.NumberFormat signDisplay option displays odd behaviour
Brawl345 opened this issue · 1 comments
Description
The signDisplay
option for Intl.NumberFormat
is bugged and has an odd behaviour. E.g. the option exceptZero
outputs "+8,537,71+
" but it should output +8.537,71 €
. Don't know if this only affects Android.
Steps to reproduce
- Create a new React Native application
- Insert this code somewhere:
<Text>{
new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR',
maximumFractionDigits: 2,
minimumFractionDigits: 2,
roundingMode: 'floor',
signDisplay: 'exceptZero',
}).format(8537.71)
}</Text>
- Start the app on Android
React Native Version
0.74.4
Affected Platforms
Runtime - Android
Output of npx react-native info
System:
OS: macOS 14.5
CPU: (10) arm64 Apple M1 Max
Memory: 307.52 MB / 32.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 20.14.0
path: /etc/profiles/per-user/user/bin/node
Yarn:
version: 3.6.4
path: /etc/profiles/per-user/user/bin/yarn
npm:
version: 10.7.0
path: /etc/profiles/per-user/user/bin/npm
Watchman:
version: 2024.03.11.00
path: /etc/profiles/per-user/user/bin/watchman
Managers:
CocoaPods: Not Found
SDKs:
iOS SDK:
Platforms:
- DriverKit 23.5
- iOS 17.5
- macOS 14.5
- tvOS 17.5
- visionOS 1.2
- watchOS 10.5
Android SDK:
API Levels:
- "30"
- "31"
- "32"
- "33"
- "33"
- "34"
Build Tools:
- 30.0.1
- 30.0.3
- 31.0.0
- 33.0.1
- 34.0.0
System Images:
- android-22 | Google APIs ARM 64 v8a
- android-31 | Google APIs ARM 64 v8a
- android-33 | Wear OS 4 ARM 64 v8a
- android-33 | Google APIs ARM 64 v8a
- android-33 | Google Play ARM 64 v8a
- android-34 | Google Play ARM 64 v8a
Android NDK: Not Found
IDEs:
Android Studio: 2024.1 AI-241.18034.62.2411.12071903
Xcode:
version: 15.4/15F31d
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.12
path: /usr/bin/javac
Ruby:
version: 2.6.10
path: /usr/bin/ruby
npmPackages:
"@react-native-community/cli": Not Found
react:
installed: 18.2.0
wanted: 18.2.0
react-native:
installed: 0.74.4
wanted: 0.74.4
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: false
iOS:
hermesEnabled: Not found
newArchEnabled: false
Stacktrace or Logs
n/a
Reproducer
https://github.com/Brawl345/rn-signDisplay-bug-reproducer
Screenshots and Videos
I was trying to fix this issue.
After debugging I found out that current logic which handles signDisplay is breaking in these cases:
-
The old logic replaces positivePrefix with just the plus sign if negativePrefix is not empty. This means any existing currency symbol or other content in positivePrefix would be lost.
Example:
Given positivePrefix = ¥ and negativePrefix = -, the old logic would replace positivePrefix with +, resulting in + instead of +¥.
Also In case JP locale it is not respecting already appended currencySymbol. -
It adds a Prefix and Suffix both in this case:
new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR',
signDisplay: 'exceptZero',
}).format(8537.71)`
Result: +8,537,71+
Expected: +8.537,71 €
So in order to fix this we surely need to revisit the logic written here:
Solution:
if (decimalFormat.getPositivePrefix().isEmpty()) {
decimalFormat.setPositivePrefix(new String(new char[]{symbols.getPlusSign()}));
} else {
// Preserve the existing prefix, which may include the currency symbol, and prepend the plus sign
decimalFormat.setPositivePrefix(new String(new char[]{symbols.getPlusSign()}) + decimalFormat.getPositivePrefix());
}
I tested this in above failing cases.
Let me know your thoughts on this, or any edge case which you thought will break this.