Recently, Android studio Flamingo 🦩 hit the stable channel. So I have updated the IDE and all works as expected.
Android studio Flamingo comes with default JDK set to
JDK17
- All works as expected until I run the unit tests for our project 💔
Our application support English and French. So we have unit tests for currency formatting to ensure it works as expected for both languages.
Tests for French currency formatted starts failing 😢 and we wonder why it starts falling on JDK17
From the failing tests, we found that there is an issue with the number separator
🤯.
For the French locale, the number separator is changed to a narrow no-break space(NNBSP) U+202F
It wasn’t changed in JDK and it doesn’t just start with
JDK17
Before JDK17
, We are using JDK11
. Until JDK12
there is no issue with the existing number separator(NBSP)
So what changes the number separator for French
In this bug, I found that it was introduced by the change in Unicode Common Locale Data Repository(CLDR) which is the
upstream source of JDK
Fix
- If you are using a
hard-coded number separator
// <= JDK12 private const val NBSP = "\u00A0"
then change it to a new number separator
// Java 13 to 17 private const val NNBSP = "\u202F"
Or
To make sure your tests are JDK-independent, use the following method
val separator = DecimalFormatSymbols.getInstance(Locale.FRENCH).groupingSeparator
Job Offers
Full sample code
/** * @author Nav Singh * */ class FrenchNumberSeparatorTest { @Test fun `when Locale is French then check number is properly formatted`() { val formattedNumber = formatNumberToFrenchLocale(1000) Assert.assertEquals("1${separator}000", formattedNumber) } @Test fun `when number is formatted for French locale then check the number separator is valid`() { val formatted = formatNumberToFrenchLocale(1000) // Hard-coded separator - works only upto JDK12 // Assert.assertEquals(NBSP, formatted.substring(1, 2)) Assert.assertEquals(separator, formatted.substring(1, 2)) } private fun formatNumberToFrenchLocale(number: Int): String { val format = NumberFormat.getInstance(Locale.FRANCE) return format.format(number.toLong()) } companion object { // Number separator in Java 8, 11 & 12. private const val NBSP = "\u00A0" // Number separator in Java 13 to 17. private const val NNBSP = "\u202F" // Get number separator and use it val separator = DecimalFormatSymbols.getInstance(Locale.FRENCH).groupingSeparator.toString() } }
References
Stay in touch
Nav Singh (@navczydev@androiddev.social) — Android Dev Social