jamesfredley commented on PR #15726:
URL: https://github.com/apache/grails-core/pull/15726#issuecomment-4732489247

   > I'm ok with the change, but I don't think I fully understand why we have 
to handle this locale issue directly
   
   Short version: this isn't Grails working around itself - it's a hard 
limitation of `java.text.DecimalFormat` once the JVM uses CLDR locale data (the 
default since JDK 9). I dug into the JDK internals to be sure we weren't just 
doing something dumb on our side, and we aren't.
   
   **Root cause**
   
   For `nb_NO` (and `nn_NO`, `sv_SE`, `fi_FI`, ...) CLDR defines the minus sign 
as **U+2212 MINUS SIGN**, not **U+002D ASCII HYPHEN-MINUS**. `DecimalFormat` 
builds its negative prefix straight from `DecimalFormatSymbols.getMinusSign()` 
and matches that prefix *literally* during `parse()`. So an ASCII `-` is simply 
not recognized as a sign - the parser stops at index 0 and the bind fails.
   
   Probe on JDK 21 (Corretto 21.0.11):
   
   ```
   === Locale nb_NO ===
     minusSign char = U+2212
     negativePrefix = U+2212
     parse("-1"  [U+002D U+0031]) -> null   consumedIndex=0/2   // ASCII minus: 
FAILS
     parse("...1" [U+2212 U+0031]) -> -1    consumedIndex=2/2   // locale 
minus: ok
     format(-1)  -> [U+2212 U+0031]
   
   === Locale en_US ===
     minusSign char = U+002D
     parse("-1"  [U+002D U+0031]) -> -1     consumedIndex=2/2   // ASCII minus: 
ok
   ```
   
   So `NumberFormat.getInstance(new Locale("nb","NO")).parse("-1")` returns 
`null`. `en_US` only works because its CLDR minus *happens* to be ASCII - which 
is exactly why this stayed hidden until a Norwegian-locale browser posted a 
form.
   
   **Why Java won't "just pass it through"**
   
   There is no leniency knob for this. `DecimalFormat` has no "accept either 
minus" mode, and it has no idea the string arrived from an HTML form. The 
request side, meanwhile, is always ASCII: per the WHATWG "valid floating-point 
number" rule an `<input type=number>` submits ASCII `-`, and on a `text` field 
the user types the `-` on their keyboard, which is also ASCII. So the wire is 
ASCII while the locale parser only accepts U+2212, and nothing in the JDK 
reconciles that gap for us.
   
   **The "just use Java's default" options I ruled out**
   
   - `-Djava.locale.providers=COMPAT` restores the pre-9 ASCII minus, but it's 
a global, deprecated JVM flag (COMPAT data is being removed) and a wrong fix 
for one parse path.
   - Forcing `symbols.minusSign = '-'` makes ASCII parse but then *rejects* a 
genuine U+2212 - strictly less lenient than what we ship now.
   
   That's why #15475 fixed the render side (emit ASCII minus into inputs) and 
this PR fixes the matching bind side. Normalizing only a leading ASCII `-` to 
the active locale's minus before `parse()` is the minimal change that keeps 
full locale-aware parsing (grouping/decimal separators) intact while accepting 
the sign every browser actually sends - and the locale's native minus still 
parses too, so it's strictly more lenient, not less.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to